作者简介
尼德兰的喵,数字芯片前端,ai与智驾赛道打工人。常年在csdn、知乎、稀土掘 金、博客园、github、gitee等各大论坛与社区打地铺久住,公众号“芯时代青年”。
把目前我们的需求明确下:
1.随机数值是可控且可以复现的,不同的种子随机出不同的结果,相同的种子随机出相同的结果,这样可以充分覆盖随机场景,且出错后稳定可复现;
2.横向看,不同的比特(即每条异步走线路径)随机的结果不同,例如随机延迟时,每条路径的延迟本身就不同,如果随机结果一致那就没有意义了;
3.纵向看,单比特走线每次随机的结果不同,例如这次跳变随机恢复为正确值,下次随机恢复为错误值;
基于这两个表格,很容易想到一种比较容易实现的可控随机方法:
$random+$urandom,既然你来都是有 YES 有 NO,那两个加在一起不就都是 YES 了么。
多说无益,咱们来做一做实验看看吧,修改之前实验的 RTL 代码为:
reg [7:0]rand_value, urand_value;
reg [7:0]new_rand_value;
always @*begin
if(power)begin
rand_value = $random;
urand_value = $urandom;
new_rand_value = $random + $urandom;
//$display("----------------------------------------------");
//$display("%m rand_value = 'h%0h", rand_value);
//$display("%m urand_value = 'h%0h", urand_value);
$display("%m new_rand_value = 'h%0h", new_rand_value);
//$display("----------------------------------------------");
end
end
仍旧以 0/1234/5678 三个种子进行三次仿真:
tc seed = 0
testbench.u_rand_test1 new_rand_value = 'hbd
testbench.u_rand_test0 new_rand_value = 'h9f
testbench.u_rand_test1 new_rand_value = 'h6f
testbench.u_rand_test0 new_rand_value = 'hf4
testbench.u_rand_test1 new_rand_value = 'hec
testbench.u_rand_test0 new_rand_value = 'h1c
tc seed = 1234
testbench.u_rand_test1 new_rand_value = 'hd8
testbench.u_rand_test0 new_rand_value = 'hba
testbench.u_rand_test1 new_rand_value = 'h7
testbench.u_rand_test0 new_rand_value = 'h8c
testbench.u_rand_test1 new_rand_value = 'h37
testbench.u_rand_test0 new_rand_value = 'h67
tc seed = 5678
testbench.u_rand_test1 new_rand_value = 'h78
testbench.u_rand_test0 new_rand_value = 'h5a
testbench.u_rand_test1 new_rand_value = 'h24
testbench.u_rand_test0 new_rand_value = 'ha9
testbench.u_rand_test1 new_rand_value = 'ha0
testbench.u_rand_test0 new_rand_value = 'hd0
通过观察这个结果不难得出结论,无论从时间维度、例化维度还是仿真种子的维度看,随机结果都是不同的,初步分析是可以满足我们的需求。再看看是否可以稳定复现,重新以 seed=1234 跑一下仿真看下:
tc seed = 1234
testbench.u_rand_test1 new_rand_value = 'hd8
testbench.u_rand_test0 new_rand_value = 'hba
testbench.u_rand_test1 new_rand_value = 'h7
testbench.u_rand_test0 new_rand_value = 'h8c
testbench.u_rand_test1 new_rand_value = 'h37
testbench.u_rand_test0 new_rand_value = 'h67
确实可以稳定复现随机的结果。从实验结果上看,$random+$urandom 是能够满足我们的需求的。
那么进一步对这个方法进行分析,从之前的特性上能够看出来,我们最常用的$urandom 之所以不能满足需求是因为对于静态模块的不同例化体而言,同一回合的$urandom 会随机出完全一样结果,可以理解为其不感知静态模块的多个例化实体。而此时以能够感知静态模块不同例化实体的$random 作为补充把这个作为随机的“地基”引入到$urandom 的结果上来,那么就填补了$urandom 的“功能缺失”。而$random 这个地基恰好又是在每个回合随机结果也不一样,缺失是对于不同的 seed 同样的模块中随机结果一致,这也没关系,$urandom 补充了这个功能上的问题。
这样以$random 和$urandom 互为补充的方式,满足了我们构造可控随机的需求,同样这两个函数的其他组合方式也是可以的,比如$random\*$urandom:
tc seed = 0
testbench.u_rand_test1 new_rand_value = 'h3c
testbench.u_rand_test0 new_rand_value = 'h34
testbench.u_rand_test1 new_rand_value = 'h7a
testbench.u_rand_test0 new_rand_value = 'he4
testbench.u_rand_test1 new_rand_value = 'h53
testbench.u_rand_test0 new_rand_value = 'h23
tc seed = 1234
testbench.u_rand_test1 new_rand_value = 'hd7
testbench.u_rand_test0 new_rand_value = 'ha5
testbench.u_rand_test1 new_rand_value = 'h32
testbench.u_rand_test0 new_rand_value = 'h94
testbench.u_rand_test1 new_rand_value = 'h22
testbench.u_rand_test0 new_rand_value = 'h2