其他分享
首页 > 其他分享> > SystemVerilog基本语法

SystemVerilog基本语法

作者:互联网

SV在线仿真平台:https://www.edaplayground.com

注:平台需机构邮箱注册,还支持Perl、python等脚本语言以及UVM验证。

1.数据类型

       
 1 program automatic assoc_test();
 2   int assoc[string];
 3 
 4   initial begin
 5     assoc["super"] = 1;
 6     assoc["special"] = 2;
 7     assoc["offer"] = 3;
 8     
 9     foreach(assoc[i]) begin  
10       $display("assoc[%s] = %0d", i, assoc[i]);
11     end
12   end
13 endprogram
14 //result:assoc[offer]=3, assoc[special]=2, assoc[super]=1
       实际项目中,经常需要打包(pack)和解包(unpack)数据。其实这些操做可以通过流操作符简单的实现。
 1 module test;
 2   function void pack_array_int(const ref bit[7:0] array[4],     output int a);
 3     a = {<<byte{array}};
 4   endfunction
 5 
 6   bit[7:0] array[4] = '{ 8'h8C, 8'h00, 8'hA4, 8'hFF };
 7   int pack_result;  
 8   
 9   initial begin
10     pack_array_int(array, pack_result);
11     
12     $display("The result is 0x%h", pack_result);
13   end     
14 endmodule

       

  注意,此处的 const ref是为了避免子程序对数组的改变。ref是对数组直接的引用,避免子程序需要拷贝数组,从而释放仿真器的压力。

另一个实例是,项目中会涉及的大小端(big endian,little endian)的转换,且需要将数据解包。

 1 module test;
 2   function void unpack(bit[127:0] big_endian_data, output bit[63:0] little_endian_array[2]);
 3     bit[127:0] temp;
 4     temp = {<<byte{big_endian_data}};
 5     for(int i=0; i<2; i++) begin
 6       little_endian_array[i] = temp[63:0];
 7       temp = temp >> 64;
 8     end
 9   endfunction
10 
11   bit[127:0] big_endian_data = 128'h1122334455667788_aabbccddeeff1122;
12   bit[63:0] little_endian_array[2]; 
13   
14   initial begin
15     unpack(big_endian_data, little_endian_array);
16     
17     foreach(little_endian_array[i]) begin
18     $display("The result is 0x%h",little_endian_array[i]);
19     end
20     
21   end     
22 endmodule

  该实例实现了将一个16byte的大端数据(big endian)转换为小端数据后,unpack成为2个64bit的数组:output bit[63:0] result[2]。

注:使用bit而不是byte是因为byte是有符号数,可能会引起产生负数。所以实际验证中一般使用bit。

      

 

2.过程语句和子程序

3.连接设计和测试平台

interface my_if(input logic clk, input logic rst_n);
    logic valid, ready;
endinterface
interface my_if(input logic clk, input logic rst_n);
    logic valid, ready;
    modport DRIVER(input clk, rst_n, ready, output ready);
    modport MONITOR(input clk, rst_n, valid, ready);
endinterface

//using interface.MONITOR
module my_dut(my_if.MONITOR vif);
    ...
endmodule
interface my_if(input logic clk);
    logic valid, rst_b, ready;
    clocking drv_cb@(posedge clk);
        input ready;
        output valid;
    endclocking
endinterface
       

4.面向对象编程基础

class transaction;
    logic data[100];
    
    function new();
        foreach(data[i]) begin
            data[i] = 2*i;
        end
    endfunction
endclass

transaction tr;//声明句柄
tr = new();//为对象开辟地址空间
class transaction;
    static int count=0;
    int id;
    function new();
        id = count++;
    endfunction
endclass

transaction tr1, tr2;
tr1=new();//id=0,count=1
tr2=new();//id=1,count=2
 1 class transaction;
 2     static int count=0;
 3     int id;
 4     int addr, data;
 5     statistics stats;//另一个类,内有成员变量int starttime
 6     
 7     function new();
 8         stats = new();
 9         id = count++;
10     endfunction
11 endclass
12 
13 //shallow copy
14 transaction src, dst;
15 initial begin
16     src = new();
17     src.stats.starttime = 30;
18     dst = new src;
19     dst.stats.starttime = 90;//同时src.stats.starttime也变成了90
20 end 
21 
22 //deep copy
23 class transaction;
24     static int count=0;
25     int id;
26     int addr, data;
27     statistics stats;//另一个类,内有成员变量int starttime
28     
29     function new();
30         stats = new();
31         id = count++;
32     endfunction
33     
34     function transaction copy();
35         copy = new();
36         copy.addr = addr;
37         copy.data = data;
38         copy.stats = stats.copy();//类statistics内部也需要维护一个复制函数
39         id = count++;
40     endfunction
41 endclass

5.随机化

 1 class packet;
 2     rand bit [7:0] data;
 3     randc int count;
 4     constraint count_cons {count>10;count<15;}//约束是声明性语句,需要用到{}
 5 endclass
 6 
 7 //创建一个对象并对其进行随机化
 8 packet pkt;
 9 initial begin
10     pkt = new();
11     assert(pkt.randomize())
12     else $fatal(0, "packet::randomize failed!");
13 end
rand int src, dst;
constraint src_dst_cons{
    src dist{0:=40,[1:3]:=60};
  //src=0,weight=40/220
  //src=1,weight=60/220
  //src=2,weight=60/220
  //src=3,weight=60/220
    
    dst dist{0:/40,[1:3]:/60};
    //dst=0,weight=40/100
   //dst=1,weight=20/100
    //dst=2,weight=20/100
    //dst=3,weight=20/100
}
 1 rand int a, low, high;
 2 const int array[5]='{1,3,5,7,9};
 3 rand bit [6:0] b;
 4 rand bit [5:0] c;
 5 rand int d;
 6 constraint a_cons {a inside [low:high];}//low<=a<=high
 7 //constraint a_cons {!(a inside [low:high]);}//a<low||a>high
 8 constraint b_cons {b inside {[$,4],[20:$]};}//(0<=b<=4)||(20<=b<=127)
 9 constraint c_cons {c inside {[$,2],[20,$]};}//(0<=c<=2)||(20<=c<=63)
10 constraint d_cons {d inside array;}//d==1||d==3||d==5||d==7
 1 class transaction;
 2     bit workmode;
 3     int crc;
 4     constraint cons_crc {if(workmode) crc==0; else crc=$random();}
 5 endclass
 6 
 7 class transaction;
 8     bit workmode;
 9     int crc;
10     constraint cons_crc {workmode -> crc==0;}
11 endclass
 1 //x有2种解:0和1,y有4种解:0、1、2、3,每一种随机结果的概率是一样的
 2 class imp;
 3     rand bit x;
 4     rand bit [1:0] y;
 5 endclass
 6 
 7 //共有5种解:x=0,y=0;x=1,y=0;x=1,y=1;x=1,y=2;x=1,y=3,但是每种解的概率不一定相同
 8 class imp;
 9     rand bit x;
10     rand bit [1:0] y;
11     constraint cons_xy {(~x)->(y==0);}//当x=0的时候,y只能为0
12 endclass
13 
14 //共有3种解:x=1,y=1;x=1,y=2;x=1,y=3,且每种解的概率一样,均为1/3
15 class imp;
16     rand bit x;
17     rand bit [1:0] y;
18     constraint cons_xy {y>0;(~x)->(y==0);}//当x=0的时候,y只能为0
19 endclass
20 
21 //共有5种解:x=0,y=0(1/2);x=1,y=0(1/8);x=1,y=1(1/8);x=1,y=2(1/8);x=1,y=3(1/8),但是每种解的概率不一定相同
22 class imp;
23     rand bit x;
24     rand bit [1:0] y;
25     constraint cons_xy {solve x before y;(~x)->(y==0);}//当x=0的时候,y只能为0
26 endclass
27 
28 //共有5种解:x=0,y=0(1/8);x=1,y=0(1/8);x=1,y=1(1/4);x=1,y=2(1/4);x=1,y=3(1/4),但是每种解的概率不一定相同
29 class imp;
30     rand bit x;
31     rand bit [1:0] y;
32     constraint cons_xy {solve y before x;(~x)->(y==0);}//当x=0的时候,y只能为0
33 endclass
      

6.线程的使用

//启动完之后,所有线程结束才继续执行后面的程序
fork
    ...
join

//线程启动之后,只要有一个线程结束就继续执行后面的程序
fork
    ...
join_any

//线程启动之后,继续执行后面的程序
fork
    ...
join_none
 1 //最终结果会显示3个3
 2 program no_auto;
 3     initial begin
 4         for(int i=0; i<3; i++) begin
 5             fork
 6                 $write(i);
 7             join_none
 8         end
 9         #0 $display("\n");
10     end
11 endprogram
12 
13 //最终结果:1 2 3
14 program no_auto;
15     initial begin
16         for(int i=0; i<3; i++) begin
17             fork
18                 automatic int j = i;
19                 $write(j);
20             join_none
21         end
22         #0 $display("\n");
23     end
24 endprogram
25 
26 //最终结果:1 2 3
27 program automatic no_auto;
28     initial begin
29         for(int i=0; i<3; i++) begin
30             fork
31                 int j = i;
32                 $write(j);
33             join_none
34         end
35         #0 $display("\n");
36     end
37 endprogram
//仿真卡死
forever begin
    wait(handshake.triggered());//non-blocking
    $display("received next event!");
    process_next_item_function()//a function defined by user
end
 1 program automatic synchronized;
 2     class producer;
 3         mailbox mbx;
 4         
 5         function new(mailbox mbx);
 6             this.mbx = mbx;
 7         endfunction
 8         
 9         task run();
10             for(int i=1; i<4; i++) begin
11                 $display("producer:before put information(%d)", i);
12                 mbx.put(i);
13             end
14         endtask
15     endclass
16     
17     class consumer;
18         mailbox mbx;
19         
20         function new(mailbox mbx);
21             this.mbx = mbx;
22         endfunction
23         
24         task run();
25             repeat(3) begin
26                 int i;
27                 mbx.get(i)
28                 $display("consumer:after get information(d%)", i);
29             end
30         endtask
31     endclass
32     
33     producer p;
34     comsumer c;
35     initial begin
36         maibox mbx;
37         mbx = new();
38         p = new(mbx);
39         c = new(mbx);
40         fork
41             p.run();
42             c.run();
43         join
44     end
45 endprogram
46 
47 //result
48 producer:before put information(1)
49 producer:before put information(2)
50 consumer:after get information(1)
51 consumer:after get information(2)
52 producer:before put information(3)
53 consumer:after get information(3)
View Code
 1 program automatic synchronized;
 2     class producer;
 3         mailbox mbx;
 4         event handshake;
 5         
 6         function new(mailbox mbx, event handshake);
 7             this.mbx = mbx;
 8             this.handshake = handshake;
 9         endfunction
10         
11         task run();
12             for(int i=1; i<4; i++) begin
13                 $display("producer:before put information(%d)", i);
14                 mbx.put(i);
15                 @handshake;//等待事件handshake的触发
16             end
17         endtask
18     endclass
19     
20     class consumer;
21         mailbox mbx;
22         event handshake;
23         
24         function new(mailbox mbx, event handshake);
25             this.mbx = mbx;
26             this.handshake = handshake;
27         endfunction
28         
29         task run();
30             repeat(3) begin
31                 int i;
32                 mbx.get(i)
33                 $display("consumer:after get information(d%)", i);
34                 ->handshake;//触发事件handshake
35             end
36         endtask
37     endclass
38     
39     producer p;
40     comsumer c;
41     initial begin
42         maibox mbx;
43         mbx = new();
44         event handshake;
45         p = new(mbx, handshake);
46         c = new(mbx, handshake);
47         fork
48             p.run();
49             c.run();
50         join
51     end
52 endprogram
53 
54 //producer和consumer两个线程之间实现了完全同步
55 producer:before put information(1)
56 consumer:after get information(1)
57 producer:before put information(2)
58 consumer:after get information(2)
59 producer:before put information(3)
60 consumer:after get information(3)
View Code

7.面向对象编程的高级技巧

 1 //将子类的句柄赋值给父类
 2 program automatic test;
 3   class father;
 4     function void call;
 5       $display("***I am father!!!***");
 6     endfunction
 7   endclass
 8 
 9   class son extends father;
10     function new();
11       super.new();
12     endfunction
13   
14     function void call;
15       $display("***I am son!!!***");
16     endfunction
17   endclass
18 
19   father fa;
20   son so;
21   initial begin
22     so = new();
23     so.call;//输出是:I am son!!!。假若在function的前面加上virtual关键字,那么SV会根据对象的类型进行方法的调用
24     fa = so;
25     fa.call;//输出是:I am father!!!。假若在function的前面加上virtual关键字,那么输出为:I am son!!!
26   end
27 endprogram
View Code
 1 //将父类的句柄赋值给子类
 2 program automatic test;
 3   class father;
 4     function void call;
 5       $display("***I am father!!!***");
 6     endfunction
 7   endclass
 8 
 9   class son extends father;
10     function new();
11       super.new();
12     endfunction
13   
14     function void call;
15       $display("***I am son!!!***");
16     endfunction
17   endclass
18 
19   father fa;
20   son so;
21   initial begin
22     fa = new();
23     fa.call;//输出应为:I am father!!!
24     so = fa;//此行为禁止,编译不通过
25     so.call;
26   end
27 endprogram
View Code
 1 virtual class base_transaction;
 2     static int count = 1;
 3     int id;
 4     function new();
 5         id = count++;
 6     endfunction
 7     pure virtual function bit compare(input base_transaction to);
 8     pure virtual function base_transaction copy(input base_transaction to=null);
 9     pure virtual function void display(input string prefix="");        
10 endclass
View Code
 1 //代码来自数字IC小站:SystemVerilog中的callback(回调)
 2 class abc_transactor;
 3   virtual task pre_send(); endtask
 4   virtual task post_send(); endtask
 5 
 6   task xyz();
 7       // Some code here
 8       this.pre_send();
 9       // Some more code here
10       this.post_send();
11       // And some more code here
12   endtask : xyz
13 endclass : abc_transactor
14 
15 class my_abc_transactor extend abc_transactor;
16   virtual task pre_send();
17           ...     // This function is implemented here
18   endtask
19 
20   virtual task post_send();
21           ...     // This function is implemented here
22   endtask
23     ...
24 endclass : my_abc_transactor
View Code

 


原文链接1:https://www.jianshu.com/p/013c4066dd85
原文链接2:https://zhuanlan.zhihu.com/p/68189350

标签:基本,function,int,语法,new,bit,class,SystemVerilog
来源: https://www.cnblogs.com/yiquwange/p/14951049.html