verilog signed addition and subtraction

42.1k Views Asked by At

I am having trouble understanding how to handle overflow when adding or subtracting signed numbers in verilog.

When I did this with unsigned numbers, it was very simple:

input [15:0] A;
input [15:0] B;
input [3:0] S;
output reg [15:0] AddAB;
...
always@(*)
    begin
        {OFAdd, AddAB} <= A + B;
        {OFSub, SubAB} <= A - B;
...
        case(S)
            0:
            begin
                Display <= AddAB;
                DisplayOF <= OFAdd;
            end
            1:
            begin
                Display <= SubAB;
                DisplayOF <= OFSub;
            end
...

And I would get the proper output. But doing the same thing with signed inputs, I get the wrong value for my overflow

input signed [15:0] A;
input signed [15:0] B;
input [3:0] S;
output reg signed [15:0] AddAB;
...
always@(*)
    begin
        {OFAdd, AddAB} <= A + B;
        {OFSub, SubAB} <= A - B;
...
        case(S)
            0:
            begin
                Display <= AddAB;
                DisplayOF <= OFAdd;
            end
            1:
            begin
                Display <= SubAB;
                DisplayOF <= OFSub;
            end
...

For instance, if A =-21846 and B = 88, I get the proper value AddAB = -21758, but I get DisplayOF = 1. The same happens with subtraction. I get the proper value for SubAB but I get an overflow on DisplayOF when I shouldn't.

If it makes any difference, my testbench looks basically like this

    A = 16'sb1010101010101010;
    B = 16'sd88;
    S = 4'd0;
    #10;

    A = 16'sb1010101010101010;
    B = 16'sd88;
    S = 4'd1;
    #10;

I'm not concerned with synthesizability, I just want to figure out how to deal with overflow on unary arithmetic on signed values.

If anyone could point me in the right direction I would be very greatful, thank you!

2

There are 2 best solutions below

0
On BEST ANSWER

{OFAdd, AddAB} <= A + B; In the example the MSB (OFAdd) is not an overflow bit. If you had access to the carry out of the final bit of an adder this could act as an overflow, but in RTL you do not have access to this only another full adder bit.

A more detailed previous answer, which shows how to use the two MSBs to detect overflow and underflow.

A basic overflow/underflow limiter:

AddAB = A + B;
case (AddAB[MSB:MSB-1])
  2’b01 : add = MAX_POS;//Overflow
  2’b10 : add = MAX_NEG;//Underflow
 default: add = AddAB[MSB-1:0]; //In Range
endcase
0
On

You have signed overflow if both inputs have the same sign and the result has the opposite sign. See https://electronics.stackexchange.com/questions/476250/signed-overflow-detection/476254#476254