简体   繁体   English

在VHDL ALU中进行借/借

[英]Carry/Borrow in VHDL ALU

I am making a generic N-bit ALU in VHDL. 我正在VHDL中制作通用的N位ALU。 I am having trouble assigning the value for the carry for addition, or borrow for subtraction. 我在分配加法或减法借用进位值时遇到麻烦。 I have tried the following: 我尝试了以下方法:

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;

This seems to set the carryborrow bit to always be 0. How can I assign it to what it should be without type errors? 这似乎将carryborrowcarryborrow位设置为始终为0。如何将其分配给应该没有类型错误的内容?

There are bugs in your code: 您的代码中有错误:

i) You have not taken into account the fact that signals are not updated immediately. i)您没有考虑到信号不会立即更新的事实。 Consequently, the following lines will not do as I think you are expecting: 因此,以下几行将不符合您的预期:

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

Instead, you need to take the lines driving output and carryborrow outside the combinational process, as you can see below. 取而代之的是,您需要将驱动outputcarryborrow借位的线放在组合过程之外,如下所示。 ii) Assuming you wish this code to be synthesisable, simply putting NULL in your always branch will result in latches being inferred. ii)假设您希望此代码是可综合的,只需将NULL放入always分支中将导致推断出锁存器。 You need to drive result in the others branch, too. 您还需要在other分支中驱动result

So, making an assumption about how your carry output is to behave with the and and or operations, this is how I would have written your code: 因此,假设您的进位输出如何与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;

I normally do this: 我通常这样做:

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

Sign extend and then do the operation to take care of overflow, when the result is one extra bit long. 当结果加长一位时,请扩展符号,然后进行操作以防止溢出。

Hmm, consider this in a 4 bit environment, say a="0101" and b="1001" . 嗯,在4位环境中考虑这个问题,例如a="0101"b="1001" Adding them shall give the output="1110" , with NO carry. 添加它们应得到output="1110" ,不带进位。

However, sign extending with resize(signed(a), n+1) and resize(signed(b), n+1) will set a="00101" and b="11001" and hence result="11110" and carryborrow='1' , which is wrong! 但是,以resize(signed(a), n+1)resize(signed(b), n+1)扩展的resize(signed(a), n+1)将设置a="00101"b="11001" ,从而设置result="11110"和进位carryborrow='1' ,这是错误的!

By sign extending vectors a and b , the numeral range has increased to 5 bits, and thus result needs to be 6 bits to be able to hold carry, and we're back to square one. 通过符号扩展向量ab ,数字范围已增加到5位,因此result必须是6位才能保持进位,然后回到平方。 Vectors a and b should only be zero extended, that is '0' & a and '0' & b before adding them to result , and then carryborrow , as MSB(Most Significant Bit) of result , will get the correct value. 向量ab只能进行零扩展,即在将它们添加到result之前为'0' & a'0' & b ,然后carryborrowcarryborrow位作为result MSB(最高有效位)将获得正确的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM