我想创建一个用于存储ASCII字符的ROM(就像查找表一样),当我从ROM中提取字符时,我可以将它显示在视频屏幕上。在不使用块ROM的情况下在verilog中创建ROM
字符应该采取明智8个像素列和16个像素行明智(16 * 8)和每个像素得到一个10位的值 - 10'B 1111111111为最大亮度和 10'B 0000000000最小。
因为我不能在Verilog中创建二维数组,所以我应该如何创建一维数组并实现它?
我想创建一个用于存储ASCII字符的ROM(就像查找表一样),当我从ROM中提取字符时,我可以将它显示在视频屏幕上。在不使用块ROM的情况下在verilog中创建ROM
字符应该采取明智8个像素列和16个像素行明智(16 * 8)和每个像素得到一个10位的值 - 10'B 1111111111为最大亮度和 10'B 0000000000最小。
因为我不能在Verilog中创建二维数组,所以我应该如何创建一维数组并实现它?
二维阵列不能在端口输入/输出 in Verilog。但是他们可以在模块内部的内被声明和使用。
这里,存储器80是位宽,并用16的深度因此,地址宽度必须log2(16) = 4
,4位宽。
您可以执行如下操作(宽视图伪代码)。在这里,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问题。
可以使用一个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
非常感谢... – Sara
好吧,如果你认为这个答案是你期望的答案,你可以将它标记为你选择的答案:) –
但按你的方法#1,我怎么输出整个MEM [0]或MEM [2]等包含80位当我所知道的是,视频屏幕上的(X,Y)坐标(该位置包含10个像素)。我的意思是我如何将X从包含10位扩展到现在在视频屏幕上的80位。 – Sara
@Sara如果我理解正确,那么在这种情况下,您需要为模块提供'address',即X(行数)'0'或'2'。输出将是一个80位的块。从该块开始,根据Y(列号)屏蔽10位以获得输出中的10位。 – sharvil111
好的..让我试试这个.. – Sara