计算 ALU 中的溢出标志
Calculating the Overflow Flag in an ALU
首先,如果这不是 post 这个问题的正确位置,请原谅我,但我不确定应该去哪里。我目前正在使用 VHDL 在 Xilinx 中模拟 ALU。 ALU 具有以下输入和输出:
输入
- A和B:两个8 位操作数
- Ci:单位进位
- Op:多路复用器的 4 位操作码
产出
- Y:8位输出操作数
- Co:单位进位
- V:溢出标志(如果溢出则为1,否则为0)
- Z:零标志(如果为 1,则为 0,否则为 0)
- S:符号标志(1 if -ve,0 if +ve)
ALU 执行下面 table 中详述的操作:
我已经使用多路复用器和加法器实现了它,如下图所示:
我的问题是:
How do I calculate the value of the overflow flag, V?
我知道:
- 正负相加不会溢出
- 如果没有carry/borrow,那么可以通过计算表达式
来计算溢出
(not A(7) and not B(7) and Y(7)) or (A(7) and B(7) and not Y(7))
其中 A(7)、B(7) 和 Y(7)是A、B和Y.
- 在carry/borrow的情况下,当且仅当最高有效位的进位和出位不同时才会发生溢出。
但是我不知道如何在 VHDL 代码中逻辑地实现这一点——尤其是在进位的情况下。
如果两个正数相加得到负数,两个负数相加得到正数,就会发生溢出。也就是说,您需要比较操作数的 MSB 和答案。如果操作数的符号和答案的符号不匹配,则打开溢出标志。
编辑:这只适用于没有进位的情况。关于进位的添加,我也需要帮助。
您发布的解决方案
v <= (not A(7) and not B(7) and Y(7)) or (A(7) and B(7) and not Y(7))
对于有符号操作数的加法是正确的并且与进位无关。
EDIT 要将其也用于减法,您必须改用实际的加法器输入,即:
v <= (not add_A(7) and not add_B(7) and Y(7)) or (add_A(7) and add_B(7) and not Y(7))
以上将适用于加法和减法,独立于进位或借位。 (顺便说一下,对于真正的实现,你应该使用 add_Y
而不是 Y
来缩短关键路径。)
如果要对most-signifcant和位的carry-in和carry-out进行异或来实现,则必须计算最低7位的部分和第一的。这使您可以访问第 6 位的 carry-out,这是第 7 位的 carry-in。然后只需附加一个 full-adder 即可获得第 7 位和 carry-out。这是代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder_overflow is
port (
a : in unsigned(7 downto 0);
b : in unsigned(7 downto 0);
y : out unsigned(7 downto 0);
v : out std_logic;
co : out std_logic);
end;
architecture rtl of adder_overflow is
signal psum : unsigned(7 downto 0); -- partial sum
signal c7_in : std_logic;
signal c7_out : std_logic;
begin
-- add lowest 7 bits together
psum <= ("0" & a(6 downto 0)) + b(6 downto 0);
-- psum(7) is the carry-out of bit 6 and will be the carry-in of bit 7
c7_in <= psum(7);
y(6 downto 0) <= psum(6 downto 0);
-- add most-signifcant operand bits and carry-in from above together using a full-adder
y(7) <= a(7) xor b(7) xor c7_in;
c7_out <= ((a(7) xor b(7)) and c7_in) or a(7);
-- carry and overflow
co <= c7_out;
v <= c7_in xor c7_out;
end rtl;
你的解决方案
(not A(7) and not B(7) and Y(7)) or (A(7) and B(7) and not Y(7))
及其下方的文字仅适用于有符号加法;减法是不正确的。两条规则是:
- 表达式 x+y+c 的有符号整数溢出(其中 c 为 0 或 1) 当且仅当 x 和 y 具有相同符号且结果为符号与操作数相反(这是你的等式),并且
- 表达式 x-y-c 的有符号整数溢出(其中 c 再次为 0 或 1) 当且仅当 x 和 y 具有相反的符号,并且符号结果的结果与 x 相反(或者等价地,与 y 相同)。
请注意,无论 carry/borrow 的值如何,这些都是正确的。您可以看到第一条规则不适用于简单的 4 位示例的减法:例如,4 减 (-4) 必须溢出,因为答案应该是 +8,这不能用 4 位表示。在二进制中,这是 0100 - 1100 = 1000
。这是根据 (2) 而不是 (1) 的溢出。
好消息是 xor-ing 符号位的进位和符号位的进位始终有效 - 加法和减法都是正确的,无论是否有进位或 borrow-in, 所以你可以使用 Martin 的代码。
如果你要做很多算术,你应该得到亨利·沃伦 Hacker's Delight 的副本。他涵盖了所有这些,甚至更多。
首先,如果这不是 post 这个问题的正确位置,请原谅我,但我不确定应该去哪里。我目前正在使用 VHDL 在 Xilinx 中模拟 ALU。 ALU 具有以下输入和输出:
输入
- A和B:两个8 位操作数
- Ci:单位进位
- Op:多路复用器的 4 位操作码
产出
- Y:8位输出操作数
- Co:单位进位
- V:溢出标志(如果溢出则为1,否则为0)
- Z:零标志(如果为 1,则为 0,否则为 0)
- S:符号标志(1 if -ve,0 if +ve)
ALU 执行下面 table 中详述的操作:
我已经使用多路复用器和加法器实现了它,如下图所示:
我的问题是:
How do I calculate the value of the overflow flag, V?
我知道:
- 正负相加不会溢出
- 如果没有carry/borrow,那么可以通过计算表达式 来计算溢出
(not A(7) and not B(7) and Y(7)) or (A(7) and B(7) and not Y(7))
其中 A(7)、B(7) 和 Y(7)是A、B和Y.
- 在carry/borrow的情况下,当且仅当最高有效位的进位和出位不同时才会发生溢出。
但是我不知道如何在 VHDL 代码中逻辑地实现这一点——尤其是在进位的情况下。
如果两个正数相加得到负数,两个负数相加得到正数,就会发生溢出。也就是说,您需要比较操作数的 MSB 和答案。如果操作数的符号和答案的符号不匹配,则打开溢出标志。
编辑:这只适用于没有进位的情况。关于进位的添加,我也需要帮助。
您发布的解决方案
v <= (not A(7) and not B(7) and Y(7)) or (A(7) and B(7) and not Y(7))
对于有符号操作数的加法是正确的并且与进位无关。
EDIT 要将其也用于减法,您必须改用实际的加法器输入,即:
v <= (not add_A(7) and not add_B(7) and Y(7)) or (add_A(7) and add_B(7) and not Y(7))
以上将适用于加法和减法,独立于进位或借位。 (顺便说一下,对于真正的实现,你应该使用 add_Y
而不是 Y
来缩短关键路径。)
如果要对most-signifcant和位的carry-in和carry-out进行异或来实现,则必须计算最低7位的部分和第一的。这使您可以访问第 6 位的 carry-out,这是第 7 位的 carry-in。然后只需附加一个 full-adder 即可获得第 7 位和 carry-out。这是代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder_overflow is
port (
a : in unsigned(7 downto 0);
b : in unsigned(7 downto 0);
y : out unsigned(7 downto 0);
v : out std_logic;
co : out std_logic);
end;
architecture rtl of adder_overflow is
signal psum : unsigned(7 downto 0); -- partial sum
signal c7_in : std_logic;
signal c7_out : std_logic;
begin
-- add lowest 7 bits together
psum <= ("0" & a(6 downto 0)) + b(6 downto 0);
-- psum(7) is the carry-out of bit 6 and will be the carry-in of bit 7
c7_in <= psum(7);
y(6 downto 0) <= psum(6 downto 0);
-- add most-signifcant operand bits and carry-in from above together using a full-adder
y(7) <= a(7) xor b(7) xor c7_in;
c7_out <= ((a(7) xor b(7)) and c7_in) or a(7);
-- carry and overflow
co <= c7_out;
v <= c7_in xor c7_out;
end rtl;
你的解决方案
(not A(7) and not B(7) and Y(7)) or (A(7) and B(7) and not Y(7))
及其下方的文字仅适用于有符号加法;减法是不正确的。两条规则是:
- 表达式 x+y+c 的有符号整数溢出(其中 c 为 0 或 1) 当且仅当 x 和 y 具有相同符号且结果为符号与操作数相反(这是你的等式),并且
- 表达式 x-y-c 的有符号整数溢出(其中 c 再次为 0 或 1) 当且仅当 x 和 y 具有相反的符号,并且符号结果的结果与 x 相反(或者等价地,与 y 相同)。
请注意,无论 carry/borrow 的值如何,这些都是正确的。您可以看到第一条规则不适用于简单的 4 位示例的减法:例如,4 减 (-4) 必须溢出,因为答案应该是 +8,这不能用 4 位表示。在二进制中,这是 0100 - 1100 = 1000
。这是根据 (2) 而不是 (1) 的溢出。
好消息是 xor-ing 符号位的进位和符号位的进位始终有效 - 加法和减法都是正确的,无论是否有进位或 borrow-in, 所以你可以使用 Martin 的代码。
如果你要做很多算术,你应该得到亨利·沃伦 Hacker's Delight 的副本。他涵盖了所有这些,甚至更多。