对类中变量随机
用 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