Function"and"(xl,x2:bit) returnboolean is begi n
return (xland x2) ='1'; end;
Если эта функция объявлена, то теперь транслятор не выдаст сообщения об ошибке при выполнении оператора if, вызывающего эту функцию:
Variablea,b,c: bit; if (a and b and c) then
* * ■
end if; так как выражение в скобках будет иметь правильный тип boolean.
Реализация процедур и функций в аппаратуре
Компиляторы-синтезаторы, как правило, транслируют процедуру или функцию в комбинационную схему. Процедуры с операторами wait не допускаются, например, такие, которые симулируют схему с памятью.
Атрибуты
Атрибутом называют особенное, долговременное свойство предмета. В языке VHDL сигналы, переменные и другие объекты, кроме своего значения, также имеют множество атрибутов. У каждого типа объектов есть несколько предопределенных атрибутов. Пользователь также может ввести ряд специальных атрибутов. Атрибуты бывают различного типа: атрибут - тип, значение, сигнал, функция, диапазон.
Атрибут объекта записывается как:
\имя объектах1 \имя атрибутах .
Ниже рассматриваются основные предопределенные атрибуты.
Атрибуты для скалярного типа
Для скалярного типа т предопределены следующие атрибуты:
т' left - самое левое значение множества элементов скалярного типа т. т' right - самое правое значение множества элементов типа т. T'high - наибольшее значение в множестве элементов типа т. Т' low - наименьшее значение в множества элементов скалярного типа т. T'image(x) - функция строкового представление выражения х типа т. T'value(x) - функция значения типа т от строкового представления х. T'pos(x) - функция номера позиции элемента х типа т. T'val (х) - функция значения элемента типа т стоящего в позиции X.
Примеры атрибутов:
type st is (one,two,three);
st'right = three, st'pos(three) = 2, st'val(l) = two. positive'low * 1, positive'high =2147483647. integer'valueC'LOOO") =1000, integer'image(330) ="330".
Атрибуты для регулярного типа
Для регулярного типа а предопределены следующие атрибуты:
A'left[(N)] - левое значение диапазона индексов по N-й размерности.
A' right[(n)] - правое значение диапазона индексов по N-й размерности.
Afhigh[(N)] - наибольшее значение диапазона индексов по N-й размерности.
А' 1 cw [ (n) ] - наименьшее значение диапазона индексов по N-й размерности.
A' range[(N)] - диапазон индексов по N-й размерности.
A' reverse_range[(N)] - обратный диапазон индексов по N-й размерности.
A' length[(N)] - протяженность диапазона индексов по N-й размерности.
A'ascending[(N)] - функция, равная true, если диапазон индексов He-N-й размерности - возрастающий.
Примеры применения атрибутов:
type s2 is array(2 downto 1, 0 to 3) of integer;
S2'left(l) - 2, s2'right(2) - 3,
S2'high(l) * 2, s2'low(2) = 0,
s2'range(2) = 0 to 3, s2'reverse_range(l)- 1 to2,
S2'length(2) = 4.
Атрибуты сигналов
Атрибуты сигналов s:
S' stable [CO] - сигнал, равный true, если за промежуток времени т не было событий у сигнала S.
S'transaction - сигнал типа bit, меняет значение на противоположное в циклах моделирования, в которых было присваивание нового значение сигналу S.
s'event - сигнал, равный true, если произошло событие в сигнале S в данном цикле моделирования.
sfactive - сигнал, равный true, если произошло присваивание нового значение сигналу s в данном цикле моделирования.
S'last_value - сигнал такого же типа, что и S, содержащий значение s до последнего события в нем,
Примером применения атрибутов сигналов является следующий процесс, моделирующий синхронные триггеры.
Process(CLK) begin
if CLK='l' andCLK'event then--D- триггер
ql<=al;
endif;
if notCLK'stable then-- D- триггер
q2<=a2; endif; if CLK'last_value /= CLK then--D- триггер
q3<=a3;
endif;
if CLK'active -- D- триггер
q4<=a4;
endif;
q5<=CLK'transaction; — т- триггер
end process;
Атрибуты пользователя
Эти атрибуты предназначены для присваивания объектам языка дополнительных свойств, не предусмотренных встроенными типами и атрибутами. При проектировании дискретных устройств такими свойствами могут быть: способ кодирования состояний автомата, указания компилятору-синтезатору по управлению оптимизацией, размещению блоков, их исполнению, назначение портов номерам выводов, начальное состояние схем памяти и т.п. Т.е. эти свойства не связаны напрямую с алгоритмом, реализуемым в программе. Задание атрибута состоит из его объявления и спецификации.
Объявление атрибута имеет синтаксис, похожий на объявление переменной:
\объявление атрибутах::=attribute\идентификатор\: \ тип\
где \тип\ - любой ранее определенный тип, например, string, positive, time.
Спецификация атрибута имеет синтаксис:
Хспецификация атрибутах::=attribute\идентификатор\ of \имя объектах[{Димя объекта\}] | othersI all: \класс объекта\ is\выражение\ \имя объекта\::= ((\идентификатор\ |\символьный литерал\
| \символ оператора\) [\сигнатура\]) \класс объекта\::- entity|architecture|configuration| package I procedure|function[type 1 subtype[ constant|si gnal jvari able | f i 1 e |component| label (literal |units I group
Здесь \идентификатор\ - имя атрибута, объявленного ранее, \имя объекта\ - имя объекта, которому присоединен атрибут,\сигнатура\ -
список типов параметров, если объектом является процедура, функция или перечисляемый литерал, предназначенный для идентификации перегружаемых процедур, функций и литералов. Спецификация атрибута обычно вставляется сразу же после объявления этого атрибута.
Атрибуты пользователя обычно не влияют на поведение модели и такие атрибуты игнорируются симулятором. Но они имеют большое значение для компилятора-синтезатора и для средств реализации схемы в кристалле. Поэтому, как правило, фирмы-поставщики компиляторов и производители микросхем предлагают для использования свои наборы атрибутов пользователя. В следующем примере атрибут указывает способ кодирования состояний автомата:
type\состояние\ is ( \сброс\ Дначало\,\работа\,\конеи.\); attributeenum_encoding : string;
attributeenunuencoding of \состояние\: type is "000 001 010100" ;
Атрибут foreign
Специальный атрибут foreign присоединяется к архитектуре, процедуре или функции. Он указывает симулятору, что соответствующий объект должен моделироваться особенным способом. Это может быть специальная программа на ассемблере или другом языке, или аппаратный ускоритель.
Структура программы на VHDL
Дискретная система может быть представлена в VHDL как объект проекта. Объект - это основная составная часть проекта. Объект может быть использован в другом проекте, который, в свою очередь, описан как объект или может являться объектом более высокого уровня в данном проекте. Симулятор может моделировать ВУ, только если оно оформлено в виде объекта проекта.
Объект проекта описывается набором составных частей проекта, таких как: объявление объекта, тело архитектуры объекта (или просто архитектура), объявление пакета, тело пакета и объявление конфигурации. Каждая из составных частей объекта может быть скомпилирована отдельно. Составные части проекта сохраняются в одном или нескольких текстовых файлах с расширением .VHD. В одном файле может сохраняться несколько объектов проекта.
Объект проекта обычно описывается согласно синтаксису:
\объект проекта\::= [\описание 1ibrary\]
[\описание use\]
\объявление объекта\
\тело архитектуры\
[\объявление конфигурации\] [\описание library\]::= library \идентификатор\ {, \идентификатор\};
где идентификаторы - названия библиотек, которые используются в объекте проекта. Они указывают транслятору местоположение этих библиотек. Описание useуказывает, какие пакеты и какие элементы этих пакетов могут быть использованы в объекте. Части объекта проекта могут компилироваться раздельно. Но перед связыванием (elaboration) все части должны быть уже скомпилированы.
Объявление объекта
Объявление объекта указывает, как объект проекта выглядит снаружи и каким образом его можно включить в другом объекте проекта в качестве компонента, т.е. он описывает внешний интерфейс объекта. Синтаксис объявления объекта:
\объявление объекта\::= entity \идентификатор\ is
[депеп"с(\объявление настроечной константы\
{; \объявление настроечной константы\});] [port (\объявление порта\ {Добъявление порта\});]
{\объявление в объекте\} [begin
{\оператор assert\ | \пассивный вызов процедуры\
| \пассивный процесс\ }] end [entity][\идентификатор\];
Здесь \идентификатор\ - имя объекта. Синтаксис объявления настроечной константы и объявления порта рассмотрены в разделе описания объектов и типов языка. Порты представляют собой интерфейсные сигналы объекта проекта. Настроечные константы genericкодируют определенные свойства объекта проекта, например, разрядность линий связи, параметры задержки, кодирование структуры моделируемого устройства.
Объявленными в объекте могут быть: объявление и тело процедуры или функции, объявление типа и подтипа, объявление глобальной переменной, файла, псевдонима, константы, объявление и спецификация атрибута, объявление группы, описание use.
В исполнительной части, которая открывается словом begin, вставляются параллельные операторы, которые не выполняют присваиваний сигналам, т.е. не влияют на поведение объекта. Поэтому
такие вызовы процедуры и процессы называются пассивными. Наиболее частое применение этих операторов - проверка соответствия входных сигналов, поступающих через порты, заданным требованиям или соответствие включения объекта в окружение, задаваемое ограничениями на настроечные константы generic. Например, проверяется время предустановки сигнала относительно фронта синхро-серии, соответствие его уровней, разрядность входных данных и т.п. При несоответствии сигналов или настроечных констант, оператор assert выдает сообщение об ошибке.
Рассмотрим пример объявления объекта RS-триггера:
entity RS_FF is
generic(delay:time); port(R, S: in bit;
Q: out bit:='0'; nQ: out bit:='l'); begin
assert (R andS) /='1' report"in rs_ff r=s=1" severity error; endentity RS_ff;
В нем настроечная константа delay задает параметр задержки, например, от входа до выхода, который будет подставлен при компиляции на этапе связывания компонентов. Порты R,S имеют режим ввода in, а порты Q,nQ - режим вывода out. При единичных сигналах на обоих входах, т.е. когда RS-тригтер функционирует неправильно, оператор assert выдает сообщение об ошибке.
Архитектура объекта
Архитектура объекта представляет собой отдельную часть, в которой описано, каким образом реализован объект. Ее синтаксис:
\тело архитектуры\::= architecture \идентификатор\ of \имя объекта\ is
{\объявление в 6локе\} begin
{ \параллельный оператор\} end[architecture][\идентификатор\];
Идентификатором обозначается имя конкретного тела архитектуры. Одному объекту проекта может соответствовать несколько архитектур, в каждой из которых описан один из вариантов реализации объекта. Поэтому имя объекта указывает, который из объектов описан в этом теле архитектуры. Объявление в теле архитектуры такое же, как в операторе блока, который описан ниже. Им может быть: объявление и тело процедуры или функции, объявление типа и подтипа, объявление файла, псевдонима, константы, глобальной переменной, объявление и спецификация атрибута, объявление группы,
описание use, а также объявление компонента. Объявленные в теле архитектуры типы, сигналы, подпрограммы видимы только в пределах этой архитектуры.
Исполнительную часть архитектуры составляют параллельные операторы, такие как процесс, блок, параллельное присваивание сигналу и др. Так как все операторы в исполнительной части тела архитектуры - параллельные, их взаимный порядок - безразличен. Хорошим стилем считается, когда параллельные операторы ставятся в последовательности, соответствующей нумерации вершин граф-схемы алгоритма, реализуемого в архитектуре.
Примером тела архитектуры служит архитектура для вышеприведенного объявления объекта RS-триггера:
architecture behav of rs_ff is begin
processes,R)
variable qi: bit; begin
if S^'l' then
qi:='l' ; elsif R='l' then
qi:='0'; end if;
Q<=qi after delay; nQ<=not qi after delay; end process; end architecture behav;
Данную программу, включающую объявление объекта и тело архитектуры можно транслировать и моделировать. Если из объявления объекта удалить исполнительную часть и описание generic, то программа будет написана синтезируемым стилем и ее можно также компилировать в логическую схему.
Объявление компонента
Объявление компонента в теле архитектуры необходимо, если в архитектуре используется оператор вставки этого компонента, который будет рассмотрен ниже. Синтаксис объявления компонента следующий :
\объявление компонентах::= component \идентификатор\ [is] [депеп'с(\объявление настроечной константы\
{; \объявление настроечной константы\});] [port (\объявление порта\ {Добъявление порта\});] end component [\идентификатор\];
Объявление пакета
В пакет обычно объединяются декларации различных объектов и типов языка, связанных общим признаком. Затем декларации из пакета можно повторно использовать в различных частях проектов, ссылаясь на этот пакет. Многие пакеты стандартизированы и их использование упрощает разработку новых проектов, а также служит для стандартизации включения и тестирования этих проектов. Несколько пакетов, подчиненных одной цели, собирают в библиотеку library. Библиотека, в которой собраны программы и пакеты пользователя, по умолчанию имеет название WORK.
Синтаксис объявления пакета:
\объявление пакета\::= package\идентификатор\ is
{объявление в пакете} end[package][\идентификатор\];
В объявлении пакета могут быть объявленными объявление процедуры или функции, объявление типа и подтипа, объявление файла, псевдонима, константы, глобальной переменной, объявление и спецификация атрибута, объявление компонента, объявление группы, описание use.
Обычно в объявлении пакета объявляются типы, используемые во всех объектах проекта или ряда проектов. Если объявлены процедуры и функции, то их спецификации описываются в теле пакета. Т.е. объявление пакета представляет собой интерфейс пакета, также как объявление объекта - это интерфейс объекта проекта.
Константам может быть не присвоено значение. Такие константы называются отложенными (deferred). Например, это могут быть заранее неопределенная кодировка состояний или разрядность шин. Тогда эти константы должны получить значение в теле пакета.
При обращении к объектам с одинаковым именем, принадлежащим разным библиотекам, необходимо использовать селективное имя объекта, указывающее, какой библиотеке оно принадлежит, например:
signal my_bit: IEEE.std_logic_1164.x0lZ;
Тело пакета
Тело пакета необходимо приводить в паре с объявлением пакета, если в последнем объявлены подпрограммы или отложенные константы. Обычно объявление и тело пакета оформляют в одном файле. Тело пакета имеет синтаксис:
\тело пакета\::= package body\идентификатор\ is
{объявление в теле пакета} end [package body][\идентификатор\];
В объявлениях тела пакета должны быть приведены полные спецификации процедур и функций, присваивания константам, которые задекларированы в объявлении этого пакета.
Ниже приведен пример пакета функций и констант, который удобно применять для упрощения программирования логики с булевскими и битовыми типами.
packageshort_boolean is
constantbO:boolean:=false; —псевдоним для false constantbl:boolean:=true; --псевдоним для true functionb(x:bit) returnboolean;— преобразование из bit в boolean function"not"(x:bit) returnboo7ean; —функции вместо not, and, or function"and"(xl,x2:bit) returnboolean ; functionMor"(xl,x2:bit) returnboolean ; end package; package bodyshort_boolean is