Hi,
I use the $urandom_range function to generate a random number for a class that is located inside a module.
I make 2 instances of this module. Once I call the function that uses $urandom_range I get the same results for 2 different instances - even if I call the function at different simulation times between the modules.
Code:
class main_class;
int b;
function local_urandom();
b = $urandom_range(100,10);
endfunction : local_urandom
endclass : main_class
module leaf_mdl();
main_class a;
logic c;
always @(posedge c) begin
a.local_urandom();
$display("In local_urandom %0t %m - %0d", $time, a.b);
end
initial begin
a = new();
c = 0;
end
endmodule
module main_mdl();
leaf_mdl#() leaf_mdl_inst0 ();
leaf_mdl#() leaf_mdl_inst1 ();
initial begin
#2;
leaf_mdl_inst0.c = 1;
#1000;
leaf_mdl_inst1.c = 1;
#2;
$display ("module A value - %0d, module B value %0d\n", leaf_mdl_inst0.a.b, leaf_mdl_inst1.a.b);
$finish;
end
endmodule
I run main_mdl, which instantiates 2 leaf_mdl. Once C is set to 1 we use $urandom_range function.
I always get the same results for both of the modules, and I expect to get different results.
Is there an LRM compliant way to achieve this?
I can think of two methods for doing this in an LRM compliant way.
Re-seed the process calling $urandom with a value based on it’s path. You would need to this for every process that calls $urandom/_range
function void reseed;
process p;
int seed;
static string path = $sformatf("%m");
p = process::self();
seed = $urandom; // initialize with master seed
foreach(path[i])
seed = seed*31 + path[i]; // "unique" hash equation
p.srandom(seed);
endfunction
always @(posedge c) begin
bit seeded;
if (!seeded) begin
reseed();
seeded = 1;
end
a.local_urandom();
$display("In local_urandom %0t %m - %0d", $time, a.b);
end
Note that some tools have a magic switch that implements this behavior for you.
Another approach is creating a singleton class object and use its random state. This is the most randomly stable approach as changes in module names or hierarchy will not affect random seeding.
class main_class;
rand int b;
local static main_class singleton;
local function new;
endfunction
static function main_class get;
if(singleton==null)
singleton = new();
return singleton;
endfunction
function int local_urandom;
assert( randomize() with {b inside {[10:100]};} );
return b;
endfunction
endclass : main_class
module leaf_mdl();
main_class a;
int b;
logic c;
always @(posedge c) begin
b =a.local_urandom();
$display("In local_urandom %0t %m - %0d", $time, b);
end
initial begin
a = main_class::get();
c = 0;
end
endmodule
module main_mdl();
leaf_mdl#() leaf_mdl_inst0 ();
leaf_mdl#() leaf_mdl_inst1 ();
initial begin
#2;
leaf_mdl_inst0.c = 1;
#1000;
leaf_mdl_inst1.c = 1;
#2;
$display ("module A value - %0d, module B value %0d\n", leaf_mdl_inst0.b, leaf_mdl_inst1.b);
$finish;
end
endmodule