一种无需IP核的FPGA RAM初始化方法:基于源码定义与赋值实现
\;\;\;\;\; 在FPGA设计中,许多人仍习惯用RAM IP核来初始化存储数据,但每次修改初始化文件或参数都要重新生成IP,会降低效率。其实,我们可以直接在Verilog代码中定义并初始化RAM,让综合工具自动推断出对应的块RAM或分布式RAM。这种方式灵活、便于维护。本文将介绍这种更灵活的RAM初始化方式。
一、在源代码中定义并初始化RAM
\;\;\;\;\; 在Verilog代码中,我们可以定义一个RAM数组,然后在initial块中为数组加载初始数据。这样综合工具会自动识别为块RAM或分布式RAM结构,实现“代码生成并初始化RAM”,无需再依赖IP核。
\;\;\;\;\; 例如下面是通过代码写的一个深度为16,宽度为8的RAM,并为其初始化了存储阵列的数据。we信号是读写选择信号,0读1写。en是高电平使能信号。
module rams_sp_rom (clk, we, addr, di, dout, en);
input clk;
input we;
input [3:0] addr;
input [7:0] di;
input en;
output [7:0] dout;
reg [7:0] ram [15:0];
reg [7:0] dout=0;initial
beginram[15] = 8'h02; ram[14] = 8'h21; ram[13] = 8'h03;ram[12] = 8'h01; ram[11] = 8'h01; ram[10] = 8'h23;ram[9] = 8'h04; ram[8] = 8'h03; ram[7] = 8'h04;ram[6] = 8'h00; ram[5] = 8'h25; ram[4] = 8'h50;ram[3] = 8'h0D; ram[2] = 8'h23; ram[1] = 8'h20;ram[0] = 8'h0D;
endalways @(posedge clk)
beginif(en)beginif (we)ram[addr] <= di;dout <= ram[addr];end
endendmodule
\;\;\;\;\; 下图是读仿真的结果。因为这个位宽深度都比较小,综合出来的就是分布式RAM结构。

\;\;\;\;\; 下图是综合的电路的结果。

\;\;\;\;\; 善于思考的读者读到这里,想必已经知道如何以同样的操作生成ROM了吧,只需要在上面的端口去掉写相关的端口即可。
\;\;\;\;\; 另外,如果想对RAM的存储阵列全部赋初值为0,使用下面的initial块即可。
integer i;
initial
begin
for (i=0; i<16; i=i+1) ram[i] = 0;
end
二、在源代码中定义并在文件中初始化RAM
\;\;\;\;\; 可直接将数据以二进制个数写入txt文件,如下图所示。

\;\;\;\;\; 以下代码生成的一个深度和位宽均为8的RAM。代码中将文件路径替换成自己的即可。
module rams_init_file (clk, we, addr, din, dout, en);
input clk;
input we;
input [7:0] addr;
input [7:0] din;
input en;
output [7:0] dout;
reg [7:0] ram [0:255];
reg [7:0] dout=0;initial begin
$readmemb("文件路径/ramdata.txt",ram);
endalways @(posedge clk)
beginif(en)beginif (we)ram[addr] <= din;dout <= ram[addr];end
endendmodule
\;\;\;\;\; 下图是读仿真的结果,这个综合出来的就是块RAM结构。

\;\;\;\;\; 下图是综合的电路的结果。

\;\;\;\;\; 当然,也可以通过综合属性指定生成的RAM类型,有以下一些类型。

\;\;\;\;\; 比如在前面的代码中如果写成如下形式,那么就是明确要求综合器综合出块RAM。
(* ram_style = "distributed" *) reg [7:0] ram [0:255];
以上就是本文全部内容。
