SystemVerilog Randomization & Random Number Generation¶

Buy Me A Coffee

SystemVerilog has a number of methods to generate pseudo-random numbers - $random, $urandom, $urandom_range, object.randomize, std::randomize and many more. We look at how these methods are different and when to use each of them.

Pseudo Random Number Generation¶

The random number generation methods provided by SystemVerilog can be broadly classified into 3 categories

  1. Constrained Pseudo Random Number Generators
  2. Non-Constrained System Functions
  3. Probabilistically distributed Random Number Generators

There are 2 important facts regarding the above 3 categories

PRNG

1. Constrained PRNG - obj.randomize & std::randomize ¶

/* Example 1.1 */ program automatic test; class pkt; logic [15:0] pkt_size; function new(); pkt_size = 100; endfunction: new function logic [7:0] get_num(); logic [7:0] scope_var; // When this function is called, randomize class // member var 'pkt_size' using the class's // in-built randomize method randomize(pkt_size); // Using SV std lib's scope randomize this // function's local'scope_var' std::randomize(scope_var); $display("pkt.get_num: pkt_size %0d scope_var %0d", pkt_size, scope_var); endfunction: get_num endclass: pkt initial begin pkt p; p = new(); p.get_num(); end endprogram
OUTPUT: pkt.get_num: pkt_size 826 scope_var 62
. function logic [7:0] get_num(); logic [7:0] scope_var; /* Interchanging the class & scope randomize usage */ // Using the class's in-built randomize std::randomize(pkt_size); // Using Class-Randomize function randomize(scope_var); $display("pkt.get_num: pkt_size %0d scope_var %0d", pkt_size, scope_var); endfunction: get_num . 
OUTPUT (From Synopsys VCS): Error-[MFNFIOR] Constraint: member field prng1.sv, 59 test, "scope_var" Member field scope_var not found in object this in randomize call. Only direct class members or member array elements can be referenced as arguments to object randomize. 1 error OUTPUT (From Mentor Questa) ** Error: prng1.sv(59): (vlog-2934) Argument for randomize() function must be a field of 'this'.
. /* Example using Constraints */ // Using the class's in-built randomize randomize(pkt_size) with < pkt_size inside ; >; // Using SV std lib's scope randomize std::randomize(scope_var) with < scope_var inside ; >; . 
program automatic test; class pkt; rand logic [7:0] saddr, daddr; rand logic [3:0] etype; logic [15:0] pkt_size; function new(); pkt_size = 100; endfunction: new endclass: pkt initial begin pkt p; p = new(); for (int i=0; i saddr %d, daddr %d, etype %d, pkt_size %d", i ,p.saddr, p.daddr, p.etype, p.pkt_size); end end endprogram
OUTPUT: p[0] -> saddr 64, daddr 2, etype 14, pkt_size 100 p[1] -> saddr 107, daddr 193, etype 0, pkt_size 100 p[2] -> saddr 86, daddr 157, etype 9, pkt_size 100 p[3] -> saddr 69, daddr 171, etype 12, pkt_size 100 p[4] -> saddr 122, daddr 135, etype 11, pkt_size 100

Seeding¶

There are 2 ways to set the random seed of an object -

pkt.seeding: pkt_size 56668 scope_var 62
# Synopsys-VCS % ./simv +ntb_random_seed=10 # Mentor-Questa % vsim -c test -sv_seed 10 -do "run -all"

Example 1.5A & 1.5B

* Example 1.5A & 1.5B */ program automatic test; class pkt; logic [15:0] pkt_size; function void seeding(int seed); logic [7:0] scope_var; $display("seeding: seed is %0d", seed); // Call srandom only if the seed arg is non-zero if (seed != 0) this.srandom(seed); randomize(pkt_size); std::randomize(scope_var); $display("pkt.seeding: pkt_size %0d scope_var %0d", pkt_size, scope_var); endfunction: seeding endclass: pkt initial begin pkt p; p = new(); if ($value$plusargs("SEED=%d", seed)) begin $display("SEED entered %0d", seed); end else begin seed = 0; end // Example 1.5A // Call srandom from within the class function `ifdef EX_1_5A p.seeding(seed); `endif // Example 1.5B // Call obj.srandom() to set the seed `ifdef EX_1_5B p.srandom(seed); // Pass seed function arg as 0 so that the seeding function // does not call srandom. p.seeding(0); `endif end endprogram

If the above 2 points were a little confusing, or if you would like to know how seeds affect random number generators - check out this article on Random Stability

2. Non-Constrained System Functions - $urandom & $urandom_range ¶

program automatic test; initial begin int unsigned var_a; logic [63:0] var_b; logic [7:0] var_c; var_a = $urandom(); var_c = $urandom_range(10, 20); $display("var_a 0x%x var_c 0x%x", var_a, var_c); var_b = $urandom(); $display("Using $urandom() to randomize 64bit var, var_b = 0x%x", var_b); //var_b = $urandom() ; $display("Using concat $urandom(), var_b = 0x%x", var_b); std::randomize(var_b); $display("std::randomize(var_b) = 0x%x", var_b); end endprogram
OUTPUT: var_a 0x0c62b465 var_c 0x0c Using $urandom() to randomize 64bit var, var_b = 0x0000000084ddb13d Using concat $urandom(), var_b = 0x4a768d1860367d0f std::randomize(var_b) = 0x7a4a73cb0e12f31f

Seeding¶

Here again you have 2 ways to set the random seed

program automatic test; initial begin int unsigned var_a, var_d, seed; logic [63:0] var_b; if ($value$plusargs("SEED=%d", seed)) begin $display("SEED entered %0d", seed); end else begin seed = 20; end var_a = $urandom(seed); var_b = $urandom(); var_d = $urandom_range(10, 2000); $display("var_a 0x%x var_b 0x%x var_d 0x%x", var_a, var_b, var_d); end

Once again, for more on this checkout Random Stability.

3. Probabilistically Distributed PRNGs - $random, $dist_normal, $dist_poisson . ¶

This excerpt from the SystemVerilog LRM 1800-2012 best explains what this category includes -

In addition to the constrained random value generation, SystemVerilog provides a set of RNGs that return integer values distributed according to standard probabilistic functions. These are: $random, $dist_uniform, $dist_normal, $dist_exponential, $dist_poisson, $dist_chi_square, $dist_t, and $dist_erlang.The value generation algorithm for these system functions is part of this standard, ensuring repeatable random value sets across different implementations. The C source code for this algorithm is included in Annex N.

program automatic test; initial begin int var_a, var_b, seed; seed = 10; for (int i=0; i var_a %d var_b %d", i, var_a, var_b); end end endprogram
CONSOLE OUTPUT: 0 -> var_a 303379748 var_b 100 1 -> var_a -1064739199 var_b 103 2 -> var_a -2071669239 var_b 110
program automatic test; initial begin int var_a, var_b, var_c, seed, seed1, seed2, seed3; // Using 3 different seed vars for a specific reason. // Read the seeding section next to find out why. seed1 = 10; seed2 = 10; seed3 = 10; for (int i=0; i; var_b = $random(seed2)%50; var_c = %50; $display("$random %0d -> var_a %d var_b %d var_c %d", i, var_a, var_b, var_c); end end endprogram
CONSOLE OUTPUT: # $random 0 -> var_a -2146792448 var_b -48 var_c 48 # $random 1 -> var_a -1686787018 var_b -18 var_c 28 # $random 2 -> var_a 576097604 var_b 4 var_c 4 # $random 3 -> var_a 1855681501 var_b 1 var_c 1 # $random 4 -> var_a -390931759 var_b -9 var_c 37

Seeding¶

program automatic test; initial begin int var_a, seed; seed = 10; for (int i=0; i
CONSOLE OUTPUT: Loop #0. var_a -2146792448 next-seed 690691 Loop #1. var_a -1686787018 next-seed 460696424 Loop #2. var_a 576097604 next-seed -1571386807 Loop #3. var_a 1855681501 next-seed -291802762 Loop #4. var_a -390931759 next-seed 1756551551
Warning-[STASKW_ISATDP] Illegal seed argument prng3.sv, 31 Expecting seed, an integer variable as the first argument to '$dist_poisson', but an argument of invalid type is passed. Please pass an integer variable as the first argument to '$dist_poisson'.
program automatic test; initial begin int var_a, var_b, seed1, seed2; seed1 = 20; seed2 = 20 for (int i=0; i5; i++) begin var_a = $random(seed1); var_b = $random(seed2); $display("$random #%0d -> var_a %d var_b %d", i, var_a, var_b); end end endprogram
OUTPUT: $random 0 -> var_a -2146101760 var_b -2146101760 $random 1 -> var_a -1226159507 var_b -1226159507 $random 2 -> var_a -1470918064 var_b -1470918064 $random 3 -> var_a -1713525709 var_b -1713525709 $random 4 -> var_a 592620358 var_b 592620358

In a Nutshell¶

So, when do you use what?

If you found this content useful then please consider supporting this site! 🫶