Задача
Выполнить одну из восьми операций над парой чисел и выдать флаги.
Тип схемы: Комбинационная схема с выбором операции.
Модуль: alu. Среда: Quartus, Vivado, ISE или свободный GHDL для моделирования.
Теорию по языку смотрите в статье VHDL — язык описания аппаратуры,
по самим микросхемам — на странице ПЛИС.
Алгоритм
- Объявить результат на разряд шире операндов — старший разряд станет переносом.
- Оператором case выбрать операцию по коду.
- Взять младшие разряды результата как выходное значение.
- Сформировать флаги: ноль, перенос и знак.
Код на VHDL
Код проверен компилятором GHDL: проходит анализ и элаборацию без ошибок и предупреждений. Скачать: v25.vhd
--=====================================================
-- Проект 25. Арифметико-логическое устройство
-- Восемь операций над двумя числами с флагами
-- нуля, переноса и знака.
--=====================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alu is
generic (
WIDTH : integer := 8
);
port (
a, b : in std_logic_vector(WIDTH-1 downto 0);
op : in std_logic_vector(2 downto 0); -- код операции
result : out std_logic_vector(WIDTH-1 downto 0);
zero : out std_logic;
carry : out std_logic;
neg : out std_logic
);
end entity alu;
architecture rtl of alu is
signal res_ext : unsigned(WIDTH downto 0); -- на разряд шире для переноса
signal res : unsigned(WIDTH-1 downto 0);
begin
process (a, b, op)
begin
case op is
when "000" => res_ext <= ('0' & unsigned(a)) + ('0' & unsigned(b)); -- сложение
when "001" => res_ext <= ('0' & unsigned(a)) - ('0' & unsigned(b)); -- вычитание
when "010" => res_ext <= '0' & (unsigned(a) and unsigned(b));
when "011" => res_ext <= '0' & (unsigned(a) or unsigned(b));
when "100" => res_ext <= '0' & (unsigned(a) xor unsigned(b));
when "101" => res_ext <= '0' & (not unsigned(a));
when "110" => res_ext <= '0' & (unsigned(a(WIDTH-2 downto 0)) & '0'); -- сдвиг влево
when others=> res_ext <= '0' & ('0' & unsigned(a(WIDTH-1 downto 1))); -- сдвиг вправо
end case;
end process;
res <= res_ext(WIDTH-1 downto 0);
result <= std_logic_vector(res);
carry <= res_ext(WIDTH);
zero <= '1' when res = 0 else '0';
neg <= res(WIDTH-1);
end architecture rtl;
Пояснения
- Расширение операндов нулём перед сложением — стандартный приём получения переноса: он оказывается в дополнительном старшем разряде.
- Флаг знака — это просто старший бит результата при трактовке числа как знакового.
- Все ветви
caseприсваивают результат, поэтому защёлки не возникают — типичная ошибка при неполном описании.
Что дальше
Следующие проекты — в разделе проекты на VHDL. Сравнить подход с языком Verilog можно в статье Verilog, а разобраться в устройстве самих кристаллов — в статье ПЛИС: FPGA и CPLD.