Носить / брать в 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
, получит правильное значение.