1

In the following code why is seed value getting altered each time it enters for loop? http://www.edaplayground.com/x/J8s

module Tb();    
integer num,seed,i,j;   

initial   
begin    
    seed = 0;

    for(j = 0;j<10 ;j=j+1)    
    begin    
        num = { $random(seed) } % 10;    
        $write("| num=%2d |",num);    
        $display(" seed is %d ",seed);    
    end    
end    
endmodule 
Jerry Coffin
  • 3,336
  • 17
  • 18
Abhi
  • 131
  • 1
  • 2
  • 11

2 Answers2

2

Consider the following two example modules:

module test_1;
  integer seed_a = 123, seed_b = 123, seed_c = 123;
  initial begin
    $display("A1: %d", $random(seed_a));
    $display("A2: %d", $random(seed_a));
    $display("A3: %d", $random(seed_a));

    $display("B1: %d", $random(seed_b));
    $display("B2: %d", $random(seed_b));
    $display("B3: %d", $random(seed_b));

    $display("C1: %d", $random(seed_c));
    $display("C2: %d", $random);
    $display("C3: %d", $random);

    $display("%d %d %d", seed_a, seed_b, seed_c);
  end
endmodule

module test_2;
  initial begin
    $display("X1: %d", $random);
    $display("X2: %d", $random);
    $display("X3: %d", $random);
  end
endmodule

The first one will produce the following output:

$ iverilog -s test_1 test.v && ./a.out 
A1: -2138988031
A2:   511825213
A3:  -650842958
B1: -2138988031
B2:   511825213
B3:  -650842958
C1: -2138988031
C2:   303379748
C3: -1064739199
 1496640334  1496640334     8495488

And the 2nd one the following:

$ iverilog -s test_2 test.v && ./a.out 
X1:   303379748
X2: -1064739199
X3: -2071669239

(The C code for $random is part of the Verilog standard. So it should be guaranteed that the values are the same for every implementation. Which is a problem in its own because the standardized Verilog RNG is not very good.)

What can we see from this? Unlike the C stdlib function srandom() that sets a state variable internal to the C random() implementation, the Verilog $random seed argument causes the passed variable to be used as RNG state variable. The default state variable internal to $random is untouched by such a call to $random. Imo the "seed" argument is a misnomer. It should be called "state" instead.

In test_2 we call $random three times with no seed argument. So we see the sequence of numbers generated by $random when its internal state variable is used (the internal state variable is initialized to 0 btw).

In test_1 we first call $random three times with seed_a. Each of those calls will perform one turn of the RNG algorithm, return a random variable and set seed_a to the new internal state. Then, we do the same thing with seed_b and yield the same sequence of numbers (and the same final state in state_b).

Finally we try to use $random(seed_c) in an attempt to set the internal state variable and assume that it is going to be uses in subsequent calls, like you would expect for a "seed value" from other languages APIs, but this fails. Instead we see the same numbers in subsequent calls that we would get if we just used $random for the first time: The subsequent numbers match the numbers produced by test_2.

So in summary: The "seed" argument to $random does not only pass a seed value, it specifies the state variable for the RNG. Thus it will not only read the seed value from this argument but also write its new state (aka "new seed value") back to the variable. This is also why you can't call $random with a constant as seed value. You must specify a variable.

CliffordVienna
  • 471
  • 3
  • 4
1

http://www.asicguru.com/verilog/tutorial/system-tasks-and-functions/68/

$random generates a random integer every time it is called. If the sequence is to be repeatable, the first time one invokes random give it a numerical argument (a seed). Otherwise the seed is derived from the computer clock.

Syntax

xzz = $random[(integer)];

So, "seed" are re-generated in every iteration of the loop.

diverger
  • 5,828
  • 5
  • 43
  • 79
  • Unfortunately this "the first time one invokes random give it a numerical argument (a seed)" business is incorrect. It describes how it is done in most languages, but the Verilog $random interface works differently. See my answer for details. – CliffordVienna Nov 24 '14 at 09:01