特点:消耗更多的存储空间,但是更易于查找元素
对于Verilog,数组经常会被用来做数据存储,例如
reg [15:0] RAM [0:4095] ;//存储数组
SV将Verilog这种声明数组的方式称之为非组合型声明,即数组中的成员之间存储数据都是互相独立的。
Verilog也不会指定软件去如何存储数组中的成员。
wire [7:0] table [3:0];
SV保留了非组合型的数组声明方式,并且扩展了允许的类型,包括event,logic,bit,byte,int,longint,shortreal和real类型。
SV也保留了Verilog索引非组合型数组或者数组片段的能力,这种方式为数组以及数组片段的拷贝带来了方便。
int a1 [7:0][1023:0];//非组合型数组
int a2 [1:8][1:1024];//非组合型数组
a2 = a1;// 拷贝整个数组
a2[3] = a1[0];// 拷贝一个数组片段
声明数组的方式,以下两种皆可
logic [31:0] data [1024]; //指定内部元素个数
logic [31:0] data [0:1023];//指定元素索引值范围
优点:与非组合型相比,更节省空间
SV将Verilog的向量作为组合型数组声明方式
wire [3:0] select; // 4比特的组合型数组
reg [63:0] data; //64比特的组合型数组
//组合型数组,该数组的每一个元素均为1比特
SV也进一步允许多维组合型数组的声明
logic [3:0][7:0] data; //2维组合数组
//索引范围声明在左侧
//数组的维度,从左到右来识别
组合型(packed)除了可以运用的数组声明,也可以用来定义结构体的存储方式
typedef struct packed {
logic [ 7:0] crc;
logic [63:0] data;} data_word;
data_word [7:0] darray;// 1位组合型数组,元素也为组合型结构体
组合型数组和其数组片段也可以灵活选择,用来拷贝和赋值等
logic [3:0][7:0] data;//2维组合型数组
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];// 2个数组片段
组合型(packed)数组
组合型(packed)数组初始化时,同向量初始化一致:
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}} ; //复制运算符
非组合型(unpacked)数组
非组合型(unpacked)数组初始化时,则需要通过’{ }来对数组的每一个维度进行赋值。
int d [0:1][0:3]= ’ { ’{7,3,0,5},’{2,0,1,6} };
//d[0][0]=7
//d[0][1]=3
//d[0][2]=0
//d[0][3]=5
//d[1][0]=2
//d[1][1]=0
//d[1][2]=1
//d[1][3]=6
非组合型数组
非组合型数组在初始化时,也可以类似结构体初始化,通过’{ }和default关键词即可以完成
int a1 [0: 7][0:1023]= ’ {default:8’h55} ;
非组合型数组的数据成员或者数组本身均可以为其赋值
byte a [0:3]10:3];
a[1][0] =8’h5;//为单个元素赋值
a[3] = ’{’hF, ’ hA, ’ hC, ’ hE};//给数组片段中的所有元素进行赋值
组合型数组
以下是组合型数组的赋值方法
logic [1:0][1:0][7:0] a; //3维数组
a[1][1][0] = 1’b0; // 为1比特赋值
a = 32’hF1A3C5E7;//给整个数组赋值
a[1][0][3:0] =4’hF; //给一个数组片段赋值
a[0] = 16’hFACE;//给一个数组片段赋值
a = {16’bz,16’b0} ; //通过连接运算符赋值
组合型数组
对于组合型数组,由于数组会被视为向量,因此当赋值左右两侧操作数的大小和维度不相同时,也可以做赋值。
如果当尺寸不相同时,则会通过截取或者扩展右侧操作数的方式来对左侧操作数赋值。
bit [1:0][15:0] a; // 32位2值逻辑向量
logic [3:0][7:0] b; //32位4值逻辑向量
logic [15:0] c; // 16位4值逻辑向量
logic [39:0] d; //40位4值逻辑向量
b = a; // 32位数组赋值给32位数组
c = a;//高16位被截断
d = a; //高8位填充为0
非组合型数组
对于非组合型数组,在发生数组间拷贝时,则要求左右两侧操作数的维度和大小必须严格一致。
这是由于非组合型数组的元素都是独立存放的。
logic [31:0] a [2:0][9: 0];
logic [0:31] b [1:3][1:10];
a = b; //非组合型数组赋值于非组合型数组
非组合型数组无法直接赋值给组合型数组,同样地,组合型数组也无法直接赋值给非组合型数组。
SV添加foreach循环来对一维或者多维数组进行循环索引,而不需要指定该数组的维度大小。
int sum [1:8] [1:3];
foreach ( sum[i,j] ) sum[i][j] = i +j; //数组初始化
foreach循环结构特点:
$dimensions(array_name)//用来返回数组的维度。
$left(array_name,dimension)//返回指定维度的最左索引值(msb)
$right(array_name,dimension)
$low(array_name,dimension)
$high(array_name,dimension)
$size(array_name,dimension)//可以返回指定维度的尺寸大小。
$increment(array_name,dimension)//如果指定维度的最左索引值大于或等于最右索引值,那么返回1,否则返回-1。
$bits(expression)//可以用来返回数组存储的比特数目。
举例:
logic [1:2][7:0] word [0:3][4:1];
//$left (word,1) will return 0
//$left (word,2) will return 4
//$left (word,3) will return 1
//$left(word,4) will return 7
wire [3:0][7:0] a [0:15];// $bits(a)返回512
struct packed {[byte tag; logic [31:0] addr;} b;// $bits(b)返回40