Menu

#1030 Icarus is not random-stable

devel
closed-invalid
nobody
None
5
2018-06-01
2018-05-31
No

In other words, random sims can't be reproduced. When random stability is important, '$random(n)' is called to set a seed, and '$random' then steps within that sequence. If you find a bug in your RTL for a given seed, you then debug using the same seed.

For this code:
r0 = $random(1);
r1 = $random;
'r1' should always have the same value, which isn't the case in Icarus.

Attached test code, and output for Icaus and ModelSim. Vivado produces the same output as ModelSim; I haven't checked anything else.
Thanks.

3 Attachments

Discussion

  • Martin Whitaker

    Martin Whitaker - 2018-05-31
    • status: open --> closed-invalid
     
  • Martin Whitaker

    Martin Whitaker - 2018-05-31

    If you want random stability, you need to pass your seed variable to every call to $random, not just the first. In the IEEE standard, this is (poorly) explained in the section on $dist functions:

    "For each system function, the seed argument is an inout argument; that is, a value is passed to the function, and a different value is returned. The system functions shall always return the same value given the same seed. This facilitates debugging by making the operation of the system repeatable. The seed argument should be an integer variable that is initialized by the user and only updated by the system function. This ensures the desired distribution is achieved."

    This applies to $random too. This allows you to have multiple independent random sequences.

    If you call $random without a seed argument, Icarus uses an internal seed variable which is unaffected by any call to $random with a seed argument. Verilog-XL and NC-Verilog do the same, and give the same results as Icarus for your test code.

     
  • Evan Lavelle

    Evan Lavelle - 2018-06-01

    Hi Martin - thanks; that surprised me. I've tried the code on EDA Playground, and VCS agrees with ModelSim, while Icarus, Riviera (which I think normally follows ModelSim), GPL-CVer, and Veriwell agree with XL.

    The problem is that the section you've quoted makes sense for $random(n), but it doesn't cover the case where no seed is provided. The LRM appears to have nothing to say about this. '$random' clearly can't map on to 'rtl_dist_uniform(seed, LONG_MIN, LONG_MAX)' as no seed is supplied, and 'rtl_dist_uniform' requires a valid seed pointer. So, basically, the behaviour is undefined here.

    ModelSim and VCS (and Vivado, probably copied from ModelSim behaviour) take the C library approach: 'srand' sets the seed, and 'rand' uses the previously-set seed, and the library calls are guaranteed not to call [s]rand behind your back. So, basically, they have an internal static copy of the seed. This allows them to ignore the requirement that the seed should be an lvalue, and they both do - you can supply the seed as a constant.

    Everybody else does something completely different: they assume that you actually supplied an lvalue which was initially set to 0. So, they also keep an internal seed, and just start it at zero. Why zero, ie. why do they all show the same results? This isn't in the LRM, so they're applying special knowledge - what XL actually did, as you've pointed out.

    My own conclusion is that both approaches are wrong, according to the LRM. My personal view is that the C one makes more sense. The other approach requires you all to agree on the magic zero, and also requires an internal static seed anyway.

    But, bythe laws of Verilog, XL still wins, so I agree, no bug.

    Thanks -

    Evan

     

Log in to post a comment.