引言

自己verilog设计寄存器堆的时候,整理了简单的相关知识点:

  • verilog定义存储器
  • 存储器读
  • 存储器写
  • 内存初始化
  • $readmemh、$readmemb的使用

存储器

定义

在Verilog当中存储器的定义本质定义一个2维数组。下面举一个定义存储器的例子:


reg[7:0] good_mem[0:255]; //good_mem是256个8位的寄存器构成的阵列,实际可以存放2Mbit的数据


再举一个定义数组的例子:


wire[7:0] addr_bus[3:0]


你可能发现了这个后面good_mem内标号顺序和正常定义数组不同,这个其实只是表示了在存储器堆里面,从上到下,每一个寄存器编号不同,无论顺序是[0:255],还是[255:0],这个存储容量都是一样的。

以下是good_mem[0:255],如果是改成good_mem[255:0]只是寄存器的编号逆序。其它没有区别。一般存储器第一个寄存器都是从0开始编号,所以设计寄存器堆/存储器后面一个都是[0:arraysize]。


reg [7:0] good_mem[0]; 
reg [7:0] good_mem[1]; 
reg [7:0] good_mem[2]; 
reg [7:0] good_mem[3]; 
        : 
        : 
reg [7:0] good_mem[255];


读操作

就是将数据从存储单元当中读出:


data_out = good_mem[address]


写操作

将数据写入存储单元:


good_mem[address] = data_in


内存初始化

这个有两种方法,第一种是直接赋值。第二种是使用$readmemb系统函数。

直接赋值


reg [0:3] good_mem [1:4] 
            :
            :
    good_mem[1] = 4'hA; 
    good_mem[2] = 4'hB; 
    good_mem[3] = 4'hC; 
    good_mem[4] = 4'hD;


调用系统函数

  • $readmemb:读取二进制数字
  • $readmemh:读取十六进制数字 如果文件中包含不定值x,或者高阻值z,或者下划线(__)这个和Verilog当中的内容相同。

$readmemb的使用

在Verilog代码目录下准备一个file.txt文件,放入二进制数据 1111 1010 0101 1x1z 1_1_ 1_111 数据写在一行里面需要用空格隔开,或者分行写也可以。


module test;
reg[3:0] memory[0:7];//申请八个四位的存储单元
reg[4:0] n;
initial
 begin
        $readmemb("file.txt",memory); //读取file.txt中的数字到memory
 for(n=0;n<=7;n=n+1) //显示结果
        $display("%b",memory[n]);
 end
endmodule


显示结果为: 1111 1010 0101 1x1z 0011 1111 xxxx xxxx

文件中不定态x和高阻值z保持不变。下划线忽略。由于文件中只有6个数据,输出八个,剩下两个就是不定态x。

$readmemh的使用

在Verilog代码目录下新建file2.txt,写入数据: 1234 5678 9ABC


module test;
reg set;
reg[15:0] memory[0:7];    
reg[4:0] n;
initial
 begin
        $readmemh("file2.txt",memory);
 for(n=0;n<=7;n=n+1)
        $display("%h",memory[n]);
 end
endmodule


显示结果为: 1234 5678 9ABC xxxx xxxx xxxx xxxx xxxx

参考资料

  1. (75条消息) 数字IC设计——数组、存储器(Memory)的定义及Verilog语言实现(二)(存储器的读、取、及初始化赋值)_摆渡沧桑的博客-_memory verilog
  2. 2.3 Verilog 数据类型 | 菜鸟教程 (runoob.com)
  3. (75条消息) verilog中readmemh的使用_甲六乙的博客-_$readmemh