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!
{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: