$urandom_range('0, '1) gives single bit output

I have searched regarding this on forum but couldn’t find so posting this question assuming a fresh question.
My code is below,

module test;
  bit [3:0] var_a;
  initial begin
    var_a = $urandom_range ('0, '1);
    $display("var - %0d",var_a);
  end
endmodule

Easy ! Isn’t it?
And I had an expectation that var_a will be printed with value between 0x0 and 0xF but to my surprise it is randomized between 1’b1 and 1’b0.
I could not understand why SV considered as single bit width ? (This behavior is same across all tools so it does not seem to be related with any specific tool)

Found this line from IEEE SV doc,

In a self-determined context, an unsized single-bit value shall have a width of 1 bit, and the value shall be treated
as unsigned.

But I could not relate this text with the code.

Below code is working as expected,

module test;
  bit [3:0] a;
  initial begin
    a = randomize_range ('0, '1);    
    $display("a - %0d",a);
  end
  function int unsigned randomize_range (int unsigned min, int unsigned max);
    randomize_range = $urandom_range (min, max);
  endfunction
endmodule

Can anyone help me with the first code output with explanation?

Hey good find. That’s pretty neat. My guess would be that this is a compile / elaboration / simulation time issue, where the compiler might not know the type and size of a system function input, and so defaults to a single bit. Later on at elaboration or simulation time the simulator sees that the function input is actually 32-bits, but the compiler has already set the literal to 1-bit. Dave will know the right answer though.

For improvements see:

https://accellera.mantishub.io/view.php?id=4910

In reply to sbellock:

The difference is which situation is a self-determined context, or part of another expression/assignment context. According to section 10.8 Assignment-like contexts, passing a value to a subroutine (task/function) is an assignment-like context. By omission, arguments to system tasks are self-determined.

BTW, it would probably be more efficient to simply write

var_a = $urandom;

In reply to dave_59:

Thanks Guys !

If I understood Dave’s reply correctly, below is the summary/assumption I could make.

  • assignments to a system task = Self Determined = unsized literal will be considered as single bit size
  • assignments to a user task = Context Determined = unsized lieteral will be expanded to a size of argument of a called user task.

If this is the understanding then it seems very dangerous because this does not seem to be clarified properly (Atleast to me) in LRM.

Please let me know if my understanding is improper.

In reply to dave_59:

Thanks Dave. So when the LRM says:

No other contexts shall be considered assignment-like contexts. In particular, none of the following shall be considered assignment-like contexts:
— A static cast

Does this mean that the code


typedef int unsigned uint;
var_a = $urandom_range (uint'('1));

should give the same result as the original question?

In reply to supal:
Your understanding is correct. It’s a complex trade off between enumerating all the possible scenarios and excluding something by mistake versus creating general rules that leaves it up to your own judgement. System tasks have to work this way in order to implement routines like $display, $signed, etc.

In reply to sbellock:

This does need clarification. The intent is that the expression inside the cast is not under the context of anything outside the static cast—t’s only under the context of the static casting type.

In reply to dave_59:

So to mirror supal’s statement, for clarity, it seems like the

No other contexts shall be considered assignment-like contexts. In particular, none of the following shall be considered assignment-like contexts:

section should include system functions and tasks.

Thanks both of you guys for the response ! We can close this thread assuming nothing more to be discussed on this.

What is a take away for me from this ? LRM is still required to be improved in this context and till then we can assume below,

  • assignments to a system task = Self Determined = unsized literal will be considered as single bit size
  • assignments to a user task = Context Determined = unsized lieteral will be expanded to a size of argument of a called user task.