Difficulty: Medium · Puzzle 6 of 6 · Topic: Datatype and Bit Puzzles
Predict the six output lines. Where does the carry of 200 + 100 survive, and where is it lost?
module p6;
bit [7:0] a = 200, b = 100;
bit [8:0] c;
initial begin
$display("t1=%0d", a + b);
$display("t2=%0d", (a + b) >> 1);
$display("t3=%0d", {1'b0, a} + b);
c = a + b; $display("t4=%0d", c);
c = (a + b) >> 1; $display("t5=%0d", c);
$display("t6=%0d", int'(a) + b);
end
endmoduleA `$display` argument is self-determined: its width is the widest operand inside it. On the right side of an assignment the width is the maximum of the left-hand side and all operands, and that context also reaches the left operand of a shift.
1) In `$display` the expression `a + b` is self-determined at 8 bits, so 300 wraps to 300 - 256 = 44.
2) `(a + b) >> 1` is still 8 bits: 44 >> 1 = 22.
3) `{1'b0, a}` is 9 bits, so the add is done in 9 bits and keeps the carry: 300.
4) `c = a + b`: the assignment context is 9 bits (the width of c), so the add is done in 9 bits: 300.
5) `c = (a + b) >> 1`: the 9-bit context also applies to the left operand of the shift, so the sum is 300 before shifting and the result is 150, not 22.
6) `int'(a)` makes the add 32 bits wide: 300.Answer: t1=44, t2=22, t3=300, t4=300, t5=150, t6=300
Checked by running the code in Icarus Verilog 13 and Verilator 5; the printed output supports the answer above. Context width decides whether the carry survives. (Icarus, 4-state) Context width decides whether the carry survives. (Verilator, 2-state)
The same source text `(a + b) >> 1` gives 22 inside `$display` but 150 when assigned to a 9-bit variable, because width is decided by context, not by the operands alone.
Without declaring a wider variable, how do you make the `t1` expression print 300? Model answer: make one operand wider before the add, for example `a + 9'(b)`, `{1'b0, a} + b` or `a + b + 9'd0`; the add is evaluated at the width of its widest operand, so any wider operand keeps the carry.
I would find the width of the context first, because the width of an add depends on where it is used. Inside the display the add is only 8 bits, so 300 wraps to 44 and the shift gives 22. Assigned to a 9-bit variable, the add is done in 9 bits, so it keeps 300 and the shifted result is 150, and a 9-bit or 32-bit operand also keeps the carry. The trap is that the same source text gives 22 in one place and 150 in another. I would check the widest operand and the destination width every time I see an add.