本章介绍SystemVerilog引入的新数据类型。绝大部分是可综合的,并会使代码更简洁易懂。
整数和实数类型(Integer and Real Types)
SystemVerilog引入了几种新的数据类型。大部分和C编程类似。主要考虑的是,如果两种语言有相同的数据类型,那么C语言建模的算法,可以更简便地转化到SystemVerilog。
Verilog的变量类型是4态的:每一位代表0,1,X或者Z。SystemVerilog引入2态类型,每一位代表0或者1。在不需要X和Z态时,你可以使用这些新类型,比如在Test Bench和For循环中用到的变量。使用2态变量可以提高仿真器效率。使用恰当,不会影响综合结果。
类型 | 描述 | 举例 |
---|---|---|
bit | 用户定位宽度 | bit [3:0] a_nibble; |
byte | 8位宽,有符号 | byte a,b; |
shortint | 16位宽,有符号 | shortint c,d; |
int | 32位宽,有符号 | int i,j; |
longint | 64位宽,有符号 | longint lword; |
类型 | 描述 | 举例 |
---|---|---|
reg | 用户定位宽度 | reg [7:0] a_byte; |
logic | 和reg相同 | logic [7:0] a_byte; |
integer | 32位宽,有符号 | integer i,j,k; |
logic 比reg更推荐,因为它可以用来替换reg或者wire。(除了inout类型,必需用wire)
类型 | 描述 | 举例 |
---|---|---|
time | 64位宽 | time now; |
shortreal | 类似C语言float | shortreal f; |
real | 类似C语言double | real g; |
realtime | 和real相同 | realtime now; |
数组(Arrays)
在Verilog-1995中,你可以定义标量和向量的线网或者变量。你也可以定义memory数组,包含变量类型的一维数组。到了Verilog-2001,允许定义多维包含线网或者变量的数组,并且取消了一些数组使用的限制。
SystemVerilog在此基础上又进了一步,优化了数组并允许更多的操作。
在SystemVerilog,数组可以包含紧凑维度(packed)或者非紧凑维度(unpacked)。看下面这个例子:
reg [3:0] [7:0] register [0:9];
紧凑维度是[3:0]和[7:0],非紧凑维度是[0:9].
紧凑维度:
- 确保在内存中连续存放
- 可以被复制到任意其他紧凑对象
- 可以被切片(部分选中)
- 限定于位类型(bit, logic, int等),部分固定位宽类型(int等)
相反,非紧凑维度由仿真器在内存中任意安放。你可以可靠地复制到同类型的其他数组。对于有不同数据类型的数组,你必须使用类型转换,根据规则转化非紧凑型到紧凑型。非紧凑型数组可以包含任意数据类型,比如说real。
SystemVerilog允许一系列针对纯完全非紧凑型数组的操作。对于数组或者切出来的数组,必须具备相同的数据类型和形状。紧凑维度可能不一样,只要数组或者切片元素具备相同的位宽。
允许的操作包括:
- 读写数组
- 读写切片数据
- 读写数组元素
- 数组,切片,元素的关系
SystemVerilog还包括动态数组(元素数目可能会在仿真过程中改变)以及联合数组(具备非连续范围)。
为了支持上述数组类型,SystemVerilog包含一系列的数组查询函数和方法。比如说,你可以用$dimensions来确认数组的维数。
类型定义(Typedef)
SystemVerilog的数据类型体系允许自定义数据类型。为了使代码简洁,引入了类型定义(typedef)机制。类型定义允许用户为他们常用的类型创建类型名。类型定义在运用到涉及复杂数组部分非常方便。
typedef reg [7:0] octet;
octet b;
等效于
reg [7:0] b;
typedef octet [7:0]
quadOctet;
quadOctet qBytes [1:10];
等效于
reg [3:0] [7:0] qBytes [1:10];
枚举类型(Enum)
SystemVerilog也引入了枚举类型,比如下面
enum{circle, ellipse, freeform} c;
枚举类型允许你定义一种值和名字对应的数据类型。这种类型在表示状态机,操作码等非数字的数据类型时非常有用。
类型定义经常与枚举类型一起使用,比如:
typedef enum {circle, ellipse, freeform} ClosedCurve;
ClosedCurve c;
枚举类型中的名字类似常数。默认类型是int。你可以在相同类型之间复制,比较等。枚举类型是强定义类型,不能给一个枚举变量直接复制数字,除非用类型转换。
c = 2; // ERROR
c = ClosedCurve' (2); // Casting - ok
然而,当你在表达式中使用枚举类型,实际上这些值和整形是等价的。比如说,你可以用枚举类型和一个整形比较,也可以在一个整形的表达式中使用枚举类型。
结构体和联合体(Struct and Union)
最后,SystemVerilog还引入了结构体(Struct)和联合体(Union)数据类型,和C语言类似:
struct {
int x, y;
} p;
结构体的成员可以用名字索引:
p.x = 1;
结构体赋值可以用花括号:
p = `{1, 2};
常用的方式是用类型定义声明一种新的类型,然后再用新类型声明变量。结构体也可以是紧凑的。
typedef struct packed {
int x, y;
} Point;
Point p;
联合体在硬件资源方面用的较多。