随机化之坑——你想要的随机VS真正的随机

文章讨论了在Verilog中使用$urandom进行随机化时遇到的问题,指出多个模块实例化时由于默认seed导致的随机结果相同。解决方案包括使用$random_range或通过srandom设置种子以确保每次实例化得到不同的随机值。同时提到了$random和$urandom_range的区别以及如何在仿真中控制随机序列。
摘要由CSDN通过智能技术生成

         随机化是我们DV强大的工具,帮助我们以极小的代价产生大量的随机组合,极大的加快了验证的收敛速度,但是有时候有些平时不太注意的细节点可能让我们的前期努力功亏一篑,甚至造成rtl bug延后到silicon测试才发现。以下便是笔者在工作中见到的一个随机化的坑,大家慢慢看,先来看一段code:

module my_lib(a,b);
    input a;
    output b;
    assign b=$urandom(0,1)?a:0;
endmodule

module top(c,d);
      input [7:0] c;
      ouput [7:0] d;
      c = $urandom();
      genvar i;
      generate
            for(i=0;i<8;i++) begin:gen_lib
                my_lib my_lib_inst(.a(c[i],.b(d[i])));
            end
      endgenerate   
endmodule

代码功能很简单,my_lib是公共的code,功能就是随机化b,random选择a或者0,top就是把一个8bits信号做同样的随机化,用my_lib在实现单个bit的随机化。我的本意是想随机化的d的每个bit,但是上面的code能实现我的想法吗,这里面有什么隐藏的bug吗?

              涉及到的随机化和random stability,有一个博主的文章写的很详细,可移步阅读:

RNG与Random stability_urandom_range_kevindas的博客-CSDN博客

                重点内容总结如下:

1. 每个module 或者interface instance的时候都会有一个初始RNG,每个RNG都由相同的default seed产生,所以多次instance之后调用$urandom得到的结果是一样的.(Thread stability)

 2. 我们在class里面常用的$urandom_range(),或者std::randomize以及obj.randomize在每次new的时候都会由parent thread随机产生下一个RNG,所以每次new之后再用$urandom随机的结果会不一样。(Object stability)

3. $random的default初始seed是0,并且不受EDA tool给的rand seed影响,但是可以通过$random(seed)来手动改变seed,参数是inout,调用不仅返回rand值,还会生成下一次rand的RNG。

所以上面code的结果c只有两种值:8{a}或者0,因为8次instance对应的my_lib的随机值都是一样的,要想8次随机完全独立不一样,需要把$urandom_range改成$random,不过这样会引入另外一个,$random每次都是从RNG0开始随机,并且随机序列一样,这样就会导致regression的结果都是一样,不受seed控制,需要把随机seed带入,并且在一开始0时刻调用一次$random(rand_seed)来改变随机序列。

所以修改之后的代码应该是这样:

module my_lib(a,b);
    input a;
    output b;
    assign b=($random%2)?a:0;//多次例化随机结果不一样了
endmodule

module top(c,d);
      input [7:0] c;
      ouput [7:0] d;
      c = $urandom();
      initial begin
          int rseed;
          $value$plusargs("ntb_rand_seed=%0d",rseed);//以VCS为例
          void'($random(rseed));//改变不同seed的随机序列,多次仿真结果不一样
      end
      genvar i;
      generate
            for(i=0;i<8;i++) begin:gen_lib
                my_lib my_lib_inst(.a(c[i],.b(d[i])));
            end
      endgenerate   
endmodule

也可以改my_lib,修改如下:

module my_lib(a,b);
    input a;
    output b;
    initial begin
          int rseed;
          process _process;
          _process = process:self;//获取进程
          $value$plusargs("ntb_rand_seed=%0d",rseed);//以VCS为例
          void'($random(rseed));//改变不同seed的随机序列,多次仿真结果不一样
          _process.srandom(rseed);//进程随机 
     end
    assign b=$urandom_range(0,1)?a:0;//多次例化随机结果不一样了
endmodule

module top(c,d);
      input [7:0] c;
      ouput [7:0] d;
      c = $urandom();
      genvar i;
      generate
            for(i=0;i<8;i++) begin:gen_lib
                my_lib my_lib_inst(.a(c[i],.b(d[i])));
            end
      endgenerate   
endmodule

几种随机的区别:

$random(seed)—— 系统随机化调用函数,返回32bit有符号数;seed参数可选,并且seed是inout类型,随机之后不仅返回随机数,seed也会更新。但是缺省情况下是从seed=0开始随机
$urandom_range()—— 系统随机化调用函数,返回指定范围内的无符号随机整数;
srandom(seed) —— 对象和进程的随机化播种方法,需手动添加种子seed;
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值