目录

        概述

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

精彩内容

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: