• 总结verilog产生随机数的$random和seed


     

     

    $random(seed)是verilog中最简单的产生随机数的系统函数。

    在调用系统函数$random(seed)时,可以写成三种样式:1)$random,2)$random(),3)$random(seed)。下面分别说明:

    1)$random

    这是最简单的一种写法,略去了seed这个传入参数,$random会使用一个默认的seed(这个默认值为0?)。也正因此,每次进行仿真时,$random产生的随机数序列都是相同的。

    2)$random()

    这种写法和写法1)的作用是相同的,同样是没有给$random传入seed。

    3)$random(seed)

    这种写法与上面两种不同,给$random传入了参数seed,因此$random根据seed来产生随机数。seed不同,产生的随机数的序列也不同。而且,每执行一次$random(seed)产生一个随机数,seed也自动更新一次。

    下面讨论seed的产生。

    据我有限的知识,seed有两种产生方式:4)直接赋值为一个确定数,5)利用系统函数$get_initial_random_seed获得值。下面分别讨论:

    4)直接赋值

    在一个initial块中直接将seed变量写成某值,如下面代码:

    integer seed;

    reg [7:0] rand_num;

    initial  begin seed = 0; end

    always @(posedge clk) begin rand_num <= $random(seed); end

    在上面代码中,seed初始值被赋为0(也可以是1或其它数),在第一个时钟上升沿,rand_num取得的第一个随机数就是$random(0)产生的,seed也随即更新;在第二个时钟上升沿时,rand_num取得第二个随机数,是$random(更新后的seed)产生的,seed又随即更新;如此下去。

    值得注意的是,如果把seed赋值为0,那么利用$random(seed)产生的随机数序列和直接执行$random产生的随机数序列是相同的。这个结论是我根据经验得出的。

    5)seed = $get_initial_random_seed()

    如下面代码:

    integer seed;

    reg [7:0] rand_num;

    initial  begin seed = $get_initial_random_seed(); end

    always @(posedge clk) begin rand_num <= $random(seed); end

    在上面代码中,利用系统函数得到的seed的值是1,此后seed更新后的值和$random(seed)产生的随机数序列都和将seed直接赋值成1,利用$random(seed)产生随机数的情况相同。这也是我根据经验得出的结论。

    我在网上没有找到关于$get_initial_random_seed的详细介绍。

    下面讨论仿真时如何改变seed的初值:

    如果seed的初值是确定的,那么不论进行多少次仿真,产生的随机数的序列总是确定的,就不能覆盖更多的情况。因此在仿真时,要能够改变seed的初值。目前我所知道的改变seed的初值有两种方法:6)修改代码;7)采用deposit方式。下面分别介绍:

    6)修改代码

    这种方式最直接,缺点是每次要修改seed时都需要重新编辑一遍代码。

    比如,第一次仿真时,代码写成下面的样子:

    integer seed;

    reg [7:0] rand_num;

    initial  begin seed = 0; end

    always @(posedge clk) begin rand_num <= $random(seed); end

    而第二次仿真时,想修改seed的初值,就写成下面的样子:

    integer seed;

    reg [7:0] rand_num;

    initial  begin seed = 1; end

    always @(posedge clk) begin rand_num <= $random(seed); end

    7)采用deposit的方式

    这种方式比较灵活,不必修改代码,也不必重新编译,直接修改输入到仿真软件的命令即可。

    下面是最简单的一个命令:

    deposit top.seed 2

    run 125ns

    exit

    上面命令的意思是,将信号(或变量)seed的初值设成1,然后开始仿真,仿真时间为125ns,然后结束仿真。

    deposit是在仿真开始之前起作用的(如果没有给deposit加上其它时间方面的条件),而且它只是将某个信号的初始值设为某一个数(可以是确定数,也可以是随机数),此后便不再干预该信号的值。如果仿真开始后有别的条件或语句改变该变量的值,则该变量就变成改变后的值。

    如果代码按下面的样子写:

    integer seed;

    reg [7:0] rand_num;

    initial  begin seed = 1; end

    always @(posedge clk) begin rand_num <= $random(seed); end

    我们来看一下,在仿真开始之前deposit将seed赋值为2,然而仿真开始后的0ns时刻,initial块又将seed赋为1,因此相当于deposit没有起到预期的作用。我们想要的是,seed的初值为2,$random(2)产生一个随机数后,seed再由2变成其它的数;而不是$random(1)产生一个随机数,然后seed又由1变成其它的数。

    为了达到我们的预期目的,要把deposit命令改成下面的样子:

    deposit top.seed 2 -after 1ns

    run 125ns

    exit

    在仿真开始的0ns时,initial块执行,将seed设为1。加上"-after 1ns"后,deposit命令就会在仿真开始后的1ns时起作用,把seed的值改为2,然后作用于第一次$random(seed)的执行,然后seed再更新。

    综上讨论,我得出以下结论:

    1. 利用$random产生随机数时最好利用上seed参数,即写成$random(seed)样式。

    2. 没有必要利用$get_initial_random_seed()函数给seed赋值,直接写成一个值即可,像4)一样。

    3. 建议用deposit的方式在仿真时改变seed的初值,使$random(seed)产生不同的随机数序列

  • 相关阅读:
    数据结构上篇
    异步编程下篇
    异步编程上篇
    异步编程中篇
    对象与原型对象下篇
    对象与原型对象上篇
    移动端开发
    函数进阶
    二.全局安装需要配置NODE_PATH命令
    一.完全删除VSC
  • 原文地址:https://www.cnblogs.com/Dinging006/p/8592393.html
Copyright © 2020-2023  润新知