VHDL:检查零失败的结果

时间:2016-03-19 03:53:13

标签: vhdl

我试图检查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;

screenshot reference

1 个答案:

答案 0 :(得分:0)

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

PROCESS(alu_operand_A,alu_operand_B,alu_control,s_alu_result)

为了更好地理解,可以通过分配所有&#39; 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将是&#39; 0&#39;再次,而不是&#39; 1&#39;。价值全部&#39; 0&#39;被分配给信号s_alu_result以进行下一个增量循环。因此,检查所有零,仍然使用旧的值,即全部&#39; U&#39;。因此,条件是错误的,并且&#39; 0&#39; 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;