西洲渡

一只还没迈入IC领域的小菜鸡

SV系统验证(2)——数据类型和字符串

Verilog中的数据类型

Verilog中有两种基本数据类型:变量类型(variables)、线网类型(wire)
两种类型均为四值逻辑(1、0、X、Z)
真实电路中不存在X,高阻态Z表示引脚悬空

变量类型(variables)

用来储存组合逻辑或者时序逻辑的值

变量类型特点:

  • 变量保存在initial、always、task、function内赋值

  • 变量只能用过程赋值(initial、always)来赋值

    1
    2
    3
    4
    reg            描述逻辑
    integer 描述循环变量和计算
    real 在系统模型中使用
    timerealtime 保存测试装置的仿真时间
  • intger或time的变量一般有相同位数的reg一样运转

其中变量类型包括:reg、integer、time、real等
reg可以被综合成寄存器、锁存器(寄存器是时序逻辑,锁存器是组合逻辑)

线网类型(nets)

用来连接硬件模块,以提供特殊的线网逻辑解决方案

  • 线网在建模结构化描述中连接线路、且总线线网的值由线网的驱动器决定
  • 驱动器可以是门,模块的实例或者连续赋值的输出
  • 只能用连续赋值语句(assign)

其中线网类型包括:wire、wor、wand等

1
2
3
4
5
##在SystemVerilog中任何一个变量要看三部分:##

* 类型(变量、线网)
* 数据类型(四值逻辑、二值逻辑)
* 符号(有符号、无符号)

SyestemVerilog的类型

变量(variables)

  • 可以使用连续赋值(assign)、过程赋值(always)

    logic a :默认变量(var)类型、无符号
    bit a:默认变量(var)类型、无符号
    var logic [63:0] a ; 也可以对其类型声明

线网类型(nets)

  • 只能用连续赋值语句(assign)

    Testbench中一般大量使用logic,只有在多个驱动源或者设计模块端口是双向(inout)的时候才用wire

SystemVerilog的数据类型

四值逻辑(Logic)

  • 在Verilog中reg常用来表示储存组合逻辑或者时序逻辑的变量,不过初学者容易混淆其综合后的硬件单元,实际它只和线网相对,用来表示储存数据的变量
  • 在SV中我们可以直接使用logic来通用储存硬件数据

四值逻辑包括:integer、logic、reg、net-type(wire、tri)

1
2
3
4
什么时候用四值逻辑?
- 在表示硬件时,必须用四值逻辑
- X值用来捕捉设计错误(如寄存器未初始化)
- Z值用来表示未连接或者三态的设计逻辑(但很少出现在系统级或者事务级)

二值逻辑(bit)

  • bit类型可以综合,但综合的电路有失真的可能,无法正确表示电路,因此在RTL中很少用到

二值逻辑包括:bit、byte、shortint、int、longint

1
2
3
什么时候用到二值逻辑?
- 在构建验证环境总线功能模型(BFM)时,无须关注底层逻辑,可使用二值逻辑
- SV在和C语言交互时,也可使用二值逻辑简化数据传输

仿真初值和转换

  • 四值逻辑变至例如reg、logic或者integer等,在仿真开始时的初值为X
  • 二值逻辑变量例如bit等,在仿真开始时的初值为0
  • 四值逻辑 => 二值逻辑(默认转换),那么Z、X => 0

SystemVerilog数据的符号

有符号

  • integer
  • byte
  • shortint
  • int
  • longint

无符号

  • logic、bit、reg、net-type(wire、tri)构成的向量
  • 在有符号类型后面加unsigned(如byte unsigned)

空类型(void)

  • SV添加void类型来表示空类型,表示不会返回数值,同C语言的void使用方法
  • SV添加shortreal表示32位单精度浮点类型,同C语言的loat;而Verilog的real类型表示双精度浮点类型,同C语言的double

自定义类型(typedef)

为了代码更加易读和维护,通常在加上“_t”后缀表示自定义类型

枚举类型(enum)

1
2
enum {red,green,blue}  RGB;
RGB枚举类型拥有三个值,其中初始值为red

Verilog没有枚举类型,因此采用define 和parameter 来定义,提高易读性

  • 枚举值默认为int类型,32-bit的二值逻辑

  • SV允许指定枚举的数据类型

    1
    2
    enum bit {ture,false} ck_t;
    enum logic[1:0] {waite,load,ready} state_e;
  • 如果一个枚举类型的数值被赋值,那么赋值应该符合其数值类型

  • 枚举类型可以转换成整型(隐式),但整型不能转化成枚举类型

自定义枚举类型

1
2
typedef enum {waite,load,ready} state_t; 
state_t state_now,state_next

枚举类型赋值

1
2
3
4
5
6
7
8
9
typedef enum {waite,load,ready} state_t;
state_t state, next_state
int foo;
state=next_state; //legal operation
foo = state + 1; //legal operation
state = foo + 1; //**ERROR:illegal assignment**
state = state + 1; //**illegal operation **
state++; //**illegal operation next **
next_state += state; //**illegal operation**

结构体类型(struct)

  • SV中添加了C一样的结构体struct,其成员可以为自定义类型或其他常量类型
    1
    2
    3
    4
    5
    6
    struct{
    int [31:0] a,b; //32-bit variables
    logic [7:0] opcode; //user-defined type
    logic [23:0] address; //24-bit variable
    bit error; //1-bit 2-state var.
    } Instruction_Word;

结构体默认是一个 变量 ,用户可以将其声明为var或者wire类型

自定义结构体类型

  • 类似于枚举类型,结构体类型也可以使用typedef来定义
    1
    2
    3
    4
    5
    6
    7
    typedef struct {// structure definition 
    logic [31:0] a,b;
    logic [7:0] opcode;
    logic [23:0] address;
    } instruction_word_t;

    instruction_word_t IW;// structure allocation

结构体类型赋值

1
2
3
4
5
6
7
8
9
10
11
12
结构体变量可以通过索引其各个成员做依次的成员赋值:
always @(posedge clock, negedge resetN)
if(!resetN)begin
IW.a=100; //reference structure member
IW.b=5;
IW.opcode=8'hFF;
IW.address=0;
end

也可以通过单分号`和花括号{}来实现整体赋初值:
IW='{100, 3, 8'hFF, 0};
IW='{address:0, opcode:8'hFF, a:100, b:5};

字符串类型

  • Verilog语言对于字符串的处理手段非常有限。
  • SV引入了string类型用来容纳可变长度的字符串。
  • 字符串类型变量的存储单元为byte类型
  • 字符串类型变量长度为N时,其字符成员索引值为从0到N-1.
  • 不同于C函数,字符串结尾**没有“空字符“即null字符“\0”**。
  • 字符串的内存是动态分配的,用户无需担心内存空间管理。

字符串常见使用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef logic[150] r_t;
r_tr;
integer i=1;
string b="";
string a={"Hi",b}; //字符串拼接
r=r_t'(a); //将字符串a内容*显式*转化成字节赋值给r
b=string'(r); //ok
b="Hi"; //oK
b={5{"Hi"}}; //oK
a={i{"Hi"}}; //oK(non-constant replication)
a={i{b}}; //oK
a={a,b}; //ok
a={"Hi",b}; //oK
b={"H",""}; //yields"H".""is the empty string
a[0]="h"; //oK,将字符串第0位赋值为h
a[0]="cough"; //字符串赋值给某一位时,取最后一个即h

字符串的索引是从左到右0 =>N-1
logic [15:0] 索引最右端是0

字符串内建方式

  • 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}:将字符串转化成十进制,十六进制,八进制,或者二进制

附录:数据类型和字符串思维导图