具有DATA-IN和DATA-OUT的verilog中的可重新配置的存储器实例作为参数传递
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有DATA-IN和DATA-OUT的verilog中的可重新配置的存储器实例作为参数传递相关的知识,希望对你有一定的参考价值。
如何制作一个内存模块,其中DATA
总线宽度作为参数传递给每个实例,我的设计根据参数重新配置自身?例如,假设我有字节可寻址存储器,并且DATA-IN
总线宽度为32位(每个周期写入4个字节),DATA-OUT
为16位(每个周期读取2个字节)。对于其他实例,DATA-IN
是64位,DATA-OUT
是16位。对于所有这些情况,我的设计应该有效。
我试过的是根据设计参数生成写指针值,例如DATA-IN
32位,写指针在写入时每个周期递增4。对于64位 - 增量将是8,依此类推。
问题是:如何根据传递给实例的参数在单个周期中写入4或8或16个字节?
//Something as following I want to implement. This memory instance can be considered as internal memory of FIFO having different datawidth for reading and writing in case you think of an application of such memory
module mem#(parameter DIN=16, parameter DOUT=8, parameter ADDR=4,parameter BYTE=8)
(
input [DIN-1:0] din,
output [DOUT-1:0] dout,
input wen,ren,clk
);
localparam DEPTH = (1<<ADDR);
reg [BYTE-1:0] mem [0:DEPTH-1];
reg wpointer=5'b00000;
reg rpointer=5'b00000;
reg [BYTE-1:0] tmp [0:DIN/BYTE-1];
function [ADDR:0] ptr;
input [4:0] index;
integer i;
begin
for(i=0;i<DIN/BYTE;i=i+1) begin
mem[index] = din[(BYTE*(i+1)-1):BYTE*(i)]; // something like this I want to implement, I know this line is not allowed in verilog, but is there any alternative to this?
index=index+1;
end
ptr=index;
end
endfunction
always @(posedge clk) begin
if(wen==1)
wpointer <= wptr(wpointer);
end
always @(posedge clk) begin
if(ren==1)
rpointer <= ptr(rpointer);
end
endmodule
din[(BYTE*(i+1)-1):BYTE*(i)]
不会在Verilog中编译,因为MSB和LSB选择位都是变量。 Verilog需要一个已知的范围。 +:
用于部分选择(也称为切片)允许变量选择索引和恒定范围值。它是在IEEE Std1364-2001§4.2.1中引入的。您还可以在IEEE Std 1800-2012§11.5.1中阅读更多相关信息,或参考之前提出的问题:What is `+:` and `-:`?和Indexing vectors and arrays with +:。
din[BYTE*i +: BYTE]
应该为你工作,或者你可以使用din[BYTE*(i+1)-1 -: BYTE]
。
此外,您应该使用非阻塞分配(<=
)到mem
。在您的代码中,读取和写入可以同时发生。使用阻塞时,访问相同字节之间存在竞争条件。它可能会合成,但您的RTL和门模拟可能会产生不同的结果。我也强烈建议代理使用函数来分配内存。可合成代码中的函数没有令人讨厌的意外需要自包含而不引用函数之外的任何内容,并且任何内部变量总是在函数开始时重置为静态常量。
根据上面提到的指南,我建议重新编码,如下所示。这是一个开始的模板,而不是免费的午餐。我省略了超出范围的指数补偿,让你自己搞清楚。
...
localparam DEPTH = (1<<ADDR);
reg [BYTE-1:0] mem [0:DEPTH-1];
reg [ADDR-1:0] wpointer, rpointer;
integer i;
initial begin // init values for pointers (FPGA, not ASIC)
wpointer = {ADDR{1'b0}};
rpointer = {ADDR{1'b0}};
end
always @(posedge clk) begin
if (ren==1) begin
for(i=0; i < DOUT/BYTE; i=i+1) begin
dout[BYTE*i +: BYTE] <= mem[rpointer+i];
end
rpointer <= rpointer + (DOUT/BYTE);
end
if (wen==1) begin
for(i=0; i < DIN/BYTE; i=i+1) begin
mem[wpointer+i] <= din[BYTE*i +: BYTE];
end
wpointer <= wpointer + (DIN/BYTE);
end
end
以上是关于具有DATA-IN和DATA-OUT的verilog中的可重新配置的存储器实例作为参数传递的主要内容,如果未能解决你的问题,请参考以下文章