Как использовать компоненты VHDL для создания аккуратного иерархического дизайна
В этой статье определяются компоненты VHDL, описывается декларация компонентов и приводятся примеры использования компонентов VHDL в вашем коде. В нем также затрагивается формулировка «для-генерации» и ее использование.
В этой статье мы обсудим использование компонентов VHDL. Компоненты позволяют нам разбивать большой дизайн на более мелкие и более управляемые детали. Более того, если мы будем использовать эту возможность, код будет более читабельным. Кроме того, мы рассмотрим инструкцию «for-generate», которая иногда может значительно упростить код.
Чтобы обсудить преимущества использования компонентов VHDL, рассмотрим возможность написания кода VHDL для четырехбитового сумматора.
Схема четырехрядного сумматора
Чтобы добавить два n-разрядных номера, мы добавляем цифры каждой битовой позиции вместе справа налево. Это дает нам сумму и перенос для каждой позиции бит. Перенос, производимый в каждом столбце, должен быть добавлен к цифрам следующего битового положения. Это означает, что для двоичного сложения требуется схема, которая может добавить три бита.
Эта схема, называемая полным сумматором (FA), имеет следующую таблицу истинности:

Здесь $$ A_i $$ и $$ B_i $$ - цифры i- го столбца, а $$ C_i $$ - перенос, произведенный предыдущим столбцом. Добавление этих трех бит дает сумму $$ S_i $$ и перенос $$ C_ {i + 1} $$. $$ C_ {i + 1} $$ будет добавлен к цифрам следующей позиции бита. Следовательно, для четырехбитового сумматора, который добавляет $$ A_3A_2A_1A_0 $$ к $$ B_3B_2B_1B_0 $$, мы имеем следующую диаграмму:

Рисунок 1. Блок-схема четырехразрядного сумматора. Изображение предоставлено Digital Design
VHDL Описание полного сумматора и четырехбитового сумматора
Основываясь на таблице истинности полного сумматора, мы получаем следующие выражения:
$$ S_i = A_i \ oplus B_i \ oplus C_i $$
$$ C_ {i + 1} = \ big (A_i \ oplus B_i \ big) C_i + A_iB_i $$
Таким образом, код VHDL полного сумматора:
Листинг 1
1 library IEEE; 2 use IEEE. STD_LOGIC_1164. ALL; 3 entity FA is 4 port(a, b, c_in: in std_logic; 5 s, c_out: out std_logic); 6 end FA; 7 architecture Behavioral of FA is 8 begin 9 s <= a xor b xor c_in; 10 c_out <= ((a xor b) and c_in) or (a and b); 11 end Behavioral;
a и b - цифры i- го столбца, а c_in - входной перенос полного сумматора. Добавление этих трех битов дает сумму, s и перенос c_out. Моделирование ISE для этого кода показано на рисунке 2.

фигура 2
Мы можем повторить строки 9 и 10 для расширения кода VHDL полного сумматора в коде VHDL четырехразрядного сумматора:
Листинг 2
1 library IEEE; 2 use IEEE. STD_LOGIC_1164. ALL; 3 entity Four_Bit_Adder is 4 Port (a: in STD_LOGIC_VECTOR (3 downto 0); 5 b: in STD_LOGIC_VECTOR (3 downto 0); 6 c0: in STD_LOGIC; 7 s: out STD_LOGIC_VECTOR (3 downto 0); 8 c4: out STD_LOGIC); 9 end Four_Bit_Adder; 10 architecture Behavioral of Four_Bit_Adder is 11 signal c3, c2, c1: std_logic; 12 begin 13 -- The first full adder 14 s(0) <= a(0) xor b(0) xor c0; 15 c1 <= ((a(0) xor b(0)) and c0) or (a(0) and b(0)); 16 -- The second full adder 17 s(1) <= a(1) xor b(1) xor c1; 18 c2 <= ((a(1) xor b(1)) and c1) or (a(1) and b(1)); 19 -- The third full adder 20 s(2) <= a(2) xor b(2) xor c2; 21 c3 <= ((a(2) xor b(2)) and c2) or (a(2) and b(2)); 22 -- The fourth full adder 23 s(3) <= a(3) xor b(3) xor c3; 24 c4 <= ((a(3) xor b(3)) and c3) or (a(3) and b(3)); 25 end Behavioral;
Моделирование ISE для этого кода показано на рисунке 3.

Рисунок 3
Однако существует альтернативный подход, который может привести к созданию более чистого кода. В этом случае мы определяем полный сумматор в качестве подсхемы и используем его четыре раза в нашем коде. В лексиконе VHDL вместо «sub-circuit» используется слово «компонент».
Использование компонентов VHDL
Декларация компонентов
Чтобы использовать полный блок сумматора в качестве компонента в нашем коде, мы можем сохранить код листинга 1 в виде отдельного файла, а именно FA.vhd, в нашем проекте.
Теперь нам нужно указать, что схема, описанная FA.vhd, является компонентом нашего основного кода. Это называется объявлением компонента. Чтобы объявить компонент FA в нашем основном коде, нам нужно добавить следующие строки:
component FA is port(a, b, c_in: in std_logic; s, c_out: out std_logic); end component;
Это говорит программному обеспечению синтеза, что FA является компонентом с тремя входами (a, b, c_in) и двумя выходами (s, c_out). Он также определяет тип данных для этих входов и выходов.
Как вы можете видеть, эти части информации точно такие же, как те, которые предоставляются частью «сущности» описания VHDL FA (строки 3-6 листинга 1).
По сути, декларация компонента описывает интерфейс компонента с его средой (см. Рис. 4).

Рисунок 4
Компонентное создание
Теперь, когда объявлен FA-компонент, мы можем использовать (или создавать экземпляр) его. Компонентный экземпляр определяет взаимосвязь компонента с другими частями системы.
Например, рассмотрим самый правый FA на рисунке 1. В этом случае, как показано на рисунке 5, A0, B0, C0, S0 и C1 схемы верхнего уровня должны быть подключены к a, b, c_in, s и c_out самой правой FA, соответственно.

Рисунок 5
Мы используем оператор «port map» для описания взаимосвязи компонента с схемой верхнего уровня. Например:
u1: FA port map (a => A0, b => B0, c_in => C0, s => S0, c_out => C1);
Здесь u1 - произвольная метка для этого компонента, а FA указывает имя компонента. Обозначение a => A0 означает, что порт FA-компонента подключен к A0 от основной цепи. Аналогично, мы можем использовать следующий код, чтобы описать крайний левый FA на рисунке 1.
u4: FA port map (a => A3, b => B3, c_in => C3, s => S3, c_out => C4);
Мы можем написать описание VHDL четырехразрядного сумматора следующим образом:
Листинг 3
1 library IEEE; 2 use IEEE. STD_LOGIC_1164. ALL; 3 entity Four_Bit_Adder is 4 Port (a: in STD_LOGIC_VECTOR (3 downto 0); 5 b: in STD_LOGIC_VECTOR (3 downto 0); 6 cin: in STD_LOGIC; 7 s: out STD_LOGIC_VECTOR (3 downto 0); 8 cout: out STD_LOGIC); 9 end Four_Bit_Adder; 10 architecture Behavioral of Four_Bit_Adder is 11 component FA is 12 port (a, b, c_in: in std_logic; 13 s, c_out: out std_logic); 14 end component; 15 signal c: std_logic_vector(4 downto 0); 16 begin 17 u1: FA port map (a => a(0), b => b(0), c_in => c(0), s => s(0), c_out => c(1)); 18 u2: FA port map (a => a(1), b => b(1), c_in => c(1), s => s(1), c_out => c(2)); 19 u3: FA port map (a => a(2), b => b(2), c_in => c(2), s => s(2), c_out => c(3)); 20 u4: FA port map (a => a(3), b => b(3), c_in => c(3), s => s(3), c_out => c(4)); 21 c(0) <= cin; 22 cout <= c(4); 23 end Behavioral;
Обратите внимание, что объявление компонента входит в «архитектуру» «Four_Bit_Adder» перед ключевым словом «begin». Моделирование ISE приведенного выше кода показано на рисунке 6.

Рисунок 6
Заявление VHDL «For-Generate»
Схема, описываемая строками 17-20 листинга 3, показана на рисунке 7.

Рисунок 7
В этой структуре есть определенный шаблон. Используя индекс i, начиная от 0 до 3, мы можем описать все эти экземпляры с помощью одного оператора:
uut: FA port map (a => a(i), b => b(i), c_in => c(i), s => s(i), c_out => c(i+1));
где i = 0 дает самый правый экземпляр FA (строка 17 листинга 3), i = 3 дает самый левый экземпляр FA (строка 20 в листинге 3) и т. д. Чтобы описать такие повторяющиеся структуры, VHDL позволяет нам использовать оператор for-generate. Операция «for-generate», которая описывает рисунок 7, будет:
1 gen: for i in 0 to 3 generate 2 uut: FA port map (a => a(i), b => b(i), c_in => c(i), s => s(i), c_out => c(i+1)); 3 end generate;
Здесь gen - произвольная метка для оператора for-generate, а i, которая находится между ключевыми словами for и in, является идентификатором, который указывает количество повторений операторов внутри структуры «для-генерации».
В этом примере диапазон i от 0 до 3. Это означает, что оператор строки 2 будет выполняться четыре раза с i = 0, 1, 2 и 3. Поскольку i принимает значения от 0 до 3, будут созданы строки 17-20 листинга 3. Следующий код использует оператор for-generate для реализации четырехбитового сумматора:
Листинг 4
1 library IEEE; 2 use IEEE. STD_LOGIC_1164. ALL; 3 entity Four_Bit_Adder is 4 Port (a: in STD_LOGIC_VECTOR (3 downto 0); 5 b: in STD_LOGIC_VECTOR (3 downto 0); 6 cin: in STD_LOGIC; 7 s: out STD_LOGIC_VECTOR (3 downto 0); 8 cout: out STD_LOGIC); 9 end Four_Bit_Adder; 10 architecture Behavioral of Four_Bit_Adder is 11 component FA is 12 port (a, b, c_in: in std_logic; 13 s, c_out: out std_logic); 14 end component; 15 signal c: std_logic_vector(4 downto 0); 16 begin 17 gen: for i in 0 to 3 generate 18 uut: FA port map (a => a(i), b => b(i), c_in => c(i), s => s(i), c_out => c(i+1)); 19 end generate; 20 c(0) <= cin; 21 cout <= c(4); 22 end Behavioral;
Вывод
Использование компонентов VHDL является полезным методом, особенно когда нам нужно реализовать ту же функциональность много раз или когда подсеть сложна и имеет длинное описание VHDL. Более того, когда схема имеет шаблон, подобный шаблону на рисунке 7, мы можем использовать оператор for-generate, чтобы значительно упростить код.
Чтобы понять преимущества этих заявлений VHDL, представьте себе, насколько неудобным был бы код, если бы мы разработали 64-битный сумматор без использования компонентов и «для-генерации» операторов!
Чтобы просмотреть полный список моих статей, перейдите на эту страницу.