数字IC验证——SystemVerilog基本语法

SV和Verilog的语法类似,和C/C++也有些共性,基本SV可包含Verilog的所有规则,本文会在以下博文内容外做补充,若有相异处下文会特意指出。Verilog语法可参考该链接第1大节。链接:https://blog.csdn.net/qq_39815222/article/details/89601331

1. 数据类型

  1. 二值逻辑和四值逻辑
    编码时一定要注意操作符左右两侧的符号类型要一致
    二值逻辑:包括 bit, byte, shortint, int, longint等,均为有符号类型(bit除外);这些类型的值只包含{0,1},目的是模拟计算机验证环境,提高仿真性能,节约空间。若有四值逻辑数给其赋值,x,z会默认被赋值为0,因此二值逻辑数要远离DUT
    四值逻辑:包括logic, integer, reg, wire等,均为无符号变量(integer除外);目的是模拟外部物理世界
  2. logic
    用法既拓展了传统的reg型,也可以像wire那样连线,但既然被应用在验证场景中,因此无需关心对应的逻辑是否被综合为寄存器还是线网,只需作为简单的变量赋值即可。
    注意:当含有多驱动(multi-drive)的场景是必须使用wire型。
  3. 动态数组和联合数组
    int  array[];               //动态数组,compile时长度不确定,simulation时长度确定
    array = new[20];      //new分配空间

    logic [31:0] array[*];    //联合数组,目的是节约空间
  4. 队列
    概念类似C语言里的队列,用法也类似,可自由插入删除数据,
    shortint  queue[$] = { 1,2,3 }
    queue.insert(1,7);    //{1,7,2,3}
    queue.delete(1);      //{1,2,3}
    queue.push_front(6);   //{6,1,2,3}
    queue.push_back(7);   //{6,1,2,3,7}
    j = queue.pop_front;    //{1,2,3,7}    同理pop_back
  5. 结构体
    类似C语言里的结构体,包括概念和用法
  6. 枚举
    enum logic [1:0] {...} state;  //可定义z,x状态

2. 语句

  • 循环语句
    循环语句用于控制执行语句的执行次数,用于在仿真代码中生成仿真激励信号。

for(int i=0; i<=5; i++)...           //for循环,相较于verilog,i可以内部定义,且作为局部变量,作用范围只限于for循环
while(i<5) begin...end    //while循环,同样存在do...while()
foreach(src[i])                //foreach循环,和for功能类似,但foreach多了可编译的功能,及判断条件里可有变量
       src[i] = i;      

  • randomize()
    随机函数

class1 example1 = new;  
if( example1.randomize() == 1)...

  • 一些关键词
  1. automatic... ref...
    用在function/task赋值
    function automatic void f1( ref data )  //此处data和外部定义的data共用同一物理地址,因此两值同时变化
    endfunction                                         //若希望内部值的改变不影响外部值的改变,可在内部定义为const ref data
  2. automatic和static
    automatic变量类似于软件中的局部变量,在它的作用域生命结束时被销毁回收存储空间
    static变量若在仿真开始时被创建,在进程执行过程中自身不会被销毁,且会被多个进程共享。
  3. inside
    if((a==1)||(a==2)||(a==3)) 等价于if( a inside {1,2,3})
  4. time
    描述时间,单位为timescale定义的精度
  5. rand
    rand随机化比较常用
    rand bit [7:0] data1;     //data1值取0-255中的任意数
    randc bit [7:0] data2;   //data2取0-255中任意值,但每次取值都不一样,只限于bit和enum类型
    constraint range1{                       //约束data1范围 
           data1>100; data1<200;
           data1>data2; }         
  6. dist { value1 := weight1   value2 :/ weight2 }
    划分权重,用在随机化操作中
    [1:2]:=40;   //每个数权重都是40
    [1:2]:/40;    //每个数权重是20
  7. solve...before...
    用在随机数产生时,constraint魔窟啊里面
    solve y before x    //先产生x,再产生y
  8. semaphores
    创建对象可复用
  9. mailbox
    创建一个信箱,使通信数据在不同process交换,可理解成fifo
  • 一些符号及搭配
  1. 通配符 .*
    可以把相同名字的net和port连在一起
    test   test1( .a(a), .b(b), .c(c) );      //或者 test   test1( .a, .b, .c );  
    等同于   test t1( .* );
  2. ==? / !=?
    判断符号两边是否像相等或不等,x,z处做通配处理
  3. ++
    SV里面可以用自增符
  4. 'value 赋值
    data0 = 'x                //SV中赋值可无需添加b,o,h等代表进制的符号
    data1 = '1               //SV中可给某个值赋值全1,注意Verilog中不行
  5. int'( value)
    强制类型转换,int也可以是其他数据类型或unsigned,signed
  6. value1'( value2 )
    位宽强制转换,value1是位宽值
  7. ##
    延迟一个时钟周期
  8. |->
    在当前时钟周期

3. 语句块

  • program
    program可以将设计和验证的调度区域通过显式的方式来安排。

该语句块可在module直接被例化,语句块里面不能出现和硬件相关的过程语句和实例(如always,module等),但是可以有initial,task等块,program与二者的关系类似于C语言里的C文件与主函数,子函数的关系。

program内部定义的变量赋值的方式应该采用阻塞赋值,在驱动外部的硬件信号时应该使用非阻塞赋值。
$exit()强制结束该系统函数所在的program

program execute_test
initial begin
...
end
task task1()
...
endtask
endprogram

  • clocking Block
    为了避免冒险竞争,通常会把clk驱动的同步信号封装在一个模块里,由interface调用。
  • interface
    接口作为中间将stimulator / monitor和DUT连接,可以集合多个信号,简化连接,方便调用。
    interface可以包含过程语句(always和initial)和连续赋值语句
    interface可以定义输入输出端口,若接口对不同连接模块的方向不同,可以将端口定义在modpot中

interface signal_test( input bit clk );                //定义
     logic [1:0] A, B;
     logic reset;
    clocking dram @( posedge clk)
           input #1ps A;
           input #5    
           output #6 B;
     endclocking
     modport user1( output A, input  B, reset);  //声明的端口可以在不同的modport里定义为不同的输入输出模式
     modport user2( clocking cb, input reset);    //调用clocking,port输入输出和user1不一样
endinterface

always #5 clk = ~clk;
signal_test.user1  signal1(clk);                     //声明user1模式
signal_temp signal2( .A(signal1.A), ......);     //interface互相直接连接
test test1( signal1 );                                      //interface与module连接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章