一种无需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是高电平使能信号。

bash 复制代码
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
begin
    ram[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;
end

always @(posedge clk)
begin
    if(en)
        begin
            if (we)
            ram[addr] <= di;
            dout <= ram[addr];
        end 
end

endmodule

          \;\;\;\;\; 下图是读仿真的结果。因为这个位宽深度都比较小,综合出来的就是分布式RAM结构。

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

          \;\;\;\;\; 善于思考的读者读到这里,想必已经知道如何以同样的操作生成ROM了吧,只需要在上面的端口去掉写相关的端口即可。

          \;\;\;\;\; 另外,如果想对RAM的存储阵列全部赋初值为0,使用下面的initial块即可。

bash 复制代码
integer i;
initial 
begin
for (i=0; i<16; i=i+1) ram[i] = 0;
end

二、在源代码中定义并在文件中初始化RAM

          \;\;\;\;\; 可直接将数据以二进制个数写入txt文件,如下图所示。

          \;\;\;\;\; 以下代码生成的一个深度和位宽均为8的RAM。代码中将文件路径替换成自己的即可。

bash 复制代码
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);
end

always @(posedge clk)
begin
    if(en)
        begin
            if (we)
            ram[addr] <= din;
            dout <= ram[addr];
        end 
end

endmodule

          \;\;\;\;\; 下图是读仿真的结果,这个综合出来的就是块RAM结构。

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

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

          \;\;\;\;\; 比如在前面的代码中如果写成如下形式,那么就是明确要求综合器综合出块RAM。

bash 复制代码
(* ram_style = "distributed" *) reg [7:0] ram [0:255];

以上就是本文全部内容。

相关推荐
仲南音1 天前
Xilinx FPGA——时钟IP核MMCM、PLL
fpga开发
I'm a winner2 天前
基于Xilinx FPGA的LVDS高速串行通信系统(三)--数据训练及握手机制【文末源码】
fpga开发
upper20202 天前
coremark移植坑之-nostartfiles -nostdlib参数
学习·fpga开发·coremark移植·riscv设计
Eloudy2 天前
Vivado 纯命令行构建 FPGA 项目教程
fpga开发
Rambo.xia2 天前
AXI跨时钟域与数据一致性——CDC FIFO深度不够、写后读冒险、多Master仲裁、乱序返回,出了Bug根本查不出来
fpga开发·bug
upper20202 天前
FPGA部署卷积神经网络识别MINST图片
fpga开发·卷积神经网络·minst·minst识别·部署神经网络·神经网络识别图片
你是我的解忧王子3 天前
嵌入式 ADC采样 原始数据分析上层(平均值 波动率 正态分布 线性补偿 系统误差)
fpga开发·数据挖掘·数据分析
9527华安3 天前
FPGA纯verilog代码ISP图像处理培训教程,基于IMX214,提供工程源码+视频教程+FPGA开发板
图像处理·fpga开发·isp·imx214·mipi
千寻xun4 天前
二、实战篇-NVME SSD控制之ZYNQ实现(六)-读写NVME SSD硬盘数据
fpga开发·nvme·nvme ssd
千寻xun4 天前
二、实战篇-NVME SSD控制之ZYNQ实现(三)
fpga开发·nvme ssd·nvme协议