【问题标题】:Carry/Borrow in VHDL ALUVHDL ALU 中的进位/借位
【发布时间】:2017-10-29 21:43:59
【问题描述】:

我正在用 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。我怎样才能将它分配给它应该是什么而不会出现类型错误?

【问题讨论】:

  • 考虑一直阅读The CARRY flag and OVERFLOW flag in binary arithmetic。二进制有符号数 (2'sC) 容易通过符号位进行溢出。你的意思是做无符号算术吗?
  • @user1155120 那么我不应该将我的向量转换为signed,对吧?
  • 我缺少你的测试台。测试你的代码通常是一种方法:它会告诉你哪里出了问题。

标签: vhdl add alu


【解决方案1】:

您的代码中存在错误:

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;

【讨论】:

    【解决方案2】:

    我通常这样做:

    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));
    

    当结果多出一位时,进行符号扩展,然后执行处理溢出的操作。

    【讨论】:

    • 这会导致错误:Error, type error in expression
    • @SaraTibbetts 或者您可以在numeric_std 中使用resize 函数,它对signed 类型执行相同的操作,但也可以正确扩展unsigned 类型。即result &lt;= std_logic_vector(resize(signed(a), n+1) + resize(signed(b), n+1))
    【解决方案3】:

    嗯,考虑一下 4 位环境,比如 a="0101"b="1001"。添加它们将给出output="1110",没有进位。

    但是,使用resize(signed(a), n+1)resize(signed(b), n+1) 扩展的符号将设置a="00101"b="11001",因此设置result="11110"carryborrow='1',这是错误的!

    通过符号扩展向量 ab,数字范围增加到 5 位,因此 result 需要为 6 位才能保持进位,我们又回到了第一方。 向量ab 只能是零扩展,即'0' &amp; a'0' &amp; b 在将它们添加到result 之前,然后是carryborrow,作为result 的MSB(最高有效位),将得到正确的值。

    【讨论】:

    • 你好 RackHam,欢迎来到 SO。我无法真正验证您的答案,但我可以请您尝试整理一下。它将受益于一些格式 - 使其更易于阅读!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多