verilogcpu-architecturealucarryflagsigned-overflow

Understanding the difference between overflow and carry flags


I am designing a 16 bit ALU in verilog based on an existing RISC ISA. The ISA says that the carry flag is set when the operation is unsigned, and overflow is set when the operation is signed. The interesting thing is that the ISA implements ADD and SUB instructions that operate on both signed and unsigned numbers. Since signed vs unsigned is simply a matter of interpretation, my initial idea was to do something like below. The idea being that overflow vs carry is only a matter of interpretation, so use the same function for both.


module ALU();
    input wire [15:0]x;
    input wire [15:0]y;
    input wire [8:0]opcode;
    output reg [15:0] result;
    output reg CFlag; // Carry
    output reg FFlag;  // Overflow

    if(opcode == ADD) begin
        result = x + y;
        // x and y have the same sign, result has a different sign.
        CFlag = FFlag = (x[15] ~^ y[15]) & res[15] ^ x[15];
    end
endmodule

But what about this edge case (shown in 4 bits)?

x = -1
y = 1

1111 + 0001 = 0000

In this case the answer is correct in 2s compliment and no flag needs to be set. But the answer is incorrect in unsigned interpretation and the carry flag should be set. I always understood carry and overflow to be the same, just different interpretation, but now I'm not sure. How would a modern ALU handle this edge case?


Solution

  • Carry and overflow are not the same at all.

    Carry indicates the result isn't mathematically correct when interpreted as unsigned, overflow indicates the result isn't mathematically correct when interpreted as signed. So as examples for your 4-bit ALU: