net或变量的数组声明可以是标量或向量。可以通过在标识符名称后面指定地址范围来创建任意数量的维度,并将其称为多维数组。Verilog中允许对reg、wire、integer和real数据类型使用数组。
reg y1 [11:0]; // y是深度12的标量reg数组,每个1位宽
wire [0:7] y2 [3:0] // y 是8位向量 net 深度为4
reg [7:0] y3 [0:1][0:3]; //y是一个二维数组,行=2,列=4,每个8位宽
必须为每个维度指定一个索引来访问数组中的特定元素,并且可以是其他变量的表达式。可以为Verilog中支持的任何不同数据类型形成一个数组。注意,n位reg的内存与n位向量reg是不同的。
分配(Assignment)
y1 = 0; //非法-无法一次分配所有元素
y2[0] = 8'ha2; // 将0xa2分配给index = 0
y2[2] = 8'h1c;
y3[1][2] = 8'hdd;
y3[0][0] = 8'haa;
例
下面显示的代码仅显示如何对不同的数组进行建模,分配和访问。 mem1是8位向量,mem2是深度为4(由[0:3]指定的深度)的8位数组,mem3是具有4行2列的16位向量2D数组。 这些变量被分配了不同的值并被打印。
module des ();
reg [7:0] mem1; // reg向量8位宽
reg [7:0] mem2 [0:3]; // 深度= 4的8位宽向量数组
reg [15:0] mem3 [0:3][0:1]; // 行数= 4,cols = 2的16位宽矢量2维数组
initial begin
int 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]);
end
for(int i = 0; i < 4; i += 1) begin
for(int j = 0; j < 2; j += 1) begin
mem3[i][j] = i + j;
$display("mem3[%0d][%0d] = 0x%0h", i, j, mem3[i][j]);
end
end
end
endmodule
Simulation Log
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.
存储器Memories
存储器是数字存储元件,有助于在数字电路中存储数据和信息。 RAM和ROM是这种存储元件的很好的例子。 可以使用reg类型的一维数组对存储元素进行建模,称为存储。 存储器中的每个元素可以代表一个单词,并使用单个数组索引进行引用。
寄存器向量Register Vector
在下面显示的代码中,设计模块时钟,复位和一些控制信号以对模块进行读写。
它包含一个称为寄存器的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) begin
if (!rstn)
register <= 0;
else begin
if (sel & wr)
register <= wdata;
else
register <= register;
end
end
assign rdata = (sel & ~wr) ? register : 0;
endmodule
硬件示意图显示,当用于写入的控制逻辑处于活动状态时,将更新16位触发器,而当将控制逻辑配置为用于读取时,将返回当前值。
Array数组
在此示例中,寄存器是一个具有四个位置的数组,每个位置的宽度为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) begin
if (!rstn) begin
for (i = 0; i < 4; i = i+1) begin
register[i] <= 0;
end
end else begin
if (sel & wr)
register[addr] <= wdata;
else
register[addr] <= register[addr];
end
end
assign rdata = (sel & ~wr) ? register[addr] : 0;
endmodule
在硬件示意图中可以看到,阵列的每个索引都是一个16位触发器,并且输入地址用于访问一组特定的触发器。
参考文献:
【1】https://www.chipverify.com/verilog/verilog-arrays-memories