Urandom_range with small maxval type

Hi,

I just noticed something interesting regarding $urandom_range. When using a type of 4b or smaller for specifying the max value $urandom_range will always return 0. $urandom_range works as expected when using a type > 4b for the max value.

Consider the following example. I have a VHDL package where I’ve defined a number of constants:

  subtype test5_t is unsigned(4 downto 0);
  constant TEST5_MAX : test5_t := "11111";

  subtype test4_t is unsigned(3 downto 0);
  constant TEST4_MAX : test4_t := "1111";

I noticed that when using a type smaller than 4b for calling $urandom_range I always get a zero output:

int test5 = $urandom_range(0, test_custom_pkg::test5_max);
int test4 = $urandom_range(0, test_custom_pkg::test4_max);
$info("UT: test5_max=%0d, test5=%0d", test_custom_pkg::test5_max, test5);
$info("UT: test4_max=%0d, test4=%0d", test_custom_pkg::test4_max, test4); 

Output:

# ** Info: UT: swap test5_max=31, test5=15
# ** Info: UT: swap test4_max=15, test4=0   // This is wrong. It always returns 0

Is this expected? The SV LRM states that urandom_range should be called with a unsigned int so you could argue that this is undefined behavior. Still this is quite unexpected.

I have tested this on Questa 2019.4_2. Any input is appreciated.

There is no portability between VHDL packages and SV packages, so you need to somehow create the equivalent SV package. Some tools will do this for you automatically, but if there is a tool issue, you will need to contact your tool vendor for support.

The following pure SV code works:

package test_custom_pkg;
  //subtype test5_t is unsigned(4 downto 0);
  //constant TEST5_MAX : test5_t := "11111";
  typedef bit[4:0] test5_t;
  const test5_t test5_max = 5'b11111;

  //subtype test4_t is unsigned(3 downto 0);
  //constant TEST4_MAX : test4_t := "1111";
  typedef bit[3:0] test4_t;
  const test4_t test4_max = 4'b1111;

endpackage

module testbench();
  int test4, test5;
  
  initial begin
    repeat (10) begin
      test5 = $urandom_range(0, test_custom_pkg::test5_max);
      test4 = $urandom_range(0, test_custom_pkg::test4_max);
      $info("UT: test5_max=%0d, test5=%0d", test_custom_pkg::test5_max, test5);
      $info("UT: test4_max=%0d, test4=%0d", test_custom_pkg::test4_max, test4);
    end
  end
endmodule