ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Systemverilog中数组、队列的用法

Systemverilog中数组、队列的用法 Systemverilog中数组、队列的用法前言数据类型定宽数组动态数组关联数组队列常用的数组操作方法注意事项前言在数字电路验证与硬件设计中SystemVerilogSV提供了丰富且灵活的数据结构其中数组与队列是最常用、也最基础的数据组织方式。无论是编写测试平台testbench、搭建验证环境还是进行数据建模都离不开对它们的熟练运用。本文将从定宽数组、动态数组、关联数组和队列四种核心数据结构入手逐一介绍它们的声明方式、使用场景与典型操作并对比它们之间的区别。数据类型无符号数据类型双状态类型bit b 双状态单bit数bit [15:0] b双状态16bit数int unsigned b双状态32bit无符号整数四状态类型time b四状态64bit无符号整数logic b四状态1bit无符号整数有符号数据类型双状态类型int b双状态32bit有符号整数byte b双状态8bit有符号整数shortint b双状态16bit有符号整数longint b双状态64bit有符号整数四状态类型integer b四状态32bit有符号整数定宽数组顾名思义定宽数组是指其元素个数在编译时即确定不可改变。定宽数组的声明// 定宽单维数组inta[0:15];// 16个整数inta[16];// 16个整数intb[6]{6,2,9,8,6,5};// 对数组进行初始化//定宽多维数组inta[0:15][0:3];// 16*4个整数inta[16][4];// 16*4个整数动态数组动态数组是指其大小在运行时决定可以动态调整其大小这样就不会造成存储空间的浪费因此动态数组在声明的时候使用的是空下标使用时必须调用new[]构造符来分配空间。intdyn[];dynnew[6];//分配6个元素dyn[0]8;//第一个值赋值为8dynnew[20](dyn);// 首先分配20个新元素并将原本的dyn数组复制给开始的6个元素最终指向一个20个元素的数组dynnew[100]//分配100个新元素只要基本数据类型相同定宽数组和动态数组之间就可以互相赋值在元素数目相同的情况下就可以把动态数组的值复制到定宽数组中关联数组关联数组使用一个索引键来访问数组中的元素其索引可以是整数、字符串或其他数据类型。与定宽数组和动态数组不同关联数组在声明时不需要指定大小其存储空间是在使用时按需动态分配的适合用于稀疏存储或按名字查找的场景。// 关联数组的声明使用 [索引类型] 指定键的类型intassoc[string];// 以字符串为键值为整数// 赋值通过键来写入元素assoc[apple]3;assoc[banana]5;assoc[cherry]8;// 遍历foreach 会遍历关联数组中的所有键值对foreach(assoc[key])begin $display(assoc[%s] %0d,key,assoc[key]);end// 删除删除指定键对应的元素assoc.delete(banana);// 检查某个键是否存在if(assoc.exists(apple))begin $display(apple 存在值为 %0d,assoc[apple]);end// 删除整个关联数组assoc.delete();关联数组与动态数组的区别索引类型关联数组的索引键可以是整数、字符串等任意数据类型动态数组的索引只能是整数。存储方式关联数组按需分配存储空间适合稀疏存储动态数组在声明后需用new[]一次性分配连续空间。大小控制关联数组无需预先指定大小元素随赋值自动增加动态数组的大小由new[]显式分配且空间连续。使用场景关联数组适合按键名查找、稀疏数据等场景动态数组适合需要连续存储、按序号访问的场景。队列队列可以在任何地方增加或删除元素其在性能上的损失比动态数组小的多。其与数组类似可以通过索引实现对任一元素的访问。q[$]{0,1,6,9};// 对队列进行初始化队列初始化时不需要q.delete(1);// 删除队列中的#1元素执行后的结果为{169}q.push_front(2);// {2,1,6,9} 在队列前面插入q.push_back(7);// {2,1,6,9,7} 在队列后面插入q.pop_front();// {1,6,9,7} 将队列前面的数据pop出q.pop_back();// {1,6,9} 将队列后面的数据pop出qq[1:$];// {6,9} ,$放在左边就表示最小值放在右边就表示最大值zq[$];// 从队列末尾取出数据,z9q.delete();//删除队列q{};//删除队列队列与关联数组的区别索引类型关联数组的索引键可以是整数、字符串等任意数据类型通过键直接访问元素队列的索引只能是整数且元素按插入顺序排列通过序号访问。存储方式关联数组按需分配存储空间适合稀疏存储队列在物理上是一段连续空间元素紧密排列。插入/删除位置关联数组通过键删除任意元素删除后不影响其他元素队列支持在头部push_front/pop_front和尾部push_back/pop_back高效地插入或删除元素中间位置的插入删除性能较差。遍历顺序关联数组的遍历顺序不固定由内部哈希决定队列的遍历顺序与元素插入顺序一致。使用场景关联数组适合按键名查找、稀疏数据等场景队列适合需要按顺序处理数据、频繁在两端增删元素的场景如 FIFO 缓冲。常用的数组操作方法for循环bit[31:0]aaa[6];for(inti0;i$size(aaa);i)begin//采用$size返回数组宽度aaa[i]i;endforeach循环foreach(md[i,j])md[i][j]0;//多维数组的下标用逗号隔开放到同一个方括号中返回最大最小值q.min();q.max();去掉重复值q.unique();数组的排序q.reverse();// 翻转q.sort();// 顺序排序q.rsort();// 倒序排序q.shuffle();// 乱序数组中元素的计算q.sum();// 计算数字内元素的和q.product();// 计算数字内元素的积q.and();// 数组内元素与q.or();// 数组内元素或q.xor();// 数组内元素异或元素的查找intlzz[]{6,7,8,6,1,2,9},zz[$]cc;// 下述例子中的item是缺省的名字也可以指定为其他名字zzlzz.findwith(item3);// {6,7,8,6,9},找出大于3的元素zzlzz.find_indexwith(item3);// {0,1,2,3,6},找出大于3的元素的索引zzlzz.find_firstwith(item%60);// {6},找出第一个被6整除的元素zzlzz.find_first_indexwith(item%60);// {0},找出第一个被6整除的元素的索引zzlzz.find_lastwith(item%60);// {6},找出最后一个被6整除的元素zzlzz.find_last_indexwith(item%60);// {3},找出最后一个被6整除的元素的索引cclzz.sum(x)with(x6);// {0,1,1,0,0,0,1} , c3 , sum函数计算时用的是数组元素的位宽注意事项可以采用$isunknown()来检测数据内部是否有X态或者Z态若代码中从一个越界的地址中读取数据那么SV将返回数组元素类型的缺省值。四状态类型的返回X双状态类型的返回0用%p可以打印数组、结构和类等定宽数组声明后大小不可改变访问时需注意下标范围越界访问会返回缺省值四状态返回X双状态返回0动态数组使用前必须调用new[]分配空间否则访问会报错重新分配时若未使用(dyn)复制旧数据原数据会丢失关联数组遍历顺序不固定由内部哈希决定不要依赖遍历顺序删除元素用delete(键)删除整个数组用delete()访问不存在的键会返回缺省值建议先用exists()检查队列push_front/pop_front在头部操作push_back/pop_back在尾部操作性能最优中间位置插入删除性能较差$表示队列边界q[$]取末尾元素q[0]取头部元素数组方法sort/rsort/reverse/shuffle会直接修改原数组sum/product/and/or/xor等归约方法返回结果但不修改原数组find系列方法返回新数组不修改原数组foreach遍历多维数组的下标用逗号隔开放在同一个方括号中如foreach(md[i,j])遍历关联数组时key为键名assoc[key]为对应值数组复制定宽数组和动态数组之间赋值时要求基本数据类型相同且元素数目一致否则可能产生截断或填充队列初始化队列初始化时不需要直接使用q[$] {0,1,6,9};即可 ~ 本节完结 ~
返回列表