路科V0SV和Verilog的对比总结

Verilog:
变量类型 veriables
四值逻辑
0
1
X
用来捕获设计错误,比如寄存器未初始化
Z
用来表示未连接或者三态的设计逻辑
但是在系统级或者事务级,Z和X很少使用
reg
用来描述 逻辑, integer 用来描述循环变量和计算
reg并不一定要被综合为register,它只是用来与线网类型相对,表示存储数据的变量
integer
和time类似,像有相同位数的reg一样运转,
表达式的integer值作为 有符号数 处理, reg 和 time 作为无符号数处理
time
和realtime类似, 用来保存测试装置的仿真时间
real
在系统模型中使用
realtime
变量类型是保存在initial always task function中赋的值
只能用 过程赋值 来完成
线网类型 nets
四值逻辑
0
1
X
Z
wire
wor
wand
用于建模连接线路,值由 线网驱动器决定
线网驱动器:可以是门或者模块的实例,也可以是连续赋值的输出
SV :
在与C交互时,可以使用二值逻辑使接口参数更加简单, 因为构建验证驱动组件时,不关注硬件底层逻辑X,Z
硬件信号
类型
变量 var
线网类型 wire
数据类型
四值逻辑 logic
构成的vector都是无符号类型
用来表示通用的存储硬件数据
####### logic resetN; // 1位宽的四值逻辑
####### logic [63:0] data; // 64位宽的变量
####### logic [0:7} array [0:255]; // 由8位向量元素构成的数组
虽然只表示数据类型,但是在声明时,会默认表示为变量var,用户可以显式声明其类型
####### var logic [63:0] addr; // 64位宽的变量类型
####### wire logic [63:0] data; // 64位宽的线网类型
二值逻辑 bit
帮助更高级抽象的建模,比如,事务级模型
####### bit : 1位二值逻辑变量
构成的vector是无符号类型
####### byte : 8位二值逻辑,类似于C语言中的char
####### shortint : 16位,类似short
####### int : 32位,类似int
####### longint : 64位,类似longlong
bit类型默认也是变量类型,
除了bit的其他二值逻辑类型的verctor,默认都是有符号类型
可以使用unsighed表示无符号类型, 比如 byte unsigned
####### 表示的范围从[-128, 127], 变为了[0, 255]
自定义类型
优势
可以用更少的代码表示更多的功能
代码可读性更好
通过typedef创建用户自定义类型
通过enum创建枚举
通过struct创建结构体类型
Verilog无法使用户扩展变量和线网类型
SV提供的自定义类型使用户构建更高层次抽象的数据类型
比如: typedef int unsigned uint; uint a, b;
一般对自定义类型加个_t后缀
enum枚举
每个值都要一个用户自定义的名字,比如枚举类型RGB
enum {red, green, blue} RGB;
Verilog没有枚举,为了提供描述变量的范围,使用参数来表示可取值的范围,或者宏定义定义各个合法值的名称
定义枚举值
默认为int,32位二值逻辑
但是,SV也允许指明数据类型,比如: enum bit {TRUE, FALSE} Boolean; enum logic [1:0] {WAITE, LOAD, READY} state;
如果枚举类型被赋值,那么所赋值应该在其数据范围内 enum logic [2:0] {WAITE = 3’b001, Load = 3’b010, READY = 3’b100} state;
如果枚举变量是四值逻辑,那么赋值为X或者Z也是合法的 enum logic {ON=1’b1, OFF=1’bz} out;
自定义枚举类型
如果枚举类型没有伴随typedef,那么该枚举类型是个匿名枚举类型
将它typedef为自定义类型,就可以用同一个枚举类型来声明多个变量或者线网 typedef enum {WAITE, LOAD, READY} state_t; state_t state next_state;
枚举类型赋值
赋值要求很严格,=两端必须是相同的枚举类型;
int foo; states_t state; foo = state + 1; // 可以 state = foo +1; // 不可以 state = states_t’(foo+1); // 可以
state++; //不可以 state= state + 1; //不可以 state = states_t’(state+1); // 可以
struct 结构体
优势
经常遇到数据表示逻辑相关的数据信号组,比如总线协议的所有控制信号,或者在状态控制器中用到的所有信号,verilog不方便
SV的结构体,成员可以是任意变量类型,包括自定义和其他常量类型
struct {
int a,b; opcode_t opcode; logic [23:0] address; bit error; } Instruction_Word;
结构体是变量的合集,所以结构体的变量一可以索引到其内部,用.符号,和C一样
Instruction_Word.address = 32’hF000001E;
结构体类型默认为变量类型,用户也可以显式声明为var或者wire
结构体也可以typedef为自定义类型,然后使用
typedef struct { …; …; } instruction_word_t; instruction_word_t IM;
可以通过索引到成员,依次赋值
也可以通过分号’和花括号{}实现整体赋值
IW = ‘{100, 3, 8’hFF, 0};
IW = ‘{address:0, opcode:8’hFF, a:100, b:5};
字符串类型
优势
Verilog没有string,SV引入string容纳可变长度的字符串
string类型的存储单元为byte类型,即char
在string变量长度为N时,索引是0到N-1
和C的差别
字符串结尾没有\0
内存动态分配,用户不需要担心内存管理
使用
typedef logic [15:0] r_t;
r_t r; integer i = 1; string b = “”; string a = {“Hi”, b}; r = r_t’(a); b = string’(r); b = “Hi”; b = {5{“Hi”}}; a = {i{“Hi”}}; //可以,非常量复制 a = {a, b}; a = {“Hi”, b}; b = {“Hi”, “”}; a[0] = “h”;
内置函数
str.len() 返回string的长度
str.putc(i, c) 将第i个字符替换为字符c,等同于 str[i] = c
str.getc(i) 返回第i个字符
str.substr(i, j) 返回第i个字符到第j个字符
另外,SV有其他的系统函数
####### $sformatf() 用来生成一个格式化的字符串
####### $display() 打印输出
接口
优势
Verilog通过模块之间的端口连接,进行模块间的通信,但是大型设计,端口连接很容易出错,所以,SV扩展了接口interface
接口提供了面向抽象级建模的方式
可以简化建模和验证大型复杂的设计
尤其是标准总线端口,Verilog需要在多个模块重复声明,通信协议也是多次定义,变更之后的更改也很麻烦
接口允许多个信号被整合到一起,用于表示单一的抽象端口
多个模块可以使用同一个接口,避免分散端口信号连接
内容
interface main_bus;
…; …; endinterface
main_bus bus(); // 接口实例
接口不止可以包含 变量或者线网,还可以封装模块之间通信的协议
还可以嵌入与协议有关的断言检查、功能覆盖率收集等模块
接口不同于模块的地方在于,接口不允许包含设计层次,即接口无法例化模块,但是接口可以例化接口
可以在接口的声明modport,来约束不同模块连接时信号灯方向
声明
接口定义和模块定义类似
也可以有端口,例如外部接入的时钟或者复位信号;
interface main_bus (input logic clock, resetN, test_mode);
例化
接口的例化方式和模块的例化方式一致
模块的端口如果声明为input、output、inout,那么在例化时可以不连接
模块的端口如果声明为interface,那么在例化时必须连接到一个接口的实例,或者另一个接口端口
如果一个模块拥有一个接口类型的端口,那么索引这个接口中的信号,需要通过.操作符,
bus.resetN
modport
接口的线网信号或者变量,对于连接到这个接口的不同模块可能有不同的连接方向,所以引入modport表示不同模块看到同一组信号时的视角方向
在接口中声明modport,需要指名modport中各个信号灯方向
当一个模块在例化时,可以选择连接到interface端口中具体的某一个modport
这种方式可以降低连接方向错误的可能,避免信号多驱动的情况
interface chip_bus(…);
modport master(...);
modport slave(…); endinterface
module primary(interface pins); //通用接口端口 … endmodule
module secondary (chip_bus pins); // 特定接口端口 … endmodule
module chip (…); chip_bus bus(..); // 接口实例 primary i1 (bus.master); // 使用master modport方式 secondary i2(bus.slave); // 使用slave modport方式 endmodule
应用
利用接口,可以将测试平台和DUT连接在一起
总结
接口对于设计复用很有利
接口减少了模块之间错误连接的可能性
如果添加了新的信号,只需要在接口中声明,不需要在每个模块中声明
由于接口可以将有关信号都集合在一起,可以在使用这些信号时,需要添加接口实例名
一种接口往往将有关信号集合在一起,因此,对于拥有多组不相关信号的设计而言,需要多个接口才能完成与其他模块的连接
其他注意点:
四值逻辑,比如reg、logic、integer,在仿真开始时的初始值为X
二值逻辑bit在仿真开始的初值为0
如果四值逻辑和二值逻辑发生转换,则把X和Z都转为0
二值逻辑也可以实现可综合电路,但是由于没有X、Z,可能出现仿真行为和综合电路的结果不一致的情况
SV中还新增了void类型,用于在函数定义时表示无返回值,同C
SV中添加了shortreal表示32位单精度浮点数,同float;
而verilog中的real表示双精度浮点型,同double
路科V0SV和Verilog的对比总结
https://dustofstars.github.io/IC验证/路科V0/路科v0sv和verilog的对比总结/