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