systemverilog第⼆章翻译
第⼆章数据类型
和Verilog相⽐,System Verilog提供了很多改进的数据结构,虽然其中的部分结构最初是为设计者创建的,但对于测试者也同样有⽤,本章将介绍这些对验证很有⽤的数据结构。字符串数组怎么转成byte
System Verilog引进了⼀些新的数据类型,它们具有如下优点。
1)双状态数据类型:更好的性能,更低的内存消耗。
2)队列、动态和关联数组:减少内存消耗,⾃带搜索和分类功能。
3)类和结构:⽀持抽象数据结构。
4)联合和合并结构:允许对同⼀数据有多种视图(view)。
5)字符串:⽀持内建的字符序列。
6)枚举类型:⽅便代码编写,增加可读性。
2.1内建数据类型
Verilog-1995有两种基本的数据类型:变量和线⽹(net)。它们各⾃都可以有4个取值:0,1,Z和X。RTL代码使⽤变量来存放组合和时序值。变量可以是单bit或多bit的⽆符号数(reg[7:0]m),32bits的有符号数(integer),64bits的⽆符号数(time)或浮点数(real)。若⼲变量可以被遗弃存放到定宽的数组⾥。所有的存储都是静态的,意味着所有的变量在整个仿真过程中都是存活的,⼦程序(routine)不能通过堆栈来保存形式参数和局部变量。线⽹可以⽤来连接设计当中的不同部分,例如门和模块实例。⼤多数设计者使⽤标量或⽮量wire来连接各个设计模块的端⼝。
System Verilog增加了很多新的数据类型以便同时帮助设计和验证⼯程师。
2.1.1 逻辑(logic)类型
在Verilog中,初学者经常分不清reg和wire。应该使⽤哪⼀个来驱动端⼝?怎么连接不同的模块?System Verilog对经典的reg 数据类型进⾏了改进,使它除了作为⼀个变量以外还可以被连续赋值、门单元和模块所驱动。为了区别reg类型,这种改进的数据类型叫做logic。任何使⽤wire的地⽅均可使⽤logic,但要求logic不能有多个结构性的驱动,例如在对双向总线建模的时候。此时需要使⽤wire类型,例如wire,System Verilog会对多个数据来源进⾏解析后确定终值。例2.1展⽰了logic类型在System Verilog中的使⽤。
2.1.2 双状态数据类型
相⽐四状态数据类型,System Verilog引⼊的双状态数据类型有益于提⾼仿真器的性能并减少内存使⽤量。最简单的双状态数据类型是bit,是⽆符号的。另四种带符号的双状态的数据类型是byte,shortint,int和longint,如例2.2所⽰。
把双状态变量连接到被测设计,如果被测设计试图产⽣X或Z,这些值会被转换成双状态值,⽽测试代码可能永远⽆法察觉。这些值被转换成了0还是1不重要,重要的是要随时检查未知的值得传播。使⽤($isunknown)操作符,可以在表达式的任意位置出现X或Z 时返回1,如例2.3所⽰。
使⽤格式符%0t和参数$time可以打印出当前的仿真时间,打印的格式再$timeformat()⼦程序中指定。3.7节有关于时间值的详细介绍。
2.2 定宽数组
相⽐于Verilog-1995中的⼀维定宽数组,System Verilog提供了更加多样的数组类型,功能也⼤⼤增强了。
2.2.1 定宽数组的声明和初始化
Verilog要求在声明中必须给出数组上下界限,因为⼏乎所有数组都使⽤0作为索引下届,所以System Verilog允许只给出数组宽度的便捷声明⽅式,跟C语⾔类似。
可以通过在变量名后⾯指定维度的⽅式来创建多维定宽数组,例2.5创建了⼏个⼆维的整数数组,⼤⼩都是8⾏4列,最后⼀个元素的值被设置为1.多维数组在Verilog-2001中已经引⼊,但这种紧凑型声明⽅式却是新的。
如果代码试图从⼀个越界的地址中读取数据,那么System Verilog将返回数组元素类型的缺省值。即对于⼀个元素为4状态类型的数组。例如logic,返回的是X,⽽对于双状态类型如int或bit则返回0。这适⽤于所有数组类型,包括定宽数组、动态数组、关联数组和队列,同时适⽤于地址中含有X或Z的情况。wire在没有驱动的时候输出是Z。
很多System Verilog仿真器在存放数组元素时候使⽤32bit的字边界,所以byte,shortint 和int都是存放在⼀个字中,⽽longint 则存放到两个字中。
如例2.7所⽰,在⾮合并数组中,字的低位⽤于存放数据,⾼位则不使⽤。图2.1所⽰的字节数组b_unpack被存到三个字的空间
⾥。如图2.1所⽰。
仿真器通常使⽤两个或两个以上的连续字来存放logic和integer等4状态类型,这会⽐存放双状态变量多占⽤⼀倍的空间。
2.2.2 常量数组
例2.8,2.9说明了如何使⽤常量数组,即⼀个单引号和⼤括号来初始化数组,可以⼀次性为数组的部分或所有元素赋值。在⼤括号前标上重复次数可以对多个元素重复赋值,还可以为那些没有显式赋值的元素制定⼀个默认值。
2.2.3 基本的数组操作for和foreach
操作数组的最常见⽅式是使⽤for或foreach循环。在例2.10中,i被声明为for循环内的局部变量。System Verilog的$size的函数返回数组的宽度。在foreach循环中,只需指定数组名并在后⾯的⽅括号中给出索隐变量,System Verilog便会⾃动遍历数组中的元素。索引变量就会⾃动声明,只在循环内有效。
注意在例2.11中,对多维数组使⽤foreach语法可能与设想不同。使⽤时并不像[i][j]这样把每个下标分别放在不同的⽅括号⾥,⽽是⽤逗号隔开后放在同⼀个⽅括号⾥,如[i,j]这种形式。
例2.11的输出结果如例2.12所⽰
如果不需要遍历数组中的所有维度,可以在foreach循环⾥忽略掉它们。例2.13把⼀个⼆维数组打印成⼀个⽅形的阵列。他在外层循环中遍历第⼀个维度,然后再内层循环中遍历第⼆个维度。
例2.13的输出结果如例2.14所⽰。
最后要补充的是,foreach循环会遍历原始声明中的数组范围。数组f[5]等同于f[0: 4],⽽foreach(f[i])等同于for循环形式
for(inti=0;i<=4i++)。对于数组rev[6:2]来说,foreach(rev[i])语句等同于for(inti=6; i>=2;i--)。
2.2.4 基本的数组操作—复制和⽐较
我们可以在不使⽤循环的情况下对数组进⾏聚合⽐较和复制,其中,⽐较只限于等于⽐较和不等于⽐较。例2.15列出了⼏个⽐较的例⼦。操作符?:是⼀个袖珍型的if语句,在例2.15中,⽤来对两个字符串进⾏选择。例⼦最后的⽐较语句使⽤了数组的⼀部分,src[1:4],他实际产⽣了⼀个有4个元素的临时数组。
对数组的算术运算不能使⽤聚合操作,应该使⽤循环,如加法运算等。对于逻辑运算,如异或运算等,只能使⽤循环或2.2.6节中描述的合并数组。
2.2.5 同时使⽤位下标和数组下标
在Verilog-1995中⼀个很不⽅便的地⽅就是数组下标和位下标不能同时使⽤。Verilog-2001对定宽数组取消了这个限制。例2.16打印出数组的第⼀个元素(⼆进制101)、它的最低位1,⾼两位⼆进制10。
虽然这个变化并不是System Verilog新增加的,但可能有很多使⽤者并不知道Verilog-2001中的这个有⽤的改进。
2.2.6 合并数组
对某些数据类型,我们希望可以作为⼀个整体访问,也可以分解成⼩单元。如:⼀个
32bits的寄存器,有时候希望可以看成4个8bits的数据,有时希望可以看成单个的⽆符号数据。System Verilog的合并数组就可以实现这个功能,既可以作为数组,⼜可以作为单独数据。与合并数组不同的是,它的存放⽅式是连续的bit集合,中间没有任何闲置空间。
2.2.7 合并数组的例⼦
声明合并数组时,合并的位和数组⼤⼩作为数据类型的⼀部分必须在变量名前⾯指定。数组⼤⼩的定义格式必须是[msb:lsb],⽽不是[size]。例2.17中的变量bytes是⼀个有4个字节的合并数组,使⽤单独的32bits的字来存放。如图2.2所⽰。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论