For some reason I have been unable to find any definitive resources or stackoverflow questions answering this:
Does verilog take care of input and output dimensions when multiplying signed numbers?
To be specific, what happens if I multiply a signed 32-bit with a signed 64-bit number? So if I have:
reg signed [31:0] a = -5;
reg signed [63:0] b = 5;
wire signed [63:0] c;
assign c = a*b;
Will c be equal to -25 (in 64-bit 2's complement scheme)?
What if I declared c as a 32 bit number? Would it still be -25 (in 32 bit 2's complement scheme)?
Thanks!
i) The multiplication operator in Verilog is leads to what is called a context-determined expression. The width used for the arithmetic in a self-determined expression depends on the widths of the operands and the result. With
assign c = a*b;
the width used for the multiplication will be the widest of a
, b
and c
. In your case, b
is the widest at 64 bits, so 64-bit arithmetic will be used for the multiplication.
You are then assigning the result to a 32-bit wide wire
- c
. So, the 64-bit result will be truncated to 32 bits; the MSBs will be lost, which may lead to a strange result, eg:
reg signed [3:0] a = 3;
reg signed [7:0] b = 63;
wire signed [3:0] c;
assign c = a*b;
http://www.edaplayground.com/x/f3b
Gives c
a value of -3
, because whilst the multiplcation is done using 8 bits (the widest of a
, b
and c
) and signed arithmetic is used (because both a
and b
are signed), the result is 189, which when truncated to a 4-bit signed number is -3.
So, it is up to you to use suitable widths for your expected range of operands.
ii) In Verilog, if you mix unsigned and signed operands, unsigned arithmetic will be used. So, in your case, as both operands are signed, signed arithmetic will be used. (Whether the result is unsigned or signed is irrelevant.)