ric*_*i90 6 verilog cpu-architecture alu carryflag signed-overflow
我正在基于现有的 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
Run Code Online (Sandbox Code Playgroud)
但是这种边缘情况(以 4 位显示)又如何呢?
x = -1
y = 1
1111 + 0001 = 0000
Run Code Online (Sandbox Code Playgroud)
在这种情况下,答案在 2 秒补码中是正确的,并且不需要设置标志。但在无符号解释中答案是不正确的,并且应该设置进位标志。我一直认为进位和溢出是相同的,只是不同的解释,但现在我不确定。现代 ALU 将如何处理这种边缘情况?
Nat*_*dge 30
进位和溢出根本不一样。
进位表示当解释为无符号时结果在数学上不正确,溢出表示当解释为有符号时结果在数学上不正确。作为 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 均为 false)。