Verilog 4:数组
原文:chipverify
什么是Verilog数组
网线或变量的数组声明可以是标量的,也可以是向量的。通过在标识符名称后面指定地址范围,可以创建任意数量的维度,这样的数组被称为多维数组。在Verilog语言中,寄存器(reg
)、线网(wire
)、整型(integer
)和实型(real
)这些数据类型都允许使用数组。
reg y1 [11:0]; // y is an scalar reg array of depth=12, each 1-bit wide
wire [0:7] y2 [3:0] // y is an 8-bit vector net with a depth of 4
reg [7:0] y3 [0:1][0:3]; // y is a 2D array rows=2,cols=4 each 8-bit wide
为了访问数组的某个特定元素,必须为每个维度指定一个索引,该索引可以是其他变量的表达式。可以为Verilog中支持的任何不同数据类型创建数组。
请注意,由n个1位寄存器组成的存储器与一个n位向量寄存器是不一样的。
数组赋值
y1 = 0; // Illegal - All elements can't be assigned in a single goy2[0] = 8'ha2; // Assign 0xa2 to index=0
y2[2] = 8'h1c; // Assign 0x1c to index=2
y3[1][2] = 8'hdd; // Assign 0xdd to rows=1 cols=2
y3[0][0] = 8'haa; // Assign 0xaa to rows=0 cols=0
数组例子
下面展示的代码简单说明了如何对不同的数组进行建模、赋值和访问。mem1
是一个 8 位向量,mem2
是一个深度为 4(由范围 [0:3] 指定)的 8 位数组,而 mem3
是一个 4 行 2 列的 16 位向量二维数组。这些变量被赋予不同的值并打印输出。
module des ();reg [7:0] mem1; // reg vector 8-bit widereg [7:0] mem2 [0:3]; // 8-bit wide vector array with depth=4reg [15:0] mem3 [0:3][0:1]; // 16-bit wide vector 2D array with rows=4,cols=2initial beginint i;mem1 = 8'ha9;$display ("mem1 = 0x%0h", mem1);mem2[0] = 8'haa;mem2[1] = 8'hbb;mem2[2] = 8'hcc;mem2[3] = 8'hdd;for(i = 0; i < 4; i = i+1) begin$display("mem2[%0d] = 0x%0h", i, mem2[i]);endfor(int i = 0; i < 4; i += 1) beginfor(int j = 0; j < 2; j += 1) beginmem3[i][j] = i + j;$display("mem3[%0d][%0d] = 0x%0h", i, j, mem3[i][j]);endendend
endmodule
仿真日志
ncsim> run
mem1 = 0xa9
mem2[0] = 0xaa
mem2[1] = 0xbb
mem2[2] = 0xcc
mem2[3] = 0xdd
mem3[0][0] = 0x0
mem3[0][1] = 0x1
mem3[1][0] = 0x1
mem3[1][1] = 0x2
mem3[2][0] = 0x2
mem3[2][1] = 0x3
mem3[3][0] = 0x3
mem3[3][1] = 0x4
ncsim: *W,RNQUIE: Simulation is complete.
什么是内存
存储器是数字存储元件,有助于在数字电路中存储数据和信息。随机存取存储器(RAM)和只读存储器(ROM)就是这类存储元件的典型例子。存储元件可以使用寄存器类型的一维数组来建模,这种数组被称为存储器。存储器中的每个元素可以代表一个字,并通过单个数组索引来引用。
寄存器向量
Verilog向量是通过在变量名左侧使用大小范围来声明的,并且这些向量会被实现为与变量大小相匹配的触发器。在下面展示的代码中,设计模块接收时钟、复位信号以及一些控制信号,以便对模块进行读写操作。
它包含一个名为寄存器的16位存储元件,该元件在写入时简单地进行更新,并在读取时返回当前值。当选择信号 sel
和写入信号 wr
在同一个时钟沿都为高电平时,对该寄存器进行写入操作。当 sel
为高电平且 wr
为低电平时,它返回当前数据。
module des ( input clk,input rstn,input wr,input sel,input [15:0] wdata,output [15:0] rdata);reg [15:0] register;always @ (posedge clk) beginif (!rstn)register <= 0;else beginif (sel & wr)register <= wdata;elseregister <= register;endendassign rdata = (sel & ~wr) ? register : 0;
endmodule
硬件原理图显示,当用于写入操作的控制逻辑处于激活状态时,一个16位的触发器会被更新;而当控制逻辑被配置为读取操作时,则会返回当前值。
内存例子
在这个例子中,register 是一个数组,它有四个存储位置,每个位置的宽度为 16 位。设计模块接受一个额外的输入信号,名为 addr,用于访问数组中的特定索引。
module des ( input clk,input rstn,input [1:0] addr,input wr,input sel,input [15:0] wdata,output [15:0] rdata);reg [15:0] register [0:3];
integer i;always @ (posedge clk) beginif (!rstn) beginfor (i = 0; i < 4; i = i+1) beginregister[i] <= 0;endend else beginif (sel & wr)register[addr] <= wdata;elseregister[addr] <= register[addr];end
endassign rdata = (sel & ~wr) ? register[addr] : 0;
endmodule
从硬件原理图中可以看出,数组的每个索引对应的是一个16位的触发器,并且输入地址用于访问特定的一组触发器。