随机化的对象:
器件配置:寄存器和系统信号
环境配置:随机化验证环境
原始输入数据:例如MCDF数据包的长度、宽度、数据间的顺序
延时:握手信号之间的时序关系,例如valid和ready、req和ack之间
协议异常:例如反馈信号给出异常,那么设计能否保持后续数据处理的稳定性
预定义的类随机函数 std::randomize()使用。即只有通过声明rand变量,并且在后期通过对象调用randomize()函数才能随机化变量
Constraint{}约束表达式的求解是由SV的约束求解器完成,满足约束的值是由**伪随机数发生器(PRNG)**从一个初始值产生
SV只能随机化2值数据类型,也就是不能随机出X值和Z值,也无法随机化字符串,不能在约束中指向句柄;
src dist{0:/40,[1:3]:/60}//权重分布 src是一个变量
c inside{[lo :hi]};//lo<= c && c<= hi
(io_space_mode) -> addr[31] ==1'b1;//当c_io满足io_space_mode=1时执行
在一个约束表达式中最多只能使用一个关系操作符(<,<=,==,>=,>)
对约束表达式加上括号并在前面加上!即可对约束取反
约束块的控制:约束块可以调用内建的constraint_mode(int a)函数打开或者关闭约束
class Package;
//声明随机变量
rand int length;
//约束变量值,两个约束相互冲突
constraint c_short {length inside {[1:32]};};
constraint c_long {length inside {[1000:1023]};};
endclass
Package p;//声明句柄
initial begin
p = new();//创建的对象
p.c_short.constraint_mode(0);//关闭c_short
assert(p.randomize());//c_long 生效
transmit(p);
p.constrant_mode(0);//关掉p中所有的约束
p.c_short.constraint_mode(1);//打开c_short
end
内嵌约束:
randomize()with{ ; ;};
随机化个别变量
在randomize()中传递参数变量时,只有参数列表的变量会被随机化,其他变量会被当做状态变量而不被随机化。//obj.randomize(b, c)
所有的约束仍然保持有效。【只有当对象使用constraint_mode(0)时,约束才会失效】
类里所有被rand修饰或者没被修饰的变量,只要被当做参数传递到randomize中,都会被随机化,而其他未被传递的参数(即便带rand修饰),也不会参与这次randomize()
在调用 randomize() 函数之前,一定要先为对象分配内存。//new()
调用 randomize() 函数时,会先执行类的构造函数function new()
随机数函数
$random() //平均分布,返回32位有符号随机数
$urandom() //平均分布,返回32位无符号随机数
$urandom_rang() //在指定范围内的平均分布; 例如: $urandom_rang(0,100)
随机函数
pre_randomize() 和 post_randomize()
如果在类中定了这两个函数,那么对象在执行了randomize()之前或之后,会分别执行这两个函数。
pre_randomize() 和 post_randomize()可以看做是randomize()的回调函数
在使用randomize之前可以使rand_mode(0/1)用将随机化的变量禁止随机,然后在赋值一个常数;
调用handle.randomize(null)函数时,sv会把所有的变量当做非随机变量(“状态变量”),仅仅检查这些变量是都满足约束条件;
外部约束:
随机变量谨慎使用有符号数据类型byte,int;该用成bit;还要注意限制位宽;
约束中避免使用复杂的运算,例如除法、乘法、取模(%);如果需要乘除使用右移或左移操作;对2的幂次方的取模操作可以用和掩膜的AND布尔操作代替;
数组的约束:
size() ——对数组的长度限定
sum() ——求和 ;product() ——求积 ;and() ——求与
用foreach对数组的每个元素进行约束
// 利用randc变量来辅助生成唯一元素值的数组
class randc8;
randc bit [7:0] val;
endclass
class LittleUniqueArray;
bit [7:0] ua[64];
function void pre_randomize();
randc rc8;
rc8 = new();
foreach (ua[i]) begin
assert(rc8.randomize());
ua[i]=rc8.val;
end
endfunction
endclass
这段代码的目的是创建一个大小为 64 的数组,其中的每个元素都是一个唯一的值。
产生随机脉冲类:
下例完成10个周期内发送4个数据的脉冲信号
Ps:单比特元素的和正常情况下也是单比特;本例中将strobe.sum()和四位的数值比较,所以数组元素的和是用4位的精度计算的;