了解溢出标志和进位标志之间的区别
Understanding the difference between overflow and carry flags
我正在基于现有的 RISC ISA 在 verilog 中设计一个 16 位 ALU。 ISA 说当操作无符号时设置进位标志,当操作有符号时设置溢出。有趣的是,ISA 实现了对有符号数和无符号数进行操作的 ADD
和 SUB
指令。由于有符号与无符号只是一个解释问题,我最初的想法是做如下的事情。溢出与进位的想法只是一个解释问题,所以对两者使用相同的函数。
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 均为假)。
我正在基于现有的 RISC ISA 在 verilog 中设计一个 16 位 ALU。 ISA 说当操作无符号时设置进位标志,当操作有符号时设置溢出。有趣的是,ISA 实现了对有符号数和无符号数进行操作的 ADD
和 SUB
指令。由于有符号与无符号只是一个解释问题,我最初的想法是做如下的事情。溢出与进位的想法只是一个解释问题,所以对两者使用相同的函数。
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 均为假)。