Verilog的随机数系统任务----$random

目录

        概述

        $random与$random()

        $random(seed)

        常用用法

        总结与参考


概述

        在做仿真的时候,难免会需要一些数据作为输入。有的时候对输入数据没什么要求,随便什么样的数据都行。这种情况下有两种办法:

  • 随便编写一些数据,但数据量一大麻烦不说,还费脑子
  • 使用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

        把结果记录下来:

仿真结果1

        然后把modelsim关了(甚至可以把电脑重启一下),喝杯卡布奇诺休息5分钟,刷刷哔哩哔哩、摸摸鱼。

        

        然后重新打开modelsim,对上面的模块重新进行仿真,再把结果记录下来:

仿真结果2

        咦?奇怪?怎么两次仿真结果是一样的呢?说好的随机数生成函数呢?这他喵的也不随机啊?

        实际上,$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平台🐵
  • 📣您有任何问题,都可以在评论区和我交流📞!
  • 📣创作不易,您的支持是我持续更新的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!

  • 69
    点赞
  • 217
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独的单刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值