关于数组的内容
Verilog数组声明的基本语法
<data_type><vector_size><array_name><array_dimension>
例如:
reg[15:0] RAM [0:4095];//储存器数组
SystemVerilog允许任何数据类型的非压缩数组
SystemVerilog将非压缩数组的声明进行了扩展,可以使用Verilog的event数据类型,以及所有SystemVerilog数据类型,包括logic、bit、int、shortreal和real,以及使用typedef可以声明用户自定义类型非压缩数组,包括使用struct和enum类型。
bit[63:0] d_array[1:128];//向量数组
shortreal cosines[0:89];//浮点数组
typedef enum {Mo,Tu,We,Th,Fr,Sa,Su}Week;
Week Year[1:52] ;//Week类型的数组
SystemVerilog可以引入整个数组或其中一段
SystemVerilog也加入引用整个非压缩数组以及一段元素的功能。一段就是在数组同一维内一个或多个邻近的元素。这样可以将整个数组或者数组待定维的内容复制到另一个数组。
注意:复制非压缩数组时,等号的左边和右边必须有同样的构架和类型。
int a1[7:0][1023:0] ;//非压缩数组
int a2[1:8][1:1024];//非压缩数组
a2 = a1;//复制整个数组
a2[3] = a1[0];//复制数组的一段
SystemVerilog数组也可以指定尺寸
SystemVerilog允许非压缩数组只指定维度大小,而不用指定开始和结束地址
logic [31:0] data[1024];
//这声明等同于
logic [31:0] data[0:1023];
//同C语言一样,非压缩数组的元素个数是限定的,地址从0开始到(宽度-1)结束。
2、压缩数组
SystemVerilog将向量声明看作是压缩数组,一个Verilog向量就是一个一维压缩数组。
wire [3:0] select;//4位压缩数组
reg [63:0] data;//64位压缩数组
//SystemVerilog可以声明多维压缩数组
logic [3:0][7:0] data;//2维压缩数组
压缩数组没有间隙
SystemVerilog对压缩数组中的元素如何储存进行了规定。整个数组的储存必须是位连续的,和向量的储存一样,压缩的每一维都是向量的字段。
压缩数组的数据类型
注意:只有位形式的数据类型才可以被压缩
压缩数组只可能由位形式的数据类型组成,包括logic、bit和reg、其他压缩数组、压缩结构体及压缩联合体。压缩数组还可以由任何Verilog线网类型(wire、wand、tri、triand、trior、tri0、tri1或trireg)组成。
typedef struct packed{logic [7:0] crc;logic [63:0] data;
}data_word;
data_word [7:0] darray;//由压缩结构体构成的一维压缩数组
引用压缩数组
压缩数组可以作为整体、位选择或部分选择引用。多维压缩数组也可以引用其中的一段。一段就是数组中一个或是多个邻近的维度。
logic [3:0][7:0] data;//二维压缩数组
wire [31:0] out = data;//整个数组
wire sign = data[3][7];//一位
wire[3:0] nib = data[0][3:0];//一部分
byte high_byte;
assign high_byte = data[3];//宽度为8位的一段
logic[15:0] word;
assign word = data[1:0];//两段
压缩数组的操作
任何向量操作都可以用于压缩数组
由于压缩数组像向量一样储存,所以对于Verilog向量的任何合法操作都可以用于压缩数组,包括选取压缩数组中的一位和一部分、拼接操作、算术操作、关系操作、位操作以及逻辑操作、
logic [3:0][15:0] a,b,result;//压缩数组
...
result = (a<<1)+b;
3、使用压缩和非压缩数组
使用非压缩数组模拟储存器,以及抽象数据类型
非压缩数组用于建模
- 下列数据类型的数组:byte、int、integer、real、非压缩结构体、非压缩联合体以及其他非位形式的数据类型。
- 通常每次只访问一个元素的数组,例如RAM和ROM
module ROM(...);byte mem[0:4095] ;//字节型非压缩数组assign data = select?mem[address]:'Z;...
压缩数组用于建模
- 由只有1位的数据类型组成的向量
- 需要子段访问的向量
logic [39:0] [15:0] packet;//40个16位字
packet = input_stream;//给所有的字赋值
data = packet[24];//选取一个16位字
tag = packet[3][7:0] ;//选取字的一部分
4、声明对数组进行初始化
压缩数组初始化
压缩数组的初始化同向量一样
赋值可以是一个常数、常数的拼接或常数的复制
logic[3:0][7:0] a = 32'h0;//向量赋值
logic[3:0][7:0] b = {16'hz,16'h0};//拼接操作符
logic[3:0][7:0] c = {16{2'b01}};//赋值操作符
非压缩数组初始化
非压缩数组使用一个值序列初始化
对于非压缩数组,在声明时可以使用’{}内的值序列进行初始化。
int d1[0:1][0:3] = '{'{7,3,0,5},'{2,0,1,6}};
//d1[0][0] = 7;
//d2[0][1] = 3;
//d1[0][2] = 0;
//d1[0][3] = 5;
//d1[1][0] = 2;
//d1[1][1] = 0;
//d1[1][2] = 1;
//d1[1][3] = 6;
SystemVerilog为值序列的声明提供了一种便捷方式。使用方式类似于Verilog的复制符,一个维度内的值序列可以重复任意次,复制操作符前面不用加撇号
int d1[0:1][0:3] = '{2{7,3,0,5},};
//d1[0][0] = 7;
//d2[0][1] = 3;
//d1[0][2] = 0;
//d1[0][3] = 5;//d1[1][0] = 7;
//d1[1][1] = 3;
//d1[1][2] = 0;
//d1[1][3] = 5;
注意’{}列表操作符和’{n{}}复制操作符不同于Verilog的拼接操作符{},以及复制操作符{n{}}。
{}的使用有两种方式
当对非压缩数组进行初始化时,大括号’{}表示一个值序列。作为一个值序列,每个都按照Verilog复制语句规则赋给相应的元素,也就是说,无位数的文本值也可以在序列中指定,与实数值相同。
为非压缩数组指定默认值
数组可以被初始化有一个默认值
默认值在’{}中使用关键字default指定,指定的值与关键字用冒号隔开。指定的值必须与数组的数据类型匹配。如果指定的值可以转换成数组的数据类型,也算是匹配的。
int a1 = [0:7][0:1023] = '{default:8'h55};
5、数组赋值
非压缩数组赋值
Verilog语言支持两种方式的非压缩数组赋值
- 给一个元素赋值
- 给一个元素的1位或者部分赋值
SystemVerilog扩展了两种新的非压缩数组赋值方法
- 用一个值序列给整个数组赋值
- 用一个值序列给数组的一段赋值
值序列是在大括号’{}中指定的。
byte a[0:3][0:3];
a[1][0] = 8'h5;//赋值给一个元素
a = '{'{0,1,2,3},
'{4,5,6,7},
'{7,6,5,4},
'{3,2,1,0}};//将一个值序列赋给整个数组
a[3] = '{'hF,'hA,'hC,'hE};//将一个值序列赋给数组的一段
使用关键字default也可以给非压缩数组指定一个默认值。和过程赋值一样,数组的不同部分也可以置成不同的默认值。
always@(posedge clock,negedge resetN)if(!resetN)begina = '{default:0};//初始整个数组a[0] = '{default:4};//初始数组的一段endelse begin...end
压缩数组赋值
多维压缩数组是有子域的向量
压缩数组是向量(可能有子域)。
- 数组的一个元素
- 整个数组(向量)
- 数组的一部分
- 数组的一段(多个相邻的子域)
bit [1:0][15:0] a;//32位四态向量
logic [3:0][7:0] b;//32位四态向量
logic [15:0] c;//16位四态向量
logic[39:0] d;//40位四态向量b = a;//将32位数组赋给32位数组c = a;//a的高16位四态向量d = a;//d的高8位填0
非压缩数组带非压缩数组
允许非压缩数组到非压缩数组的赋值
只要两个非压缩数组具有相同的维数和元素位数以及相同的类型,才可以直接赋值。通过将一个数组的每个元素复制到目标数组的相应元素,就实现了赋值。两个数组中的元素编号不必相同。但数组的结构和类型必须完全匹配。
logic [31:0] a[2:0] [9:0];
logic [0:31] b[1:3] [1:10];
a = b;//非压缩数组之间的赋值
不同尺寸的非压缩数组间的赋值需要转换
非压缩数组到压缩数组的赋值需要转换。在非压缩数组中,每一个元素都单独储存而不能看做是一个向量。然而非压缩数组可以通过位流转换对压缩数组赋值。
压缩数组到非压缩数组的赋值需要转换。压缩数组被看做一个向量,而向量无法直接赋给非压缩数组,因为压缩数组中的元素是独立储存的。但是通过位流转换操作可以实现赋值。
7、使用位流转换复制数组和结构体
位流转换将数组换成一个临时位向量。
位流转换将非压缩数组临时地转换成向量形式位流。数组中元素的分离特性丢失了–临时向量只是简单的位流。然后临时向量可以赋值给其他数组。源数组和目标数组的位数必须相同,但两个数组中每个元素的宽度可以不同。
位流转换机制主要用于一下情况:
- 把非压缩数组赋值给不同结构的非压缩数组
- 把非压缩数组赋值给压缩数组
- 把压缩数组赋值给非压缩数组
- 把结构体赋值给压缩或非压缩数组
- 把定位或动态宽度的数组赋值给动态宽度数组
- 把结构体赋值给另一个不同结构的结构体
位流转换使用Systemverilog静态转换操作符。转换需要至少目标数组是用typedef表示的自定义类型。
typedef int data_t [3:0][7:0];//非压缩类型
data_t a;//非压缩数组
int b[1:0][3:0][3:0];//非压缩数组
a = data_t'(b);//将非压缩数组赋给不同结构的非压缩数组
转换操作通过将源数组(或结构体)转换为临时向量表达式(位流),然后将位数组赋给目标数组的各个元素实现。赋值是从左到右进行的。例如源位流最左边的几位赋给目标数组的第一个元素,接下来的几位赋给第二个元素,以此类推。
8、由数组构成的数组
数组可以是压缩和非压缩的混合维度
//64位压缩数组组成的非压缩数组
logic [63:0] men [0:4095];
//32位元素组成的非压缩数组,每个元素都是由4字节组成的压缩数组
wire [3:0][7:0] data [0:1023];
由数组构成的数组的索引
非压缩维度的索引先于压缩维度
当对由数组组成的数组进行索引时,先引用的是非压缩的维度,从左到右。其次引用压缩的(向量部分)维度,从左到右。
9、数组中使用用户自定义类型
数组可以包含用户自定义类型
用户自定义类型可以作为数组的元素。
//定义一个无符号整数的用户类型,
//然后又声明了有128个这种类型元素的非压缩数组
typedef int unsigned uint;
unint u_array[0:127];//用户自定义类型组成的数组
用于数组元素类型声明的用户自定义类型也可以是数组,这样可以创建复合数组。
typedef logic [3:0] nibble;//压缩数组
nibble [31:0] big_word;//压缩数组//等同于
logic [31:0][3:0] big_word;
//由用户自定义类型建立的复合数组的例子
typedef logic [3:0] nibble;//压缩数组
typedef nibble nib_array[0:3];//非压缩
nib_array compound_array[0:7];//非压缩//等同于
logic [3:0] compound_array[0:7][0:3];
10、数组通过端口及任务和函数的传送
Systemverilog允许非压缩数组作为端口和自变量
通过端口,或作为任务和函数的自变量传送数组时,端口或任务/函数的形式自变量必须声明为数组。数组通过端口传送的规则和约束与数组赋值给其他数组的规则相同。
module CPU(...)
...
logic [7:0] lookup_table[0:255];
lookup i1 (.LUT(lookup_table));
...
endmodulemodule lookup (output bit [7:0] LUT [0:255]);
...initial load(LUT);//任务调用task load (inout logic[7:0] t [0:255]);...endtask
endmodule
11、结构体和联合体构成的数组
数组可以包含结构体或者联合体
压缩和非压缩数组的元素可以是结构体和联合体。在压缩数组中,结构体和联合体也必须是压缩的。
typedef struct packed{//压缩结构体logic [31:0] a;logic [7:0] b;
}packet_t;
packet_t [23:0] packet_array;//由24个结构体组成的压缩数组
typedef struct{//非压缩结构体int a;real b;
}data_t;
data_t data_array[23:0];//由24个结构体组成的非压缩数组
12、结构体和联合体中的数组
结构体和联合体可以包含数组
结构体和联合体可以包含压缩或非压缩数组。压缩的结构体和联合体只可以包含压缩数组。
struct packed{//压缩结构体logic parity;logic [3:0][7:0] data;//二维压缩数组
}data_word;struct{//非压缩结构体logic data_ready;logic [7:0]data[0:3];//字节组成的压缩数组
}packet_t;