携带/借用VHDL ALU

时间:2017-10-29 21:43:59

标签: vhdl add alu

我在VHDL中制作通用的N位ALU。我无法为进位添加值,或借用减法。我尝试过以下方法:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; 

entity alu is
    generic(n: integer :=1); --Default to 1
    port (
        a : in std_logic_vector(n-1 downto 0);
        b : in std_logic_vector(n-1 downto 0);
        op : in std_logic_vector(1 downto 0);
        output : out std_logic_vector(n-1 downto 0);
        carryborrow: out std_logic 
    );
end alu;

architecture Behavioral of alu is
    signal result: std_logic_vector(n downto 0); 
begin
process( a, b, op )
begin
    case op is
    when "00" => 
        result(n) <= '0'; 
        result(n-1 downto 0) <= a and b; --and gate 
        output <= result(n-1 downto 0); 
        carryborrow <= '0'; 
    when "01" => 
        result(n) <= '0'; 
        result(n-1 downto 0) <= a or b; --or gate 
        output <= result(n-1 downto 0); 
        carryborrow <= '0'; 
    when "10" => 
        result(n) <= '0'; 
        result(n-1 downto 0) <= std_logic_vector(signed(a) + signed(b)); --addition
        output <= result(n-1 downto 0); 
        carryborrow <= result(n); 
    when "11" => 
        result(n) <= '0';
        result(n-1 downto 0) <= std_logic_vector(signed(a) - signed(b)); --subtraction
        output <= result(n-1 downto 0); 
        carryborrow <= result(n); 
    when others => 
        NULL; 
    end case; 

end process;

end Behavioral;

这似乎将carryborrow位设置为始终为0.如何在没有类型错误的情况下将其分配给它应该是什么?

3 个答案:

答案 0 :(得分:3)

您的代码中存在错误:

i)您没有考虑到信号不会立即更新的事实。因此,以下几行不会像我认为的那样完成:

    result(n) <= '0'; 
    result(n-1 downto 0) <= a and b; --and gate 
    output <= result(n-1 downto 0); 

相反,您需要在组合流程之外使用驱动outputcarryborrow的行,如下所示。 ii)假设您希望此代码是可合成的,只需将NULL放在always分支中将导致推断锁存。您也需要在其他分支中驾驶result

因此,假设您的进位输出如何与andor操作一起使用,这就是我编写代码的方式:

architecture Behavioral of alu is
    signal result: std_logic_vector(n downto 0); 
begin
process( a, b, op )
begin
    case op is
    when "00" => 
        result <= '0' & (a and b); --and gate 
    when "01" => 
        result <= '0' & (a or b); --or gate 
    when "10" => 
        result <= std_logic_vector(resize(signed(a), n+1) + resize(signed(b), n+1)); --addition
    when "11" => 
        result <= std_logic_vector(resize(signed(a), n+1) - resize(signed(b), n+1)); --subtraction
    when others => 
        result <= (others => 'X');
    end case; 
  end process;

  output <= result(n-1 downto 0); 
  carryborrow <= result(n); 

end Behavioral;

答案 1 :(得分:1)

我通常这样做:

result <= std_logic_vector(signed(a(n-1) & a) + signed(b(n-1) & b));
result <= std_logic_vector(signed(a(n-1) & a) - signed(b(n-1) & b));

符号扩展,然后执行操作以处理溢出,当结果是一个额外的位。

答案 2 :(得分:0)

嗯,请在4位环境中考虑,例如Edita="0101"。添加它们应得到b="1001",没有进位。

但是,以output="1110"resize(signed(a), n+1)扩展的符号将设置resize(signed(b), n+1)a="00101",从而设置b="11001"result="11110",这是错误的!

通过符号扩展向量carryborrow='1'a,数字范围已增加到5位,因此b必须为6位才能保持进位,并且我们重新回到第一个。 向量resulta仅应扩展为零,即将b'0' & a分别添加到'0' & bresult之前,如下所示: carryborrow的MSB(最高有效位)将获得正确的值。