Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
vhdl.doc
Скачиваний:
3
Добавлен:
01.04.2025
Размер:
396 Кб
Скачать
☆

Интерфейс

... да вот фейс-то у меня не подходящий.

Ну чтож, вот мы и подошли к какому-то началу. Как говорится интерфейс он и в Африке интерфейс. То есть это те же входные и выходные сигналы, а также какие-нибудь передаваемые в архитектуру параметры, оформленные по правилам языка VHDL. В общем виде объявление интерфейса выглядит следующим образом:

  • entity NAME_ENTITY is

  • ----------------------------

  • generic (

  • -- Здесь указываются параметры);

  • port (

  • -- Здесь указываются порты);

  • -- Область объявлений

  • begin --ставится, если далее следуют параллельные операторы интерфейса

  • -- Параллельные операторы (обычно assert), вызовы подпрограмм

  • end NAME_ENTITY;

Приведем пример общего случая VHDL интерфейса, при этом не забываем объявлять библиотеки, если необходимо:

  • library ieee;

  • use ieee.std_logic_1164.all;

  • entity ADDER_N is

  • ----------------------------

  • generic (

  • -- Задаем разрядность сумматора

  • N : natural := 4);

  • ----------------------------

  • port (

  • a, b : in std_logic_vector(0 to N-1); -- Операнды

  • s : out std_logic_vector(0 to N-1); -- Сумма

  • c : out std_logic -- Перенос

  • );

  • ----------------------------

  • constant GND : std_logic := '0';

  • constant VCC : std_logic := '1';

  • constant TRI : std_logic := 'Z';

  • ----------------------------

  • begin

  • ----------------------------

  • assert N > 1

  • report "N is too small"

  • severity error;

  • ----------------------------

  • end ADDER_N;

Этот VHDL интерфейс проиллюстрирован на рисунке 10.

А теперь то же самое, но без generic:

  • library ieee;

  • use ieee.std_logic_1164.all;

  • entity ADDR_4 is

  • port (

  • a, b : in std_logic_vector(0 to 3); -- Операнды

  • s : out std_logic_vector(0 to 3); -- Сумма

  • c : out std_logic -- Перенос

  • );

  • end ADDR_4;

Этот VHDL интерфейс проиллюстрирован на рисунке 11.

А может быть и пустой интерфейс. Это когда у Вас крутится все внутри и нет никаких связей с внешним миром. Используется для создания тестовых VHDL моделей:

  • library ieee;

  • use ieee.std_logic_1164.all;

  • entity TEST_BENCH is

  • end TEST_BENCH;

Интерфейс может быть как внешним для проекта, так и внутренним, применяемым для компонентов проекта. Про компоненты мы поговорим позже. Порты VHDL-интерфейса могут быть следующих видов:

  • in - входной порт (только для чтения значения сигнала);

  • out - выходной порт (только для записи значения сигнала);

  • Inout - двунаправленный порт (чтение и запись);

  • buffer - выходной порт, значение которого можно считывать;

  • linkage - двунаправленный порт с ограниченным использованием (практически не используется).

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

Архитектура

... после программы ВРЕМЯ - архитектор перестройки.

Архитектура содержит две основные части:

  1. Часть, содержащую описания (декларации);

  2. Часть, содержащую исполняемые операторы.

В общем виде архитектура выглядит следующим образом:

  • architecture NAME_ARCHITECTURE of NAME_ENTITY is

  • -- Здесь содержатся:

  • -- - описания типов данных;

  • -- - функции и процедуры;

  • -- - компоненты более низкого уровня иерархии;

  • -- - описания сигналов и глобальных переменных.

  • begin

  • -- Здесь содержатся исполняемые операторы.

  • end NAME_ARCHITECTURE;

Теперь напишем простой VHDL код для компонента NAND c двумя входами:

  • -------------------------------------------

  • -- VHDL код для компонента NAND2

  • -------------------------------------------

  • library ieee;

  • use ieee.std_logic_1164.all;

  • ---------------------------------

  • entity NAND2 is

  • port (

  • a, b : in std_logic;

  • c : out std_logic

  • );

  • end NAND2;

  • ---------------------------------

  • architecture aaa of NAND2 is

  • begin

  • c <= not (a and b);

  • end aaa;

Ну вот, у нас получился вполне законченный синтезируемый VHDL-код. Поверьте, он будет воспринят любым существующим синтезатором. Конечно, это очень простой пример, но не все сразу. Теперь мы покажем, как используются компоненты и сигналы, несколько усложнив схему (рисунок 12):

  • --------------------------------------------------

  • -- VHDL код для трех компонентов NAND2

  • --------------------------------------------------

  • library ieee;

  • use ieee.std_logic_1164.all;

  • ---------------------------------

  • entity NAND2X3 is

  • port (

  • a, b, c, d : in std_logic;

  • q : out std_logic

  • );

  • end NAND2X3;

  • ---------------------------------

  • architecture bbb of NAND2X3 is

  • signal s1, s2 : std_logic;

  • component NAND2

  • port (

  • a, b : in std_logic;

  • c : out std_logic);

  • end component;

  • begin

  • D1: NAND2 port map (a => a, b => b, c => s1);

  • D2: NAND2 port map (a => c, b => d, c => s2);

  • D3: NAND2 port map (a =>s1, b =>s2, c =>q);

  • end bbb;

Данный VHDL код использует компонент NAND2, описанный ранее. Вообще-то данный пример приведен в учебных целях и автор никогда бы так не стал писать, хотя любой синтезатор поймет и правильно воспримет этот код. Почему так писать не стоит. Да хотя бы, потому что можно написать проще и главное - понятнее. Метод, которым мы описали схему, изображенную на рисунке 12, называется структурным описанием. Такой метод, по личному мнению автора, имеет право на жизнь в крупных проектах, т.е. когда мы разбиваем проект на несколько компонентов. А теперь давайте воспользуемся другим методом описания - поведенческим:

  • --------------------------------------------------

  • -- VHDL код для трех компонентов NAND2

  • --------------------------------------------------

  • library ieee;

  • use ieee.std_logic_1164.all;

  • ---------------------------------

  • entity NAND2X3 is

  • port (

  • a, b, c, d : in std_logic;

  • q : out std_logic

  • );

  • end NAND2X3;

  • ---------------------------------

  • architecture ccc of NAND2X3 is

  • signal s1, s2 : std_logic;

  • begin

  • s1 <= not (a and b);

  • s2 <= not (c and d);

  • q <= not (s1 and s2);

  • end ccc;

А если учесть, что !(!(a*b)*!(c*d)) = (a*b)+(c*d), то можно переписать VHDL-код следующим образом:

  • --------------------------------------------------

  • -- VHDL код для трех компонентов NAND2

  • --------------------------------------------------

  • library ieee;

  • use ieee.std_logic_1164.all;

  • ---------------------------------

  • entity NAND2X3 is

  • port (

  • a, b, c, d : in std_logic;

  • q : out std_logic

  • );

  • end NAND2X3;

  • ---------------------------------

  • architecture ddd of NAND2X3 is

  • begin

  • q <= (a and b) or (c and d);

  • end ddd;

Кстати говоря, язык VHDL позволяет одному интерфейсу иметь несколько архитектурных тел. Давайте возьмем пример из реального проекта - компонент управления светодиодным индикатором ошибки. Допустим у нас есть два сигнала (ERR1, ERR2), информирующие об ошибке всего проектируемого устройства и для каждого сигнала есть разрешение индикации (EN1, EN2). Светодиод должен загораться по любому разрешенному сигналу. Для проектирования воспользуемся компонентом NAND2X3. На данном этапе попробуем две архитектуры этого компонента, а дальше выберем наиболее оптимальную. Посмотрите на следующий VHDL-код:

  • --------------------------------------------------

  • -- VHDL код для трех компонентов NAND2

  • --------------------------------------------------

  • library ieee;

  • use ieee.std_logic_1164.all;

  • ---------------------------------

  • entity NAND2X3 is

  • port (

  • a, b, c, d : in std_logic;

  • q : out std_logic

  • );

  • end NAND2X3;

  • ---------------------------------

  • architecture bbb of NAND2X3 is

  • signal s1, s2 : std_logic;

  • component NAND2

  • port (

  • a, b : in std_logic;

  • c : out std_logic);

  • end component;

  • begin

  • D1: NAND2 port map (a => a, b => b, c => s1);

  • D2: NAND2 port map (a => c, b => d, c => s2);

  • D3: NAND2 port map (a =>s1, b =>s2, c =>q);

  • end bbb;

  • ---------------------------------

  • architecture ddd of NAND2X3 is

  • begin

  • q <= (a and b) or (c and d);

  • end ddd;

  • --------------------------------------------------

  • -- VHDL код управления индикацией

  • --------------------------------------------------

  • library ieee;

  • use ieee.std_logic_1164.all;

  • ---------------------------------

  • entity ERR_LED is

  • port (

  • ERR1, EN1, ERR2, EN2 : in std_logic;

  • LED : out std_logic);

  • end ERR_LED;

  • ---------------------------------

  • architecture arch of ERR_LED is

  • --component NAND2X3 is

  • --port (

  • --a, b, c, d : in std_logic;

  • --q : out std_logic);

  • --end component;

  • signal serror : std_logic;

  • begin

  • C1: entity WORK.NAND2X3(bbb) port map(a => ERR1, b => EN1, c => ERR2, d => EN2, q => serror);

  • LED <= '0' when serror = '1' else 'Z';

  • end arch;

Синтезатор Leonardo Spectrum для микросхемы MAX3128ATC144 из данного VHDL-кода сгенерирует схему, показанную на рисунке 13.

Если в выражение WORK.NAND2X3(bbb) подставить архитектуру ddd, то Leonardo все равно сгенерирует такую же схему, можете проверить. Повторю, что данная схема получилась для конкретной микросхемы (технологии) ПЛИС. Другое дело если Вы пишите VHDL-модель, тогда разные архитектуры могут вести себя по-разному. Кстати, обратите внимание, что объявление компонента NAND2X3 закомментировано. VHDL допускает не объявлять используемые компоненты, если они определены ранее и подключаются записью типа:

  • NAME: entity WORK.NAME_ENTITY(NAME_ARCHITECTURE)

  • generic map(...)

  • port map(...);

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]