Носить / брать в VHDL ALU

Я делаю общий N-битный АЛУ в VHDL. У меня проблемы с назначением значения для переноса для сложения или заимствования для вычитания. Я пробовал следующее:

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. Как я могу присвоить его тому, что должно быть без ошибок типа?

2 ответа

Решение

В вашем коде есть ошибки:

я) Вы не учли тот факт, что сигналы не обновляются сразу. Следовательно, следующие строки не будут работать так, как я думаю, вы ожидаете:

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

Вместо этого вам нужно взять линии вождения output а также carryborrow вне комбинационного процесса, как вы можете видеть ниже. II) Если вы хотите, чтобы этот код был синтезируемым, просто поместив NULL в вашей всегда ветке будет выводиться защелки. Вам нужно ехать result в другой ветке тоже.

Итак, сделав предположение о том, как ваш выходной сигнал будет вести себя с and а также or операции, вот как я бы написал ваш код:

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;

Я обычно делаю это:

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

Знак расширяют, а затем выполняют операцию, чтобы позаботиться о переполнении, когда в результате получается один лишний бит.

Хм, рассмотрим это в 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'что не так!

По знакам, расширяющим векторы a а также bчисловой диапазон увеличился до 5 бит, и, таким образом, result должно быть 6 бит, чтобы иметь возможность держать перенос, и мы вернулись к исходной точке. векторы a а также b должен быть расширен только на ноль, то есть '0' & a а также '0' & b перед добавлением их в result, а потом carryborrowв качестве старшего значащего бита result, получит правильное значение.

Другие вопросы по тегам