Difficulty: Medium · Puzzle 4 of 6 · Topic: Datatype and Bit Puzzles
Predict all five lines and explain which expressions are evaluated as unsigned.
module p4;
logic signed [7:0] s = -8'sd2; // 1111_1110
initial begin
$display("slice=%0d", s[7:4]);
$display("signed_slice=%0d", $signed(s[7:4]));
$display("shift=%0d", s >>> 4);
$display("cmp=%0d signed_cmp=%0d", s[7:4] > 4'sd0, $signed(s[7:4]) > 4'sd0);
$display("plus=%0d", s[7:4] + 4'sd1);
end
endmodulePart-select expressions lose signedness unless you cast them. `>>>` uses the signedness of the left operand. Once any operand of a comparison or an addition is unsigned, the whole expression is unsigned.
1) `s[7:4]` is 4'b1111 but a part-select expression is unsigned by default, so decimal is 15.
2) `$signed(s[7:4])` reinterprets 4'b1111 as signed -1.
3) `s >>> 4` arithmetic-shifts signed -2 to -1, so it matches line 2, not line 1.
4) `s[7:4] > 4'sd0` mixes an unsigned part-select with a signed constant, so the compare is unsigned: 15 > 0 is 1. With `$signed(...)` both sides are signed: -1 > 0 is 0.
5) `s[7:4] + 4'sd1` is an unsigned 4-bit add: 15 + 1 wraps to 0.Answer: slice=15, signed_slice=-1, shift=-1, cmp=1 signed_cmp=0, plus=0
Checked by running the code in Icarus Verilog 13 and Verilator 5; the printed output supports the answer above. A part-select is unsigned until you cast it. (Icarus, 4-state) A part-select is unsigned until you cast it. (Verilator, 2-state)
`s[7:4]` looks like a slice of a signed vector but is unsigned, so `s[7:4] > 4'sd0` is true (15 > 0) until you wrap it in `$signed`, and `s[7:4] + 4'sd1` wraps 15 to 0 instead of giving -1 + 1.
How would `s >> 4` differ from `s >>> 4` in this example? Model answer: `s >> 4` is a logical shift, it zero-fills even though s is signed, giving 8'b0000_1111 = 15; `s >>> 4` sign-fills and gives -1.
I would remember that a part-select is always unsigned, even from a signed vector. So the slice prints 15, the signed cast of the slice is minus 1, and the arithmetic shift of the whole signed value gives minus 1 as well. The compare of the plain slice against zero is unsigned, so true, but with the signed cast it is minus 1 against 0, which is false, and the plain add wraps 15 plus 1 to 0. The trap is trusting that the slice inherits the sign. I would check each place a slice enters a comparison or an add.