在FPGA设计实现中,经常要用到RAM,这里的RAM一般指的是是静态的RAM。一般FPGA(如xilinx)中就有所谓的block RAM, 它就是现成的RAM资源,我们如果合理编写verilog代码,就可以使我们想要的RAM被综合成block RAM,从而节省逻辑资源,而且性能更优。
在书写某些模块时候,用到了特别大的RAM,比如reg [14:0] mem[0:9999999];通常情况下会出现无法综合的情况,这时候我们就需要自己书写一个RAM模块,然后在原来模块中调用RAM模块。
module double_ram_gclis
#(
parameter DATA_WDTH = 6'd15, //输入数据的位宽
parameter COL = 2048, //RAM中数据个数
parameter COL_BITS = 11 //地址线位数
)
(
input clk, //时钟信号
input [COL_BITS-1:0] addra, //写入数据的地址
input [DATA_WDTH-1:0] dina, //写入的数据
input wea, //写有效信号
input [COL_BITS-1:0] addrb, //输出数据的地址
output [DATA_WDTH-1:0] doutb //输出的数据
);
reg [DATA_WDTH-1:0] mem[0:COL-1]; //定义RAM
assign doutb = mem[addrb + 0];
always @ ( posedge clk )
begin
if( wea == 1'b1 ) //写有效时候,把dina写入到addra处
begin
mem[addra] <= dina;
end
else
;
end
endmodule
当然根据实际需要也可以在此基础上做一定改进,此处增加了一个输出端口,而且输出位宽是输入的4倍。
module double_ram_band
#(
parameter DATA_WDTH = 6'd15, //输入数据的位宽
parameter COL = 2048, //RAM中数据个数
parameter COL_BITS = 11 //地址线位数
)
(
input clk,
input [COL_BITS-1:0] addra,
input [DATA_WDTH-1:0] dina,
input wea,
input [COL_BITS-1:0] addrb,
input [COL_BITS-1:0] addrb2,
output [4 * DATA_WDTH-1:0] doutb,
output [4 * DATA_WDTH-1:0] doutb2
);
reg [DATA_WDTH-1:0] mem[0:COL-1];
assign doutb = {mem[addrb + 2], mem[addrb + 1], mem[addrb + 0], mem[addrb - 1]};
assign doutb2 = {mem[addrb2 + 2], mem[addrb2 + 1], mem[addrb2 + 0], mem[addrb2 - 1]};
always @ ( posedge clk )
begin
if( wea == 1'b1 )
begin
mem[addra-1] <= dina;
end
else
;
end
endmodule
PS:改进也不是无限制的,有许多情况的修改会导致综合变得特别慢,比如我曾经把单输入变为了4输入,always中也一次给4个地址赋值,导致综合变慢,资源使用急剧增加,原因是,增加output端口特别简单 只需要增加几根连线和多路选择器就行,但增加输入端口 比较麻烦,普通的Block Ram一般都是单端口或双端口的,若想综合出四个输入端口的B RAM 综合器只能把多个双端口或短端口RAM合起来,一份数据放在两个RAM里,同时还要判断写地址无冲突 更加增加了逻辑电路。因此如果做了改进建议先单独综合试一下~