SV复习(五)随机化

目录

0. 基础

1. 随机化方法

2. Constraint

3. inside

4. dist

5. 条件约束

6. foreach 约束

7. disable constraint

7. static constraint

8. inline constraint

9. soft constraint

10. unique

11. 约束的双向性质

12. Solve before

13. 随机系统函数


0. 基础

下面几种类型可以随机化:

  • 单个变量或整形数
  • 数组
  • 数组长度
  • 对象句柄

语法:

  • rand bit [3:0] addr;生成0-15的随机数
  • randc bit [3:0] addr; 生成0-15的随机数,完全遍历完16个数之后才会开始开始下一轮,每一轮随机的数不重样
  • object.randomize();对象内变量随机化命令

rand_mode:
<object_hanlde>.<variable_name>.rand_mode(enable); 打开或关闭某个变量的随机化,或者

<object_hanlde>.rand_mode(enable);打开或关闭某个类内的所有变量的随机化。

<object_hanlde>.<constraint_name>.rand_mode(enable); 打开或关闭某个变量的随机化

class packet;
  rand byte addr;
  rand byte data;  
endclass
 
module rand_methods;
  initial begin
    packet pkt;
    pkt = new();
     
    //disable rand_mode of addr variable of pkt
    pkt.addr.rand_mode(0);
     
    //calling randomize method
    pkt.randomize();
     
    $display("\taddr = %0d \t data = %0d",pkt.addr,pkt.data);
     
    $display("\taddr.rand_mode() = %0d \t data.rand_mode() = %0d",pkt.addr.rand_mode(),pkt.data.rand_mode());
  end
endmodule

输出:

addr = 0 data = 110
addr.rand_mode() = 0 data.rand_mode() = 1

1. 随机化方法

  • randomize()
  • pre_randomize()
    • 可以为类设置随机化的先决条件,例如rand_mode()
  • post_randomize()
    • 用来在随机化后进行检查

例如下面的例子,如果在wr_rd为1的时候,address需要保持不变,定义一个pre_randomize方法来控制变量是否随机化。

//class
class packet;
  rand  bit [7:0] addr;
  randc bit       wr_rd;
        bit       tmp_wr_rd;    
 
  //pre randomization function - disabling randomization of addr,
  //if the prevoius operation is write.
  function void pre_randomize();
    if(tmp_wr_rd==1) addr.rand_mode(0);
    else                 addr.rand_mode(1);
  endfunction
 
  //post randomization function - store the wr_rd value to tmp_wr_rd
  //and display randomized values of addr and wr_rd
  function void post_randomize();
    tmp_wr_rd = wr_rd;
    $display("POST_RANDOMIZATION:: Addr = %0h,wr_rd = %0h",addr,wr_rd);
  endfunction
endclass
 
module rand_methods;
  initial begin
    packet pkt;
    pkt = new();
 
    repeat(4) pkt.randomize();
  end
endmodule

输出:

POST_RANDOMIZATION:: Addr = 6e,wr_rd = 1
POST_RANDOMIZATION:: Addr = 6e,wr_rd = 0
POST_RANDOMIZATION:: Addr = 88,wr_rd = 1
POST_RANDOMIZATION:: Addr = 88,wr_rd = 0

2. Constraint

为随机变量设置约束:
第一种,在内部设置:

class packet;
  rand  bit [3:0] addr;
 
  constraint addr_range { addr > 5; }
endclass

第二种,在外部设置:

class packet;
 
  rand  bit [3:0] addr;
  //constraint block declaration
  constraint addr_range;
endclass
 
//constraint implementation outside class body
constraint packet::addr_range { addr > 5; }

同样,constraint也会被子类继承。

3. inside

让随机值约束在inside指定的范围内:
constraint addr_range { addr inside {1,3,[5:10],12,[13:15]}; }

constraint addr_range { addr !(inside {[5:10]}); }
也可以将上下界指定为随机值(上下界都可以取到):

class packet;
  rand bit [3:0] addr;
  rand bit [3:0] start_addr;
  rand bit [3:0] end_addr;
   
  constraint addr_1_range { addr inside {[start_addr:end_addr]}; }
endclass

4. dist

可以使得随机化的数据

constraint addr_1_range {   addr_1 dist { 2 := 5, [10:12] := 8 }; }

上面的权重是这样的:
addr == 2 , weight 5
addr == 10, weight 8
addr == 11, weight 8
addr == 12, weight 8

  constraint addr_2_range {   addr_2 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

5. 条件约束

class packet;
  rand bit [3:0] addr;
       string    addr_range;
 
  constraint address_range { if(addr_range == "small")
                                addr < 8;
                             else
                                addr > 8;
                           }
endclass

6. foreach 约束

class packet;
  rand byte addr [];
  rand byte data [];
 
  constraint avalues { foreach( addr[i] ) addr[i] inside {4,8,12,16}; }
  constraint dvalues { foreach( data[j] ) data[j] > 4 * j; }
  constraint asize   { addr.size < 4; }
  constraint dsize   { data.size == addr.size; }
endclass

7. disable constraint

跟randomize_mode一样,constraint也可以设置mode控制是否添加约束:
pkt.addr_range.constraint_mode(0); 0表示关闭约束

7. static constraint

静态约束跟普通约束不同的是,静态约束的使能和关闭对所有实例都生效:

class packet;
  rand  bit [7:0] addr;
   
  static constraint addr_range { addr == 5; }
endclass

如果下面实例化了两个packet:a1和a2,如果对a1的addr变量设置constraint_mode(0),则a2的addr的约束也会关闭。

8. inline constraint

inline的约束允许使用with关键字在类外对变量增加新的约束:

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

上面pkt.randomize() with { addr == 8;};将给变量添加新的约束,使得输出都为8,但是通过with添加的新约束必须包含在类中定义的范围内,否则会报错。

9. soft constraint

软约束是为了解决inline方式的弊端。比如有这样的场景,我们已经测试了很多正常约束的case,可能会使用with的方式来生成约束的子集,但我们永远无法通过with来生成约束的补集,而这可能在测试异常情况时需要用到。一个方法是修改constraint,但无疑会有很大麻烦。
这时只需要在constraint中为变量增加soft关键字即可:

class packet;
  rand bit [3:0] addr;
  constraint addr_range { soft addr > 6; }
endclass
 
module soft_constr;
  initial begin
    packet pkt;
    pkt = new();
 
    repeat(2) begin
      pkt.randomize() with { addr < 6;};
      $display("\taddr = %0d",pkt.addr);
    end
  end
endmodule

10. unique

使用unique关键词加在一组随机变量或者随机数组前,可以使得这些变量在约束范围内各不相同:

rand bit [31:0] array[10];
   
  constraint array_c {unique {array}; foreach(array[i]) array[i] < 10;}

11. 约束的双向性质

上面的例子一般都只涉及单个变量的约束,而实际上sv中约束的变量是并行地设置的,因此约束中如果涉及多个约束变量的约束,则这一约束是双向的。
例如:

constraint c_name { if(a == 0) b == 1;
                    else       b == 0; }

上面的例子b的值依赖a,而实际上a的值也会依赖b,如果将b通过inine的方式约束为1,则a也被约束为0。

class packet;
  rand bit a;
  rand bit b;
 
  constraint a_value { a == 1; }
  constraint b_value { if(a == 0) b == 1;
                       else       b == 0; }
endclass
 
module bidirectional_const;
  initial begin
    packet pkt;
    pkt = new();
    pkt.randomize() with { b == 1; };
    $display("Value of a = %0d \tb = %0d",pkt.a,pkt.b);
  end
endmodule

上面的例子试图用inline的方式约束b,但b的约束会反作用到a,使得a约束为0,但a已经约束为只能为1,所以程序报错。

12. Solve before

solve before可以强制约束中先进行哪个变量的约束。

在上面提到的约束双向性中,多个变量之间有依赖关系时约束是双向的,这可能会导致一些问题,比如下面的例子:

class packet;
  rand bit       a;
  rand bit [3:0] b;
 
  constraint a_b { (a == 1) -> b == 0; }
endclass
 
module inline_constr;
  initial begin
    packet pkt;
    pkt = new();
    repeat(10) begin
      pkt.randomize();
      $display("\tValue of a = %0d, b = %0d",pkt.a,pkt.b);
    end
  end
endmodule

b可以取0-15中的值,而只要b不为0,a都会被约束为0,所以这个例子产生的结果是这样的:

Value of a = 0, b = 6
Value of a = 0, b = 3
Value of a = 1, b = 0
Value of a = 0, b = 15
Value of a = 0, b = 7
Value of a = 0, b = 2
Value of a = 0, b = 15
Value of a = 0, b = 4
Value of a = 0, b = 7
Value of a = 0, b = 11

a=1的情况非常少。如果我们希望a的产生不依赖b,可以使用solve before:

class packet;
  rand bit       a;
  rand bit [3:0] b;
 
  constraint sab { solve a before b;}
  constraint a_b { (a == 1) -> b == 0;}
endclass
 
module inline_constr;
  initial begin
    packet pkt;
    pkt = new();
    repeat(10) begin
      pkt.randomize();
      $display("\tValue of a = %0d, b = %0d",pkt.a,pkt.b);
    end
  end
endmodule

输出:

Value of a = 0, b = 9
Value of a = 0, b = 14
Value of a = 0, b = 3
Value of a = 0, b = 13
Value of a = 1, b = 0
Value of a = 1, b = 0
Value of a = 1, b = 0
Value of a = 0, b = 5
Value of a = 0, b = 3
Value of a = 0, b = 4

13. 随机系统函数

随机化的系统函数主要有两个:

  • urandom() 生成无符号随机数,括号内可以填入不同随机种子
    • urandom_range(max,min) 生成范围内的随机数,上下界可以不按顺序写,默认下届为0
  • random() 生成有符号随机数。
module system_funcations;
  bit [31:0] addr1;
  bit [31:0] addr2;
  bit [64:0] addr3;
  bit [31:0] data;
  initial begin
    addr1 = $urandom();
    addr2 = $urandom(89);
    addr3 = {$urandom(),$urandom()};
    data  = $urandom * 6;
 
    $display("addr1=%0d, addr2=%0d, addr3=%0d, data=%0d",addr1,addr2,addr3,data);
  
    addr1 = $urandom_range(30,20);
    addr2 = $urandom_range(20); //takes max value as '0'
    addr3 = $urandom_range(20,30); //considers max value as '30' and min value as '20'
    $display("addr1=%0d, addr2=%0d, addr3=%0d",addr1,addr2,addr3);
  end
endmodule

输出:

addr1=303379748, addr2=2153631232, addr3=423959822444962108, data=546103870
addr1=27, addr2=6, addr3=25
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值