Signed arithmetics in Verilog: The only rule one needs to know

The golden rule is: All operands must be signed.

Verilog, it seems, is strongly inclined towards unsigned numbers. Any of the following yield an unsigned value:

So the bottom line is to either use the $signed system function, or define signed wires and registers.

For example, to multiply a signed and unsigned register, yielding a signed value (of course), go something like this:

reg         [15:0] a; // Unsigned
reg signed  [15:0] b;
wire signed [16:0] signed_a;
wire signed [31:0] a_mult_b;

assign signed_a = a; // Convert to signed
assign a_mult_b = signed_a * b

Note that signed_a is one bit wider than “a”, so there’s room for the sign bit, which is always zero. If this wasn’t for this extra bit, a’s MSB would be treated as the sign bit in signed_a.

It may seem necessary to explicitly determine signed_a’s MSB with sometime like {1′b0, a} instead of just “a”, but the Verilog standard is pretty explicit about the signed vs. unsigned being determined by the expression only, and not by the left hand side. So “a” is treated as an unsigned value, and is hence extended by zero.

Copyright © 2021-2022. All rights reserved. (59ca02e6)