1. SestemVerilog概述
1.1 发展历史
2. 数据类型
2.1Verilog的数据类型
Verilog语言提供两种基本的数据类型,即变量类型(variables)和**线网类型(nets)**,==这两种类型都是四值逻辑==,即可表示0、1、X和Z值。
- 变量类型(variables)
- 变量类型保存在initial、always、task 和function内赋的值。变量只能用过程赋值来赋值。
- 类型是integer 或time的变量一般像有相同数量位数的reg—样运转。
- 在表达式中integer的值作为有符号数处理,而reg或time的值作为无符号数处理。
- 用reg描述逻辑,integer 描述循环变量和计算,real在系统模型中使用,time和realtime保存测试装置的仿真时间。
- 线网类型(nets)
- 线网用于建模结构化描述中的连接线路和总线线网的值由线网的驱动器决定。
- 驱动器可以是门或模块的实例或者连续赋值的输出。
2.2 SystemVerilog新添加的数据类型
- Verilog并没有严格区分信号的类型,变量和线网类型均是四值逻辑。SV添加了许多新的数据类型来帮助设计和验证工程师。
- SV将硬件信号区分为
类型
和数据类型
类型
即表示该信号为变量(variables)或者**线网类型(nets)**。- 对于变量类型赋值可以使用连续赋值、或者过程赋值。
- 对于线网类型赋值只能使用连续赋值语句(assign) 。
数据类型
则表示该数据是四值逻辑(logic)还是二值逻辑(bit) 。
- TIPS
避坑指南:简而言之,你可以在testbench (module)中大量使用logic类型变量,而很少使用wire。什么时候需要wire呢?多于一个驱动源的时候,或者设计模块端口是双向( inout)的时候。
2.3 四值逻辑数据类型
- 在Verilog中,reg经常用来表示存储组合逻辑或者时序逻辑的变量,不过初学者容易混淆其综合后的硬件单元。实际上,reg并不一定会被综合为register,而它只是用原来与线网类型相对,表示存储数据的变量。
- 在SV中,我们可以直接使用logic(数据类型)来达到==通用的存储硬件数据==的目的
logic resetN; //l a 1-bit wide 4-state variable
logic [63:0] data; //a 64-bit wide variable
logic [0:7] array [0:255]; // an array of 8-bit variables
- logic虽然只是表示数据类型,而在声明时,它==默认会表示变量类型(variable)==,用户也可以显示声明其类型
var logic [63:0] addr; //a 64-bit wide variablewire
wire logic [63:0]data; //a 64-bit wide net
2.4 二值逻辑数据类型
SV添加了二值逻辑数据类型,用来对在RTL更高抽象级的模型建模,例如系统级或者事务级模型
- 二值逻辑数据类型
- bit
a 1-bit 2-state integer //==双状态,单比特== - byte
an 8-bit 2-state integer,similar to a c char //==双状态,8比特有符号整数== - shortint
a 16-bit 2-state integer,similar to a c shortint : a 32-bit 2-state integer, similar to a c int //==双状态,16比特有符号整数== - longint
a 64-bit 2-state integer,similar to a c longlong //==双状态,64比特有符号整数==
- bit
- 在RTL级别,X值用来捕捉设计错误,例如寄存器未初始化,Z值用来表示未连接或者三态的设计逻辑,但是在系统级或者事务级,Z和X很少被使用。
- 类似于logic类型默认为变量类型,bit类型默认也为变量类型。
2.5 有符号类型和无符号类型
- logic或者bit构成的向量(vector)是无符号类型。
- integer、byte、shortint、int、longint为有符号类型。可以在有符号类型后添加unsigned来表示无符号类型
title: 示例
byte有符号类型,表示的数值范围是[-128,127]。
byte unsigned表示无符号类型,等同于bit[7:0],表示的数值范围是[0,255]。
- 在构建验证环境总线功能模型(BFM,Bus-Functional Model)时,无需关注硬件底层逻辑(X或者Z值),所以可使用二值逻辑实现。
- 同样,SV在与C发生语言交互时,也可以使用二值逻辑来使得两种语言的边界数据传输更为简单。
2.6 内建数据类型
- 按照四值逻辑的类型和二值逻辑的类型划分
- 四值逻辑类型: integer、logic、reg、net-type(例如wire、tri)
- 二值逻辑类型: byte、shortint、int、longint、bit
- 按照有符号和无符号的类型进行划分
- 有符号类型: byte、shortint、int、longint、integer
- 无符号类型: bit、logic、reg、net-type(例如wire、tri)
2.7 仿真行为
- 四值逻辑变量例如reg、logic或者integer等,在仿真开始时的初值为X。
- 二值逻辑变量例如bit等,在仿真开始时的初值为0。
- 如果四值逻辑与二值逻辑的数据类型之间发生的默认转换,那么Z和X值将转换为0。
- 二值逻辑也可以用来实现可综合电路,只是二值逻辑由于没有X和Z值,因此可能会出现仿真行为同综合电路结果不一致的情况。
2.8 其他类型
- SV添加void类型来表示空类型,经常用在函数定义时表示不会返回数值,同C语言的void使用方法。
- SV添加shortreal表示32位单精度浮点类型,同C语言的float;而Verilog的real类型表示双精度浮点类型,同C语言的double.
3. 自定义类型
通过用户自定义类型,以往Verilog的代码将可以通过更少的代码来表示更多的功能。用户自定义类型使得代码自身的可读性更好。
3.1 通过typedef
来创建用户自定义类型。
Verilog不允许用户定义新的数据类型。SystemVerilog通过使用typedef提供了一种方法来定义新的数据类型。
typedef int unsigned uint;//uint为int undesign的指代
uint a, b;
3.2 通过enum
来创建枚举类型。
枚举类型(enum)提供方法来描述抽象变量的合法值范围,其每一个值都需要提供一个用户自定义的名字。
- 默认的枚举类型是int,即32位的二值逻辑数据类型
- 为了能够更准确地描述硬件,SV允许指明枚举类型的数据类型,例如:
![[Pasted image 20220920173106.png|500]] - 如果一个枚举类型数值被赋值,那么所赋的值必须符合其数据类型。
![[Pasted image 20220920173149.png|400]]
如果枚举类型是四值逻辑数据类型,那么对枚举值赋为X或者Z也是合法的。
![[Pasted image 20220920173240.png|400]] - 自定义枚举类型
- 枚举类型也可以声明为自定义类型,这就使得可以用同一个枚举类型来声明多个变量或者线网.
![[Pasted image 20220920173452.png|500]] - 如果枚举类型并没有伴随着typedef,那么该枚举类型指的则是一个匿名枚举类型(anonymous enumerated type)。
- 枚举类型赋值时则相对严格,例如下面的例子中,赋值操作符”=“的左右两侧应该尽量为相同的枚举类型。
![[Pasted image 20220920173624.png|500]]
- 枚举类型也可以声明为自定义类型,这就使得可以用同一个枚举类型来声明多个变量或者线网.
3.3 通过struct
来创建结构体类型。
Verilog语言没有方便的特性可以将相关的信号收集整理到一个信号组中。SV添加了同C一样的结构体struct,而结构体的成员可以是任何变量类型,包括自定义类型或者其它常量类型。
![[Pasted image 20220920173802.png|500]]
- 结构体类型的变量可以用来索引到其内部的变量,索引方式同C语言一致
![[Pasted image 20220920173912.png|500]] - 结构体类型默认也是变量类型,用户也可以显示声明其为var或者wire类型。
- 自定义结构体类型
![[Pasted image 20220920174028.png|500]] - 赋值
结构体变量可以通过索引其各个成员做依次的成员赋值,也可以通过分号′和花括号{}来实现整体赋初值:
![[Pasted image 20220920174212.png|500]]
4. 字符串类型
4.1 概述
- 默认的枚举类型是int,即32位的二值逻辑数据类型。为了能够更准确地描述硬件,SV允许指明枚举类型的数据类型
- 字符串类型变量的存储单元为byte类型。
- 字符串类型变量长度为N时,其字符成员索引值为从O到N-1.
- 不同于C函数,字符串结尾没有”空字符”即null字符”\O”。
- 字符串的内存是动态分配的,用户无需担心内存空间管理。
4.2 字符串内建方法
- str.len():返回字符串的长度。
- str.putc(i, c):将第i个字符替换为字符c,等同于str[i]=c。
- str.getc(i):返回第i个字符。
- str.substr(i, j):将从第i个字符到第j个字符的字符串返回。
- str.{atoi(), atohex(), atooct, atobin}:将字符串转变为十进制、十六进制、八进制或者二进制数据。
5. 问答题
- 在状态机或者组着电路中的case语句中的default分支或者if-else if-else中的else分支语句,有时会把变量赋值为’×’,这实际上只会影响仿真,但对综合电路不会产生影响,试问这么做是为什么?不影响电路综合可能是由于什么原因?
- 四值逻辑的数据类型应该在哪些地方声明,例如硬件部分,还是软件部分,或者是其它结构中?为什么需要这么做?
四值逻辑的数据类型用于表征硬件电路,信号共有4种状态”0、1、x、z”,分别表示低电平、高电平、不确定态和高阻态。采用四值逻辑可以表征电路中不稳定的状态或者无驱动状态。如果用二值逻辑表示硬件电路,尽管能综合但综合电路与实际电路有出入,建模过程中存在失真问题。通常二值逻辑用于较高抽象级的模型建模,四值逻辑用于较低抽象级。 - 在处理枚举类型变量和整形变量的相互赋值情况中,应该注意哪些容易出错的地方?在从整形到枚举类型转换的过程中,有哪些方法?