我应该用 VHDL 编写一个简单的 32 位 Alu。一切都很好,除了两件事。ALU 应该有一个执行和溢出标志,我不知道如何实现它。
首先是一个一般性问题。电路图显示,对于减法,ALU 将减数取反并加“1”以在 2 秒补码中创建输入值的负等效值。这是否意味着我应该为输入使用无符号值?还是我应该坚持使用 std_logic_vector?
由于进位位是不“适合”结果字的位,因此我尝试将 Summands 零扩展,创建一个临时的 33 位 Sum 信号,然后简单地将结果分为进位和实际总和。不幸的是,我在模拟时得到的只是“UU...U”作为总和的输出。(我按照这里的描述做了:https ://en.wikibooks.org/wiki/VHDL_for_FPGA_Design/4-Bit_ALU )
对于溢出标志:由于 ALU 的描述是行为性的,我无法访问任何进位,这意味着我无法通过简单地对最后两个进位进行异或来确定是否发生溢出(假设值在 2 秒内-补充,但我在这一点上不太确定,因为我的第一个问题显示......)。是否有另一种方法来识别溢出?就像简单地将在互联网上找到的“溢出发生时...”规则变成 if 语句?
到目前为止,这是我的代码。这个版本在加/减时给了我“UUU...U”的输出。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ALU is
Port ( Clk : in STD_LOGIC;
A : in std_logic_vector (31 downto 0);
B : in std_logic_vector(31 downto 0);
Y : out std_logic_vector(31 downto 0);
OP : in std_logic_vector(2 downto 0);
Nul : out boolean;
Cout : out STD_LOGIC);
end ALU;
architecture Behavioral of ALU is
signal Smd0, Smd1, Sum : std_logic_vector (31 downto 0);
signal temp : std_logic_vector (32 downto 0);
signal Cry : STD_LOGIC;
signal snul : boolean;
begin
Smd0 <= A;
Smd1 <= B;
Y <= Sum;
Cout <= Cry;
nul <= snul;
process(Clk) begin
if (rising_edge(Clk)) then
if ( Sum = "00000000000000000000000000000000") then -------Zero flag
snul <= true;
else
snul <= false;
end if;
case OP is
when "000" =>
Sum <= Smd0 and Smd1;
when "001" =>
Sum <= Smd0 xor Smd1;
when "010" =>
temp <= std_logic_vector((unsigned("0" & Smd0) + unsigned(Smd1)));
Sum <= temp(31 downto 0);
Cry <= temp(32);
when "100" =>
Sum <= Smd0 and not Smd1;
when "101" =>
Sum <= Smd0 xor not Smd1;
when "110" =>
Sum <= std_logic_vector((unsigned(Smd0) - unsigned(Smd1)));
when "111" =>
if (A < B) then
Sum <= "00000000000000000000000000000001";
else
Sum <= "00000000000000000000000000000000";
end if;
when others =>
NULL;
end case;
end if;
end process;
end Behavioral;
对代码的任何评论将不胜感激,因为我对 VHDL 完全陌生(我们讨论了半场讲座......),这是我通过谷歌搜索和玩耍发现的。
这是给定的电路图:
//编辑:
另一件事。我的零标志在“000”之后无法正常工作。除了第一种情况,知道为什么它的输出很好吗?