Signed adder implementation

1.7k Views Asked by At

Suppose that I have two logic vectors:

logic [4:0] a;
logic [4:0] b;

that hold 2's complement values. I want to perform a subtraction and extend the result by 1 bit. For example, assume that I want to compute -12 - 13 and store the result of -25:

logic [5:0] sum;
sum = a - b;

The above simulates as I expect and I get the expected value of 6'b100111. Working through this by hand:

  1 0 1 0 0   -12
  1 0 0 1 0   invert bits of +13
          1   carry-in
---------------
1 0 0 1 1 1   = -25

So, the MSB of the result is simply the carry-out of the addition. However, if I compute 12 - 13, the result should be 6'b111111, but instead I get the simulated result of 6'b011111. Working through this example by hand:

  0 1 1 0 0   12
  1 0 0 1 0   invert bits of +13
          1   carry-in
---------------
0 1 1 1 1 1   = +31

So, the result is not correct as the carry-out into the MSB is zero.

I can fix the simulated result by changing the RTL as follows:

logic [5:0] sum;
sum = $signed(a) - $signed(b);

which returns the expected result of 6'b111111. After reading through the SystemVerilog LRM to understand what's happening here, I discovered that additions are done at the bit size of the largest operand, including the LHS of assignment operations. In addition, using the $signed keyword causes the 5-bit input operands to be sign-extended to 6-bits. Taking this into account and performing the operation by hand again:

[0] 0 1 1 0 0   12
[1] 1 0 0 1 0   invert bits of +13
            1   carry-in
---------------
 1  1 1 1 1 1   = -1

where [0] and [1] are the sign-extension bits. From this it is clear that the MSB is actually calculated by a full-adder ([0] + [1] + carry-out from previous column).

My question is this:

  1. Am I correct in thinking that a signed adder does indeed require a full-adder on the MSB to calculate the correct result?
  2. If above is correct, what will a synthesis tool make of this? Will it also know to instantiate a full-adder on the MSB?

I had always assumed that writing an adder in SystemVerilog, where the inputs are n-bits wide, would cause a synthesis tool to instantiate a n-bit adder where the (n+1)-bit output was simply the carry-out of that adder.

1

There are 1 best solutions below

6
Serge On

You forgot about sign extension. -13 (10011) in 6-bit incarnation is supposed to be 110011. Therefore, you are interpreting the second resulst incorrectly. It is not +31 (6-bit), it should be interpreted as -1 in the 5-bit version. To make a 6-bit result do sigh-extend both operands:

  ext
  0 | 0 1 1 0 0   -- 12
  1 | 1 0 0 1 1   -- -13
  ==|==========
  1 | 1 1 1 1 1   -- -1 (6 bit)

With unsigned numbers only you can get away without extension, because it is always '0'.