1.sv随机约束和分布
随机测试相比于定向测试要求更复杂,随机不意味着绝对自由,需要满足一定的联系
器件配置:通过寄存器和系统信号
环境配置:随机化验证环境,例如合理的时钟和外部反馈信号
原始输入数据:例如mcdf数据包的长度,带宽,数据间的顺序
延时:握手信号之间的时序关系,例如valid和ready,req和ack之间的时序关系
协议异常:如果反馈信号给出异常,那么设计是否可以保持后续数据处理的稳定性
随机化函数 std::randomsize
调用randomize()的变量必须是rand 变量
class Packet;
rand bit [31:0] src, dst, data[8]; //随机化变量
randc bit [7:0] kind; //randc周期随机性,所有可能的值都产生过,才会产生新的一轮
constraint x {src > 10;
src < 15;} //添加约束
endclass
Packet p;
initial begin
p = new();
assert(p.randomize()) else //随机化类
$ fatal(0, "Packet::randomize failed")
transmit(p);
end
sv对于logic类型,也只能随机化0或 1,不能随机化X和Z
class data;
rand bit [2:0] month;//范围0~7
rand bit [4:0] day;
constraint c_date {
month inside {[1:12]};
day inside{[1:31]}; //约束表达式
}
endclass
rand int src, dst;
constraint c_dist{
src dist{0:=40,[1:3]:=60};
// src = 0, weight = 40/220
// src = 1, weight = 60/220
dst dist {0:/40, [1:3]:/60;
// dst = 0, weight = 40/100
// dst = 1, weight = 20/100
}
a[$]表示当前数组的最后一位
$指定最大值或者最小值
[$:20] [20:$]
class BusOp;
...
constraint c_io{
(io_space_mode)->
addr[31] == 1'b1; //有条件的约束->
}
约束条件是并行的
2.sv约束块控制
constraint_mode(0)//控制constraint打开和关闭
assert(t.randomsize() with
{ addr >= 50; addr <=1500;
data < 10;}); //内嵌约束 randomize() with
constraint c1{
soft addr inside
{[0:100],[1000:2000]};} //soft软约束,外部出现新的约束,软约束的优先级低
3.随机函数
pre_randomsize() post_randomsize()
$random()平均分布,返回32位有符号随机数
$urandom()平均分布,返回32位无符号随机数
$urandom_range()在指定范围内的平均分布
class Rising;
byte low;//not random
rand byte med, hi;//rand
constraint up
{ low < med; med < hi; }
endclass
initial begin
Rising r;
r = new();
r.randomize();//随机化hi,不改变low
r.randomize(med);//只随机化med
r.randomize(low); //只随机化low
end
如果只出现r.randomize(low),产生的结果是low出错,high ,med =0 ,没有任何randomize发生, 默认都是0
4.数组约束
class dyn_size;
rand logic [31:0] d[];
constraint d_size {d.size() inside {[1:10]};} //动态数组不仅要约束内容,还要约束size
endclass
unique修饰唯一的变量
da[i] <= da[i+1]; //注意i的取值范围
rand 修饰句柄t,t.randomize()如果句柄指向的类的对象中的变量没有rand修饰,那么t.value不会随机化
5.随机控制
initial begin
for(int i=0; i<15; i++) begin
randsequence (stream)
stream: cfg_read := 1 |
io_read := 2 |
mem_read := 5;
cfg_read :{ cfg_read_task;} |
{cfg_read_task;} cfg_read;//执行cfg_read,或者继续执行cfg_read
mem_read :{ mem_read_task;} |
{mem_read_task;} mem_read;
io_read :{ io_read_task;} |
{io_read_task;} io_read;
endsequence
end // for
end
randcase
1: len = $urandom_range(0,2); //10%
8: len = $urandom_range(6,8); //80%
1: len = $urandom_range(8,9);
endcase