SystemVerilog学习(3)——数组

一、定宽数组

相比于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()来删除所有数据成员。

四、其他

关于数组类型,还有关于关联数组,链表,数组方法,数组排序的相关内容,这里不做过多展开。

相关推荐
XINVRY-FPGA2 天前
XCZU19EG-2FFVC1760I Xilinx赛灵思FPGA Zynq UltraScale+MPSoC
c++·嵌入式硬件·阿里云·fpga开发·云计算·硬件工程·fpga
XINVRY-FPGA3 天前
赛灵思 XC7K325T-2FFG900I FPGA Xilinx Kintex‑7
人工智能·嵌入式硬件·ai·fpga开发·fpga·pcb工艺·zynq
XINVRY-FPGA3 天前
XCZU7EG‑L1FFVC1156I 赛灵思XilinxFPGA ZynqUltraScale+ MPSoC EG
c++·嵌入式硬件·阿里云·fpga开发·云计算·fpga·pcb工艺
贝塔实验室4 天前
基于XC7V690T的在轨抗单粒子翻转系统设计
设计模式·fpga开发·系统架构·流程图·软件构建·个人开发·fpga
XINVRY-FPGA4 天前
XC7K410T‑2FFG900I 赛灵思XilinxFPGA Kintex‑7
嵌入式硬件·安全·阿里云·ai·fpga开发·云计算·fpga
XINVRY-FPGA8 天前
XC6SLX100T-2FGG484I 赛灵思 XilinxFPGA Spartan-6
c++·人工智能·嵌入式硬件·阿里云·ai·fpga开发·fpga
北城笑笑12 天前
FPGA 37 ,FPGA千兆以太网设计实战:RGMII接口时序实现全解析( RGMII接口时序设计,RGMII~GMII,GMII~RGMII 接口转换 )
fpga开发·fpga
迎风打盹儿13 天前
FPGA上实现SD卡连续多块读的命令
fpga·sd卡·tf卡·多块读取·cdm18
0基础学习者14 天前
按键消抖(用状态机实现)
前端·笔记·fpga开发·verilog·fpga
weixin_4465042215 天前
通信协议详解(十):PSI5 —— 汽车安全传感器的“抗干扰狙击手”
嵌入式硬件·fpga