Memory的例化使用与FPGA中ram的替换解决方案
1. 使用寄存器组(Memoeies)的目的
Memoeies,此处指由reg变量组成的寄存器数组。例化memories的目的是
(1) verilog中的书写的Memories是可以综合,并在FPGA上运行的。为了尽量少的使用IP,同时设置好memories的时序,以便于后期使用的IP的替换。一般按照经验来说,当一个memories的使用小于2kbit时,是可以直接使用寄存器组进行设计的,当使用的Memories大于2kbit,考虑功耗面积等约束,寄存器组要替换为专用的SRAM。
(2)现在的ASIC的验证环境一般由UVM方法学进行搭建,但是UVM验证环境需要专门的验证人员进行搭建。对于小白设计师,也可以用verilog来编写测试激励,观察仿真波形。对于FPGA来说,片上的RAM一般来说2MB已经很大了,当你要存一张大于2MB的图片时,要怎么办呢?这个时候可以在tb文件中例化一个寄存器,并把图片例化到寄存器中。
2. 以寄存器组为核心模拟SRAM(FPGA中RAM)输入输出时序代码如下所示:
以下代码模拟了SRAM的输入输出时序,当需要做综合,需要替换IP时,可以直接进行替换,也可以替换FPGA中的RAM资源,并且可以直接综合生成bit流文件。
module memories(
clka,
addra,
dina,
pusha,
clkb,
addrb,
popb,
doutb
);
input clka;
input [63:0] addra;
input [31:0] dina;
input pusha;
input clkb;
input [63:0] addrb;
input popb;
output [31:0] doutb;
reg [31:0] memories[63:0];
reg [31:0] doutb_reg;
assign doutb = doutb_reg;
always @ (posedge clka) begin
if (pusha)
memories[addra] <= #1 dina;
end
always @ (posedge clkb) begin
if (popb)
doutb_reg <= #1 memories[addrb];
end
endmodule
3.Tb文件中Memories的例化及初始化可以用如下代码进行:
reg [31:0] memories[0:63];
initial begin
$readmemh("D:/simple_project_ddr/emccd_top/tb1.txt",memories);
end
使用系统任务函数进行存储:系统任务函数从指定的文本中读取数据并加载到存储器。
$readmemb(加载二进制文件)
$readmemh(加载十六进制文件)
文本数据样式如下所示:
为了进行测试,我写了一个简单的tb文件如下所示:
`timescale 1ns / 1ps
module read_mem();
reg clk;
reg [31:0] dout;
reg rst_n;
reg [0:63] addr;
reg read_en;
reg [9:0] cnt;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rst_n = 0;
#100 rst_n = 1;
end
reg [31:0] memories[0:63];
initial begin
$readmemh("D:/simple_project_ddr/emccd_top/tb1.txt",memories);
end
always@(posedge clk) begin
if (read_en)
dout <= #1 memories[addr];
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 10'b0;
else
cnt <= cnt + 1;
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
addr <= 64'b0;
else if(read_en)
addr <= addr + 1;
else
addr <= addr;
end
assign read_en = (cnt >= 10'b00_1000_0000) ? 1 : 0;
endmodule