Difficulty: Medium · Puzzle 2 of 6 · Topic: Datatype and Bit Puzzles
What are the three outputs, and why does the first comparison surprise people?
module p2;
logic signed [3:0] s = -1;
logic [3:0] u = 4'h1;
initial begin
$display("s<u=%0d", s < u);
$display("$signed(u)>s=%0d", $signed(u) > s);
$display("s+u=%0d", s + u);
end
endmoduleMixed signed/unsigned expressions follow conversion rules before the operator executes. Also check expression width.
1) In `s < u`, `u` is unsigned, so `s` is converted to unsigned 4'b1111 (15); 15 < 1 is false.
2) `$signed(u)` forces signed compare in second line: 1 > -1 is true.
3) `s + u` is still mixed signed/unsigned at 4-bit width: 15 + 1 wraps to 0.Answer: s<u=0, $signed(u)>s=1, s+u=0
Checked by running the code in Icarus Verilog 13 and Verilator 5; the printed output supports the answer above. One unsigned operand makes the whole compare unsigned. (Icarus, 4-state) One unsigned operand makes the whole compare unsigned. (Verilator, 2-state)
`s < u` is false although -1 < 1: one unsigned operand makes the whole comparison unsigned, so -1 becomes 4'b1111 = 15.
If `u` were declared `logic signed [3:0]`, what would `s<u` and `s+u` become? Model answer: both operands are signed, so s<u is 1 (-1 < 1) and s+u is 0 (-1 + 1).
I would first find the signedness of each operand, because one unsigned operand makes the whole comparison unsigned. So minus one becomes 4 bits of ones, which is 15, and 15 less than 1 is false, giving 0. With the signed cast the compare is 1 greater than minus 1, which is true, and the sum wraps to 0 at 4 bits. The trap is believing that the signed variable keeps the expression signed. Next I would check whether every operand in the expression is declared signed.