• system verilog rand randc constraint randomize


    对类中变量随机

    用 rand randc 修饰类中变量bit等:

    rand

    rand修饰符:rand 修饰的变量,每次随机时,都在取值范围内随机取一个值,每个值被随机到的概率一样

    // y的取值范围为0~255,每次随机时,都在此范围取值,每个值被取到的概率为1/256
    
    rand bit[7:0] y
    
    • 1
    • 2
    • 3

    randc

    randc修饰符:randc 表示周期性随机,即所有可能的值都取到过后,才会重复取值

    // y的取值范围是0~3,调用randomize()后,会返回一个y取值范围的随机序列,当这个序列的每个值都被y取到后,会在重新生成随机序列,开始下一个周期的随机取值
    
    randc bit[1:0] y
    
    • 1
    • 2
    • 3

    使用randc产生唯一元素数组

    // 使用randc产生唯一元素数组
    // val的随机序列的范围为0-255,所以取64个值不会重复
    
    class UniqueArray;
    	bit[7:0] ua[64];
    	randc bit[7:0] val;
    	foreach(ua[i]) begin
    		randomize();
    		ua[i] = val;
    		$display("ua[%d] = %h",i,ua[i]);
    	end
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    constraint 增加约束

    • 权重分布:

    关键词:dist 用来产生随机数值的权重分布
    操作符 := 和 :/

    • := 表示指定的数值每一个值的权重是相同的
    • :/ 操作符表示指定的数值均分重权

    在这里插入图片描述

    • 集合约束
    • inside表示变量属于某一个值的集合,,使用“$”指定最大最小值
    • 想选择集合之外的数值,只需使用取反操作符“!”对约束取反即可
    //inside运算符
    
    rand int 	c;
    int 		lo, hi;	//非随机变量
    constraint c_range{
      c inside {[lo:hi]}; //lo
    }
    
    constraint c_range{
      !(c inside {[lo:hi]});  //取反操作
    }
    
    //使用$指定最大和最小值
    rand bit [6:0] b;  // 0<= b <=127
    rand bit [5:0] e;  // 0<= e <= 63
    
    constraint c_range{
      b inside {[$:4], [20:$]}; // 0<=b<=4 ||20<=b<=127
      c inside {[$:4], [20:$]}; // 0<=e<=4 ||20<=b<=63
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 数组大小约束
    // d.size() 查看数组大小
    
    class dyn_size;
      	rand logic [31] d[];
      	constraint d_size {d.size() inside{[1:10]};}   //动态数组的大小为1-10之间
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 数组内元素约束

    约束块中的代码是声明性的,并行执行,所有的表达式同时生效

    // 使用foreach对数组中每一个元素进行约束
    class good_sum;
      	rand uint len[];    //声明无符号整型 随机属性 动态数组len[]
      	constraint c_len{
        	foreach (len[i]) len[i] inside {[1:255]}; //使用foreach遍历所有元素,约束取值在1-255之间
        	len.sum() <1024;  //每个数组内元素的和小于1024
        	len.size() inside {[1:8]};  //动态数组内元素个数在1-8之间
      }
     endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 条件约束
    • -> 条件触发
    • if-else
    class BusOp;
      ....
      constraint c_io{
        (io_space_mode) -> addr[31]==1'b1;   // // 当io_space_mode条件为真时,执行右边代码
      }
     
    //if-else 约束
    class busop;
      	...
    	constraint c_len_rw{
      	if(op==READ)
        	len inside {[BYTE:LWRD]};
      	else
        	len == LERD;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    对类的实例 randomize():

    随机属性还需配合randomize()函数使用,即只有通过声明rand变量,并且在后期通过对象调用randomize()函数才可以随机化变量。约束constraint也同随机变量一起在类中声明

    randomize() 函数为类里所有的rand和randc类型的随机变量,赋一个随机值

    • rand为普通随机,表示每次随机化这个类时,这些变量都会赋一个值(抽签,抽完放回去继续抽)
    • randc修饰符,表示周期随机性,即所有可能的值赋过值后随机值才可能重复(抽签,抽完不放回继续抽)
    • constraint_mode(0) 关闭约束
    • constraint_mode(1) 打开约束
    class Packet;
      	rand int length;
      	constraint c_short{length inside {[1:32]};}
      	constraint c_long {length inside {[1000:1023]};}
    endclass
     
    Packet p;
    	initial begin
      	p = new();
      	//通过禁止c_short约束产生长包
      	p.c_short.constraint_mode(0);   // 关闭约束
      	assert(p.randomize());//断言检查,成功返回1,失败返回0
      	transmit(p);
     
    	p.constraint_mode(0); //禁止所有的约束
    	p.c_short.constraint_mode(1); // 打开c_short
    	assert(p.randomize());
    	transmit(p);
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    // 随机化个别变量
    
    class Rising;
      	byte low;
      	rand byte med, hi;
      	constraint up{low<med; med<hi;}
    endclass
    
    initial begin
      	Rising r;
      	r = new();
      	r.randomzie(); //随机化med 和 hi,low默认为0
      	r.randomize(med); //只随机化med,其他变量保持不变
      	r.randomize(low); //只随机红包mow, med 和hi保持不变
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • sv中允许使用randomize()with 来增加额外的约束,和在类中增加的约束是等效
    • 同时应注意类的内部约束和外部约束之间应该是协调的,若相互违背,则随机化失败
    class Transaction;
      rand bit [31:0] addr, data;
      constraint c1{
        soft addr inside {[0:100],[1000:2000]}; //soft为软约束
      }
    endclass
     
    Transaction t;
    initial begin
      t = new() ;
      //addr的范围 50-100 1000-1500 data <10
      assert(t.randomize() with {addr >= 50; addr <= 1500; data < 10;});
      driveBus(t);
     
      //强制addr取固定值2000,data>10
      assert(t.randomize() with {addr == 2000; data >10;})driveBus(t);
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    // (1)当x = 0的时候y一定为0;(2)当x != 0的时候,y的值随意;  (3)当y == 0的时候,x值是随意的;(4)当 y != 0的时候,x一定不为0;
    (x == 0) -> (y == 0);     //x=0,1;y = 0,1,2,3
    
    • 1
    • 2

    产生随机数:

    系统方法

    • $random() 平均分布,返回32位有符号的随机数
    • $urandom() 平均分布,返回32位无符号的随机数
    • $urandom_range() 在指定范围内的平均分布
    // $random产生一个32bit的有符号随机数,可以是正数、也可以是负数
    // 其种子变量(必须是reg类型、整型或时间型变量)
    
    $random(seed)  // 相同的种子生成的随机数值也相同
    
    int randval;
    randval = $random % 60;      //随机产生一个-59~59之间的有符号数
    
    // 拼接操作符{ }将$random返回的有符号数转换成了无符号数
    randval = {$random % 60};      // 随机产生一个0~59之间的无符号数
    
    // $urandom_range(min,max) 参数最小值min是可以省略的 , 且最大值与最小值的位置是可以互换的
    function int unsigned $urandom_range(int unsigned maxval, int unsigned minval = 0);
    
    // 下述三个随机值都在0~7的范围内
    val1 = $urandom_range(7,0) ;
    val2 = $urandom_range(7) ;
    val3 = $urandom_range(0, 7) ;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    对象方法

    • srandom() 在类方法内/外为随机数据发生器(RNG)添加随机种子
    • randomize() 为对象中的随机化变量随机赋值
    // srandom()——对象方法,在类方法内/外为随机数据发生器(RNG)添加随机种子
    
    // 类内添加seed
    class Packet;
      rand bit[15:0]  header;
    
      function new(int seed) ;
        this.srandom(seed) ;
        ...
      endfunction
    endclass
    
    
    // 类外添加seed
    Packet p=new(200) ;    // seed = 200,创建对象p
    p.srandom(300) ;       // seed = 300,重新创建p
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    // randomize 虚方法,会为对象中的所有随机变量产生随机值。如果randomize()成功的为对象中的所有随机变量赋随机值,则返回1,否则返回0.
    
    virtual function int randomize();
    
    • 1
    • 2
    • 3
    // randomize()成功的为对象中的所有随机变量赋随机值,则返回1,否则返回0.
    
    class SimpleSum;
      rand bit[7:0]  x, y, z;
      constraint c{ z== x+y}; 
    endclass
    
    task InlineConstraintDemo(SimpleSum p) ;
      int success;
      success = p.randomize() with {x<y;} ;      //随机化成功,则返回1,即success为1
    endtask
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

  • 相关阅读:
    【信号与系统】相位卷绕以及连续信号的符号表示
    新型攻击方法分析
    信息化和数字化的核心差异
    健身用什么耳机,几款比较适合健身场景的耳机推荐
    [spring学习]13、声明式事务(@Transaction)
    框架学习1:Spring常见问题
    第08章 中文分词
    ROS2:使用colcon build编译成功但是在运行时提示找不到共享库
    这些 MySQL 最朴素的监控方式!用完爱不释手!
    Blazor系统教程(.net8)
  • 原文地址:https://blog.csdn.net/qq_40456702/article/details/126873378