路科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

作者

Gavin

发布于

2022-05-10

更新于

2022-05-10

许可协议

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×