system verilog的随机和约束

背景:验证两种方法一种是直接用例,指哪打哪,即遍历每一个具体的例子;另一种是随即用例:全面打击,覆盖意想不到的地方。直接用例在测试量很大时费时费力。

 1.为什么使用随机

        使验证能朝着可量化流程方向发展;让可测激励空间的向量更加容易枚举。提高验证的效率。

特点:1)自动生成测试随机激励  : 改变驱动DUT的数据特性

           2)  随机选择测试用例 : 随机运行已知的有效测试

                3)随机测试平台中的参数 :  随机选择端口,地址,操作参数等。 

   2.randomization 随机化

 (1)类中的变量可以用关键字rand与randc来随机化取值。其中整数型变量、数组、数组大小、对象句柄可以被以上两个关键字修饰。

class packet;
    rand reg[16:0] length;      //0~16取到的概率是项等的
    randc reg [7:0] types;  //randc表示周期性随机,即所有的可能值都取过之后随机值才可能重复;

(2)randomize()

随机成员如果要随机化,必须由被例化的对象显示调用系统随机函数randomize()

举例说明

//class
class packet;
  rand  bit [2:0] addr1;
  randc bit [2:0] addr2;
endclass
 
module rand_methods;
  initial begin
    packet pkt;
    pkt = new();
    repeat(10) begin
      pkt.randomize();
      $display("\taddr1 = %0d \t addr2 = %0d",pkt.addr1,pkt.addr2);
    end
  end
endmodule

(3)rand_mode()

        通过修改rand_mode()的参数值,可以允许或禁止随机化;默认情况下参数为1;语法格式如下:

 addr.rand_mode(0); //参数为0表示禁止随机化
 packet.addr.rand_mode(0);
 
对象名.成员名.rand_mode(0);//关闭成员的随机化
对象名.rand_mode(0);//关闭所有成员的随机化
class Fruits;
  rand bit [3:0] var1;
  rand bit [1:0] var2;
endclass
 
module tb;
  initial begin
    Fruits f = new(); 
    $display ("Before randomization var1=%0d var2=%0d", f.var1, f.var2);
    
    
    f.var1.rand_mode (0);// 关闭var1的随机化
    
    // Print if var1 has randomization enabled/disabled
    if (f.var1.rand_mode())
      $display ("Randomization of var1 enabled");
    else
      $display ("Randomization of var1 disabled");
    
    f.randomize();
    
    $display ("After randomization var1=%0d var2=%0d", f.var1, f.var2);
  end
endmodule

3.随机化中的约束

        为什么要约束?

                纯粹的随机激励需要很长时间才能产生有意义的效果;约束能使有意义的效果产生的概率提升;默认情况下,约束条件的每个可能解决方案都具有相同的可能性,可以创建(distributions)来修改它;约束和分配的权重可以构成测试工作平台的基础激励。

(1)约束的主要种类

集合成员约束: inside;

权重分布(weighted distribution): dist; 

唯一性约束(unique constraints):unique

条件约束: if-else

迭代约束 : foreach

(1.1)集合成员约束 : inside

 用inside操作符产生一个随机数的集合,随机变量在这个集合中选取,且每个值取到的概率相同。

实例如下:

constraint addr_range {addr inside {1,3,4,6,9};}
constraint addr_range  { addr inside {[5:10]}; }
constraint addr_range  { addr inside {1,3,[5:10],12,[13:15]}; }
constraint addr_range  { addr !(inside {[5:10]}); }//对范围取反

集合可以是范围,也可以是多个数的列举,还可以对范围进行取反操作等

 rand bit [3:0] start_addr;
 rand bit [3:0] end_addr;
 rand bit [3:0] addr;
 constraint  addr_range  { addr inside {[start_addr:end_addr]}; }//范围的边界也可以是随机值

下面看例子

class packet;
  rand bit [3:0] addr_1;
  rand bit [3:0] addr_2;
  rand bit [3:0] start_addr;
  rand bit [3:0] end_addr;
  constraint addr_1_range {   addr_1 inside {[start_addr:end_addr]}; }
  constraint addr_2_range { !(addr_2 inside {[start_addr:end_addr]}); }
endclass
 
module constr_inside;
  initial begin
    packet pkt;
    pkt = new();
 
    $display("------------------------------------");
    repeat(3) begin
      pkt.randomize();
      $display("\tstart_addr = %0d,end_addr = %0d",pkt.start_addr,pkt.end_addr);
      $display("\taddr_1 = %0d",pkt.addr_1);
      $display("\taddr_2 = %0d",pkt.addr_2);
      $display("------------------------------------");
    end
  end
endmodule

结果如下

 (1.2)权重分布(weighted distribution): dist;

dist操作符产生随机数的权重分布,不同值出现的概率不同。dist操作符带有一个值的列表以及相应的权重,中间用 := 或 :/ 分开。:=操作符表示范围内的每个值的权重是相同的,:/表示权重要均分到每一个值。

addr dist { 2 := 5, [10:12] := 8 };
         //addr = 2 , weight 5
        // addr = 10, weight 8
         //addr = 11, weight 8
         //addr = 12, weight 8
 addr dist { 2 :/ 5, [10:12] :/ 8 };
         //addr = 2 , weight 5
        // addr = 10, weight 8/3
        // addr = 11, weight 8/3
         //addr = 12, weight 8/3

例子

class packet;
  rand bit [3:0] addr;
 
  constraint addr_range { addr dist { 2 := 5, 7 := 8, 10 := 12 }; }
endclass
 
module constr_dist;
  initial begin
    packet pkt;
    pkt = new();
    $display("------------------------------------");
    repeat(10) begin
      pkt.randomize();
      $display("\taddr = %0d",pkt.addr);
    end
    $display("------------------------------------");
  end
endmodule

 输出结果:

class packet;
  rand bit [3:0] addr_1;
  rand bit [3:0] addr_2;
 
  constraint addr_1_range {   addr_1 dist { 2 := 5, [10:12] := 8 }; }
  constraint addr_2_range {   addr_2 dist { 2 :/ 5, [10:12] :/ 8 }; }
endclass
 
module constr_dist;
  initial begin
    packet pkt;
    pkt = new();
 
    $display("------------------------------------");
    repeat(10) begin
      pkt.randomize();
      $display("\taddr_1 = %0d",pkt.addr_1);
    end
    $display("------------------------------------");
    $display("------------------------------------");
    repeat(10) begin
      pkt.randomize();
      $display("\taddr_2 = %0d",pkt.addr_2);
    end
    $display("------------------------------------");
  end
endmodule

 输出结果

 通过solve...before改变权重

class ABC;
  rand  bit      a;
  rand  bit [1:0]   b;
 
  constraint c_ab { a -> b == 3'h3; }
endclass
 
module tb;
  initial begin
    ABC abc = new;
    for (int i = 0; i < 8; i++) begin
      abc.randomize();
      $display ("a=%0d b=%0d", abc.a, abc.b);
    end
  end
endmodule

各种值的概率:

 在约束中加上solve..before的情况:

class ABC;
  rand  bit      a;
  rand  bit [1:0]   b;
 
  constraint c_ab { a -> b == 3'h3; 
 
            // Tells the solver that "a" has
            // to be solved before attempting "b"
            // Hence value of "a" determines value 
            // of "b" here
                    solve a before b;
                  }
endclass
 
module tb;
  initial begin
    ABC abc = new;
    for (int i = 0; i < 8; i++) begin
      abc.randomize();
      $display ("a=%0d b=%0d", abc.a, abc.b);
    end
  end
endmodule

取值概率:

(1.3)唯一性约束(unique constraints):unique

 

在随机化过程中,可以使用唯一约束生成变量集或数组中唯一元素的唯一值 .

唯一约束允许:

跨变量生成唯一值;在数组中生成唯一元素

class unique_elements;
  rand bit [3:0] var_1,var_2,var_3;
  rand bit [7:0] array[6];
   
  constraint array_c {unique {array};}//唯一约束,关键字unique
   
  function void display();
    $display("var_1 = %p",var_1);
    $display("var_2 = %p",var_2);
    $display("var_3 = %p",var_3);
    $display("array = %p",array);
  endfunction
endclass
 
program unique_elements_randomization;
  unique_elements pkt;
 
  initial begin
    pkt = new();
    pkt.randomize();
    pkt.display();  
  end
endprogram

结果

 累了。。。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值