首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不使用块ROM在verilog中创建ROM

不使用块ROM在verilog中创建ROM
EN

Stack Overflow用户
提问于 2015-11-28 22:46:21
回答 2查看 7.4K关注 0票数 2

我想创建一个ROM (就像一个查找表)来存储ASCII字符,当我从ROM中提取字符时,我可以在视频屏幕上显示它。

假设字符以8个像素为列,16个像素为行(16*8),并且每个像素获得10位值- 10'b 1111111111表示最大亮度,10'b 0000000000表示最小亮度。

既然我不能在verilog中创建一个2D数组,我该如何创建一个1D数组并实现它呢?

EN

回答 2

Stack Overflow用户

发布于 2015-11-29 00:41:56

您可以使用reg创建这样的内存,如下所示:

代码语言:javascript
复制
module charmem (
  input wire clk,
  input wire [7:0] charaddr,
  input wire [3:0] scanaddr,
  input wire [2:0] pixeladdr,
  output reg [9:0] pixel
  );

  reg [9:0] chars[0:32767]; // 256 chars, 16 scans, 8 pixels
  initial begin
    $readmemh ("chardef.hex", chars, 0); // this IS synthesizable on Xilinx
  end

  always @(posedge clk) begin
    scan <= chars[{charaddr,scanaddr,pixeladdr}];
  end
endmodule

chardef.hex将是一个文本文件,每行包含10位十六进制数字。前8个十六进制数字将是第一个字符的第一次扫描的像素。接下来,对第一个字符进行第二次扫描,直到第8个像素对第一个字符进行第二次扫描。然后,第二个字符的第一次扫描的8个像素,依此类推。

请注意,即使你不能在Verilog中使用n维矩阵(使用n>=3),你也可以利用你的维数是2的幂(256x16x8),所以可以使用一个1D向量来实现它,只需将索引连接起来形成一个唯一的内存地址(好的,正如你所使用的,如果你把它看作一个位元素矩阵而不是一个10位元素向量,它实际上是一个2D向量)。

还要注意的是,尽管你已经要求了一个非块RAM解决方案,但你会想要使用它,因为像这样的reg的分布式内存解决方案肯定会消耗你许多宝贵的逻辑资源,并且需要很长时间才能合成,我看不出为什么这个ROM不能在块RAM中实现。

假设您的视频控制器将有两个计数器:例如,xy。假设您的活动区域是640x480,并且您要绘制的字符ASCII码存储在character (一个8位reg)中,您可以这样做:

代码语言:javascript
复制
wire [9:0] pixel;

charmem chartable (
  .clk(clk),
  .charaddr(character),
  .scanaddr(y[3:0]),
  .pixeladdr(x[2:0]),
  .pixel(pixel)
);

要使charmem在视频控制器未更新活动区域时输出黑色像素,可以向其添加videoenable信号,因此如果该信号为“1”,则该像素是从只读存储器中检索的像素,否则是黑色像素。

代码语言:javascript
复制
  always @(posedge clk) begin
    if (videoenable == 1'b1)
      scan <= chars[{charaddr,scanaddr,pixeladdr}];
    else
      scan <= 10'h000;
  end

videoenable将按如下方式更新:

代码语言:javascript
复制
reg videoenable;
always @* begin
  if (x >= 10'd0 && x <= 10'd639 &&
      y >= 10'd0 && y <= 10'd479)
      videoenable = 1'b1;
  else
      videoenable = 1'b0;
end
票数 1
EN

Stack Overflow用户

发布于 2015-11-29 00:10:28

中,二维数组不能位于端口输入/输出。但是它们可以在模块中的中声明和使用。

此处,存储器为80位宽,深度为16。因此,地址宽度必须为log2(16) = 4,为4位宽。

你可以像下面这样实现一些东西(宽视图伪代码)。这里,mem[0]是最小地址块,且每个块具有第0位作为最低有效位,第79位作为最低有效位:

代码语言:javascript
复制
module memory(address,read_en,clk,reset,out);

// clk,reset declarations

// address to be accessed in memory
input reg [3:0] address;
// read/write signal
input read_en;
//output signal, for data read from memory
output [79:0] out;

// internal memory, accessed through address only
reg [79:0] mem [16];

// inside always block
// clock synchronous block
always @(posedge clk, negedge reset)
begin
// reset logic, followed by: 
if(read_en)
begin
out <= mem[address];
end
end

endmodule

如果不使用内存,通过地址将会有点困难。这次内存被声明为压缩数组,所以它的1280(16*80)位wide.Following是压缩数组的方法:

代码语言:javascript
复制
// rest all declarations are same.
reg [1279:0] mem;
out<=mem[(((address+1)*80)-1) -: 80];

-:运算符用于位切片。如下所示,请参阅Verilog slicing link了解更多信息。

代码语言:javascript
复制
x -: Y, the start position is x and count down from x by Y. Y is necessarily a constant.

在使用压缩数组和未压缩数组之间没有任何区别(或者可能有一点区别)。因此,最好使用混合数据块阵列。

有关将数据从文件加载到只读存储器的信息,请参阅this链接。尽管$readmemh应该让它成为non-synthesizable.

有关使用访问内存的更多信息,请参阅this链接。该网站展示了可合成模块。

有关二维数组,请参阅this问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33972595

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档