我目前正在用 VHDL 编写一个 32 位 ALU(加/减)。我遇到了溢出位的问题。根据运算(加法,减法)和输入值,我看不到何时设置溢出。
你能帮助我吗 ?
最好的问候,安德烈
只是为了给 Martin 的答案添加一些额外的信息,您需要小心使用 2 的补码算法检测溢出。
例如,如果您有以二进制补码格式表示的 3 位有符号值,并且您想检测溢出,则需要对额外位进行符号扩展,然后查看额外位是否与最重要的所需位不同:
例如,如果要计算 a = b + c:
--Declare the signals
signal overflow : std_logic;
signal a : signed(2 downto 0);
signal b : signed(2 downto 0);
signal c : signed(2 downto 0);
-- Declare some additional signals with one more MSB than the original signals
signal a_extended : std_logic(3 downto 0);
signal b_extended : std_logic(3 downto 0);
signal c_extended : std_logic(3 downto 0);
-- Sign extend the MSB
b_extended <= b(2) & b;
c_extended <= c(2) & c;
-- Perform the addition
a_extended <= b_extended + c_extended;
-- Detect the overflow case
overflow <= '1' when a_extended(3) /= a_extended(2) else '0';
-- Calculate the answer
-- Limit to 100 (-4) or 011 (+3) in the case of overflow
process(a_extended)
begin
if a_extended(3) /= a_extended(2) then
if a_extended(3) = '1' then
a <= "100";
else
a <= "011";
end if;
else
a <= a_extended(2 downto 0);
end if;
end process;
规范说它应该做什么?应该描述在什么条件下应该设置溢出标志。
通常,当输出对于存储而言太大时,会设置溢出位。您可以将其视为对两个 32 位数字求和的答案中的第 33 位。在有符号算术中,如果运算结果的幅度太大,则可能发生这种情况,而与符号无关。使用 2-s 补码算法,你必须小心一点,因为最大的负数比你可以用给定位数表示的最大正数稍微负一些。
就实际操作而言,只需创建一个numeric_std
比输入宽 1 位的向量,执行
a<=b+c;
并让合成器创建逻辑。然后,您不必担心细节。
"a" 的 MSB 可以去掉(使用a(a'high)
和使用它作为溢出。