VHDL:检查零结果失败

VHDL: check for result of zero fails

我试图检查 ALU 的结果是否为零。我从测试中得到零结果,但模拟显示 alu_zero 不是“1”。谁能告诉我为什么?

Library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY alu IS
 PORT(
  alu_operand_A,alu_operand_B:in std_logic_vector(31 downto 0);
  alu_control:in std_logic_vector(1 downto 0);
  alu_result:out std_logic_vector(31 downto 0);
  alu_zero:out std_logic
 );
END alu;

ARCHITECTURE behavioral OF alu IS
  signal s_alu_result:std_logic_vector(31 downto 0);
  BEGIN
  PROCESS(alu_operand_A,alu_operand_B,alu_control)
   BEGIN
   CASE alu_control IS
    WHEN "00"=>s_alu_result<=alu_operand_A + alu_operand_B;
               alu_result<=alu_operand_A + alu_operand_B;
    WHEN "01"=>s_alu_result<=alu_operand_A - alu_operand_B;
               alu_result<=alu_operand_A - alu_operand_B;
    WHEN "10"=>s_alu_result<=alu_operand_A and alu_operand_B;
               alu_result<=alu_operand_A and alu_operand_B;
    WHEN "11"=>s_alu_result<=alu_operand_A or alu_operand_B;
               alu_result<=alu_operand_A or alu_operand_B;
    WHEN OTHERS=>alu_result<=(others=>'X');
   END CASE;

  if s_alu_result="00000000000000000000000000000000" then
    alu_zero<='1';
  else
    alu_zero<='0';
  end if;
  END PROCESS;

END behavioral;

您的代码中的概念性错误是,信号分配没有立即发生。相反,如果您没有使用 after 子句指定延迟,则新信号值将安排在下一个增量周期。但是,该过程不会再次执行,因为 s_alu_result 不是敏感列表。因此,alu_zero 未分配给 '1',因为 s_alu_result 在检查时仍然全部为 'U'。最短的修复方法是将 s_alu_result 添加到敏感度列表:

PROCESS(alu_operand_A,alu_operand_B,alu_control,s_alu_result)

为了更好地理解,可以通过将全“0”的常量值分配给信号 s_alu_result 并删除所有不必要的信号和分配来进一步减少代码:

Library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY alu2 IS
  PORT(
    alu_zero : out std_logic
   );
END alu2;

ARCHITECTURE behavioral OF alu2 IS
  signal s_alu_result : std_logic_vector(31 downto 0);
BEGIN
  PROCESS
  BEGIN
    s_alu_result <= (others => '0');

    if s_alu_result="00000000000000000000000000000000" then
      alu_zero<='1';
    else
      alu_zero<='0';
    end if;

    wait;                               -- empty sensitivity list
  END PROCESS;
END behavioral;

敏感度列表现在是空的,因此,我必须在末尾插入一个 wait; 语句来模拟正确的行为。如果你模拟这个,alu_zero 将再次为“0”,而不是“1”。值全“0”被分配给下一个增量周期的信号 s_alu_result。因此,全零检查仍然使用旧值,即全 'U'。因此,条件为假,'0' 分配给 all_zero.


进一步说明:

  • 要去除计算 alu_results_alu_result 的重复行,您应该先分配 s_alu_result,然后再分配 alu_result <= s_alu_result

  • 不要使用 Synopsys 的非标准 VHDL 包 std_logic_unsigned。请改用 numeric_std。那么您的操作数必须是 unsigned 类型而不是 std_logic_vector 类型,以指示应将位序列视为无符号数。然后您还可以将零检查简化为:s_alu_result = 0.

最终代码如下所示:

Library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY alu IS
 PORT(
  alu_operand_A : in  unsigned(31 downto 0);
  alu_operand_B : in  unsigned(31 downto 0);
  alu_control   : in  std_logic_vector(1 downto 0);
  alu_result    : out unsigned(31 downto 0);
  alu_zero      : out std_logic
 );
END alu;

ARCHITECTURE behavioral OF alu IS
  signal s_alu_result : unsigned(31 downto 0);
BEGIN
  PROCESS(alu_operand_A, alu_operand_B, alu_control, s_alu_result)
  BEGIN
    CASE alu_control IS
      WHEN "00"   => s_alu_result <= alu_operand_A + alu_operand_B;
      WHEN "01"   => s_alu_result <= alu_operand_A - alu_operand_B;
      WHEN "10"   => s_alu_result <= alu_operand_A and alu_operand_B;
      WHEN "11"   => s_alu_result <= alu_operand_A or alu_operand_B;
      WHEN OTHERS => s_alu_result <= (others => 'X');
    END CASE;

    alu_result <= s_alu_result;

    if s_alu_result = 0 then
      alu_zero <= '1';
    else
      alu_zero <= '0';
    end if;
  END PROCESS;

END behavioral;