一、定宽数组
相比于Verilog-1995中的一维定宽数组,SV提供了更加多样的数组类型,功能上也大大增强。
1.1 定宽数组的声明与初始化
Verliog要求在声明中必须给出数组的上下界。因为几乎所有的数组都使用0作为索引下届,所以SV允许只给出数组的宽度的便捷声明方式,这与C语言是类似的。
//定宽数组的声明
int lo_hi[0:15] //16个整数[0]...[15]
int c_style[16] //16个整数[0]...[15]
可以通过在变量名后面指定维度的方式来创建多维定宽数组。下面的代码就创建了几个二维的整数数组,大小都是8行4列,最后一个元素的值被设置为1。在Verilog-2001中就引入了多维数组,但是这种便捷的声明方式只在SV中存在。
//多维数组声明
int array2 [0:7][0:3] //完整的声明
int array3 [8][4] //紧凑的声明
array2[7][3] = 1; //设置最后一个元素
如果试图从一个越界的地址中读取数据,那么SV会返回数组元素的缺省值(例如:四值类型;logic返回X,双状态类型返回0)。
1.2 常量数组
下面的例子展示了如何使用常量数组,即一个单引号加大括号来初始化数组。在大括号前标上重复次数可以对多个元素重复赋值,还可以为那些没有显示赋值的元素指定一个缺省值。
//初始化一个数组
int ascend[4] = '{0,1,2,3};
int descend[5];
descend = '{4,3,2,1,0};
descend[0:2] = '{5,6,7};
ascend = '{4{8}}; //四个值都是8
descend = '{9,8,default:1}; //{9,8,1,1,1}
1.3 基本的数组操作
操作数组的常见方式是for和foreach循环。
initial begin
bit [31:0] src[5],dst[5];
for(int i = 0 ; i < $size(src) ; i++)
src[i] = i;
foreach (dst[j])
dst[j] = src[j] * 2;
end
二、动态数组
我们前面介绍的基本的Verilog数组类型都是定宽数组,其宽度在编译的时候就确定了。但是如果直到程序运行之前都不知道数组的宽度呢?例如,你可能想在仿真开始的时候生成一批事务,事务的总量是随机的。如果把这些事务存放到一个定宽数组里,那这个数组的宽度就必须足以容纳最大的事务量,这就造成了资源的浪费,SV提供了动态数组类型,可以在仿真的时候分配空间或调整宽度,这样在仿真中就可以使用最小的存储量。
动态数组在声明的时候使用空的下标[ ]。这意味着数组的宽度不在编译的时候给出,而在程序运行时再定。数组在最开始的时候是空的,所以你必须调用new[ ]操作符来分配空间,同样在方括号中传递数组宽度。可以把数组名传给new[ ]构造符,并把已有数组的值复制到新数组里。
//使用动态数组
int dyn[],d2[]; //声明动态数组
initial begin
dyn = new[5]; //分配5个元素
foreach (dyn[j]) dyn[j] = j; //对数组初始化
d2 = dyn; //复制一个动态数组
d2[0] = 5; //修改复制值
$display(dyn[0],d2[0]); //显示数组(0,5)
dyn = new[20](dyn); //分配20个整数值并进行复制
dyn = new[100]; //分配100个新的整数值
//旧值不存在了
dyn.delete(); //删除所有元素
end
三、队列
SystemVerilog 引进了一种新的数据类型---队列,它结合了链表和数组的优点。队列与链表相似,可以在一个队列中的任何地方增加或删除元素,这类操作在性能上的损失比动态数组小得多,因为动态数组需要分配新的数组并复制所有元素的值。队列与数组相似,可以通过索引实现对任一元素的访问,而不需要像链表那样去遍历目标元素之前的所有元素。
队列的声明是使用带有美元符号的下标:[\]。队列元素的编号从О到。例2.19示范了如何使用方法(method)在队列中增加和删除元素。注意队列的常量( literal)只有大括号而没有数组常量中开头的单引号。
System Verilog 的队列类似于标准模板库(standard template library)中的双端队列。你通过增加元素来创建队列.SystemVerilog 会分配额外的空间以便你能够快速插人新元素。当元素增加到超过原有空间的容量时,SystemVerilog 会自动分配更多的空间。其结果是,你可以扩大或缩小队列,但不用像动态数组那样在性能上付出很大代价,SystemVerilog会随时记录闲置的空间。注意不要对队列使用构造函数new[]。
可以通过内建方法push_back(val)、push_front(val)、 pop_back()和pop_front()来顺序添加或者移除并且获得数据成员; 可以通过insert(pos, val)来在指定位置插入数据成员; 可以通过delete()来删除所有数据成员。
四、其他
关于数组类型,还有关于关联数组,链表,数组方法,数组排序的相关内容,这里不做过多展开。