Как использовать компоненты vhdl для создания аккуратного иерархического дизайна

Как использовать компоненты vhdl для создания аккуратного иерархического дизайна
Как использовать компоненты vhdl для создания аккуратного иерархического дизайна
Anonim

Как использовать компоненты VHDL для создания аккуратного иерархического дизайна

В этой статье определяются компоненты VHDL, описывается декларация компонентов и приводятся примеры использования компонентов VHDL в вашем коде. В нем также затрагивается формулировка «для-генерации» и ее использование.

В этой статье мы обсудим использование компонентов VHDL. Компоненты позволяют нам разбивать большой дизайн на более мелкие и более управляемые детали. Более того, если мы будем использовать эту возможность, код будет более читабельным. Кроме того, мы рассмотрим инструкцию «for-generate», которая иногда может значительно упростить код.

Чтобы обсудить преимущества использования компонентов VHDL, рассмотрим возможность написания кода VHDL для четырехбитового сумматора.

Схема четырехрядного сумматора

Чтобы добавить два n-разрядных номера, мы добавляем цифры каждой битовой позиции вместе справа налево. Это дает нам сумму и перенос для каждой позиции бит. Перенос, производимый в каждом столбце, должен быть добавлен к цифрам следующего битового положения. Это означает, что для двоичного сложения требуется схема, которая может добавить три бита.

Эта схема, называемая полным сумматором (FA), имеет следующую таблицу истинности:

Image
Image

Здесь $$ 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 $$, мы имеем следующую диаграмму:

Image
Image
Рисунок 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.

Image
Image
фигура 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.

Image
Image
Рисунок 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).

Image
Image
Рисунок 4

Компонентное создание

Теперь, когда объявлен FA-компонент, мы можем использовать (или создавать экземпляр) его. Компонентный экземпляр определяет взаимосвязь компонента с другими частями системы.

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

Image
Image
Рисунок 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.

Image
Image
Рисунок 6

Заявление VHDL «For-Generate»

Схема, описываемая строками 17-20 листинга 3, показана на рисунке 7.

Image
Image
Рисунок 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-битный сумматор без использования компонентов и «для-генерации» операторов!

Чтобы просмотреть полный список моих статей, перейдите на эту страницу.