systemverilog_数组
一.概述
1.数组的分类
systemverilog中,除了有定长数组外,还扩展了动态数组、队列和关联数组;
2.数组的基本规则
(1)在声明变量时,变量名右侧的维度大于变量名左侧的维度,变量名同一侧的维度从左向右递减;
(2)变量的索引,索引位于变量名右侧,且维度从左导游递减;
(3)systemverilog中,数组的每个元素存储时使用的是32bite字边界,当单个元素超过32位时,就增加到多个32bite字边界;
(4)在sysytemverilog中,存储一bit4值逻辑需要消耗2bit存储空间(四个状态0,1,X,Z);
(5)byte,shortint,int,longint只能声明非组合型数组(存疑)???
,bit、logic既可以声明组合型数组和非组合型数组;
二.定长数组
1.定义
在声明时必须明确指定大小(上下界或宽度)的数组。
2.非组合型数组
(1)定义
数组,各元素,独立分配存储空间;
(2)语法
在变量声明时,维度声明在变量名右
侧;
声明语法:
c
变量类型 变量名 维度;
初始化及赋值语法 :
多个元素或整体初始化或赋值时,每一维一个**'{}**
非组合型数组初始化或赋值时,赋的值和被赋值的元素结构必须一致;
c
被赋值元素 = 赋的值;
(3)例子
A 例子1:非组合型数组结构及存储空间分配
代码:
c
module test_array;
bit [7:0] a [0:2] = '{1,2,3};
initial begin
$display("a = %b",a[0]);
end
endmodule
说明:
声明了3个元素,每个元素(a[0]、a[1]、a[2]各)都会分配32位宽的存储空间,但是只使用了低8位;
B 例子2:非组合型数组的声明初始化及赋值
代码:
c
module test_array;
int b [3:0][2:0];
int c [1:0][2:0];
initial begin
b = '{'{0,1,2},'{3,4,5},'{6,7,8},'{9,10,11}};
c = '{'{12,13,14},'{15,16,17}};
$display("b[1][2] = %0d",b[1][2]);
b[1][2] = 18;
$display("b[1][2] = %0d",b[1][2]);
b[0] = c[0];
$display("b[0][2] = %0d",b[0][2]);
b[0]= '{19,20,21};
$display("b[0][2] = %0d",b[0][2]);
end
endmodule
结果:
(4)特殊点
A非组合型数组,每一个维度指定,可以按照[msb:lsb]的方式,也可以按照[size]的方式;
B非组合型数组的初始化或赋值,可以用'{default:值}的方式,表示将每一个元素都赋值为指定的值;
3.组合型数组
(1)定义
数组,各元素,组合分配地连续的存储空间;
(2)语法
在变量声明时,维度声明在变量左
侧;
声明语法:
c
变量类型 维度 变量名;
初始化及赋值语法 :
很灵活,支持拼接赋值,位宽不一致(同verilog,短了高位补0,长了截断);
c
被赋值元素 = 赋的值;
(3)例子
A非组合型数组的声明和初始化
代码
c
module test_array;
bit [3:0][7:0] d;
initial begin
d = 32'h8888_8888;
$display("d = %h",d);
d = {8'h12,8'h34,8'h56,8'h78};
$display("d = %h",d);
end
endmodule
结果:
说明:
声明了4个8位宽的组合型数组,存储空间分配的存储空间的梁旭的4*8=32位:
(4)特殊点
A组合型数组连续存放的优点有:节省存储空间,方便存读;
4.混合型数组
(1)定义
数组,既包含组合型数组的部分,又包含非组合型数组的部分;
(2)语法
声明语法:
c
变量类型 维度 变量名 维度;
初始化及赋值语法 :
组合型部分按照组合型部分赋值,非组合型部分按照非组合型赋值;
(3)特殊点
组合型数组组合部分不可以赋值给非组合型数组,非组合型数组不可以赋值给组合型数组的组合部分;
5.foreach循环
(1)简介
在**()**中给出变量名和索引,sysytemverilog会自动遍历数组中的元素;
(2)语法
c
foreach(元素名[索引])begin
具体操作;
end
(3)例子
代码:
c
module test_array;
int a [10];
initial begin
foreach(a[i])begin
a[i] = i;
$display("a[%0d] = %0d",i,a[i]);
end
end
endmodule
结果:
(4)注意点
索引是可以引用,但不可以更改;
6.数组相关的系统函数
(1)dimensions
A作用:返回数组的维度;
B语法:
c
dimensions(数组名);
C例子
c
module test_array;
int a [0:3][0:1];
bit [3:0] b [0:1];
initial begin
$display("The dimensions of a is %0d",$dimensions(a));
$display("The dimensions of b is %0d",$dimensions(b));
end
endmodule
结果:
(2)$size
A作用:返回指定维度的尺寸大小
B语法
c
$size(数字名,维度);
C例子
代码:
c
int a[0:3][0:2];
bit [3:0] b [0:2];
initial begin
$display("a's first dimension is %0d",$size(a,1));
$display("a's thied dimension is %0d",$size(a,3));
$display("b's second dimension is %0d",$size(b,2));
end
endmodule
结果:
三.动态数组
1.定义
在声明时不需要明指定大小,且可以随时改变大小的数组;
2.语法
(1)声明语法:
c
类型 数组名 [];
(2)初始化大小或改变数组大小的语法:
方法1:通过new函数
c
变量名 = new[大小];
方法二:通过变量赋值
c
变量名 = 赋值变量;
方法三:常量赋值:同非组合型数组
c
变量名 ='{值1,值2,...};
(3)开辟新的存储空间并保留原值
c
变量名 = new[大小](变量名);
(4)清空动态数组
方法一:
c
数组名.delete();
方法二:
c
数组名=new[0];
3.例子
代码:
c
module test_array;
int a[],b[],c[];
initial begin
$display("%0d,%0d",$size(b,2),$size(b,1));
a = new[4];
b = new[3];
c = new[2];
$display("a's size is %0d",$size(a,1));
$display("b's size is %0d",$size(b,1));
b = a;
$display("b's size is %0d",$size(b,1));
c = '{1,2};
//
foreach(b[i])begin
b[i] = i;
$display("b[%0d] = %0d",i,b[i]);
end
b = new[5](b);
foreach(b[i])begin
$display("b[%0d] = %0d",i,b[i]);
end
//
b.delete();
$display("b's dimension is %0d",$dimensions(b));
$display("%0d,%0d",$size(b,2),$size(b,1));
end
endmodule
结果:
四.队列
1.定义
队列是数组和链表的结合,我们可以在任意位置添加或删除数据成员;
2.语法
(1)队列的声明
c
类型 队列名 [$];
(2)队列的初始化和赋值
方法一:通过赋常量(注意{}旁没有'
)
c
队列名 = {值1,值2,...}; //注意{}没有'
方法二:通过赋队列(队列2会将值和队列大小同时赋给队列1)
c
队列1名 = 队列2名; //注意{}没有'
方法三:可以通过拼接赋值
c
队列1名 = {队列2名,值,队列3名};
(3)常用的系统函数
A insert
说明:在指定位置插入值
语法:队列.insert(位置,值);
注意:队列不能插入队列
B delete
说明:删除指定位置的值,或删除所有元素
语法:队列名.delete(索引);//删除指定位置的值,仅适用于队列,不适用于动态数组
队列名.selete();
C push和pop
队列名.push_front(值):在队列前面插入一个值;
存储变量=队列名.pop_front:在队列前面取出一个值;
队列名.push_back(值):在队列后面插入一个值;
存储变量=队列名.pop_back:在队列后面取出一个值;
3.例子
代码:
c
module test_array;
int a [$];
int b [$];
int c [$];
initial begin
a = {1,2,3};
b = {5,6};
c = {10,b[0:1]};
$display("a is %p",a);
$display("b is %p",b);
$display("c is %p",c);
b = a;
$display("b is %p",b);
b.insert(1,7);
b.delete(2);
$display("b is %p",b);
void'(a.pop_front);
a.push_front(8);
void'(b.pop_back);
b.push_back(9);
$display("a is %p",a);
$display("b is %p",b);
end
endmodule
结果:
4.注意点
(1)队列的索引$表示最后一个元素;
五.关联数组
1.定义
索引可以是任意类型(logic,bit,byte,short,int,long,字符串,枚举类型),存储可以不连续的一种数组;
2.语法
(1)声明语法
c
数据类型 大小 名字 [索引类型及大小];
(2)初始化、赋值、改变大小
A 赋常量(键为索引,值为取值)
关联数组名 = '{键1:值1,键2:值,...}
B 赋关联数组
关联数组1名 = 关联数组2名;
(3)关联数组相关的函数
A delete
作用:删除关联数组中的键值对;
语法:关联数组名.delete(索引);
(4)例子
代码:
c
int a [string];
int b [string];
initial begin
a = '{"name":1,"age":12,"weigh":45};
$display("a is %p",a);
b = '{"hong":1,"lan":2};
$display("b is %p",b);
b = a;
$display("a is %p",b);
b.delete("age");
$display("a is %p",b);
end
endmodule
结果:
六.数组常用方法
1.缩减方法
(1)sum
作用:元素求和
语法:和值存储变量 = 数组.sum();
(2)product
作用:元素求积
语法:积值存储变量 = 数组.product();
(3)and
作用:元素按位与
语法:结果存储变量 = 数组.and();
(4)or
作用:元素按位或
语法:结果存储变量 = 数组.or();
(5)xor
作用:元素按位异或
语法:结果存储变量 = 数组.xor();
(6)例子
代码:
c
module test_array14;
int a[0:3];
initial begin
a = '{1,2,3,4};
$display("sum is %0d",a.sum());
$display("product is %0d",a.product());
$display("and is %0b",a.and());
$display("or is %0b",a.or());
$display("xor is %0b",a.xor());
end
endmodule
结果:
2.定位方法
(0)注意
定位函数的返回值是一个队列,而不是一个元素,所以打印要用
%p ;
(1)min
作用:元素最小值
语法:结果存储变量 = 数组.min();
(2) max
作用:元素最小值
语法:结果存储变量 = 数组.max();
(3)unique
作用:遍历不同的值
语法:结果存储变量 = 数组.unique();
(4)例子
代码:
c
endmodule
module test_array15;
int b[];
initial begin
b = '{1,2,3,3,5,5,7,9};
$display("max is %p",b.max());
$display("min is %p",b.min());
$display("unique is %p",b.unique());
end
endmodule
结果:
3.排序方法
(1)reverse
作用:倒序
语法:结果存储数组 = 数组.reverse();
(2)sort
作用:增序排列
语法:结果存储数组 = 数组.sort();
(3)rsort
作用:降序排列
语法:结果存储数组 = 数组.rsort();
(4)例子
代码:
c
module test_array16;
int a [0:5] = '{1,3,5,7,8,9};
int b [] = '{2,3,5,6,7,9};
int c [$] = {1,3,4,5,7,8};
initial begin
a.reverse();
$display("reverse is %p",a);
b.sort();
$display("sort is %p",b);
c.rsort();
$display("rsort is %p",c);
end
endmodule
结果:
4.size
四种数组中,哪个数组可以使用size内嵌方法?
动态数组、队列、关联数组都可以,定长数组不可以;
要注意函数$size和内嵌方法size的区别
所有数组$size函数,但是后续三个数组可以用用size内嵌方法