SV_11_随机约束

目录

1. 随机变量

1.1两种变量类型

2. randomize()

2.1 constraint_mode()

2.2 rand_mode()

2.3 randomize() with

2.3 pre/post_randomize()

3. constraint blocks

3.1 set membership

3.2 distributions constraints

3.3 Implication constraints

3.4  Iterative constraints

4. Variable Ordering

5. randcase


摘要:约束驱动的测试生产允许用户为功能验证自动生成测试,随机测试比传统的、直接的测试方法更有效,随机测试可以找到直接测试难以覆盖的内容。SV允许用户声明随机约束,由求解器处理约束,生产满足约束的随机值。

  • verilog使用$random产生随机整数,默认32位;
  • SV添加了rand变量、randc变量、randomize()方法以及randomize_mode()的随机开关等。

1. 随机变量

SV可以随机化SV支持的所有变量;

数组也可以进行随机化声明;

1.1两种变量类型

  • rand:随机平均分布;
  • randc:随机周期出现
    • 随机循环遍历范围内的所有值;
    • 变量只能是reg或enum类型;
    • 最大位数为16位,数值范围为0-65535。
 1 typedef enum { UNICAST=11, MULTICAST, BROADCAST} pkt_type;
 2 
 3 program rand_ex;
 4   class frame_t;
 5     rand pkt_type ptype;
 6     rand integer len;
 7     randc bit [1:0] no_repeat;
 8     rand bit  [7:0] payload [];
 9     // Constraint the members
10     constraint legal {
11       len >= 2;
12       len <= 5;
13       payload.size() == len;
14     }
15     function string getType(pkt_type ltype);
16       begin
17         case(ltype)
18          UNICAST   : getType = "UNICAST";
19          MULTICAST : getType = "MULTICAST";
20          BROADCAST : getType = "BROADCAST";
21          default   : getType = "UNKNOWN";
22         endcase
23       end
24     endfunction
25     // Print the members of the class
26     task print();
27       begin
28         integer i =0;
29         $write("Packet type %s\n",getType(ptype));
30         $write("Size of frame is %0d\n",len);
31         if (payload.size() > 0) begin
32           $write("Payload is ");
33           for (i=0; i < len; i++) begin
34             $write(" %2x",payload[i]);
35           end
36           $write("\n");
37         end
38         $write("no_repeat is %d\n",no_repeat);
39       end  
40     endtask
41   endclass
42 
43   initial begin
44     frame_t frame = new();
45     integer j = 0;
46     // Print frame before randomize
47     $write("-------------------------------\n");
48     frame.print(); 
49     $write("-------------------------------\n");
50     for (j = 0 ; j < 10;j++) begin
51       if (frame.randomize() == 1) begin
52         // Print frame after randomize
53         frame.print(); 
54       end else begin
55         $write("Failed to randomize frame\n");
56       end
57       $write("-------------------------------\n");
58     end
59   end
60 endprogram
61 
62 //compile result    
63  -------------------------------
64  Packet type UNKNOWN
65  Size of frame is x
66  no_repeat is 0
67  -------------------------------
68  Packet type MULTICAST
69  Size of frame is 3
70  Payload is  0b df 40
71  no_repeat is 0
72  -------------------------------
73  Packet type BROADCAST
74  Size of frame is 3
75  Payload is  fa 4e 15
76  no_repeat is 1
77  -------------------------------
78  Packet type BROADCAST
79  Size of frame is 5
80  Payload is  c4 aa c4 cf 4f
81  no_repeat is 2
82  -------------------------------
View Code

2. randomize()

  • constraint_mode()
  • rand_mode()
  • randmize() with
  • pre_randomize()
  • post_randomize()

2.1 constraint_mode()

  •  constraint_mode():控制随机约束的开启,初始状态都是激活的;
1 task object[.constraint_identifier]::constraint_mode( bit on_off );
2 or
3 function int object.constraint_identifier::constraint_mode();
 1 typedef enum {UNICAST=11,MULTICAST,BROADCAST} pkt_type;
 2 
 3 program constaint_mode_ex;
 4   class frame_t; 
 5     rand pkt_type ptype;
 6     rand integer len;
 7     rand bit  [7:0] payload [];
 8     constraint common {
 9       payload.size() == len;
10     }
11     // Constraint the members
12     constraint unicast {
13       len <= 2;
14       ptype == UNICAST;
15     }
16     // Constraint the members
17     constraint multicast {
18       len >= 3;
19       len <= 4;
20       ptype == MULTICAST;
21     }
22     function string getType(pkt_type ltype);
23       begin
24         case(ltype)
25          UNICAST   : getType = "UNICAST";
26          MULTICAST : getType = "MULTICAST";
27          BROADCAST : getType = "BROADCAST";
28          default   : getType = "UNKNOWN";
29         endcase
30       end
31     endfunction
32     // Print the members of the class
33     task print() ;
34       begin
35         integer i =0;
36         $write("Packet type %s\n",getType(ptype));
37         $write("Size of frame is %0d\n",len);
38         if (payload.size() > 0) begin
39           $write("Payload is ");
40           for (i=0; i < len; i++) begin
41             $write(" %2x",payload[i]);
42           end
43           $write("\n");
44         end
45       end  
46     endtask
47   endclass
48  
49   initial begin 
50      frame_t frame = new();
51      integer j = 0;
52      $write("-------------------------------\n");
53      // Do contraint for Unicast frame
54      frame.multicast.constraint_mode(0);
55      if (frame.multicast.constraint_mode() == 0) begin
56        if (frame.randomize() == 1) begin
57          frame.print(); 
58        end else begin
59          $write("Failed to randomize frame\n");
60        end
61      end else begin
62         $write("Failed to disable constraint multicast\n");
63      end
64      $write("-------------------------------\n");
65      // Check the status of constraint multicast
66      $write ("Constraint state of multicast is %0d\n",
67          frame.multicast.constraint_mode());
68      $write("-------------------------------\n");
69      // Now disable the unitcast and enable multicast
70      frame.unicast.constraint_mode(0);
71      frame.multicast.constraint_mode(1);
72      if (frame.randomize() == 1) begin
73        frame.print(); 
74      end else begin
75        $write("Failed to randomize frame\n");
76      end
77      $write("-------------------------------\n");
78   end
79 endprogram
80 
81 //compile result    
82  -------------------------------
83  Packet type UNICAST
84  Size of frame is 1
85  Payload is  7d
86  -------------------------------
87  Constraint state of multicast is 0
88  -------------------------------
89  Packet type MULTICAST
90  Size of frame is 3
91  Payload is  df 40 f7
92  -------------------------------
View Code

2.2 rand_mode()

  •  控制随机的开启,初始状态都是激活的;rand_mode()可作为函数进行调用。
1 task object[.random_variable]::rand_mode( bit on_off );
2 or
3 function int object.random_variable::rand_mode();
 1 program rand_mode_ex;
 2   class frame_t;
 3     rand bit [7:0] src_addr;
 4     rand bit [7:0] dst_addr;
 5     task print();
 6       begin 
 7         $write("Source      address %2x\n",src_addr);
 8         $write("Destination address %2x\n",dst_addr);
 9       end
10     endtask  
11   endclass
12 
13   initial begin
14     frame_t frame = new();
15     integer j = 0;
16     $write("-------------------------------\n");
17     $write("Without Randomize Value\n");
18     frame.print();
19     $write("-------------------------------\n");
20     $write("With Randomize Value\n");
21     j = frame.randomize();
22     frame.print();
23     $write("-------------------------------\n");
24     $write("With Randomize OFF and Randomize\n");
25     frame.rand_mode(0);
26     j = frame.randomize();
27     frame.print();
28     $write("-------------------------------\n");
29     $write("With Randomize ON and Randomize\n");
30     frame.rand_mode(1);
31     j = frame.randomize();
32     frame.print();
33     $write("-------------------------------\n");
34     $write("With Randomize OFF on dest addr and Randomize\n");
35     frame.dst_addr.rand_mode(0);
36     j = frame.randomize();
37     frame.print();
38     $write("-------------------------------\n");
39   end
40 endprogram
41 
42 //compile result
43 Without Randomize Value
44  Source      address 00
45  Destination address 00
46  -------------------------------
47  With Randomize Value
48  Source      address 36
49  Destination address 3c
50  -------------------------------
51  With Randomize OFF and Randomize
52  Source      address 36
53  Destination address 3c
54  -------------------------------
55  With Randomize ON and Randomize
56  Source      address 7d
57  Destination address e2
58  -------------------------------
59  With Randomize OFF on dest addr and Randomize
60  Source      address 0b
61  Destination address e2
62  -------------------------------
View Code

2.3 randomize() with

  •  用于在调用randomize()类方法的时候声明一个内联约束;
  • 内联约束的形式与对象约束形式相同;
  • 内联约束与对象约束一起应用。
1 inline_constraint _declaration ::=
2 class_variable_identifier . randomize [
3    ( [ variable_identifier_list | null ] ) ]
4 with constraint_block
 1 program randomize_with;
 2   class frame_t;
 3     rand bit [7:0] src_addr;
 4     rand bit [7:0] dst_addr;
 5     constraint c {
 6       src_addr <=  127;
 7       dst_addr >=  128;
 8     }
 9     task print();
10       begin 
11         $write("Source      address %2x\n",src_addr);
12         $write("Destination address %2x\n",dst_addr);
13       end
14     endtask  
15   endclass
16 
17 
18   initial begin
19     frame_t frame = new();
20     integer i = 0;
21     $write("-------------------------------\n");
22     $write("Randomize Value\n");
23     i = frame.randomize();
24     frame.print();
25     $write("-------------------------------\n");
26     $write("Randomize with Value\n");
27     i = frame.randomize() with {
28       src_addr > 100;
29       dst_addr < 130;
30       dst_addr > 128;
31     };
32     frame.print();
33     $write("-------------------------------\n");
34   end
35 endprogram
36 
37 //compile result
38  -------------------------------
39  Randomize Value
40  Source      address 02
41  Destination address ab
42  -------------------------------
43  Randomize with Value
44  Source      address 79
45  Destination address 81
46  -------------------------------
View Code

2.3 pre/post_randomize()

每个类都会包含pre/post_randomize()函数,在每次randomize()之前之后都会调用。 

  • 当object.randomize()被调用时,它首先对object及其所有启用的随机对象调用pre_randomize()。然后递归地调用super.pre_randomize()。然后递归调用super.post_randomize()来执行操作;
  • 可以重载任何类中的pre_randomize()来执行初始化,设置前提条件;可以重载任何类中的post_randomize()来执行清理、打印诊断和检查随机对象的后置条件。
 1 program pre_post_randomize;
 2 
 3   class frame_t;
 4     rand bit [7:0] data;
 5     bit  parity;
 6     constraint c {
 7      data >  0;
 8     }
 9     function void pre_randomize();
10       begin
11         $write("pre_randomize  : Value of data %b and parity %b\n",data,parity);
12       end
13     endfunction
14     function void post_randomize();
15       begin
16         parity = ^data;
17         $write("post_randomize : Value of data %b and parity %b\n",data,parity);
18       end
19     endfunction
20    endclass
21 
22   initial begin
23     frame_t frame = new();
24     integer i = 0;
25     $write("-------------------------------\n");
26     $write("Randomize Value\n");
27     $write("-------------------------------\n");
28     i = frame.randomize();
29     $write("-------------------------------\n");
30   end
31 endprogram
32 
33 //compile result
34     
35  -------------------------------
36  Randomize Value
37  -------------------------------
38  pre_randomize  : Value of data 00000000 and parity 0
39  post_randomize : Value of data 00000110 and parity 0
40  -------------------------------
View Code

3. constraint blocks

  • inclusive and exclusive (set membership)
  • distribution
  • conditional constraint
  • foreach

3.1 set membership

  • inclusive:inside { set [ set]  };
  • exclusive:!( expression inside { set [ set ] } );
 1 program set_membership;
 2   class frame_t;
 3     rand bit [7:0] src_port;
 4     rand bit [7:0] des_port;
 5     constraint c {
 6        // inclusive
 7        src_port inside { [8'h0:8'hA],8'h14,8'h18 };
 8        // exclusive
 9        !(des_port inside { [8'h4:8'hFF] });
10     }
11     function void post_randomize();
12       begin
13         $display("src port : %0x",src_port);
14         $display("des port : %0x",des_port);
15       end
16     endfunction
17   endclass
18 
19   initial begin
20     frame_t frame = new();
21     integer i,j = 0;
22     for (j=0;j < 4; j++) begin
23       $display("-------------------------------");
24       $display("Randomize Value");
25       $display("-------------------------------");
26       i = frame.randomize();
27     end   
28     $display("-------------------------------");
29   end
30 endprogram
31 
32 //compile result    
33  -------------------------------
34  Randomize Value
35  -------------------------------
36  src port : 3
37  des port : 2
38  -------------------------------
39  Randomize Value
40  -------------------------------
41  src port : 0
42  des port : 2
43  -------------------------------
44  Randomize Value
45  -------------------------------
46  src port : 18
47  des port : 3
48  -------------------------------
49  Randomize Value
50  -------------------------------
51  src port : 2
52  des port : 0
53  -------------------------------
View Code

3.2 distributions constraints

权重分布

 1     
 2 constraint_block ::=
 3 ...
 4 | expression dist { dist_list } ;
 5 dist_list ::= dist_item { , dist_item }
 6 dist_item ::= value_range [ dist_weight ]
 7 dist_weight ::=
 8 := expression
 9 | :/ expression
10 dist_item ::=
11 value_range := expression
12 | value_range :/ expression
13 expression_or_dist ::= expression [ dist { dist_list } ]
  • := weight (直接指定权重);
  • :/ weight (所有元素平均分配权重);
 1 program distribution;
 2   class frame_t;
 3     rand bit [7:0] src_port;
 4     rand bit [7:0] des_port;
 5     rand bit [15:0] length;
 6     constraint len {
 7       length dist {
 8         [64  :  127 ] := 10,
 9         [128 :  511 ] := 10,
10         [512 :  2048] := 10
11       };
12     }
13     constraint src {
14       src_port dist {
15         0  := 1,
16         1  := 1,
17         2  := 5,
18         4  := 1
19       };
20     }
21     constraint des {
22       des_port dist {
23         [0   : 5   ] :/ 5,
24         [6   : 100 ] := 1,
25         [101 : 200 ] := 1,
26         [201 : 255 ] := 1
27       };
28     }
29 
30     function void post_randomize();
31       begin
32         $display("src port : %0x",src_port);
33         $display("des port : %0x",des_port);
34         $display("length   : %0x",length);
35       end
36     endfunction
37   endclass
38 
39   initial begin
40     frame_t frame = new();
41     integer i,j = 0;
42     for (j=0;j < 4; j++) begin
43       $display("-------------------------------");
44       $display("Randomize Value");
45       $display("-------------------------------");
46       i = frame.randomize();
47     end
48     $display("-------------------------------");
49   end
50 
51 endprogram
52 //compile result
53     
54  -------------------------------
55  Randomize Value
56  -------------------------------
57  src port : 0
58  des port : 36
59  length   : bd
60  -------------------------------
61  Randomize Value
62  -------------------------------
63  src port : 2
64  des port : 5e
65  length   : 43b
66  -------------------------------
67  Randomize Value
68  -------------------------------
69  src port : 2
70  des port : 83
71  length   : 4fe
72  -------------------------------
73  Randomize Value
74  -------------------------------
75  src port : 2
76  des port : e4
77  length   : 6d9
78  -------------------------------
View Code

3.3 Implication constraints

两种约束条件声明:

  • =>
  • if - else
 1 program conditional_con;
 2   class frame_t;
 3     typedef enum {RUNT,NORMAL,OVERSIZE} size_t;
 4     rand bit [15:0] length;
 5     rand size_t size;
 6   
 7     constraint frame_sizes {
 8       size == NORMAL -> {
 9         length dist {
10           [64  :  127 ] := 10,
11           [128 :  511 ] := 10,
12           [512 :  1500] := 10
13         };
14       }
15       if (size == RUNT)  {
16         length >= 0;
17         length <= 63;
18       } else if (size == OVERSIZE) {
19         length >= 1501;
20         length <= 5000;
21       }
22     }
23     function void post_randomize();
24       begin
25         $display("length   : %0d",length);
26         case(size)
27           RUNT     : $display ("Frame size_t is RUNT");
28           NORMAL   : $display ("Frame size_t is NORMAL");
29           OVERSIZE : $display ("Frame size_t is OVERSIZE");
30         endcase
31       end
32     endfunction
33   endclass
34 
35   initial begin
36      frame_t frame = new();
37      integer i,j = 0;
38      for (j=0;j < 4; j++) begin
39        $write("-------------------------------\n");
40        $write("Randomize Value\n");
41        i = frame.randomize();
42      end
43      $write("-------------------------------\n");
44   end
45 
46 endprogram
47 
48 //compile result
49     
50  -------------------------------
51  Randomize Value
52  length   : 4948
53  Frame size_t is OVERSIZE
54  -------------------------------
55  Randomize Value
56  length   : 4317
57  Frame size_t is OVERSIZE
58  -------------------------------
59  Randomize Value
60  length   : 1774
61  Frame size_t is OVERSIZE
62  -------------------------------
63  Randomize Value
64  length   : 610
65  Frame size_t is NORMAL
66  -------------------------------
View Code

3.4  Iterative constraints

迭代约束条件允许使用循环变量和索引表达式以参数化的方式约束数组变量

  • foreach 构造器指定对数组元素的迭代。
 1 program iterative_con;
 2   class frame_t;
 3     rand bit [15:0] data [];
 4   
 5     constraint frame_sizes {
 6       data.size inside {[1:10]};
 7       foreach (data[i])
 8         data[i] == i;
 9     }
10     function void post_randomize();
11       begin
12         $display("length   : %0d", data.size());
13         for (integer i = 0; i < data.size(); i++) begin
14          $write ("%2x ",data[i]);
15         end
16         $write("\n");
17       end
18     endfunction
19   endclass
20 
21   initial begin
22      frame_t frame = new();
23      integer i,j = 0;
24      for (j=0;j < 4; j++) begin
25        $write("-------------------------------\n");
26        $write("Randomize Value\n");
27        i = frame.randomize();
28      end
29      $write("-------------------------------\n");
30   end
31 
32 endprogram
33 
34 //compile result
35     
36  -------------------------------
37  Randomize Value
38  length   : 4
39  00 01 02 03 
40  -------------------------------
41  Randomize Value
42  length   : 2
43  00 01 
44  -------------------------------
45  Randomize Value
46  length   : 8
47  00 01 02 03 04 05 06 07 
48  -------------------------------
49  Randomize Value
50  length   : 9
51  00 01 02 03 04 05 06 07 08 
52  -------------------------------
View Code

4. Variable Ordering

  • 求解者必须确保所选的随机值在合法值组合上具有一定的值分布。
  • SV提供了solve before 关键字;
 1 program ordering;
 2   class frame_t;
 3     rand bit zero;
 4     rand bit [15:0] data [];
 5   
 6     constraint frame_sizes {
 7       solve zero before data.size;
 8       zero -> data.size == 0;
 9       data.size inside {[0:10]};
10       foreach (data[i])
11         data[i] == i;
12 
13     }
14     function void post_randomize();
15       begin
16         $display("length   : %0d", data.size());
17         $write ("zero:%2x \n",zero);
18         for (integer i = 0; i < data.size(); i++) begin
19          $write ("%2x ",data[i]);
20         end
21         $write("\n");
22       end
23     endfunction
24   endclass
25 
26   initial begin
27      frame_t frame = new();
28      integer i,j = 0;
29      for (j=0;j < 4; j++) begin
30        $write("-------------------------------\n");
31        $write("Randomize Value\n");
32        i = frame.randomize();
33      end
34      $write("-------------------------------\n");
35   end
36 
37 endprogram
38 
39 //compile result
40 # KERNEL: -------------------------------
41 # KERNEL: Randomize Value
42 # KERNEL: length   : 0
43 # KERNEL: zero: 1 
44 # KERNEL: 
45 # KERNEL: -------------------------------
46 # KERNEL: Randomize Value
47 # KERNEL: length   : 1
48 # KERNEL: zero: 0 
49 # KERNEL: 00 
50 # KERNEL: -------------------------------
51 # KERNEL: Randomize Value
52 # KERNEL: length   : 0
53 # KERNEL: zero: 1 
54 # KERNEL: 
55 # KERNEL: -------------------------------
56 # KERNEL: Randomize Value
57 # KERNEL: length   : 3
58 # KERNEL: zero: 0 
59 # KERNEL: 00 01 02 
60 # KERNEL: -------------------------------
View Code

5. randcase

randcase 语句指定了一个语句块,引入case语句对权重进行分支操作。

 1 module randcase_statement;
 2 
 3  task do_randcase();
 4    begin
 5      randcase
 6        20 : begin
 7               $write ("What should I do ? \n");
 8             end
 9        20 : begin
10               $write ("Should I work\n");
11             end
12        20 : begin
13               $write ("Should I watch Movie\n");
14             end
15        40 : begin
16               $write ("Should I complete tutorial\n");
17             end
18      endcase 
19    end
20  endtask
21 
22  initial begin
23    repeat(10) begin
24      // You need to run for more iteration to
25      // get proper distribution
26      do_randcase();
27    end  
28    $finish;
29  end
30 endmodule
31 
32 //compile result
33     
34  Should I watch Movie
35  Should I complete tutorial
36  Should I watch Movie
37  What should I do ? 
38  Should I complete tutorial
39  Should I watch Movie
40  Should I complete tutorial
41  Should I complete tutorial
42  Should I work
43  Should I watch Movie
View Code
`sv rand_mode`是Verilog仿真环境中用于控制随机数生成的一种功能设置。它允许开发者指定在仿真过程中如何生成随机数序列。通常,在测试路径、覆盖率分析等需要随机数据输入的场景下,会利用到随机数的功能。 有几种常见的 `rand_mode` 设置: 1. **rand**:这是默认模式,它在每次仿真步骤开始时都会生成一个新的随机值。这种模式适用于大部分情况下的随机化需求,因为它可以提供独立于时间变化的随机序列。 2. **randc**:此模式生成的每个新随机值都基于上一次生成的值。这意味着在连续的仿真步之间,相同的序列可能会重复出现,除非引入了外部的干扰因素来破坏这个序列的线性依赖。这对于某些类型的测试是有用的,例如在验证时序敏感电路的行为时,通过保持输入的某种形式的一致性来进行对比测试。 3. **nosys**:在该模式下,Verilog仿真的随机数生成并不实际地模拟硬件中的随机数发生器。相反,它只提供一种伪随机数生成机制,并不会影响实际的仿真结果。这种方式常用于快速原型设计或验证初期阶段,当对真实硬件中的随机性要求较低时尤其有用。 选择合适的 `rand_mode` 可以优化仿真效率和满足特定的测试需求。例如,在性能关键的应用中,可能更倾向于使用 `nosys` 来减少随机数生成的时间开销;而在需要精确模拟随机事件影响的测试场景中,则应使用 `rand` 或者 `randc`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值