当前位置:网站首页>Verilog的随机数系统任务----$random
Verilog的随机数系统任务----$random
2022-08-02 09:40:00 【孤独的单刀】
目录
概述
在做仿真的时候,难免会需要一些数据作为输入。有的时候对输入数据没什么要求,随便什么样的数据都行。这种情况下有两种办法:
- 随便编写一些数据,但数据量一大麻烦不说,还费脑子
- 使用Verilog提供的随机数生成系统任务$random来帮助生成大量的随机数,一个系统任务统统搞定!
$random 是Verilog提供的一个随机数生成系统任务,调用该任务后,将会返回一个32bit的integer类型的有符号的值。其调用格式有3种:
- $random;
- $random();
- $random(seed);
$random与$random()
$random与$random()用起来方法和结果都是一样的,可以写一个小TB测试一下:
`timescale 1ns / 1ns
module random_test();
reg [31:0] rand_data; //定义一个32位数据
//每10ns产生一个随机数
initial begin
rand_data = 0;
repeat(5) begin
#10 rand_data = $random;
end
#5 $finish;
end
endmodule
上面的TB文件要做的事很简单:每隔10ns生成一个随机数,重复5次。其结果如下:
可以看到生成了5个32bit 的随机数,有整数也有负数。
接下来我们把上面的TB中的系统任务 $random替换成$random()的,其他不变,再看看仿真结果:
和之前的结果是一致的,这说明$random替换成$random()其实用起来效果是一样的,所以我们一般都用$random。
$random的返回值是一个32位的整数,但是有时不见得需要这么大的数。如果希望随机数的值能固定在某个范围,那么可以这么使用:$random%b;那么生成的随机数的范围就是 [ ( -b+1 ) : (b- 1 ) ]。 这其实就是对b取余,那可不就是把范围给框住了嘛!
同样的,用上面的TB测试一下,同时多生成几个随机数方便对比(除数用10,生成范围[-9:9]):
`timescale 1ns / 1ns
module random_test();
reg [31:0] rand_data; //定义一个32位数据
//每10ns产生一个随机数
initial begin
rand_data = 0;
repeat(10) begin
#10 rand_data = $random%10;
end
#5 $finish;
end
endmodule
其结果如下:
生成的值都在范围[-9:9]内(注意有几个重复的)。
此外,如果我们希望只生成正数范围内的随机数,那么可以这么使用:{$random}%b;那么生成的随机数的范围就是 [ 0 : (b - 1 ) ]。
还是用上面的TB测试下正数范围的随机数生成结果【0:9】的效果。看下仿真结果:
嗯很好,结果已经全是【0:9】范围内的数了。
$random(seed)
先别说其他的,直接用modelsim仿真一下下面的模块:生成10次【0:9】范围内的随机数:
`timescale 1ns / 1ns
module random_test();
reg [31:0] rand_data; //定义一个32位数据
//每10ns产生一个随机数
initial begin
rand_data = 0;
repeat(10) begin
#10 rand_data = {$random}%10;
end
#5 $finish;
end
endmodule
把结果记录下来:

然后把modelsim关了(甚至可以把电脑重启一下),喝杯卡布奇诺休息5分钟,刷刷哔哩哔哩、摸摸鱼。
然后重新打开modelsim,对上面的模块重新进行仿真,再把结果记录下来:

咦?奇怪?怎么两次仿真结果是一样的呢?说好的随机数生成函数呢?这他喵的也不随机啊?
实际上,$random并不是一个真正意义上的随机数生成函数,如果我们每次仿真调用它的时间一致其实是种子seed一致,那么其生成的随机数就是一致的。
在上面的仿真中,我们省略了seed种子这一参数,由仿真工具默认生成,而仿真工具生成种子是根据仿真时间来定的。所以在我们每次进行仿真时,其实在同一时刻都是在调用相同的seed,所以仿真结果一致也不奇怪了。
忘了说,$random中的seed数据类型可以是reg,integer或者time。
接下来,我们改一下TB,加上seed:
`timescale 1ns / 1ns
module random_test();
reg [31:0] rand_data; //定义一个32位数据
//每10ns产生一个随机数
initial begin
rand_data = 0;
repeat(10) begin
#10 rand_data = {$random(1)}%100;
end
#5 $finish;
end
endmodule
第1次我们用 1作为seed,看看结果:
由于每次都使用1作为seed,所以10次生成的随机数都是68(0是初始值,不是随机生成的)。
把seed改成10,结果如下:
由于每次都使用10作为seed,所以10次生成的随机数都是48(0是初始值,不是随机生成的)。
所以,如果您希望每次仿真都有最好的随机性,那么最好都每次都改一下seed。
常用用法
平常的仿真中调用随机数生成函数的常用用法是:
输入 data_in,位宽【a-1:0】,即位宽a,其值范围2^a,Verilog语法即2**a; //2**a表示2的a次方。
所以如果需要模拟data_in的随机输入,通常这样调用:data_in = {$random}%(2**a);
比如:
input [3:0] data_in; //其值范围为2进制0000~1111(即十进制0-15),
data_in = {$random}%(2**4); //即data_in = {$random}%16),生成的随机数范围为0-15,完美覆盖输入数据的全部范围。
总结与参考
- $random与$random()的用法、结果都是一致的
- $random%b可以生成范围 [ ( -b+1 ) : (b- 1 ) ]内的随机数
- {$random}%b可以生成范围 [ 0: (b- 1 ) ]内的随机数
参考资料1:IEEE Standard for Verilog Hardware Description Language(IEEE Std 1364-2005)
- 博客主页:wuzhikai.blog.csdn.net
- 本文由 孤独的单刀 原创,首发于CSDN平台
- 您有任何问题,都可以在评论区和我交流!
- 创作不易,您的支持是我持续更新的最大动力!如果本文对您有帮助,还请多多点赞、评论和收藏!
边栏推荐
- leetcode:639. 解码方法 II
- 中国发布丨滴滴因违反网络安全法等被罚80.26亿元!调查细节公布
- QT专题:组合会话框和文本编辑器
- 适配器模式适配出栈和队列及优先级队列
- sql concat(),如何才能拼接表的名字
- Use the scrapy to climb to save data to mysql to prevent repetition
- 重磅大咖来袭!阿里云生命科学与智能计算峰会精彩内容剧透
- 带你认识40G单纤双向光模块-QSFP+ BiDi光模块
- 【New Edition】DeepFakes: Creation, Detection and Influence
- AutoJs学习-实现科赫雪花
猜你喜欢
随机推荐
node封装一个图片拼接插件
带你认识40G单纤双向光模块-QSFP+ BiDi光模块
每日一题练习1-15
[Concurrent programming] - Thread pool uses DiscardOldestPolicy strategy, DiscardPolicy strategy
动态规划每日一练(3)
百战RHCE(第四十七战:运维工程师必会技-Ansible学习2-Ansible安装配置练习环境)
Talk about the understanding of Volatile
【云原生】快出数量级的性能是怎样炼成的?就提升了亿点点
AutoJs学习-实现科赫雪花
HikariCP database connection pool, too fast!
未知内容监控
Naive Bayesian Method of Li Hang's "Statistical Learning Methods" Notes
软件测试之发现和解决bug
YugaByte adds Voyager migration service in its 2.15 database update
【打新必读】麦澜德估值分析,骨盆及产后康复电刺激产品
练习16-两道模拟题
cococreator 动态设置精灵
软件测试与质量 之白盒测试
中国发布丨滴滴因违反网络安全法等被罚80.26亿元!调查细节公布
Rust 从入门到精通03-helloworld