system verilog rand randc constraint randomize

对类中变量随机

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

rand

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

// y的取值范围为0~255,每次随机时,都在此范围取值,每个值被取到的概率为1/256

rand bit[7:0] y

randc

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

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

randc bit[1:0] y

使用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

在这里插入图片描述

constraint 增加约束

  • 权重分布:

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

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

在这里插入图片描述

  • 集合约束
  • inside表示变量属于某一个值的集合,,使用“$”指定最大最小值
  • 想选择集合之外的数值,只需使用取反操作符“!”对约束取反即可
//inside运算符

rand int 	c;
int 		lo, hi;	//非随机变量
constraint c_range{
  c inside {[lo:hi]}; //lo<c&&c<hi
}

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
}
  • 数组大小约束
// d.size() 查看数组大小

class dyn_size;
  	rand logic [31] d[];
  	constraint d_size {d.size() inside{[1:10]};}   //动态数组的大小为1-10之间
endclass
  • 数组内元素约束

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

// 使用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
  • 条件约束
  • -> 条件触发
  • 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;
	}

对类的实例 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
// 随机化个别变量

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
  • 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)当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

产生随机数:

系统方法

  • $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) ;

对象方法

  • 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
// randomize 虚方法,会为对象中的所有随机变量产生随机值。如果randomize()成功的为对象中的所有随机变量赋随机值,则返回1,否则返回0.

virtual function int randomize();
// 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值