gpt4 book ai didi

vhdl - VHDL 中的 32 位 ALU 执行

转载 作者:行者123 更新时间:2023-12-02 17:43:18 24 4
gpt4 key购买 nike

我应该用 VHDL 编写一个简单的 32 位 Alu。一切正常,除了两件事。 ALU 应该有一个进位和溢出标志,但我不知道如何实现它。

首先是一个一般性问题。电路图显示,对于减法,ALU 反转减数并添加“1”以创建 2s 补码中输入值的负等效值。这是否意味着我应该为输入使用无符号值?还是应该坚持使用 std_logic_vector?

由于进位位是不“适合”结果字的位,我尝试对加数进行零扩展,创建一个临时的 33 位和信号,然后简单地将结果分为进位和实际总和。不幸的是,我在模拟时得到的只是“UU ... U”作为总和的输出。(我按照此处所述进行操作:https://en.wikibooks.org/wiki/VHDL_for_FPGA_Design/4-Bit_ALU)

对于溢出标志:由于 ALU 的描述是行为性的,我无法访问任何进位,这意味着我无法通过简单地对最后两个进位进行异或来确定是否发生溢出(假设值是 2s 补码,但我不太确定这一点,正如我的第一个问题所示......)。还有另一种识别溢出的方法吗?就像简单地将人们在 Internet 上找到的“当...发生溢出”规则转换为 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 是全新的(我们讨论了半个讲座......)这是我通过谷歌搜索和尝试发现的。

这是给定的电路图:

CDiag

//编辑:

还有一点。我的零标志在“000”之后不能正常工作。除了第一种情况,你知道为什么它的输出很好吗?

最佳答案

回答你的第一个问题: 是的,使用 IEEE.std_numeric 库中的无符号。它非常适合此类操作。

其次,可以通过比较输出和输入来检测溢出。例如,在二进制补码中,如果执行 +ve 加上 +ve 并溢出,结果将设置 msb,因此结果为 -ve。

总结加减法

Addition     | (+ve) - (+ve) | (+ve) - (-ve) | (-ve) - (+ve) | (-ve) + (-ve)|
-----------------------------------------------------------------------------
Result (+ve) | - | - | - | overflow |
-----------------------------------------------------------------------------
Result (-ve) | overflow | - | - | - |
-----------------------------------------------------------------------------

Subtraction | (+ve) - (+ve) | (+ve) - (-ve) | (-ve) - (+ve) | (-ve) - (-ve)|
-----------------------------------------------------------------------------
Result (+ve) | - | - | overflow | - |
-----------------------------------------------------------------------------
Result (-ve) | - | overflow | - | - |
-----------------------------------------------------------------------------

可以为乘法和除法计算出类似的规则,但稍微复杂一些。

编辑

下面是解决此问题的建议方法(我希望你确实意识到 vhdl(大部分)不区分大小写?你似乎喜欢使用 shift 键)。根据你的问题,我不知道你想将哪个标志作为溢出标志,所以我没有放入。

library ieee;
use ieee.std_logic_164.all;
use ieee.numeric_std.all;

entity alu is
port (
signal clk : in std_logic;
signal a : in std_logic_vector(31 downto 0);
signal b : in std_logic_vector(31 downto 0);
signal y : in std_logic_vector(31 downto 0);
signal op : in std_logic_vector(3 downto 0);
signal nul : out boolean;
signal cout : out std_logic
)
end entity;

architecture behavioral of alu is
type op_type is (op_and, op_a_and_nb, op_a_xor_nb, op_compare,
op_xor, op_add, op_sub, op_nop);
signal enum_op : op_type;

signal a_minus_b : std_logic_vector(32 downto 0);
signal a_plus_b : std_logic_vector(32 downto 0);
signal reg : std_logic_vector(32 downto 0);

begin

a_minus_b <= std_logic_vector(signed(a(a'high) & a) - signed(b(b'high) & b));
a_plus_b <= std_logic_vector(signed(a(a'high) & a) + signed(b(b'high) & b));

process(op)
begin
case op is
when "000" => enum_op <= op_and;
when "001" => enum_op <= op_xor;
when "010" => enum_op <= op_add;
when "100" => enum_op <= op_a_and_nb;
when "101" => enum_op <= op_a_xor_nb;
when "110" => enum_op <= op_sub;
when "111" => enum_op <= op_compare;
when others => enum_op <= op_nop;
end case;
end process;

process(clk)
begin
if rising_edge(clk) then
case enum_op is
when op_add => reg <= a_plus_b;
when op_sub => reg <= a_minus_b;
when op_and => reg <= '0' & (a and b);
when op_xor => reg <= '0' & (a xor b);
when op_a_and_nb => reg <= '0' & (a and not b);
when op_a_xor_nb => reg <= '0' & (a xor not b);
when op_compare =>
reg(32) <= '0';
reg(31 downto 1) <= (others => '0');
reg(0) <= a_minus_b(32);
when op_nop =>
reg(32) <= '0';
end if;
end process;

y <= reg(31 downto 0);
count <= reg(32);
nul <= unsigned(reg) = '0';

end architecture;

关于vhdl - VHDL 中的 32 位 ALU 执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17978200/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com