I am sharing a simple SystemVerilog code where the ternary operation is misbehaving because of the reduction or ("|b") operation. I know many other work arounds. I just wanted to know what's going wrong here under the hood.
module tb();
bit signed [0:3] a = 5;
bit signed [0:3] b = -3;
bit [0:1] op;
bit signed [0:4] result;
initial begin
op = 0;
result = 0;
result = (op == 0)? a+b : (op == 1)? a-b: (op == 2)? ~a : |b;
$display("%0p %0p %0p", result, a, b);
op = 1;
result = 0;
result = (op == 0)? a+b : (op == 1)? a-b: (op == 2)? ~a : |b;
$display("%0p %0p %0p", result, a, b);
op = 2;
result = 0;
result = (op == 0)? a+b : (op == 1)? a-b: (op == 2)? ~a : |b;
$display("%0b %0b %0p", result, a, b);
op = 3;
result = 0;
result = (op == 0)? a+b : (op == 1)? a-b: (op == 2)? a : |b;
$display("%0p %0p %0p", result, a, b);
end
endmodule
I am sharing the code here. I am sure that the unary operation is to blame here. if I put only "b" instead of "|b" it will work as expected.
The problem with your code is both the different bit lengths and mixing signed and unsigned operands in the same expression.
In almost all binary operations, i
op j
, the operands i
and j
are transformed in context with one another. That means if the operands are of different lengths, the smaller one gets 0-extended or signed-extended. Sign extension only happens if all operands in that context are signed. The extension of operands happens before applying the operator.
With ternary operator i
? j
: k
, i
is self-determined and is not in context with j
and k
which are with each other. The left-hand-side of an assignment is in context with its right-hand-side.
In your example, result
is a 5-bit signed variable, and the variables a
and b
are both 4-bit signed variables. That means all operands need to be extended to 5-bits. However, with the operation |b
, b
is self determined but its result is 1-bit unsigned. That result becomes an unsigned operand to the ternary operator, that means the entire expression context is unsigned. So b
gets zero-extended instead of sign-extended.
Section 11.8.2 Steps for evaluating an expression in the IEEE 1800-2023 SystemVerilog LRM goes over this in detail.
You could work around this problem if