Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Problems with random number generation

Status
Not open for further replies.

BartlebyScrivener

Member level 5
Joined
Feb 8, 2012
Messages
90
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
2,081
Problems with SystemVerilog random number generation

For my test bench I need lots of independent random numbers. I have about 5 instances where I use a for loop and $urandom_range(x,y) to generate a selction of random numbers fine. However, I now want to be able to perform multiple runs of the simulation, changing the random number pattern each time. I looked in the standard, and it didn't appear that urandom_range accepts a seed, so I tried dist_uniform. But it doesn't work.

I wrote a basic test bench to see what the values I was getting were.


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module forloop;
 
  logic clk;
 
  initial begin
    clk = 1;
    forever #(1ns) clk = ~clk;
  end
  
  initial begin
    forever@(posedge clk) begin
      for (int i=0; i<10; i++) begin      
        $display("DU %g: %g", i,  $dist_uniform(0, 1, 100));
        $display("UR %g: %g", i, $urandom_range(1, 100));
      end
    end
  end
 
endmodule



and it appears the dist_uniform value remains constant irrespective of the for loop and irrespective of the for loop and clk?!

Is there a simple way to modify urandom_range so that I can ask for a new pattern?

How can I do this? Thanks.
 
Last edited:

Thanks, I'm still struggling with this though, which seed will that set and how would I call it? For example I have a few blocks using urandom in different ways...


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
logic [0:`NODES-1][log2(`X_NODES)-1:0] f_x_dest;
  logic [0:`NODES-1][log2(`Y_NODES)-1:0] f_y_dest;
  logic [0:`NODES-1][log2(`Z_NODES)-1:0] f_z_dest;
 
  logic [0:`NODES-1] i_en;
 
  always_ff@(posedge clk) begin
    if(~reset_n) begin
      for(int i=0; i<`NODES; i++) begin
          f_x_dest[i] <= 0;
          f_y_dest[i] <= 0;
          f_z_dest[i] <= 0;
      end
    end else begin
      for(int i=0; i<`NODES; i++) begin
          f_x_dest[i] <= $urandom_range(`X_NODES-1, 0);
          f_y_dest[i] <= $urandom_range(`Y_NODES-1, 0);
          f_z_dest[i] <= $urandom_range(`Z_NODES-1, 0);
      end
    end
  end
 
  always_ff@(posedge clk) begin
    if(~reset_n) begin
      for(int i=0; i<`NODES; i++) begin
        i_en[i] <= 0;
      end
    end else begin
      for(int i=0; i<`NODES; i++) begin
        i_en[i] <= ($urandom_range(100,1) <= `DOWNSTREAM_EN_RATE) ? 1 : 0;
      end
    end
  end



Which works fine, but the random number patterns are always the same each run. I would like to be able to change the pattern, but I'm not sure how!

Thanks for your time
 
Last edited:

start with a 'random' seed, such as the time - converted, of course, to a proper seed value
 

Thanks Kam, but I do not know how to seed urandom_range. For example, in the code given, nowhere do I pass a seed.
 

Random number system function has a argument called seed. The seed parameter controls the numbers that $random returns such that different seeds generate different random streams. The seed parameter shall be either a reg, an integer, or a time variable. The seed value should be assigned to this variable prior to calling $random. For each system function, the seed parameter is an in-out parameter; that is, a value is passed to the function
and a different value is returned.



EXAMPLE:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module Tb(); 
integer num,seed,i,j; 
 
initial 
begin 
for(j = 0;j<4 ;j=j+1) 
begin 
seed = j; 
$display(" seed is %d",seed); 
for(i = 0;i < 10; i=i+1) 
begin 
num = { $random(seed) } % 10; 
$write("| num=%2d |",num); 
end 
$display(" "); 
end 
end 
endmodule



RESULT:
seed is 0
| num= 8 || num= 7 || num= 7 || num= 7 || num= 7 || num= 7 || num= 5 || num= 2 || num= 1 || num= 9 |
seed is 1
| num= 8 || num= 8 || num= 2 || num= 2 || num= 6 || num= 3 || num= 8 || num= 5 || num= 5 || num= 5 |
seed is 2
| num= 8 || num= 1 || num= 0 || num= 5 || num= 0 || num= 8 || num= 6 || num= 7 || num= 1 || num= 6 |
seed is 3
| num= 8 || num= 2 || num= 2 || num= 3 || num= 8 || num= 6 || num= 1 || num= 4 || num= 3 || num= 9 |


The $random function has its own implicit variable as seed when the used is not giving explicitly giving seed. The following example shows that seed = 0 and implicit seed are having same sequence. It means that the implicitly taken seed is also 0.



EXAMPLE:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module Tb(); 
integer num,seed,i,j; 
 
initial 
begin 
seed = 0; 
 
for(j = 0;j<2 ;j=j+1) 
begin 
if(j ==0) 
$display(" seed is %d",seed); 
else 
$display(" No seed is given "); 
 
for(i = 0;i < 10; i=i+1) 
begin 
if( j == 0) 
num = { $random(seed) } % 10; 
else 
num = { $random() } % 10; 
$write("| num=%2d |",num); 
end 
$display(" "); 
end 
end 
endmodule



RESULT:
seed is 0
| num= 8 || num= 7 || num= 7 || num= 7 || num= 7 || num= 7 || num= 5 || num= 2 || num= 1 || num= 9 |
No seed is given
| num= 8 || num= 7 || num= 7 || num= 7 || num= 7 || num= 7 || num= 5 || num= 2 || num= 1 || num= 9 |

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 argument for the seed parameter 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.


http://testbench.in/TB_15_SYSTEM_FUNCTION_RANDOM_A_MYTH.html
 
Last edited by a moderator:
Ok, thanks for that, but I would like to pass a seed to $urandom_range as per the code I put up. I need to use random numbers with min and max values, similar to the code I put.
 

So I have written a test bench to try and work this out. It seems that if you initialise a single variable using $urandom(seed) then any $urandom_range(max,min) calls will begin a new pattern. So I will just have a dummy variable at the start of my program which I initialise with a seed value.


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
module forloop #(parameter SEED);
 
  logic clk;
  
  logic [0:49][0:2] a;
  logic [0:49][0:2] b;
  logic [0:49][0:2] c;
 
  initial begin
    clk = 1;
    forever #(1ns) clk = ~clk;
  end
  
  initial begin
    c=$urandom(SEED);
    for (int i=0; i<50; i++) begin      
      a[i] = ($urandom_range(100,1) <= 50) ? 1 : 0;
      b[i] = ($urandom_range(100,1) <= 50) ? 1 : 0;
      c[i] = $urandom_range(0,1);
      d[i] = $urandom_range(0,1);
    end
    $write("Seed %g Sequence a: ", SEED);
    for (int i=0; i<50; i++) begin   
      $write("%g, ", a[i]);
    end
    $write("\n");
    $write("Seed %g Sequence b: ", SEED);
    for (int i=0; i<50; i++) begin   
      $write("%g, ", b[i]);
    end
    $write("\n");
    $write("Seed %g Sequence c: ", SEED);
    for (int i=0; i<50; i++) begin   
      $write("%g, ", c[i]);
    end
    $write("\n");
  end
 
endmodule

 

There is no need to use $srandom here. All SystemVerilog simulators should a switch to set the seed. Modelsim/Questa has -sv_seed <arg> The <arg> can be a number or the word random which uses the system time to generate a seed. When you use the random seed, Questa will print out the chosen seed that that you can re-run the simulation for debugging if needed.

You should read section 18.14 on the SystemVerilog 1800-2012 which talks about random stability. Also, there is a DVCon12 presentation **broken link removed**.
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top