5

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?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
richbai90
  • 4,994
  • 4
  • 50
  • 85

1 Answers1

23

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:

  • 1111 + 0001 = 0000 should set carry (15 + 1 = 0 is false) and clear overflow (-1 + 1 = 0 is true).

  • 0111 + 0010 = 1001 should clear carry (7 + 2 = 9 is true) and set overflow (7 + 2 = -7 is false).

  • 1001 + 1001 = 0010 should set both (9 + 9 = 2 and -7 + -7 = 2 are both false).

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • 3
    http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt has some good worked example and explanation of different ways an ALU could calculate it. It doesn't mention subtraction / borrow, though. – Peter Cordes Sep 10 '21 at 01:02
  • Both of them just check if there's 1 in the left-most bit (which is not presented in the memory), is that correct? The difference is only the type of numbers they're working with? – CrazyMan Mar 24 '22 at 11:06
  • 1
    @CrazyMan: The "left-most bit" is the carry; i.e. what would be bit 4 (counting from 0) of the result if the addition were done in a wider ALU with zero-extended operands. So the first and second examples above shows that this is not the same as the overflow flag. The overflow flag isn't purely a function of the result (even if it were widened); it depends also on what inputs produced it. The result `01001` should set the overflow flag if it is the result of `0111 + 0100`, but clear it if it is the result of `1000 + 0001`. – Nate Eldredge Mar 24 '22 at 12:56
  • @NateEldredge Thanks, I now understand it somewhat better. Can you, please, explain, how the processor determines if the Overflow Flag should be set if simply two numbers are being added? Is information about type of the number also stored somewhere? – CrazyMan Mar 24 '22 at 13:16
  • 4
    @CrazyMan: No, this is the whole point; the machine has no idea as to the "type" of the input numbers, they are just bits. So the overflow flag will *always* be set according to whether there would be an overflow *if the inputs were to be interpreted as signed*. Formally, it always equals the xor of the carry into bit 3, and the carry into bit 4 (the latter being the usual carry flag). – Nate Eldredge Mar 24 '22 at 13:20
  • 2
    @CrazyMan: So if you intend to be doing purely unsigned arithmetic, and you are thinking of `0111 + 0010 = 1001` as 7+9, the overflow flag gets set anyway, and you simply ignore it. Likewise if you intend to be doing signed arithmetic, you would inspect the overflow flag and ignore the carry flag. – Nate Eldredge Mar 24 '22 at 13:20