为什么$ urandom_range返回相同的值?

时间:2016-09-29 18:17:46

标签: verilog system-verilog register-transfer-level test-bench

我用UVM跑了一个测试台。在组件的run_phase()任务之一中,我执行fork...join_none以启动以下循环,该循环贯穿整个模拟:

fork
   forever @(posedge trigger) begin
      force dut.a = $urandom_range('h00,'hFF);
      force dut.b = $urandom_range( 'h0, 'hF);
      force dut.c = $urandom_range('h00,'hFF);
      force dut.d = $urandom_range( 'h0, 'hF);
      force dut.e = $urandom_range('h00,'hFF);
      force dut.f = $urandom_range( 'h0, 'hF);
   end

 ...
 some other stuff
 ...
join_none

信号 a c e 被强制为相同的值。对于 b d e 也是如此。

如果以后出现新的触发器,新值会被随机化并强制执行,但我再次得到a == c == eb == d == e

似乎$urandom_range只为每个参数的选择(0到FF,0到F)调用一次,并且返回值重新用于三个force命令。 / p>

编辑:我能够在最小的TB上重现问题:http://www.edaplayground.com/x/4_ph

对于我正在使用的供应商来说,这似乎是一个问题,选择其他工具可以解决问题。

编辑2:我还没弄清楚为什么会发生这种情况,但似乎与 force 语句就像一个连续的分配(即如果RHS信号在未来,强制LHS将遵循它,直到 force 发布 d,它不像'='赋值。

所以我的猜测是问题在于将函数的返回值用作RHS。 (我不知道这个返回值的生命周期)

我的解决方案是将$ urandom值保存到具有静态生存期的变量,然后将该变量强制转换为RTL(如J Reid建议的那样)

3 个答案:

答案 0 :(得分:1)

您的代码存在两个问题。 第一个你有$ urandom_range反转的参数;它是( max min ),而 min 是可选的默认值为0.有些模拟器会解决这个问题,但它不是标准的。

第二个问题是因为你反复强制使用相同的表达式。模拟器可能不会将其视为新表达式,并且不会再次调用$ urandom。尝试在每个release之前添加force语句。

 forever @(posedge trigger) begin
      release dut.a; force dut.a = $urandom_range('hFF);
      release dut.b; force dut.b = $urandom_range('hF);
      release dut.c; force dut.c = $urandom_range('hFF);
      release dut.d; force dut.d = $urandom_range('hF);
      release dut.e; force dut.e = $urandom_range('hFF);
      release dut.f; force dut.f = $urandom_range('hF);
   end

答案 1 :(得分:1)

为什么不使用具有随机变量和约束的类???

// outside of the test-bench
class my_stimulus;
    rand bit [7:0] a, c, e;  // can be logic if you like
    rand bit [3:0] b, d, f;  // rand won't give X or Z

    constraint c1 { 
        unique {a, c, e}; 
        unique {b, d, f};       
    }       
endclass;   

// inside the actual testbench 
my_stimulus to_dut = new; 

fork
   forever @(posedge trigger) begin
    if (!(to_dut.randomize()) $error;
    force dut.a = to_dut.a;
    ...
    force dut.f = to_dut.f;
   end
...
join_none   

唯一约束会导致错误或每次都为您提供唯一值。具有指定的大小消除了设置边界的需要,但是也可以使用另一个约束来完成。

答案 2 :(得分:0)

我遇到了一个非常类似的问题" urandom_range"作为使用NCSIM的OP。然而," urandom"工作得很好。不应该有任何理由" urandom"不应该在你的情况下工作,而不是" urandom_range" (假设" urandom"当然正常工作)。 " urandom"的结果只会被截断。

背景信息:万一有人好奇,我在NCSIM中遇到了关于" urandom_range"的错误。 (但不是" urandom")无论如何,对函数的第一次调用总是返回最小指定值。但随后的所有电话都运转良好。