ОПИСАНИЕ ЦИФРОВЫХ УСТРОЙСТВ В СРЕДЕ ПАКЕТА
WebPACK ISE НА ЯЗЫКЕ VHDL
Цель работы:
– знакомство с языком описания схем VHDL;
– практическоеосвоение методики проектирования цифровых устройств на современной элементной базе (ПЛИС) с использованием языка VHDL.
Приборы и оборудование:
– компьютер совместимый с IBM PC, 32-256 Мб. ОЗУ;
– операционная система WINDOWS 2000, XP;
– лабораторный стенд, содержащий ПЛИС Xilinx xc95288xl;
– пакет WebPACK ISE.
Содержание работы:
– знакомство с языком описания схем VHDL;
– создание описания цифрового устройства с использованием VHDL- редактора пакета WebPACK ISE (логические функции проектируемого устройства задаются преподавателем индивидуально каждому студенту);
– моделирование спроектированного устройства в программе ModelSim;
– проверка правильности функционирования спроектированного устройства на лабораторном стенде.
Форма отчётности студентов:
Индивидуальный отчёт в электронной форме с типовым титульным листом. Допустимые форматы – RTF, HTML, DOC.
Выполнение и защита лабораторной работы производится строго во время занятий. Защита работы – демонстрация результатов моделирования спроектированного цифрового устройства и собеседование с преподавателем.
ЯЗЫК ОПИСАНИЯ СХЕМ VHDL
В середине 80-х годов Министерство обороны США (U.S. Department of Defense, DoD) и Институт инженеров по электротехнике и электронике (Institute of Electrical and Electronic Engineers, IEEE) поддержали разработку довольно мощного языка описания схем VHDL. С самого начала и по настоящее время отличительными особенностями этого языка является следующее:
– проектируемые устройства можно иерархически разбивать на составные элементы;
– каждый элемент устройства имеет ясно очерченный интерфейс (для соединения его с другими элементами) и точное функциональное описание (для его моделирования);
|
– функциональное описание может быть основано на алгоритме, либо на реальной конструкции, которыми определяется работа элемента. Например, первоначально можно описать работу элемента посредством алгоритма, и это сделает возможной верификацию элементов более высокого уровня, в которых используется данный элемент; позднее алгоритмическое определение можно заменить структурной схемой;
– все можно моделировать: параллелизм, временные соотношения и синхронизацию тактовыми сигналами. На языке VHDL можно описать как асинхронные, так и синхронные последовательностые структуры;
– можно моделировать выполняемые устройством в целом логические действия и его временные характеристики.
Таким образом, с самого начала VHDL является языком документации и моделирования, позволяющим точно задавать и имитировать поведение цифровых систем.
СТРУКТУРА ПРОГРАММЫ
При создании языка VHDL имелось в виду воплотить в нем принципы структурного программирования с заимствованием идей у языков программирования Паскаль и Ада. Ключевая идея состояла в том, чтобы задать интерфейс схемного модуля, а его внутреннее устройство скрыть.
Основное описание и организация структуры VHDL показаны на рис. 1.
Рис. 1. Структура проекта на VHDL.
Оператор пакета является необязательным для раздела описаний. Оператор entity содержит описание входного и выходного интерфейса проекта, так как каждая микросхема имеет выходы или входы. Оператор architecture содержит описание функционирования проекта. Проект может содержать любое количество операторов пакетов, объектов и архитектур. Из структурной схемы языка видно, что архитектура содержит параллельные операторы, такие как netlists, и классические последовательные операторы. Параллельные операторы выполняются независимо от порядка, в котором они написаны. Параметры, передаваемые по значению, передаются между операторами с помощью сигналов, присвоение сигнала осуществляется драйвером.
|
Наиболее мощные конструкции языка встречаются внутри последовательных операторов. Такие конструкции размещаются вместо параллельных операторов, например, оператора процесса, функций и процедур. Последовательные операторы похожи на операторы языков программирования, они выполняются в том же порядке, в котором пишутся. Значения содержатся в переменных или константах. Сигналы используются для передачи входных и выходных значений процесса или от других параллельных операторов.
На рис. 2 в качестве примера приведена очень простая программа на языке VHDL для 2х-входового вентиля «ЗАПРЕТ». В больших проектах объекты и архитектуры иногда бывают помещены в отдельные файлы, связь между которыми компилятор обнаруживает по их объявленным именам
Рис. 2 Программы на языке VHDL для вентиля «ЗАПРЕТ».
Как и в других языках программирования, в языке VHDL пробелы и переходы с одной строки на другую в общем случае игнорируются, и для удобства чтения их можно вставлять как угодно. Комментарии (comments) начинаются с двух дефисов (--) и заканчиваются концом строки.
|
В языке VHDL определено много специальных строк символов, называемых зарезервированнымисловами (reserved words) или ключевымисловами (keywords). В приведенном примере имеется несколько ключевых слов: entity,port, is, in, out, end, architecture, begin, when, else и not. Определяемые пользователем идентификаторы (identifiers) начинаются с буквы и содержат буквы, цифры и подчеркивания. (Символ подчеркивания не может следовать за другим символом подчеркивания и не может быть последним символом идентификатора). В данном примере идентификаторами являются Inh, X, Y, BIT, Z и Behavioral. "BIT" – это встроенный идентификатор предопределенного типа; он не считается зарезервированным словом, так как его можно переопределять. Зарезервированные слова и идентификаторы не чувствительны к регистру.
ОПИСАНИЕ ИНТЕРФЕЙСА
В языке VHDL логическая схема представляется как объект проекта. Представляемая логическая схема может быть достаточно сложной, как, например, микропроцессор или весьма простой, как логический вентиль 2И-НЕ. Каждый объект проекта в свою очередь имеет два различных типа описаний: описание интерфейса и одно или более архитектурные тела.
В табл. 1 представлен синтаксис объявления объекта. Целью объявления объекта, помимо присвоения объекту имени, является определение сигналов внешнего интерфейса или портов (ports) в части объявления объекта, которая называется объявлением портов (port declaration). Кроме ключевых слов entity, is, port и end, объявление объекта содержит следующие элементы:
Entity_name – выбираемое пользователем имя объекта;
Signal_names – список выбираемых пользователем имен сигналов внешнего интерфейса, состоящий из одного имени или из большего числа имен, разделенных запятой;
Mode – одно из четырех зарезервированных слов, определяющих направление передачи сигнала:
а) in сигнал на входе объекта;
б) out сигнал на выходе объекта; заметьте, что значение такого сигнала нельзя «прочитать» внутри структуры объекта; он доступен только объектам, использующим данный объект;
в) buffer сигнал на выходе объекта, такой что его значение можно читать также внутри структуры данного объекта;
г) inout сигнал, который может быть входным или выходным для данного объекта; обычно этот режим используется применительно к входам-выходам ПЛУ с тремя состояниями;
Signal _ type – встроенный или определенный пользователем тип сигнала.
Замечание. Обратите внимание, что после заключительного signal _ type нет точки с запятой; изменение порядка следования закрывающей скобки и точки с запятой после нее типичная синтаксическая ошибка программиста, начинающего писать на языке VHDL.
Таблица 1. Синтаксис объявления объекта на языке VHDL.
entity | entity_name is |
port | (signal_names: mode signal_type; |
signal_names: mode signal_type; | |
………………………………….. | |
signal_names: mode signal_type); | |
end | entity_name |
Порты объекта, а также направление передачи и типы сигналов – это все, что видят другие модули, использующие данный модуль.
Проиллюстрируем это понятие на примере. Описание интерфейса для схемы дешифратора, которая преобразует входной четырехразрядный код в напряжение низкого уровня на одном из 10 выходов.
entity Id_1 is
port (A: in bit_vector(0 to 3); Y: out bit_vector(0 to 9));
end Id_1;
АРХИТЕКТУРНЫЕ ТЕЛА
Описание интерфейса по существу определяет только входы-выходы объекта проекта. Кроме этого необходимо иметь средства описания поведения объекта. В языке VHDL для этой цели служит так называемое архитектурное тело. Это тело может определять поведение объекта непосредственно или представлять структурную декомпозицию на более простые компоненты.
В табл. 2 представлен синтаксис объявления архитектурного тела.
Таблица 2. Синтаксис определения архитектуры на языке VHDL.
architecture | Architecture _ name of entity _ name is |
type declarations | |
signal declarations | |
constant declarations | |
function definitions | |
procedure definitions | |
component declarations | |
begin | |
Concurrent_statement | |
………………………… | |
Concurrent_statement | |
end | Architecture _ name; |
Имяобъекта(entity _ name) в этом определении должно быть таким же, какое раньше было присвоено объекту в объявлении объекта. Имя архитектуры (architecture _ name) –это выбираемый пользователем идентификатор, обычно так или иначе связанный с именем объекта; при желании имя архитектуры может быть тем же самым, что и имя объекта.
Сигналы внешнего интерфейса архитектуры (порты) наследуются от той части объявления соответствующего объекта, где объявляются порты. У архитектуры могут быть также сигналы и другие объявления, являющиеся для нее локальными, подобно тому, как это имеет место в других языках высокого уровня. В отдельном «пакете», используемом несколькими объектами, можно сделать объявления, общие для этих объектов.
Объявления в табл. 2 могут располагаться в произвольном порядке. Начать легче всего с объявления сигнала (signal declaration), которое сообщает ту же самую информацию о сигнале, какую содержит объявление порта, за исключением того, что вид сигнала не задается:
signal signal_names: signal_type;
В архитектуре может быть объявлено любое число сигналов, начиная с нуля, и они приблизительно соответствуют поименованным соединениям в принципиальной схеме. Их можно считывать и записывать внутри определения архитектуры и, подобно другим локальным элементам, на них можно ссылаться только в пределах данного определении архитектуры.
Переменные (variables) в языке VHDL похожи на сигналы, за исключением того, что, как правило, они не имеют никакого физического смысла в схеме. Переменные используются в функциях, процедурах и процессах языка VHDL. Объявление переменной выглядит следующим образом:
variable variable_names: variable _ type;
Ниже, в качестве примера, показано архитектурное тело для дешифратора Id_1:
Architecture DC of Id_1 is
Begin
Process(A)
Begin Y<=”1111111111”
Case A(0 to 3) is
when( “0000” ) => Y <=”0111111111”
when( “1000” ) => Y <=”1011111111”
when( “0100” ) => Y <=”1101111111”
when( “1100” ) => Y <=”1110111111”
when( “0010” ) => Y <=”1111011111”
when( “1010” ) => Y <=”1111101111”
when( “0110” ) => Y <=”1111110111”
when( “1110” ) => Y <=”1111111011”
when( “0001” ) => Y <=”1111111101”
when( “1001” ) => Y <=”1111111110”
end case;
end process;
end DC;
В архитектурном теле отсутствует программный цикл, осуществляющий сканирование входов от до , вместо этого применен оператор выбора case, в котором управляющее выражение – битовый вектор. В зависимости от значений входного вектора , определяется значение выходного вектора . Нумерация разрядов в векторе осуществляется слева направо.
ОПЕРАТОРЫБЛОКОВ
Базовым элементом описания в языке VHDL служит блок, т.е. ограниченный фрагмент текста, содержащий раздел описания и исполняемый раздел. Следовательно, архитектурное тело представляет собой блок. Однако в рамках архитектурного тела могут существовать внутренние блоки.
Рассмотрим пример. Блоки А и В вложены во внешний блок архитектурного тела. Возможно любое число уровней вложенности. Использование такой структуры позволяет иерархически представить структуру объекта и записать условия «защиты». Если условие будет иметь значение «истина», это разрешит выполнение определенных типов внутренних операторов.
Наличие метки перед оператором блока обязательно. Имя метки заканчивается двоеточием и может стоять перед оператором блока или на предыдущей строке. Наличие других операторов между оператором блока и меткой не допускается:
architecture Block of System is
-------- раздел описаний типов внешнего блока
Begin
-------- выполняемые операторы внешнего блока
A:block
-------- раздел описаний типов внутреннего блока А
Begin
-------- выполняемые операторы внутреннего оператора А
end block A;
B:block
-------- раздел описаний типов внутреннего блока В
Begin
-------- выполняемые операторы внутреннего оператора B
end block B;
end Block;
ПРОЦЕССЫ
Наиболее значимым элементом для моделирования на языке VHDL является оператор процесса. Оператор содержит последовательные операторы и позволяет разработчику описывать схемы на поведенческом уровне абстракции. Например:
Process(Insig)
variable v1: Integer; -- описание переменных
Begin
v1:= Insig; -- присвоение переменной
v1:= function_name(v1+1); -- Вызов функции
end process;
При проектировании аппаратных средств оператор процесса применяется в двух случаях: для комбинационных и последовательностных схем. Для комбинационных схем оператор выглядит так:
process( signal1, signal2, …,signalN )
Begin
…
end process;
А для последовательностной схемы – несколько иначе:
process( X_signal )
Begin
if X_signal and X_signal’evtent then
…
end if;
end process;
Для комбинационных схем определяется весь список вводимых в процесс сигналов. Это так называемый список чувствительности или сигналов запуска процесса. Если какой-либо сигнал из этого списка меняет свое значение, то процесс активизируется и выполняются операторы блока этого процесса.
Для поледовательностных схем список чувствительности, включает в себя операторы времени и условия запуска с атрибутами. Если этого списка нет, то должен быть оператор времени wait
ТИПЫ, ПЕРЕМЕННЫЕ И КОНСТАНТЫ
Каждому сигналу, переменной и константе в программе на языке VHDL необходимо поставить в соответствие тип (type). Типом определяется множество или диапазон значений, которые может принимать данный элемент, и обычно имеется набор операторов (таких как сложение, логическое И и т.д.), связываемых с данным типом.
В языке VHDL есть всего лишь несколько предопределенных типов (predefined types); они перечислены в табл. 3.
Таблица 3. Предопределенные типы языка VHDL.
bit | character | severity _ level |
bit _ vector | integer | string |
boolean | real | time |
Типом integer определяется диапазон значений целых чисел от –2147483647 до +2147483647 (от до ). В некоторых реализациях языка VHDL этот диапазон может быть и шире. Типом boolean предусматриваются два значения: true и false. Тип character содержит все символы 8-битового набора ISO, из которых первые 128 являются символами стандарта ASCII. Встроенные операторы для типов integer и boolean приведены в табл. 4.
Таблица 4.Предопределенные операторы для типов integer и boolean в языке VHDL.
+ | Сложение | and | И |
– | Вычитание | or | ИЛИ |
* | Умножение | nand | И-НЕ |
/ | Деление | nor | ИЛИ-НЕ |
mod | Деление по модулю | xor | Исключающее ИЛИ |
rem | Остаток от деления по модулю | xnor | Исключающее ИЛИ-НЕ |
abs | Абсолютное значение | not | Дополнение (инверсия) |
** | Возведение в степень |
Чаще всего в типичных программах на языке VHDL используются определяемые пользователем типы (userdefined types), а из них самыми употребительными являются перечислимые типы (enumerated types), которые определяются путем перечисления их значений. Предопределяемые типы boolean и character – это перечислимые типы. Формат объявления типа в случае перечислимого типа указан в первой строке табл. 5. Здесь value_list представляет собой список (перечисление) всех возможных значений этого типа, разделяемых запятыми. Значениями могут быть определяемые пользователем идентификаторы или символы (где под «символом» понимается символ ISO, заключенный в одинарные кавычки). Идентификаторы чаще всего применяются для обозначения альтернатив или состояний конечного автомата, например:
type traffic_light_state is (reset, stop, wait, go);
Символы используются в очень важном случае стандартного определяемого пользователем логического типа std_logic (см. табл. 6), являющегося частью стандартного пакета IEEE 1164. Этот тип включает не только ‘0’ и ‘1’, но также и семь других значений, которые оказываются полезными при моделировании логического сигнала (бита) в реальной логической схеме.
Таблица 5. Синтаксис объявления типов и констант в языке VHDL.
type | Type_name is {value_list); |
subtype | Subtype_name is type_name start to end; |
subtype | Subtype_name is type_name start downto end; |
constant | Constant_name: type_name:= value; |
Таблица 6. Определение типа STD_LOGIC в языке VHDL.
type STD_ULOGIC is | (‘U’,--не инициализировано |
‘X’,--сильное неизвестное | |
‘0’, --сильный ноль | |
‘1’, --сильная единица | |
‘Z’, --высокий импеданс | |
‘W’,--слабое неизвестное | |
‘L’,--слабый ноль | |
‘H’,--слабая единица | |
‘-’,--безразлично); | |
subtype STD_LQGIC is resolvedSTD_ULOGIC; |
Язык VHDL позволяет пользователю создавать также подтипы (subtypes) согласно синтаксису, указанному в табл. 5. Значения подтипа должны быть слитным подмножеством значений, предусмотренных основным типом, начиная со start и кончая end. Для перечислимого типа «слитность» означает расположение на соседних позициях в исходном списке значений value _ list. Вот несколько примеров определения подтипов:
subtype twoval _ logic is std _ logic range ‘0’ to ‘1’;
subtype fourval _ logic is std _ logic range ‘X’ to ‘Z’;
subtype negint is integer range -2147483647 to -1;
subtype bitnum is integer range 31 downto 0;
Заметьте, что порядок следования значений в указываемом диапазоне может быть в сторону возрастания или в сторону убывания в зависимости от того, какое из ключевых слов to или downto употреблено.
В языке VHDL есть два предопределенных подтипа integer:
subtype natural is integer range 0 to highest_integer;
subtype positive is integer range 1 to highest_integer;
Переменная (variable) в языке VHDL отслеживает состояние процесса только внутри него и вне процесса ее не видно. Синтаксис определения переменной внутри процесса подобен синтаксису объявления сигнала в архитектуре, за исключением того, что используется ключевое слово variable:
variable variable-names: variable-type;
variable RUN: Boolean:=False;
variable COUNT: Integer:=0;
variable ADDR: bit_vector(0 to 11);
Константы (constants) способствуют удобству чтения программ, возможности их поддержания и сопровождения, а также переносу на какой-либо другой язык. Синтаксис объявления констант (constant declaration) в языке VHDL указан в последней строке в табл. 5; его можно проиллюстрировать следующими примерами:
constant BUS_SIZE: integer:= 32;
constant MSB: integer:= BUS_SIZE-1;
constant Z: character:= ‘Z’;
Обратите внимание, что значение константы может быть задано простым выражением. Константы можно использовать повсюду, где встречаются соответствующие значения.
Другую очень важную группу определяемых пользователем типов образуют типы массивов (array types). Как и в других языках, в языке VHDL массив (array), по определению, – это упорядоченный набор элементов одного и того же типа, отдельные компоненты которого выбираются с помощью индекса массива (array index). Возможны несколько вариантов синтаксиса объявления массива в языке VHDL; они представлены в табл. 7. В первых двух вариантах start и end являются целыми числами, которыми задается возможный диапазон изменения индекса массива и, следовательно, полное число элементов массива. В последних трех вариантах диапазоном изменения индекса массива являются все значения указанного типа (range-type) или подмножество этих значений.
Таблица 7. Синтаксис объявления массивов в языке VHDL.
type type_name is array (start to end) of element_type; |
type type_name is array (start downto end) of element_type; |
type type_name is array (range_type) of element_type; |
type type_name is array (range_type range start to end) of element_type; |
type type_name is array (range_type range start downto end) of element_type; |
В табл. 8 приведены примеры объявления массивов. Первые два примера совсем обычны и демонстрируют задание диапазона изменения индекса в сторону возрастания и в сторону убывания. Следующий пример показывает, как можно воспользоваться константой WORD_LEN при объявлении массива. Отсюда видно также, что границу диапазона можно задать простым выражением. Из третьего примера следует, что сам элемент массива может быть массивом; таким образом создается двумерный массив. Последний пример показывает, что множество возможных значений элементов массива можно задать, указав перечислимый тип (или подтип); в этом примере массив состоит из четырех элементов согласно данному нами чуть раньше определению типа traffic _ light _ state .
Таблица 8. Примеры объявления массивов в языке VHDL.
type monthly_count is array (1 to 12) of integer; type byte is array (7 downto 0) of STD_L0GIC; constant WORD _LEN: integer:= 32; type word is array (WORD_LEN-1 downto 0) of STD_L0GIC; constant NUM_REGS: integer:= 8; type reg _ file is array (1 to NUM_REGS) of word; type state_count is array (traffic _ light _ state) of integer; |
Элементы массива считаются упорядоченными слева направо в том же направлении, в каком индекс пробегает свои значения. Таким образом, индексы самых левых элементов массивов типов monthly_count, byte, word, reg_file и statecount в табл. 8 равны 1, 7, 31, 1 и reset соответственно.
Обращение к отдельным элементам массивов в операторах программы на языке VHDL осуществляется путем указания имени массива и индекса элемента в круглых скобках. Если, например, М, В, W, R и S – сигналы или переменные тех пяти типов массивов, которые приведены в табл. 9, то любая из записей М(11), В(5), W(WORD_LEN-5), R(0,0), R(0) и S (reset) является правильным указанием элемента.
Массивы-литералы (array literals) можно задать, перечисляя в скобках значения элементов. Например, переменной В типа byte можно задать значение, состоящее из одних единиц, оператором
В: = (‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘1’ ‘1’);
В языке VHDL возможно и в более сжатой форме задавать значения, указывая индекс. Например, следующая запись обеспечивает присвоение единичных значений всем элементам переменной W типа word, за исключением младших разрядов каждого байта, которым присваиваются нулевые значения:
W:= (0 => ‘0’, 8 => ‘0’, 16 => ‘0’, 24 => ’0’, others=>’1’);
Рассмотренные правила справедливы при любом типе элементов (element-type),но литерал типа STD_LOGIC легче всего записать в виде «строки». Строкой (string) в языке VHDL является последовательность символов ISO, заключенная в двойные кавычки. Строка – это, конечно, массив символов; поэтому массиву типа STD_LOGIC заданной длины можно присвоить значение, выраженное строкой той же длины, если только символы в строке принадлежат набору из девяти символов, которыми, по определению, исчерпываются возможные значения элементов типа STDLOGIC: ‘0’, ‘1’, ‘U’ и т.д. Таким образом, предыдущие два примера можно переписать в виде:
В: = “11111111”;
W: = “11111110111111101111111011111110”;
Можно также указывать подмножество непосредственно следующих один за другим элементов массива или, как говорят, вырезку из массива (array slice),задавая начальный и конечный индексы подмножества.
Наконец, массивы или элементы массивов можно объединять с помощью оператора конкатенации & (concatenation operator),который соединяет массивы и элементы в том порядке, в каком они записаны слева направо. Например, запись ‘0’ & ‘1’ & “1Z” эквивалентна строке “011Z”, а выражение В (6 downto 0) & В (7) представляет собой циклический сдвиг 8-разрядного массива В на 1 разряд влево.
Самым важным типом массивов в типичной программе на языке VHDL является определяемый пользователем в соответствии со стандартом IEEE 1164 логический тип STD_LOGIC_VECTOR, которым задается упорядоченный набор элементов типа STD_LOGIC.
Определение этого типа имеет вид:
type std_logic_vector is array (natural range <>) of, std_logic;
Это пример типа массивабез ограничений (unconstrained array type):диапазон возможных значений индекса массива не задан, за исключением того, что он должен быть подмножеством определенного типа, в данном случае – типа natural. Эта особенность языка VHDL позволяет записывать архитектуры, функции и другие элементы программ в более общем виде, до некоторой степени независимо от размеров массивов и диапазонов возможных значений индексов. Действительный диапазон значений индекса определяется в тот момент, когда сигналу или переменной ставится в соответствие этот тип.
АТРИБУТЫ
Атрибуты – это значения, связанные с поименованным элементом (константой, переменной, сигналом). Для построения моделей и моделирования особенно важную роль играют атрибуты. Есть несколько групп атрибутов, например, для типов, массивов, сигналов и пр.рассмотрим группу атрибутов, определенную для сигналов:
1) S’last_ value (прошлое значение S) – предыдущее значение, которое сигнал S имел непосредственно перед последним изменением S. Относится к тому же самому типу, что и S. Может исползоваться для проверки, не изменился ли сигнал (if S/=S’last_value).
2) S’stable(T) – тип Boolean. Атрибут имеет истинное значение, если сигнал S стабилен в течение последних T единиц времени. Если T=0, атрибут записывается как S’stable.
3) S’delayed(T) есть значение, которое сигнал S имел на T единиц ранее. Относится к тому же самому типу, что и S.
4) S’event, тип Boolean, принимает истинное значение, если только что произошло изменение сигнала S.
Эти атрибуты полезны для обнаружения изменений сигналов и детального времени моделирования.
ПРОЦЕДУРЫИ ФУНКЦИИ
В языке VHDL описание функции осуществляется как в обычных языках программирования. Указывается имя функции и, если необходимо, входные параметры. Функция имеет оператор возврата с определенным типом возвращаемого аргумента.
Функция может быть описана, например, следующим образом:
function Is_zero(n: Integer) return Boolean is
-- описание типов, переменных, констант, подпрограмм
Begin
-- последовательные операторы
if n=0 then return True;
else return False;
end if;
end;
Возвращаемое значение может быть определено в виде выражения либо вычислено через соответствующую последовательность операторов.
Язык VHDL предусматривает также описание процедур. Процедура может иметь как внутренние, так и внешние параметры. В остальном описание процедуры аналогично описанию функции. Ниже показан пример описания процедуры:
procedure Count(Incr: Boolean; big: out Bit; num: inout Integer) is
-- описание типов, переменных, констант, подпрограмм
Begin
if Incr then
num:= num+1;
end if;
if num > 101 then
big:= ‘1’;
Else
big:= ‘0’;
end if;
End
В списке параметров указываются и входные и выходные параметры. За списком параметров следует раздел описания.
БИБЛИОТЕКИ И ПАКЕТЫ
VHDL-библиотека (library)– это место, где компилятор VHDL хранит информацию об отдельном варианте проекта, включая промежуточные файлы, используемые при анализе, моделировании и синтезе в рамках данной разработки. Место библиотеки в файловой системе компьютера зависит от реализации. Для очередного VHDL-проекта компилятор автоматически создает библиотеку под именем «work» и использует ее.
VHDL-пакет (package) – это файл, содержащий определения элементов, которые могут быть использованы другими программами. В пакет можно включить элементы такого рода, как сигнал, тип, константа, функция, процедура и объявления компонентов.
Помещенные в пакет сигналы являются «глобальными» и доступны любому VHDL-объекту, использующему этот пакет. Типы и константы, упомянутые в пакете, известны в любом файле, использующем этот пакет.
Проект может «использовать» тот или иной пакет, если в начало файла, относящегося к данному проекту, помещено предложение use (use clause). Например, чтобы воспользоваться всеми определениями пакета, содержащего стандарт IEEE 1164, нам следует написать:
use ieee.std_logic_1164.all;
Здесь “ieee” – это имя библиотеки, ранее введенное предложением library. В этой библиотеке файл с именем “std_logic_ll64” содержит желаемые определения. Приставка “all” велит компилятору использовать все определения этого файла. Вместо “all” можно написать имя какого-то одного элемента, когда необходимо использовать только его определение, например:
use ieee.std_logic_1164.std_ulogic;
ОПЕРАТОРЫУПРАВЛЕНИЯ
Среди операторов управления, используемых в языке VHDL, можно выделить стандартные и специальные, характерные только для данного языка как, например, wait. Рассмотрим основные и наиболее часто используемые операторы управления.
Оператор if (если)
if increment and not decrement then
count:= count +1;
elsif not increment and decrement then
count:= count -1;
elsif increment and decrement then
count: =0;
Else
count:= count;
end if;
Условия в операторе должны быть типа Boolean. Возможно наличие любого числа фраз elsif. Фразы elsif и else являются необязательными.
Оператор case (выбор) проиллюстрируем несколькими примерами.
Пример 1.
case X(0 to 1) is
when “00” => Z <= 0;
when “01” => Z <= 1;
when “10” => Z <= not 2;
when “11” => Z <= Z;
end case;
Пример 2.
case N is
when 0 => Z <= 0;
when 1 => Z <= 1;
when 2 => Z <= not 2;
when 3 => Z <= 2;
end case;
Пример 3
case day is
when Saturday to Sunday =>
work:= False;
work_out:= False;
when Monday | Wednesday | Friday =>
work:= True;
work_out:= True;
when others =>
work:= True;
work_out:= False;
end case;
Оператор выбора case осуществляет декодирование на основе значения управляющего выражения, а затем выполняет выбранный оператор (или группу операторов). В примере 1 управляющее выражение – битовый вектор, примере 2 – целое, в примере 3 – символьное. В общем случае в качестве управляющего выражения может использоваться любой дискретный тип, как в показанных примерах, либо одномерный массив символов.
В языке VHDL существует оператор назначения сигнала с выбором, позволяющий сделать более сжатую запись:
with X1&X2&X3 select
f <= ‘0’ after 20 ns when “000”,
‘1’ after 20 ns when “001”,
‘0’ after 20 ns when “010”,
‘1’ after 20 ns when “011”,
‘0’ after 20 ns when “100”,
‘1’ after 20 ns when “101”,
‘1’ after 20 ns when “110”,
‘1’ after 20 ns when “111”,
Операторы цикла реализуют те же функции, что и во всех языках программирования. Рассмотрим примеры с использованием операторов управления for, wile, loop, next, exit:
Пример 1
for i in 0 to 3 loop
A(i):= 2**I
end loop;
Пример 2
Sum:= 0;
i:= 1;
Sum_Int: while i<=n loop
sum:= Sum + 1;
i:= i + 1;
end loop Sum_int;
Пример 3
Sum:= 0;
i:= 0;
Sum_Int: while i<=N loop
i:= i + 1;
next Sum_Int when i=3;
Sum:= Sum +1;
end loop Sum_Int;
Пример 4
Sum:= 1;
loop
VAL(X);
exit when X<0;
Sum:= Sum +X;
end loop;
Пример 1 иллюстрирует базовый цикл for, а пример 2 – цикл while и использование метки цикла. Цикл примера 2 вычисляет сумму первых n целых. В примере 3 производится вычисление той же самой суммы, но без числа 3, поскольку итерация пропускается при помощи оператора next. Пример 4 показывает