Consider the following code:
module test;
reg signed [3:0] signed_reg3 = 4;
reg ubit = 0;
initial begin
$display("! => typename: %s, size: %d, %d", $typename(!ubit), $bits(!ubit), signed_reg3 - !ubit);
$display("~ => typename: %s, size: %d, %d", $typename(~ubit), $bits(~ubit), signed_reg3 - ~ubit );
end
endmodule
The result in the simulator of the two prints is:
! => typename: reg, size: 1, 3
~ => typename: reg, size: 1, 5
(Here is the Demo ) As we can see, there is a difference in the result of evaluation of the following two arithmetic expressions:
signed_reg3 - !ubit
signed_reg3 - ~ubit
In the first case the !ubit
result is interpreted as unsigned value, while in the second, ~ubit
seem to be interpreted as signed. This is something I do not understand, as the same print is showing that both type and size of either result is the same (reg
of size 1
bit).
Please explain what is happening here.
You are displaying the result of $bits
in a different context from when used within an arithmetic expression.
Table 11-21 shows the logical-not !
returning a 1-bit result and its operand is self-determined. Whereas the bitwise-not ~
returns a bit width of its context determined operand. The fact that !
always returns a 1-bit value is something that was further clarified in the next revision of the IEEE 1800-2017 SystemVerilog LRM.
Section 11.8.2 Steps for evaluating an expression explains how the bit-widths get propagated through context determined expressions.
To summarize
signed_reg3 - !ubit
The logical negation applies to the 1-bit value ubit
before it gets extended to 4-bits because its operand is self-determined.
signed_reg3 - ~ubit
Since ~ubit
is part of the context of the subtraction operator, its operand gets extended before bitwise-negation and subtraction.