How to get different randomization across different instances of the same module

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?

Thanks,
Danny

In reply to dannyg:

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