Why regA
and regB
have two different values, while regC
and regD
work as I would expect?
reg signed [31:0] regA;
reg signed [31:0] regB;
reg signed [15:0] regC;
reg signed [15:0] regD;
initial begin
regA = 0.006 * 2**31;
regB = 0.006 * (32'b1 << 31);
regC = 0.006 * 2**15;
regD = 0.006 * (16'b1 << 15);
$display("regA = 0x%b, %d", regA, regA);
$display("regB = 0x%b, %d", regB, regB);
$display("regC = 0x%b, %d", regC, regC);
$display("regD = 0x%b, %d", regD, regD);
end
Icarus Verilog returns this
regA = 0x11111111001110110110010001011010, -12884902
regB = 0x00000000110001001001101110100110, 12884902
regC = 0x0000000011000101, 197
regD = 0x0000000011000101, 197
In the case of regA, you have a signed 32-bit data type that is overflowing and wrapping around to a negative value. The other cases are not overflowing.
When you write a bare numeric literal like 2
, you get a signed 32-bit value. With 32'b1
you get an unsigned 32-bit value. So regA/regC are signed 32-bit, regB/regD are unsigned 32-bit. And 2**31
is the point at which the signed 32-bit type will overflow, vs. 2**32
for unsigned 32-bit. So only the regA calculation is overflowing.
Note that all of the integer calculations are happening before the conversion to floating point, so the multiply by 0.006 doesn't come into play here.