You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

32位ALU加减运算结果异常问题排查求助

问题描述

我正在为大学项目设计一款处理器,回头检查代码时发现ALU单元的加减运算无法输出正确结果。例如在测试台中,将0x00000001与0x00000001相加,结果为0x00000000;进行减法运算时,结果却为0x00000010。

原VHDL代码

use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity ALU_32bit is
    Port ( A : in  std_logic_vector (31 downto 0);
           B : in  std_logic_vector (31 downto 0);
           ALU_Sel : in  std_logic_vector (3 downto 0);
           ALU_Out : out  std_logic_vector (31 downto 0);
           Zero : out  std_logic;
           Cout : out  std_logic;
           Ovf : out  std_logic);
end ALU_32bit;

architecture Behavioral of ALU_32bit is
              
 signal ALU_result: std_logic_vector(31 downto 0);
 signal Total_result:std_logic_vector(32 downto 0) := (others => '0');
 signal Carryout, Overflow : std_logic;

begin

  process(A, B, ALU_Sel) 
  begin
      case (ALU_Sel) is
  
        when "0000" => --Addition 
             Total_result <= std_logic_vector(signed('0' & A) + signed('0' & B));
             ALU_result <= Total_result(31 downto 0);
             Carryout <= Total_result(32);            
        when "0001" => --Subtraction
          Total_result <= std_logic_vector(signed('0' & A) - signed('0' & B));
             ALU_result <= Total_result(31 downto 0);
             Carryout <= Total_result(32);
        when "0010" => --Bitwise AND
          ALU_result <= A and B;
        when "0011" => --Bitwise OR
          ALU_result <= A or B;
        when "0100" => --Bitwise NOT
          ALU_result <= not A;
        when "1000" => --Numerical Right Shift
          ALU_result <= std_logic_vector(signed(A) srl 1);
        when "1001" => --Logical Right Shift
          ALU_result <= std_logic_vector(unsigned(A) srl 1);
        when "1010" => --Logical Left Shift
          ALU_result <= std_logic_vector(unsigned(A) sll 1);
        when "1100" => --Logical Left Rotate
          ALU_result <= std_logic_vector(unsigned(A) rol 1);
        when "1101" => --Logical Right Rotate
          ALU_result <= std_logic_vector(unsigned(A) ror 1);
        when others => --Default Case; No opcode
          ALU_result <= x"00000000";
      end case;
        
        -- Overflow detection for addition
      if ((A(31) = '0' and B(31) = '0' and ALU_result(31) = '1')  or
            (A(31) = '1' and B(31) = '1' and ALU_result(31) = '0')) 
      then
            Overflow <= '1';
      else
            Overflow <= '0';
      end if;

      -- Overflow detection for subtraction
      if ((A(31) = '0' and B(31) = '0' and Total_result(31) = '1') or
           (A(31) = '1' and B(31) = '1' and Total_result(31) = '0')) 
      then
           Overflow <= '1';
      else
           Overflow <= '0';
      end if;
        
  end process;  

  
 ALU_Out <= ALU_result;
 Zero <= '1' when ALU_result = x"00000000" else '0';
 Ovf <= Overflow;
 Cout <= Carryout;
 
end Behavioral;

问题分析

  • 非阻塞赋值时序错误:process中用<=给Total_result赋值属于非阻塞赋值,赋值操作要等到process结束后才生效。同一process内紧接着读取Total_result时,取到的是上一次的旧值(初始为全0),这直接导致加法结果为0、减法结果错误。
  • 减法溢出逻辑错误:原代码的减法溢出判断完全不符合有符号数减法的溢出规则,正确的溢出场景是被减数与减数符号相反,且结果符号与被减数相反。
  • 算术右移操作符错误:srl是逻辑右移,无法保留有符号数的符号位,算术右移应该使用sra操作符。

修正后的代码

use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity ALU_32bit is
    Port ( A : in  std_logic_vector (31 downto 0);
           B : in  std_logic_vector (31 downto 0);
           ALU_Sel : in  std_logic_vector (3 downto 0);
           ALU_Out : out  std_logic_vector (31 downto 0);
           Zero : out  std_logic;
           Cout : out  std_logic;
           Ovf : out  std_logic);
end ALU_32bit;

architecture Behavioral of ALU_32bit is
    signal ALU_result: std_logic_vector(31 downto 0);
    signal Carryout, Overflow : std_logic;
begin
    process(A, B, ALU_Sel) 
        variable temp_total: std_logic_vector(32 downto 0); -- 用变量存储临时计算结果
    begin
        -- 初始化默认值,避免综合器警告
        ALU_result <= (others => '0');
        Carryout <= '0';
        Overflow <= '0';
        
        case ALU_Sel is
            when "0000" => -- 加法
                temp_total := std_logic_vector(signed('0' & A) + signed('0' & B));
                ALU_result <= temp_total(31 downto 0);
                Carryout <= temp_total(32);
                -- 加法溢出检测:同符号相加结果异符号
                if (A(31) = '0' and B(31) = '0' and temp_total(31) = '1') or
                   (A(31) = '1' and B(31) = '1' and temp_total(31) = '0') then
                    Overflow <= '1';
                end if;
            when "0001" => -- 减法 (A - B)
                temp_total := std_logic_vector(signed('0' & A) - signed('0' & B));
                ALU_result <= temp_total(31 downto 0);
                Carryout <= temp_total(32);
                -- 减法溢出检测:异符号相减结果与被减数异符号
                if (A(31) = '0' and B(31) = '1' and temp_total(31) = '1') or
                   (A(31) = '1' and B(31) = '0' and temp_total(31) = '0') then
                    Overflow <= '1';
                end if;
            when "0010" => -- 按位与
                ALU_result <= A and B;
            when "0011" => -- 按位或
                ALU_result <= A or B;
            when "0100" => -- 按位非
                ALU_result <= not A;
            when "1000" => -- 算术右移
                ALU_result <= std_logic_vector(signed(A) sra 1); -- 替换为sra操作符
            when "1001" => -- 逻辑右移
                ALU_result <= std_logic_vector(unsigned(A) srl 1);
            when "1010" => -- 逻辑左移
                ALU_result <= std_logic_vector(unsigned(A) sll 1);
            when "1100" => -- 逻辑左旋转
                ALU_result <= std_logic_vector(unsigned(A) rol 1);
            when "1101" => -- 逻辑右旋转
                ALU_result <= std_logic_vector(unsigned(A) ror 1);
            when others => -- 默认情况
                ALU_result <= x"00000000";
        end case;
    end process;  

    ALU_Out <= ALU_result;
    Zero <= '1' when ALU_result = x"00000000" else '0';
    Ovf <= Overflow;
    Cout <= Carryout;
end Behavioral;

关键修改说明

  • 用变量替代信号存储临时结果:变量使用阻塞赋值:=,能在process内立即获取计算后的新值,彻底解决非阻塞赋值的时序问题。
  • 修正减法溢出检测逻辑:调整为符合有符号数减法的溢出判断规则。
  • 替换算术右移操作符:将srl改为sra,确保有符号数右移时符号位正确保留。
  • 增加默认初始化:在process开头给信号赋默认值,避免综合器产生不必要的警告。

内容的提问来源于stack exchange,提问作者DilligentSlacker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:17:01