数字IC设计——数组、存储器(Memory)的定义及Verilog语言实现(二)(存储器的读、取、及初始化赋值)

数字IC设计——Verilog数组、存储器(Memory)的定义(二)

在介绍SRAM的Verilog定义之前先介绍一下,Verilog关于数组的定义。

一、Verilog寄存器的数组定义

Verilog中提供了两维数组来帮助我们建立内存的行为模型。具体来说,就是可以将内存定义为一个reg类型的数组,这个数组中的任何一个单元都可以通过一个下标去访问。这样的数组的定义方式如

  1. 数组(内存)定义
	reg [wordsize : 0] array_name [0 : arraysize];

例如:

	reg [7:0] my_memory[0:255];

其中 [7:0]内存的宽度(位宽),而 [0:255] 则是 内存的深度(也就是有多少存储单元),其中宽度为8位,深度为256。地址0对应着数组中的0存储单元。

  1. 写操作:如果要存储一个值到某个单元中去,可以这样做:
	my_memory[address] = data_in;
  1. 读操作: 而如果要从某个单元读出值,可以这么做:
 	data_out = my_memory[address];
  1. 读取内存中的某一位或者多位
    只需要读一位或者多个位,就要麻烦一点,因为Verilog不允许读/写一个位。这时,就需要使用一个变量转换一下:

    例如:

    data_out = my_memory[address];
	data_out_it_0 = data_out[0];

这里首先从一个单元里面读出数据,然后再取出读出的数据的某一位的值

  1. 内存的初始化定义
    初始化内存有多种方式,这里介绍的是使用 $ readmemb$ readmemh系统任务来将保存在文件中的数据填充到内存单元中去。
    $ readmemb$ readmemh是类似的,不过 $ readmemb 用于 内存的二进制 表示,而 $ readmemh 则用于内存内容的16进制 表示。这里以$readmemh系统任务来介绍。
    具体语法:
	$readmemh("file_name", mem_array, start_addr, stop_addr);

需要注意的是:
file_name是包含数据的文本文件名,mem_array是要初始化的内存单元数组名,start_addrstop_addr是可选的,指示要初始化单元的起始地址和结束地址。

  1. 内存的初始化例子
module  memory ();
reg [7:0] my_memory [0:255];
 
initial begin
$readmemh("memory.list", my_memory);
end

endmodule

这里使用内存文件memory.list来初始化my_memory数组。

而下面就是一个内存文件的例子。

	//  Comments are allowed 
	CC         // This is first address i.e 8'h00
	AA         // This is second address i.e 8'h01
	@55     // Jump to new address 8'h55
	5A         // This is address 8'h55
	69         // This is address 8'h56

对于内存文件,要注意的是下列几点:
a、注释标记//在内存文件中是被允许的;
b、使用@符号将跳到新的目标地址,没有@符号就表示地址将顺序递增。

如上述的内存文件就只初始化8’h00,8’h01,8’h55和8’h56 4个内存地址单元

  1. 关于系统任务,有下列常见的用法:
    1)顺序初始化所有的数组单元
    这种情况下,可以使用@符号来指示地址,也可以不使用它,而只在每一行存放要存放的数据。
    这样数据将顺序按地址递增存放,从0地址开始。
    2)只初始化部分的数组单元
    这种情况下,可以使用@符号来指示下一个要初始化的地址,然后对该地址单元进行初始化
    3)只初始化数组的地址区间的一部分单元
    这个时候,还可以使用$readmemh任务的start_addr 和 stop_addr选项来指定初始化的范围。
    例如,只初始化100到104这5个单元,就可以这么做:
    内存文件memory.list定义为:
	CC
	AA
	55 
	5A
	69

而$readmemh(“memory.list”, my_memory, 100, 104);就指定使用memory.list来初始化my_memory的100-104单元。
参考博客

二、存储器在Verilog中的定义
  1. 存储器在Verilog中的定义
    存储器其实是一个寄存器数组的定义
	reg [msb:1sb] memory1[upper1:lower1], memory2[upper2:lower2],. . . ;

例如如下定义:

reg [7:0] mem[0:255];	//mem为256个8位寄存器的数组。
reg Bog [1:5];			//Bog为5个1位寄存器的数组。

MyMem和Bog都是存储器。数组的维数不能大于2。注意存储器属于寄存器数组类型。线网数据类型没有相应的存储器类型

Verilog中含有用户自己定义存储区的语句,如上述语句,定义的意思为

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

定义了256个8位的寄存器型数据

但是RAM和reg型式有不同的。FPGA里面的RAM分成Block RAMDistributed RAM,Block RAM是嵌入的RAM块,定制的ram资源,例如M9K,M4K;Distributed RAM是分布式RAM,即用FPGA里的寄存器和查找表构成,用逻辑单元拼出来的。

RAM可以由reg构成,但是RAM不能直接当寄存器组用。比如你设一个reg[7:0] mem[0:255],在一个时钟里你可以直接访问所有的数据,但是RAM里面你一次只能访问一个地址的数据。
RAM一般数据宽度不能设置太大,很消耗资源。

  1. 单个寄存器说明既能够用于说明寄存器类型,也可以用于说明存储器类型
	parameter ADDR_SIZE = 16 , WORD_SIZE = 8;
	reg [1: WORD_SIZE] RamPar [ ADDR_SIZE-1 : 0], DataReg;

其中,RamPar是存储器,是16个8位寄存器数组,而DataReg是8位寄存器。

  1. 寄存器数组和寄存器的赋值
    在赋值语句中需要注意如下区别:存储器赋值不能在一条赋值语句中完成,但是寄存器可以。因此在存储器被赋值时,需要定义一个索引。

下例说明它们之间的不同。

	reg [1:5] Dig; //Dig为5位寄存器。
	. . .
	Dig = 5'b11011;

上述赋值都是正确的, 但下述赋值不正确:

	reg BOg[1:5]; //Bog为5个1位寄存器的存储器。
	. . .
	Bog = 5'b11011;

有一种存储器赋值的方法是分别对存储器中的每个字赋值。例如:

	reg [0:3] Xrom [1:4]
	. . .
	Xrom[1] = 4'hA;
	Xrom[2] = 4'h8;
	Xrom[3] = 4'hF;
	Xrom[4] = 4'h2;
  1. 为存储器赋值的另一种方法是使用系统任务:
      1) $readmemb (加载二进制值)
      2) $readmemb (加载十六进制值)

      这些系统任务从指定的文本文件中读取数据并加载到存储器。文本文件必须包含相应的二进制或者十六进制数。例如:
	reg [1:4] RomB [7:1] ;
	$ readmemb ("ram.patt", RomB);

Romb是存储器。文件“ram.patt”必须包含二进制值。文件也可以包含空白空间和注释。下面是文件中可能内容的实例。

1101
1110
1000
0111
0000
1001
0011

系统任务$ readmemb促使从索引7即Romb最左边的字索引,开始读取值。如果只加载存储器的一部分,值域可以在$ readmemb方法中显式定义。例如:

$readmemb ("ram.patt", RomB, 5, 3);

在这种情况下只有Romb[5],Romb[4]和Romb[3]这些字从文件头开始被读取。被读取的值为1101、1100和1000。
文件可以包含显式的地址形式。

@hex_address value

如下实例:

@5 11001
@2 11010

在这种情况下,值被读入存储器指定的地址。
  当只定义开始值时,连续读取直至到达存储器右端索引边界。例如:

$readmemb ("rom.patt", RomB, 6);
//从地址6开始,并且持续到1。
$readmemb ( "rom.patt", RomB, 6, 4);
//从地址6读到地址4。
  • 38
    点赞
  • 206
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值