了解溢出标志和进位标志之间的区别

Understanding the difference between overflow and carry flags

我正在基于现有的 RISC ISA 在 verilog 中设计一个 16 位 ALU。 ISA 说当操作无符号时设置进位标志,当操作有符号时设置溢出。有趣的是,ISA 实现了对有符号数和无符号数进行操作的 ADDSUB 指令。由于有符号与无符号只是一个解释问题,我最初的想法是做如下的事情。溢出与进位的想法只是一个解释问题,所以对两者使用相同的函数。


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

但是这种边缘情况(以 4 位显示)呢?

x = -1
y = 1

1111 + 0001 = 0000

在这种情况下,2s 恭维答案是正确的,不需要设置标志。但在无符号解释中答案不正确,应设置进位标志。我一直认为进位和溢出是一样的,只是解释不同,但现在我不确定了。现代 ALU 将如何处理这种极端情况?

进位和溢出根本不一样。

进位表示结果在解释为无符号时在数学上不正确,溢出表示结果在解释为有符号时在数学上不正确。因此,作为 4 位 ALU 的示例:

  • 1111 + 0001 = 0000 应设置进位(15 + 1 = 0 为假)并清除溢出(-1 + 1 = 0 为真)。

  • 0111 + 0010 = 1001 应清除进位(7 + 2 = 9 为真)并设置溢出(7 + 2 = -7 为假)。

  • 1001 + 1001 = 0010 应同时设置(9 + 9 = 2 和 -7 + -7 = 2 均为假)。