2015-11-28 323 views
0

我想创建一个用于存储ASCII字符的ROM(就像查找表一样),当我从ROM中提取字符时,我可以将它显示在视频屏幕上。在不使用块ROM的情况下在verilog中创建ROM

字符应该采取明智8个像素列和16个像素行明智(16 * 8)和每个像素得到一个10位的值 - 10'B 1111111111为最大亮度和 10'B 0000000000最小。

因为我不能在Verilog中创建二维数组,所以我应该如何创建一维数组并实现它?

回答

0

二维阵列不能在端口输入/输出 in Verilog。但是他们可以在模块内部的内被声明和使用。

这里,存储器80是位宽,并用16的深度因此,地址宽度必须log2(16) = 44位宽

您可以执行如下操作(宽视图伪代码)。在这里,mem[0]是至少地址块,每块有第0位为LSB与第79位为MSB:

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是用于填充阵列的方法:

// rest all declarations are same. 
reg [1279:0] mem; 
out<=mem[(((address+1)*80)-1) -: 80]; 

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

x -: Y, the start position is x and count down from x by Y. Y is necessarily a constant. 

没有差别(或者,有点差)使用打包和压缩数组之间。所以,更喜欢使用混合模块阵列

要从文件加载数据到ROM中,请参阅this链接。尽管$readmemh将使其不可合成

有关详细信息,请参阅this链接访问内存。此网站显示可合成模块

对于二维阵列,请参阅this问题。

+0

但按你的方法#1,我怎么输出整个MEM [0]或MEM [2]等包含80位当我所知道的是,视频屏幕上的(X,Y)坐标(该位置包含10个像素)。我的意思是我如何将X从包含10位扩展到现在在视频屏幕上的80位。 – Sara

+0

@Sara如果我理解正确,那么在这种情况下,您需要为模块提供'address',即X(行数)'0'或'2'。输出将是一个80位的块。从该块开始,根据Y(列号)屏蔽10位以获得输出中的10位。 – sharvil111

+0

好的..让我试试这个.. – Sara

0

可以使用一个reg,像这样创造这样的记忆:

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个像素,直到第一个字符的第16次扫描的8个像素。然后,第二个字符的第一个扫描的8个像素,依此类推。

请注意,即使您不能在Verilog中使用n维矩阵(n> = 3),您可以利用尺寸为2的幂(256x16x8),因此可以使用1D矢量来实现它,通过将索引连接起来形成一个唯一的内存地址(就像用户一样,如果将它看作是位元素矩阵而不是10位元素矢量,它实际上是一个2D矢量)。

请注意,尽管您已经要求使用非Block-RAM解决方案,但您仍然希望将其用作分布式内存解决方案,因此这样的分区内存将肯定会占用您的许多宝贵逻辑资源,并且会花费很长时间综合,我没有看到为什么这个ROM不能在block-RAM中实现的原因。

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

wire [9:0] pixel; 

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

为了charmem输出黑色像素时视频控制器没有更新活动区域,您可以添加一个videoenable信号给它,所以如果它是'1',像素是从ROM中检索的像素,否则是黑色的。

always @(posedge clk) begin 
    if (videoenable == 1'b1) 
     scan <= chars[{charaddr,scanaddr,pixeladdr}]; 
    else 
     scan <= 10'h000; 
    end 

videoenable将被更新为这样:

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 
+0

非常感谢... – Sara

+0

好吧,如果你认为这个答案是你期望的答案,你可以将它标记为你选择的答案:) –

相关问题