Verilog RAM/ROM的数据初始化


FPGA设计中RAM和ROM作为存储器用来存储可变或不可变类型的数据。
ROM初始化一般是加载固定数据,RAM声明时默认为不定态数据,初始化时可以让数据为全1或者全0。

一、初始化方式

  1. 复位时按地址写入初值
    always@ (posedge clk_in or negedge rst_n_in ) begin
        if( !rst_n_in ) begin
            ram_reg[0] <= xxx;
            ram_reg[1] <= xxx;
            ...
            ram_reg[n-1] <= xxx;
        end else begin
            ...
        end
    end
    
  2. 使用initial 和 for循环来初始化
    用于初始化为有规律的数据,RAM初始化常使用这种方式。
    initial begin : ram_init
        integer i;
        for(i=0;i<n;i++) begin
            ram_reg[i] = xxx;
        end
    end
    
    变量的定义必须在命名块中,因此这里需要使用命名的initial块。
  3. 通过读文件的方式初始化
    将数据存储在.dat文件中,通过读文件实现初始化。
    这种方式RAM使用较少,一般ROM初始化时喜欢采用这种做法。
    initial begin
        $readmemh("filepath",rom_reg);
    end
    

二、测试

方式1的正确性不言而喻。
方式2和方式3中,initial块一般来说是用在仿真中的,对其能否综合,编写如下的测试代码:

  1. 定义了两块寄存器,用来实现RAM

  2. ram_1通过方式2初始化

  3. ram_2通过方式3初始化,dat文件内容从0x0f ~ 0x08
    [图片]

  4. 循环对ram中的内容进行读取

  5. 调用ila核,来抓取读取的数据

`timescale 1ns / 1ps
//
// Engineer: wkk 
// Create Date: 2023/12/23 20:50:45
// Module Name: init_value_test
//
module init_value_test(
    input   clk_in    ,
    input   rst_n_in  ,
    
    output  nc_out 
);

reg [7:0]  ram_1 [7:0];
reg [7:0]  ram_2 [7:0];

reg  [2:0]  ram_addr ;
wire [7:0]  ram_1_out;
wire [7:0]  ram_2_out;

initial begin : init_ram1
    integer i;
    for( i=0;i<7;i = i+1 ) begin
        ram_1[i] = i+1;
    end
end

initial begin : init_ram2
    $readmemh("E:/FPGA/init_value_test/init_value_test.srcs/data/ram_data.dat",ram_2);
end

always @( posedge clk_in or negedge rst_n_in ) begin
    if( !rst_n_in ) begin
        ram_addr <= 'b0;
    end else begin
        ram_addr <= ram_addr + 1'b1;
    end
end

assign ram_1_out = ram_1[ram_addr];
assign ram_2_out = ram_2[ram_addr];

ila_0 ila_0_inst (
        .clk(clk_in), // input wire clk

        .probe0(ram_1_out), // input wire [7:0]  probe0  
        .probe1(ram_2_out), // input wire [7:0]  probe1 
        .probe2(ram_addr)   // input wire [2:0]  probe2
);

endmodule

增加了一个nc_out 端口,实际上是没有什么作用的,但是必须要加,否则会报错:

[Place 30-494] The design is empty
Resolution: Check if opt_design has removed all the leaf cells of your design.  Check whether you have instantiated and connected all of the top level ports.

原因:顶层文件没有输出接口

测试结果
[图片]

通过ila核抓出的数据,表明方式2和方式3成功的实现了初始化操作。

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Verilog是一种硬件描述语言,可以用来描述数字电路的行为和结构。在Verilog中,ROM(只读存储器)和RAM(随机存储器)是两种不同的存储器类型。它们有不同的访问方式、读写速度、存储容量和成本。 ROM是一种只读存储器,其中存储的数据无法被修改。ROM中的数据一般是在设计过程中预先指定的,因此ROM通常用于存储程序代码和常量数据。 在Verilog中,可以使用“initial”语句来初始化ROM中的数据,例如: ``` module rom ( input [7:0] addr, output reg [7:0] data ); reg [7:0] mem [0:255]; initial begin mem[0] = 8'h12; mem[1] = 8'h34; mem[2] = 8'h56; // ... end always @(addr) data <= mem[addr]; endmodule ``` 在上面的代码中,定义了一个8位地址和8位数据ROM。使用“initial”语句初始化ROM中的数据,然后使用“always”语句,使得当地址变化时,从ROM中读取对应的数据RAM是一种可读可写存储器,其中存储的数据可以被修改。RAM通常用于存储程序中需要动态修改的数据。 在Verilog中,可以使用“reg”类型声明一个寄存器,然后使用“always”语句来实现RAM。例如: ``` module ram ( input [7:0] addr, input [7:0] din, input wr_en, output reg [7:0] dout ); reg [7:0] mem [0:255]; always @(addr, wr_en) begin if (wr_en) mem[addr] <= din; dout <= mem[addr]; end endmodule ``` 在上面的代码中,定义了一个8位地址、8位写入数据、写使能信号和8位读出数据RAM。使用“reg”类型声明一个寄存器,然后使用“always”语句,根据地址和写使能信号判断是写入数据还是读取数据,并将数据写入或读出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴风雨中的白杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值