Основы программирования на VHDL

Модели вычислителей VHDL

Начинающий программист VHDL легко осваивает структурный пчшь программирования, которым формально описывается структу­ра ВУ. Без трудностей он программирует стилем потоков данных, пыражая операторами параллельного присваивания прохождение данных через некоторую комбинационную схему. Но при переходе к поведенческому стилю, основанному на операторах процессов, не­редко возникают сложности с пониманием выполнения этих опера-1оров, программированием желаемого поведения системы и отлад­кой составленной программы.

Он знает, что VHDL — это язык программирования. Но у него воз­никает вопрос, программирования чего? При программировании на Он программист представляет, что он с помощью языка описывает ипдуманный алгоритм для его реализации на модели ЭВМ, содер-жмщей АЛУ, регистровую, оперативную, дисковую память и т.д., что существуют определенные типы данных и механизмы доступа к ним. Другими словами, он программирует некоторую программист­скую модель вычислителя для реализации данного языка.

Алгоритм, описанный на VHDL, как и любой другой параллель­ный алгоритм, представляет собой определенное множество вычис­лительных процессов, организованных на строго заданной модели иычислителя (рис. 17).


Составление программы VHDL означает программирование этой модели. Поэтому далее рассмотрим программистскую модель вычис­лителя для реализации языка VHDL. Для понимания реализации VHDL в симуляторах будет также рассмотрена модель вычислителя с точки зрения разработчика симуляторов. Наконец, будет приведе­на аппаратная модель реализации VHDL, т.е. модель, реализуемая в СБИС или ПЛИС.

Модель вычислителя для программирования на VHDL

Наиболее полно программистская модель вычислителя VHDL описана в руководстве к стандарту языка [1]. В нем параллельно с описанием синтаксиса и семантики всех языковых конструкций приводятся объяснения их реализации в модели некоторого вирту­ального симулятора. Но, изучая это руководство, с первого раза трудно постичь основы этой модели. Ниже описывается упрощенная модель вычислителя VHDL, которая не противоречит модели, опи­сываемой в [1].

В отличие от большинства современных языков программирова­ния, язык VHDL основан на параллельной многопроцессорной моде­ли. Нижний уровень модели образует архитектура виртуального процессорного элемента (ВПЭ), а верхний уровень - множество ВПЭ, объединенных некоторой запрограммированной системой межпро­цессорных связей.

Структура ВПЭ состоит из арифметико-логического устройства (АЛУ), ОЗУ данных (ОЗУД), ОЗУ программы (ОЗУП) и определенно­го количества источников (ИС) и приемников (ПС) сигналов (рис. 18).


ЛЛУ выполняет такой же набор операций, какой требуется для Iтипизации большинства языков программирования, как, например, сложение, умножение, деление с фиксированной и плавающей запя-и>И. логические операции и т.д. Кроме того, АЛУ выполняет многие друие операции, специфические для VHDL, такие как операции над днимими с заданной разрядностью, функции с многозначным логи­ческим представлением разрядов. При выполнении операций по­стоянно проверяется корректность результата, и фиксируются ошиб­ки, как-то: выход за заданный диапазон представления числа, деле­ние на ноль и т.п.

П ОЗУ данных хранятся переменные, участвующие в вычислени­ях. Переменные имеют статические адреса, но можно реализовать и динамический доступ к переменным. Источники и приемники сиг-мнмов служат, в основном, для связи ВПЭ с внешним миром. При поступлении сигнала приемник фиксирует это событие. В приемни­ке хранится как текущее, так и предыдущее состояние сигнала. При и i.i иол нении операции с идентификатором сигнала, как с операндом, выполняется чтение приемника или источника сигнала. Источник генерирует сигнал не сразу после выполнения оператора присва-шищия, а в момент остановки ВПЭ.

li ОЗУ программы хранится программа в виде цепочки операто­ром. Операторы, включая условные операторы, выполняются после-допптельно друг за другом, как в обычных языках программирова­нии. Но на операторах wait выполнение программы останавливает-с и. Такая программа записывается в VHDL-программе как один пираллельный оператор, называемый процессом, а ВПЭ выполняет его как вычислительный процесс.

Операнды оператора wait - это набор входных сигналов, назы-иасмый списком чувствительности, заданный промежуток времени пидоржки или булевское выражение. Оператор wait ожидает появле­ния внешнего события: прихода сигналов или истечения срока за­данной задержки. После появления внешнего события программа продолжает выполнение со следующего оператора. Только при вы­полнении оператора wait в источниках сигналов генерируются сиг-пимы, которым в программе было присвоено новое значение. После исполнения последнего оператора программа переходит к своему первому оператору.

Отдельным входом-выходом ВПЭ является шина передачи гло-шшьных (shared) переменных. Глобальная переменная может прини-


маться (участвовать как операнд) или передаваться из ПЭ (как результат операции присваивания) в произвольные моменты времени.

К ВПЭ можно подключать дисковую память. При этом операторы открытия, чтения, записи, закрытия файлов используются анало­гично, как в других языках.

Верхний уровень программистской модели составляет множество ВПЭ, объединенных линиями связи, по которым передаются сигна­лы (рис. 19). Консоль для связи с программистом (клавиатура и дисплей), дисковая память и ОЗУ глобальных переменных исполь­зуются всеми ВПЭ как обшие.

Количество ВПЭ в системе равно числу процессов в программе VHDL после ее компиляции. В структуре параллельного вычислите­ля столько линий межпроцессорной связи, сколько необходимо для исполнения VHDL-программы.

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


При запуске скомпилированной программы сперва все перемен­ные принимают заданное начальное значение. Затем во всех ВПЭ начинают выполняться вычислительные процессы со своих первых операторов. При достижении операторов wait ВПЭ генерируют новые значения сигналов и останавливаются. Эти сигналы, пройдя через соответствующие им линии связи до других ВПЭ, запускают в них продолжение вычислительных процессов. Такое функционирование вычислительной системы может продолжаться неопределенно долго, пока оно не будет остановлено с консоли или не выполнится опера­тор assert, требующий останова. В большинстве программ VHDL один из процессов является ведущим и задает поток возбуждающих состояний сигнала для других процессов. Например, этот процесс моделирует источник исходных данных или генератор синхросиг­нала. Тогда ВПЭ — генератор возбуждающего сигнала — запускает смежные с ним ВПЭ. Эти ВПЭ запускают ВПЭ следующие за ними и т.д. Таким образом, по вычислительной системе проходят волны за­пусков. Поэтому модель вычислителя для реализации VHDL можно трактовать как волновой процессор со специализированной тополо­гией.

Если в процессе не использованы операторы wait с установленной задержкой, то цикл запуска-остановки этого процесса выполняется почти мгновенно, а точнее — с дельта-задержкой. Здесь дельта-задержка - исчезающе малый промежуток времени, одинаковый для всех таких процессов.

Основное назначение консоли - это запуск программы на испол­нение и вывод сообщений на экран, которые генерируются специ­альными операторами assert и report.

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


При программировании на VHDL необходимо учитывать следующее.

Все процессы исполняются параллельно.

а Одновременно исполняемые процессы образуют фронт волны запусков процессов. Этот фронт может передвигаться с вре­менным шагом, равным дельта-задержке.

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

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

Область действия всех переменных (кроме глобальных) огра­
ничена рамками операторов процесса. Вне процессов перемен­
ные невидимы.

а Порядок доступа к глобальным переменным непредсказуем. Следует с осторожностью программировать с этими перемен­ными.

Вычислительная модель си муля тор a VHDL

Модель вычислителя с точки зрения программиста не может быть реализована в виде реальной многопроцессорной вычислительной системы из-за чрезмерно высоких аппаратурных затрат. С другой стороны, язык VHDL разрабатывался с целью реализации в симуля-торах дискретных систем. Такой симулятор, как правило, исполня­ется на однопроцессорной ЭВМ. Рассмотрим архитектуру вычисли­теля VHDL с точки зрения разработчика симулятора.

На рис. 20 условно показана архитектура симулятора VHDL. В данной модели каждый ВПЭ реализован как отдельный вычисли­тельный процесс (ВП). Все вычислительные процессы разделяют во времени один и тот же аппаратный ресурс - центральный процес­сорный элемент (ЦПЭ) микропроцессора ПЭВМ.

Все ВП разделены на три подмножества - очередь спящих про­цессов, очередь готовых процессов и исполняемый процесс. Боль­шинство ВП относится к числу спящих, т.е. к ВП, для исполнения которых нет готовых входных данных. Например, такой ВП ожида­ет какой-либо входной сигнал из списка чувствительности его one-


ратора wait. При поступлении сигнала этот ВП переносится в оче­редь готовых к исполнению ВП. Один из готовых ВП, выбранный произвольно, пересылается в кэш-ОЗУ микропроцессора для испол­нения. Исполняемый ВП выполняет свои операторы в соответствии с семантикой функционирования ВПЭ на ресурсах ЦПЭ микро­процессора и с использованием соответствующих библиотек проце­дур. При достижении оператора wait ВП останавливается. Вырабо­танные им сигналы запоминаются и пересылаются другим ВП, ко­торые являются приемниками этих сигналов. Затем остановленный ВП пересылается в очередь спящих процессов.

Один особенный исполняемый ВП служит диспетчером для ос­тальных процессов. Он называется ядром симулятора и формирует очереди спящих ВП и готовых к исполнению ВП, а также выбирает ВП для исполнения. Он также рассылает сигналы от исполняемого ВП к другим ВП. Кроме того, он ведет счетчик времени моделирова­ния Тс, выполняет связь с консолью, обслуживает обращение к дис­ковой памяти и памяти глобальных переменных.

Для моделирования программист создает проект — каталог с фай­лами VHDL, имеющий название проекта. После компиляции в про­екте создается библиотека проекта, которая имеет название проекта и содержит все скомпилированные объекты проекта. После запуска программы на моделирование выполняется связывание объектов


проекта и назначение начальных значений переменным и сигналам (elaboration).

Затем запускается собственно моделирование. При этом выбран­ные программистом сигналы записываются в отдельной области па­мяти в своем развитии и могут быть отображены на дисплее в виде таблиц или графиков.

Для того чтобы сохранить семантику исполнения множества па­раллельных процессов, такую же, как у системы из ВПЭ, симулятор в каждом цикле моделирования выполняет следующие шаги:

1. Каждый остановленный ВП, для которого произошло новое событие, т.е. пришло новое значение сигнала, который ожи­дается соответствующим оператором wait,запускается на ис­полнение; в ВП, остановленных для ожидания задержки, про­веряется окончание этой задержки и если задержка истекла, эти ВП также запускаются.

2. Каждый запущенный ВП исполняется до своей остановки на операторе wait,при этом вычисляются новые значения сигна­лов в операторах присваивания сигналам.

3. Вычисляется новое значение текущего времени Тв как бли­жайший момент времени, в который будет запущен какой-либо ВП, остановленный на операторе waitожидания оконча­ния задержки или момент времени следующей активации ис­точников сигнала.

4. Счетчик времени принимает новое значение Тс = Тв.

5. Каждому сигналу, для которого было вычислено новое значе­ние, присваивается это значение, т.е. источники сигналов ак­тивизируются; эти изменения сигналов проверяются, являют­ся ли они событиями для каких-либо ВП.

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

Моделирование имеет такую особенность, что серия, включающая от нуля до нескольких циклов (обычно не более 1000)с дельта-задержкой сменяется одним циклом с конкретной задержкой. До­пустим, что в модели находятся два процесса, обменивающихся од­ной глобальной переменной. Тогда порядок обмена этой переменной


не контролируется программистом, так как он не может определить, какой из этих процессов сработает первым в серии циклов с дельта-задержкой. Для того чтобы эти процессы были запущены не в про­извольном, а именно в последнем цикле с дельта-задержкой из се­рии циклов, причем после всех процессов, такие процессы обозна­чаются как отложенные (postponed).

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

Другой метод предполагает предсказание тех процессов, которые будут исполняться в следующем цикле моделирования. Тогда моде­лирование ускоряется за счет того, что проверяется готовность к ис­полнению не всех процессов, а только предсказанных [4].

При составлении VHDL-программ желательно иметь в виду сле­дующее,

Даже небольшой процесс занимает в памяти несколько кило­байт. Максимальное количество процессов в скомпилирован­ной программе определяется объемом динамической памяти компьютера.

D Смена одного ВП другим ВП представляет собой смену кон­текста в работе ЦПЭ, которая может длиться несколько тысяч тактов ЦПЭ.

D Наибольшую долю времени занимает исполнение ВП ядра си­мулятора, которая возрастает нелинейно с увеличением числа ВП и числа сигналов в списках чувствительности их операто­ров wait. Поэтому, чем меньше процессов в скомпилированной программе и сигналов в списках чувствительности - тем быст­рее выполняется эта программа в симуляторе.

D Нельзя программировать процесс без оператора wait (или без списка чувствительности), т.к. после того, как этот процесс станет активным, он монопольно захватит ресурсы ЦПЭ.


Аппаратная модель реализации VHDL

Одним из важнейших назначений VHDL является описание про­ектов дискретных устройств при автоматизированном проектирова­нии микросхем. В основе технологии разработки микросхем (заказ­ных СБИС или ПЛИС) лежит автоматическая трансляция VHDL-описания дискретного устройства в схему на логическом уровне, ко­торая выполняется с помощью компилятора-синтезатора. Здесь под синтезом понимается получение аппаратной модели, которая испол­няет исходную VHDL-программу и преобразование её в схему на ло­гическом уровне. Причем подбор структуры модели и её логическая оптимизация по критериям минимума аппаратуры и максимума бы­стродействия с учетом элементного базиса целевой микросхемы вы­полняются автоматически.

Работа компилятора-синтезатора основана на взаимно-однозначном инъективном отображении программистской модели, отвечающей исходной VHDL-программе, в аппаратную модель. Это означает, что каждому из ВПЭ с его программой ставится в соответствие некото­рый специализированный процессорный элемент (СПЭ) (рис.21), причем ПС, ИС и ИС/ПС отвечают входам, выходам и входам-выходам ВПЭ. В свою очередь, граф линий связи между ВПЭ и граф соединений между СПЭ - изоморфны (рис. 22). Так как отображение инъективно, то одна VHDL-программа может дать большое мно­жество функционально эквивалентных схем, отличающихся по сте­пени оптимальности и элементному базису.

Различают два типа СПЭ: СПЭ с памятью и СПЭ без неё. СПЭ без памяти представляют собой комбинационную схему, состояние вы­ходов которой (источников сигнала) представляет собой некоторую логическую функцию от состояния её входов (приемников сигнала).


Если по семантике оператора процесса предполагается, что не все его переменные и сигналы выполняют присваивания при некотором запуске процесса, то это означает, что такие переменные и сигналы должны хранить свое предыдущее состояние при этом запуске. По­этому эти процессы отображаются в СПЭ с памятью.

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

В отличие от ВПЭ, задержка от входов СПЭ до его выходов равна величине, определяемой характеристиками элементного базиса, а не дельта-задержке или задержке, заданной оператором wait.

При отображении в аппаратуру вместо оператора каждого типа подставляется соответствующая ему логическая схема. Так, опера­ции and ставится в соответствие логическое "И", а операции "*" -комбинационный умножитель.

На аппаратную модель реализации VHDL налагается ряд ограни­чений, связанных с особенностями элементной базы СБИС или ПЛИС. Эти ограничения имеют прообразы в программистской моде­ли. В основном, они образуют множество объектов и операторов языка, которые не могут быть отображены в аппаратуру, так как не имеют в ней соответствующего эквивалента.

Например, на сегодняшний день не могут быть автоматически отображены в аппаратуру сигналы и переменные типа с плавающей запятой, динамического, файлового типа, операция деления, опера­торы wait с параметром задержки, операторы вывода на консоль


assert и report. Также в большинстве случаев глобальные перемен­ные не находят своего отображения.

Некоторые значения перечисляемого типа, например, стандарт­ного типа stcLlogic, такие как "и" - не инициализированное, "X" -неизвестное, "-" - безразличное, также не могут быть отображены в аппаратуру, а другие, как например, "н" - слабая единица или "L" -слабый ноль, отображаются, соответственно, в 1 и 0.

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

Говорят, что VHDL-программа, в которой отсутствуют несинтези-руемые объекты, операторы и конструкции, написана стилем для синтеза. При составлении программы стилем для синтеза желатель­но принять во внимание следующее.

а Существует несколько распространенных компиляторов-синтезаторов от разных фирм-поставщиков. Эти компиляторы различаются, в частности, списком несинтезируемых элемен­тов языка VHDL. Причем с появлением новых версий компи­ляторов этот список обычно сокращается.

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


Объекты и типы языка



Объекты и типы языка

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

В приведенных ниже описаниях синтаксиса текст в квадратных скобках означает необязательный элемент, фигурными скобками выделяется текст, который может повторяться 0,1,2,... раз, верти­кальными линиями разделяются альтернативы. Ключевые слова языка выделены полужирным шрифтом.

Комментарии

В языке VHDL комментарии начинаются двумя дефисами и про­должаются до конца строки. В книге комментарии выделены курси­вом, как и во многих редакторах языка VHDL.

Литералы

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

Числовой литералпредставляет собой целое или вещественное число.

Десятичный литерал- это числовой литерал в системе счисления по основанию (базису) 10, например, 120.

Вещественный литералотличает обязательное наличие точки, отделяющей целую часть от дробной, например, 120.0, 1.20е2.

Базисный литерал- это число в системе счисления с заданным базисом от 0 до 16. Его условный синтаксис:

\базисный литерал\::=\базис\#\число в базисе\#[\экспонента\], например, 10#112# = 1б#70# = 5#422# = 2#1110000# = 2#111#е4.


Символьный литералиспользуется как значение для операторов или как элемент перечисляемого типа, например, бит. Он записыва­ется как символ в одиночных кавычках, например, 'Г, 'F*, '@'.

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

Идентификатор может состоять из произвольной цепочки симво­лов, в том числе из букв кириллицы. Но эта цепочка должна быть заключена между обратными косыми. Это, так называемый, расши­ренный идентификатор. Например:

С, A_and_B, \наш сигнал\, \а+в\, \process\

являются корректными идентификаторами.

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

Строчный литерал.Строчным литералом является цепочка сим­волов, заключенная в двойные кавычки, например, "абвг". Литерал битовой строки может иметь различный вид в зависимости от базиса системы счисления. Например, литералы "01111010", в"01111010", х"7А" представляют собой одно и то же значение, причем в и х озна­чают двоичный и шестнадцатиричный базисы, соответственно.

В числовых литералах и битовых строках допускается вставлять символы подчеркивания для удобства чтения, которые удаляются при компиляции. Например, x'^BBA^CDCD", "1101_011Г\ 1_024.

Тип

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


Перечисляемый типопределяется как список (перечисление) всех возможных значений данного типа. Объявления этого типа выгля­дит как:

type\имя типа\ is (\перечисляемый литерал\

{Д перечисляемый литерал\});

Элементы списка литералов нумеруются при компиляции слева -направо, начиная с нуля. Например, объявление

type\цвет\ is (\красный\,\желтый\Дзеленый\);

означает, что состояния идентификатора \цвет\ будут кодироваться так, что \красный\ соответствует 0, \зеленый\ - 2. Целый тип.Объявление этого типа выглядит как:

type\имя типа\ is range\диапазон целых\;

где \диапазон целых\::=\выражение\ to \выражение\

|\выражение\ downto\выражение\ .

Выражение целого типа в диапазоне должно быть вычислимо в

период компиляции. Максимальный диапазон целых задается как:

-2147483647 to 2147483647.

Тип с плавающей запятойопределяется аналогично целому типу, но с диапазоном с плавающей запятой. Максимальный диапазон за­висит от компилятора.

Регулярный типпредставляет собой множество элементов одина­кового типа. Различают неограниченные и ограниченные регуляр­ные типы. Неограниченный тип объявляется как:

type\имя регулярного типа\ is

array(\имя типа диапазона\гапде<>) of \имя типа элементах;

где \имя типа диапазонах имя типа integer или какого-либо подти­па от integer.

Ограниченный регулярный тип объявляется как:

type\имя регулярного типа\ is

array (Хдиапазон целых\ of \имя типа элементах);

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


VHDL допускает многомерные массивы. В их определениях диа­пазоны индексов перечисляются через запятую, например:

type MATR is array(integer range<>, integer range<>) of integer

Комбинированный типопределяет множество значений, как и регулярный тип, но эти значения могут быть разнотипными. Объяв­ление комбинированного типа выглядит как:

type\имя комбинированного типа\ is record\имя элементах:\тип элементах; {\имя элементах:\тип элементах;} endгесо^[\имя комбинированного типа\];

Физический типпредставляется целым числом, единица которого имеет вес единицы измерения некоторой физической величины. Наиболее распространенным физическим типом в VHDL является время time, которое измеряется в фемтосекундах (fs), пикосекундах (ps), наносекундах (ns) и т.д. Объекты физического типа, как прави­ло, не синтезируются, но они могут участвовать как операнды в вы­числениях констант других типов. Задание физического типа отли­чает VHDL от других языков.

Другие типы объектов

Особенными типами являются тип ссылки (access)и тип файла (file).Тип ссылки позволяет манипулировать с массивами перемен­ных, объем которых заранее неизвестен и которые создаются и лик­видируются динамически во время вычислений, как и в других языках. Тип файла обеспечивает доступ к файлам, записанным в дисковой памяти. Переменные такого типа применяют для ввода-вывода исходных данных и результатов вычислений.

Подтип

Подтипом называется тип с дополнительными ограничениями. Объявление подтипа имеет следующий упрощенный синтаксис:

\подтип\::=subtype\имя подтипах is \базовый тип\ [\ограничение\];

Здесь \ограничение\ - диапазон или подмножество, в зависимости от базового типа. Подтип используют для отождествления группы объектов. Ограничение подтипа позволяет выявить ошибки на этапе моделирования. Объекты разных подтипов, у которых один родона-чальный тип, могут участвовать в вычислениях без конфликтов ти­пов.


Предопределенные типы данных

Основные типы данных VHDL определены в пакете standard, ко­торый подключается к проекту по умолчанию. Вот так в нем опре­делены некоторые стандартные типы объектов:

typeboolean is(false, true);

type bit is CO', '!');

typeinteger is range-2147483647 to 2147483647;

subtypenatural isinteger range0 to2147483647;

typebit„vector is array(natural range<>) ofbit;

Также определены типы character как набор букв, цифр и зна­ков, включая буквы альтернативного алфавита, подтип positive, включающий положительные значения типа integer, тип string как одномерный регулярный тип из элементов типа character.

Сигнал

Сигналом является объект, который переносит значение от одно­го процесса к другому и вместе с ним - синхронизирующее воздей­ствие. Сигнал может быть запомнен в своей истории и воспроизведен в симуляторе в виде графика или таблицы. Объявление сигнала вы­глядит как:

signal:\идентификатор\{,\идентификатор\}[:= \начальное значение\];

где - \начальное значение\ - выражение, представляющее константу, значение которой принимает сигнал перед первым запуском процесса.

Константа

Константой является объект, не изменяющий свое значение при вычислениях. После объявления константы присваивание ей значе­ния запрещено (кроме случая отложенной константы). Пример объ­явления константы:

constantthousand: integer:=1000;

Переменная

Переменная - это объект, хранящий значение в пределах опера­торов процесса, функции или процедуры. В отличие от сигнала, присваивание переменной выполняется немедленно. Синтаксис объявления переменной:

\объявление переменной\::=

[shared] variable\идентификатор\{Дидентификатор\}:\тип\ [:=\начальное значением;


Пример объявления переменной:

variable byte_int: integer range-128 to 127:=0;

При объявлении глобальных переменных используют ключевое слово shared. Глобальную переменную можно объявлять в любом месте объявлений проекта.

Порт

В структуре программы VHDL выделяются объекты проекта, на­зываемые entity. Их не следует путать с объектами языка. Порт представляет собой интерфейсный сигнал объекта проекта. Как и в декларации сигнала, в декларации порта указывается его идентифи­катор, тип, начальное значение. Дополнительно указывается режим работы: in - прием, out - передача, inout - прием и передача, buffer - передача и использование как сигнал-операнд внутри объ­екта проекта и link. Упрощенный синтаксис объявления портов объ­екта проекта следующий:

\объявление портов объекта\::=port (\объявление порта\

{; \объявление порта\}); \объявление порта\::=\идентификатор\: inI out|inout|buffer|1ink

\тип\ [:=\начальное значение\] .

Режим link является анахронизмом. Он был введен для аналого­вого моделирования, но теперь в аналоговом VHDL он не использу­ется.

Настроечная константа generi с

Настроечная константа generic кодирует определенное свойство объекта проекта. Она используется, например, для задания разряд­ности линий связи, кодирования структуры моделируемого устрой­ства. При вставке компонента через интерфейс связывания настро­ечных констант, настройка объекта верхнего уровня передается объ­ектам нижнего уровня. Упрощенный синтаксис объявления настроечных констант следующий:

\объявление настроечных констант\::=

депепс(\о6ъявление настроечной константы\

{; \объявление настроечной константы\}); \объявление настроечной константы\::=

\идентификатор\:\тип\[:=\начальное значение\]


Переменная цикла

Переменная цикла - это специальный объект в том смысле, что он не требует объявления. Подробнее о ней сказано при описании оператора цикла loop.

Начальное значение объекта

Начальное значение объекта в его объявлении - это то значение, которое принимает объект перед первым циклом моделирования. Если начальное значение не присвоено, то симулятор присваивает наименьшее значение данного типа, если тип - числовой или самое левое значение, если тип - перечисляемый.

Это значение может быть выражением. Но значение выражения должно быть вычисленным до момента трансляции данного объяв­ления. Например, первое объявление:

signal bb:bit:=aa; signal aa:bit : = Ч';

неверно, так как при его рассмотрении компилятор еще не имеет сведений об идентификаторе аа.

В аппаратной модели начальное значение объекта эквивалентно состоянию триггеров и шин сразу после включения питания до при­хода сигналов сброса, т.е. оно не определено. Поэтому компиляторы-синтезаторы, как правило, не допускают (иногда - игнорируют) на­чальные значения всех объектов, кроме констант или объектов, ко­торые не изменяют свое значение при вычислениях.

Выражения

В VHDL выражения выполняют арифметические или логические вычисления над одним или несколькими операндами. Выражения используются в операторах присваивания сигналу, переменной, при присваивании начального значения, как операнд в других операто­рах, как входной параметр вызова процедуры или функции.

Операции в выражениях

Операции VHDL перечислены в таблице 3.1 в порядке их при­оритета.


Тип операции Символ или ключевое слово
Логические and, or, nand, nor, xor, хпог
Сравнения =, /=f <, <=, >, >=
Сдвига sll, srl, sla, sra, rol, ror
Сложения +, -, & (конкатенация)
Унарные (знак) + » -
Умножения *, /, mod, rem
Различные **, abs, not

Логические операции имеют самый низкий приоритет. Операнды логических операций должны быть одного типа bit или boolean, или одномерного регулярного типа (векторы) из элементов типа bit или boolean. Для однозначной компиляции логических выражений необ­ходимо использовать скобки, например:

(a or b) andс and(d or с).

Операции сравнения выполняются над операндами одинакового типа и возвращают тип boolean. Операции равенства "=" и неравен­ства "/=" выполняются над всеми типами. Остальные операции сравнения выполняются над перечисляемыми типами, целыми ти­пами и одномерными регулярными типами (векторами) из элементов такого типа.

При сравнении перечисляемых типов элемент, стоящий в ряду правее (старший), считается большим. При сравнении векторов сравниваются пары элементов векторов, начиная с самых левых. Если пара элементов неодинакова, то вектор с более старшим эле­ментом считается бо лыиим. Если пара элементов одинакова то рас­сматривается следующая пара элементов. Например, в сравнении векторов битов "0111" >=м01011" результат будет true.

Операции сдвига выполняют сдвиг вектора битов на число разря­дов типа integer. Например, результатом выражения "100110" sra 3 будет вектор "111100", т.е. происходит арифметический сдвиг вправо на 3 разряда.

Операции сложения - вычитания "+", "-" предопределены для целых чисел и чисел с плавающей запятой. Операция конкатенации "&" применяется со всеми одномерными регулярными типами или с их элементами. С помощью этой операции векторы - операнды объ­единяются в более длинные векторы. Например, выражение "101" & 'Г & "10" даст результат "101110".


Унарные операторы применяются к одиночным операндам. Опе­ратор минус инвертирует значение операнда. Операторы умножения "*", деления "/" применяются с целыми операндами и операндами с плавающей запятой. Операторы mod(модуль), rem (остаток) приме­няются с целыми числами. Операции абсолютного значения abs и возведения в степень "**" определены для целых чисел и чисел с плавающей запятой, причем показатель степени должен быть це­лым.

Для многих операций языка существуют функции с таким же обозначением. Эти функции выполняют аналогичные действия, что и операции, но над другими типами операндов. Например, функция "+" из пакета numeric„bit библиотеки IEEE выполняет сложение век­торов битов, которые кодируют целые числа. Такие функции пере­гружают операции в зависимости от типа операндов.

При программировании для синтеза следует учесть, что правый операнд для операций "/". mod,rem может быть равным только сте­пени двойки, а левый операнд операции "**" должен быть равен 2, так что эти операции будут означать сдвиг двоичного кода.

Операнды в выражениях

Простейшими операндами являются литерал и идентификатор, такой как имя сигнала или переменной. Само выражение может быть операндом, если его окружить круглыми скобками. Операнда­ми могут быть также агрегат, атрибут, вызов функции, имя с ин­дексом, квалифицированное имя, значение комбинированного типа и его поля, вырезка регулярного типа, функция преобразования ти­па. Далее подробно рассматриваются эти виды операндов.

Простое выражениечаще всего представляет собой имя объекта со знаком +,- или без него. Для многих операторов операнды долж­ны быть простыми выражениями. Особенно это касается стиля про­грамм для синтеза.

Имя с индексомдает значение элемента регулярного типа, номер которого задается выражением зскобках. Например, vect(4) озна­чает 4-й бит вектора vect, arr(i,j) означает элемент (i,j) двумер­ного массива агг.

Имя-вырезказадает цепочку элементов объекта регулярного ти­па. Его упрощенный синтаксис:

\имя-вырезка\::=\имя\(\выражение\ to | downto \выражение\)


\выражение\ - должно вычислять значение, не превосходящее диа­пазон индексов объекта регулярного типа с именем \имя\. Направ­ление изменения индекса to или downto должно совпадать с направ­лением, заданным в объявлении типа. Например, если объявлен сигнал:

signalA: bit„vector(15 downto0);

то А(15 downto 8) - старший байт сигнала А.

Поле комбинированного типа.Чтобы оперировать с полем объек­та комбинированного типа его вставляют в выражение согласно син­таксису:

\поле комбинированного типа\::=\имя комбинированного типа\.\имя поля\

где \имя поля\ - может представлять поле любого типа, а также его имя с индексом, имя-вырезку, агрегат. Например, если объявлены тип и сигнал:

type comp„vect is record

(Re: bit_vector(0 to 15); Im:bit_vector(0 to15)); end record; signalA: comp_vect;

то A.Re(0 to 7) - старший байт поля Re сигнала А типа comp_vect.

Вызов функции.При вызове функции выполняется функция с заданными значениями параметров. Упрощенный синтаксис вызова функции:

\вызов функции\::=\имя функции\ ([\имя параметра =>\] \выражение\ {,[\имя параметрах => ] \выражение\});

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

При позиционированном связывании выражения-параметры под­ставляются в порядке, определенном порядком следования имен па­раметров в определении функции. При поименованном связывании каждое имя параметра связывается с соответствующим параметром с помощью символов "=>", причем порядок следования параметров может быть произвольным.

Например, в пакете iEEE.Math_.Real определена функция синуса:

functionSin (x: inreal) returnreal;


Ее вызов по аргументу вещественного типа выглядит как: SIN(x=>math_2_pI * angle) или sin(math_2„pi * angle),

где math__2_pi - константа, равная 2, определенная в этом пакете.

Преобразование типа.Так как в VHDL присваивание значения объекту требует строгого соответствия типов, то в случае, если типы объектов не совпадают, необходимо выполнить преобразование типа. Его синтаксис соответствует синтаксису вызова функций с одним аргументом.

Различают два вида преобразования типа: переход типа и вызов функции преобразования типа. Переход типа применяется для пре­образования тесно связанных типов или подтипов. Такими парами типов являются, например, real и integer, integer и natural, регу­лярные типы с одинаковым числом элементов того же самого типа и с одинаковыми диапазонами индексов. Например, при переходе из значения с плавающей запятой к целому значению:

C:=integer(123.5);

результат с округляется до ближайшего целого, т.е. до 124.

Если типы не тесно связанные, то необходимо выполнить вызов функции преобразования типа. Например, типы boolean и bit - не тесно связанные т.к. принадлежат к перечисляемым типам с раз­личными множествами элементов. Поэтому, например, преобразова­ние переменной х типа boolean в переменную Y типа bit может вы­полняться функцией преобразования типов, которая включает опе­ратор:

if X then Y: = 'l'; elseY: = '0'; end if;

Часто программисты пользуются своими функциями преобразо­вания типов. Большинство стандартных и коммерческих библиотек содержат наборы функций преобразования типов.

Атрибут.У объектов языка имеется некоторое множество свойств и особенных значений. Атрибут объекта - это специальная функция, которая возвращает его особенное значение. Например, атрибут objectl'left возвращает значение самого левого элемента объекта objectl перечисляемого типа. Подробнее об атрибутах будет рас­смотрено в разделе, посвященном атрибутам.

Агрегат.Агрегатом называется операция, которая объединяет одно или несколько значений в значение составного типа, т.е. регу­лярного или комбинированного типа. Его упрощенный синтаксис:


\агрегат\::=(\связывание элементов\ {Довязывание элементов\}) \связывание элементов\::=[\альтернативы\ =>] \выражение\ \альтернативы\::=Лальтернатива\ {Д альтернатива\}

\альтернатива\: :=\простое выражение\|\диапазон\|\имя элемента\| others

Связывание элементов означает подстановку одного выражения в одно или несколько заданных полей или элементов значений состав­ного типа. Связывание элементов может происходить в порядке ну­мерации элементов составного типа. Тогда оно называется позицио­нированным связыванием. Например, в объявлении:

variablev_5: bit_vector (0 to 4) : = С09, '0', ,01, '1', Ч') ;

битам 0, 1 и 2 присвоено начальное значение 0, а битам 2,3 -значение 1. Если каждый элемент связывается со своим значением по имени, то такое связывание называется поименованным. Напри­мер, для той же переменной v_5:

(3|4 => '1\ others => '0') или (0 to 2 => '0'; 3 to 4 => 'Г).

Здесь ключевое слово othersозначает остальные элементы значе­ния и оно должно стоять последним в списке связываний. Возмож­ны и комбинированные агрегаты, в которых первым используется позиционное связывание, а затем - поименованное связывание, на­пример:

СО9,'О9, 3 to 4 => '1\ others -> 'О').

Но такое связывание допускают далеко не все трансляторы VHDL.

Такая альтернатива, как простое выражение, применяется только для регулярных типов и должна определять номер элемента из диапазона этого типа, например, агрегат (i => '!', others=> '0') задает вектор в котором на £-м месте стоит 1, а остальные биты — нулевые.

Альтернатива \имя элементах применяется только для комбиниро­ванных типов, например:

type complex is record(Re: integer; im: integer ); end record; variablex iscomplex:=(Re => 1000, im => 0);

Квалифицированное выражение.Результат выражения может принадлежать нескольким типам одновременно. Если этот результат должен принадлежать к конкретному типу, то его необходимо обо­значить как результат, квалифицированный с заданным типом. Синтаксис такого выражения:

\квалифицированное выражение\::=\имя типа\'(\выражение\)


Например, если объявлено

type vect is bit„vector(0 to 9); var x: vect;

то выражение (3=>'l'.others => '0') может принадлежать к типу векторов любой длины и разных типов. Поэтому для присваивания переменной этого выражения необходимо выполнить его квалифи­цированным:

x^vect'O^'l' .others -> '0');

Статические выражения

Как уже указывалось, структура виртуальной параллельной вы­числительной системы и ее параметры формируются при компиля­ций программы VHDL и остаются неизменными в процессе ее ис­полнения. Точнее, это происходит на последнем этапе - этапе свя­зывания объектов (elaboration). В программах часто встречаются выражения, от результатов которых зависят структура и параметры системы. Это например, настроечные переменные (generic), опреде­ляющие порядок включения блоков, их разрядность. Некоторые операторы, например, case, вставки компонента, требуют, чтобы в них входили статические выражения. Результаты этих выражений должны иметь конкретные значения перед исполнением программы и не должны зависеть от входных сигналов и переменных. Такие выражение получили название статических. Другими словами, не­посредственно перед моделированием статическое выражение долж­но быть вычислено до константы или приведено к сигналу или пере­менной конкретного типа. Выражения от литералов, констант, ста­тических выражений и функций от них являются статическими выражениями.

Например, если объявлены сигналы

signal n: integer;

signal A: bit_vector(16 downto n+1);

то на момент начала моделирования операнд п неизвестен и симуля-тор будет пытаться подставить п = -2147483647, что вызовет ава­рийную остановку симулятора при размещении сигнала А в памяти, т.е. здесь выражение п+1 - не статическое.

Если симулятор дает широкие возможности исполнения про­граммы, обеспечиваемые большими ресурсами памяти компьютера и последовательным многократным исполнением операторов, то при аппаратной реализации программы эти возможности значительно


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

В предыдущем примере симулятор может работать, если сигнал п - типа natural, который по умолчанию принимает начальное нуле­вое значение. Но для синтеза такая программа не годится, так как, во-первых, присваивание начального значения игнорируется или запрещается, во-вторых, в аппаратуре должны быть четко заданы разрядность регистров и шин, объем памяти и т.п.

Реализация выражения в аппаратной модели VHDL

Если выражение не упрощается при компиляции до константы или другого объекта, то оно реализуется в аппаратной модели в виде логических комбинационных схем. Операции в выражениях ото­бражаются в схемы, выполняющие эти операции над операндами соответствующих типов.

Логические операции реализуются в соответствующих элементах: and— в элементе "И", not- элементе "НЕ" и т.д. При операциях над битовыми или булебскими данными реализуются одиночные логические элементы. При выполнении операции над операндами регулярного типа каждому элементу операнда ставится в соответст­вие один логический элемент.

Операции равенства и неравенства реализуются с помощью соот­ветствующего числа элементов "И" с объединением их выходов в элементе "ИЛИ". Операции "больше" или "больше или равно" вы­полняются с помощью многоразрядной схемы сумматора-вычитателя, выход переполнения которой соответствует булевскому результату этой операции.

Операции, сложения, вычитания, изменения знака выполняются с помощью схемы сумматора, а операция умножения - с помощью комбинационного умножителя. При этом если операнды типа positive или natural, то умножение выполняется на умножителе без учета знака, а если типа integer - на умножителе со знаком.

Операция абсолютного значения absвыполняется на схеме полу­чения положительного числа из отрицательного и мультиплексора, который в зависимости от знака числа пропускает результат на вы­ход схемы.

Операция деления, модуля, остатка и возведения в степень, кото­рые соответствуют сдвигу объекта, представленного двоичным чис­лом, реализуются в схеме сдвигателя. При этом если операнд типа integer, то сдвиг вправо выполняется с учетом знака.


Операция "&" конкатенации пары операндов регулярного типа соответ­ствует объединению двух шин, пере­сылающих эти операнды, в одну, со­стоящую из исходных шин.

При выполнении операций сложе­ния и вычитания разрядность резуль­тата должна быть равна максимальной разрядности операндов. Операнды

операции умножения должны иметь суммарную разрядность, рав­ную разрядности произведения.

Если операнды объявлены как тип integer без диапазона, то им соответствуют 32-разрядные типы и соответствующие 32-разрядные схемы реализации операций. Для минимизации оборудования реко­мендуется принять объявление переменной с диапазоном: например, если переменные объявлены как:

variable a, b: integer range (-128 to 127);

то выражение a+b выполняется на 8-разрядном сумматоре.

Сложное выражение от нескольких операндов при отсутствии скобок и с равноприоритетными операциями выполняется последо­вательно слева направо. Ему соответствует схема из цепочки моду­лей, выполняющих эти операции. Вставка скобок в это выражение задает приоритет выполнения операций, который отображается в аппаратную схему. Благодаря этому результирующая схема имеет вид дерева из модулей, задержка логических схем которого может быть намного меньше, чем в исходной схеме. На рис. 24 показаны аппаратные схемы, соответствующие выражениям a+b+c+d и (a+b)+(c+d).

Таким образом, вставка скобок в выражение является одним из способов управления ходом синтеза, выполняемого компилятором-синтезатором.

Последовательные операторы

Последовательные операторы в VHDL вставляются в операторы процессов и исполняются последовательно в виртуальных процес­сорных элементах программистской модели. Все операторы в VHDL оканчиваются точкой с запятой. Несколько операторов можно раз­мещать в одной строке и один оператор может занимать несколько строк.


Оператор присваивания

Он выполняет присваивание переменной или сигналу результата выражения. Этот оператор выглядит следующим образом:

\результат\:= \выражение\; - для присваивания переменной \результат\ <= \выражение\; - для присваивания сигнала.

Здесь результат \результат\ может быть именем, например, var, именем с индексом, как var(l), вырезкой, как var(0 to 1), полем, как гее.var или агрегатом, как (ReTim).

Присваивание переменной отличается от присваивания сигналу. Присваивание переменной выполняется немедленно.

Выполнение оператора присваивания сигналу означает вычисле­ние его выражения, и лишь назначение сигналу. Само же присваи­вание сигналу фактически выполняется в момент остановки процес­са по ожиданию события. Поэтому если в одном процессе стоит не­сколько присваиваний одному сигналу, то истинное присваивание происходит в момент остановки процесса. Если перед остановкой процесса выполнялось чтение этого сигнала (участие его в качестве операнда в выражении), то будет прочитано значение, присвоенное в прошлом запуске процесса.

При выполнении присваивания для части элементов сигнала со­ставного типа или перечисляемого типа, например, имени с индек­сом, вырезке считается, что выполняется присваивание всем элемен­там сигнала, причем те элементы, которые не указаны в операции присваивания, принимают старое значение. Например, по фрагменту программы

signal d:bit_vector(0 to 7);

d <= (others => '0'); d(l to 3) <= "Oil"; d(4 to 5) <= "IIй; wait ...

сигналу d будет присвоено значение "00111100".

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


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

Если пользоваться пакетом ieee.STD_logic_1164, to сигнал, объ­явленный как stcLlogic, можно присваивать в разных процессах, так как в этом пакете есть функция разрешения для такого типа сигналов.

Присваивание сигналу при моделировании

При моделировании дискретных систем важное место занимает моделирование распространения сигнала с учетом задержки в про­водниках или в вентилях. Для этого используют следующий расши­ренный синтаксис присваивания сигналу:

\присваивание сигналу\::=\результат\ <= [\способ задержки\] \график\; \спосо6 задержки\::= transport |[reject \выражение времени\] inertia! \график\::= \выражение\ [after \выражение времени\]

{, \выражение\ [after \выражение времени\] }

Здесь график (waveform) представляет собой запись, состоящую из одной или нескольких пар: величина сигнала - задержка сигна­ла. В первой паре задержка может не указываться, подразумевается, что она нулевая.

Способ задержки transportозначает, что при присваивании сиг­налы, представленные в графике, будут задержаны подобно тому, как сигнал задерживается в линии задержки или в проводниках. Величина задержки отсчитывается относительно момента остановки процесса и задается выражением \выражение времени\, которое име­ет тип time.

Способ задержки inertia!реализует поведение задержки в ис­точнике сигнала, который не реагирует на слишком короткие вход­ные импульсы. Фразой rejectзадается минимальная ширина им­пульса, которая выдается источником. Если этой фразы нет, то ми­нимальная ширина импульса задается в фразе after.По умолчанию в операторе применяется способ задержки inertia"!.В следующем ряде примеров показано действие оператора.

Y<= х after 10 ns;

- значение сигнала х на момент запуска процесса присвоится сигна­лу Y с задержкой 10 не, при этом импульсы шириной менее 10 не будут подавлены.

Y<= '0\ '1' after 10 ns, '0' after 20 ns, '1' after 30 ns;


- сигналу Y сначала присвоится 0, через 10 не - 1, через 20 не - 0, и
через 30 не - 1. Иногда таким способом задаются тестовые последо­
вательности сигналов.

Y<= а, А+в after delay_sum;

- сигналу Y сначала присвоится А, а через задержку, определяемую
статическим выражением delay_sum - сумма сигналов А и в.

Y<= transport X after 1000 ns;

- модель линии задержки сигнала х с задержкой 1 мкс.

Y<= reject t_rej inertial A and в after t_d;

- моделируется вентиль "И" с задержкой t_d , который не пропус­
кает импульсы короче t_rej.

Оператор ожидания события wai t

Этот оператор уже упоминался при описании модели для про­граммирования на VHDL и принципов работы симулятора. На этом операторе процесс останавливается, в момент остановки выполняют­ся присваивания сигналам, и процесс продолжает исполнение при появлении события, которое выбирается этим оператором. Синтак­сис оператора wai t:

\оператор waitY- :=wait [on \имя сигнала\ {Димя сигнала\}]

[until \6улевское выражение\] [for \выражение времени\];

где ключевое слово on начинает список чувствительности, until -условие ожидания, a for - означает задержку ожидания. По опера­тору

wait on clk, rst;

продолжение выполнения процесса начнется по событию изменения сигналов clk или RST. По оператору

wait until CLK='l';

продолжение начнется в момент изменения состояния clk из '0' в '1', т.е. по фронту этого сигнала. Оператор

wait for clk_period;

остановит процесс на время, заданное переменной clk_period типа ti me.

Возможно комбинирование списка чувствительности и условия ожидания в одном операторе. Оператор wait без списка чувствитель-


ности, условия ожидания и задержки останавливает процесс до кон­ца моделирования.

Оператор i f

Этот условный оператор в зависимости от заданных условий вы­полняет цепочки последовательных операторов, причем от условия зависит, которая из цепочек операторов выполняется. Упрощенный синтаксис оператора:

\оператор if\::=if \условие 1\ then

{\последовательный оператор 1\}

[ { elsif \условие 2\ then

{\последовательный оператор 2\}]

[else

{"^последовательный оператор 3\}]

end if;

Каждое из условий должно быть выражением, вычисляющим ре­зультат булевского типа. При выполнении этого оператора условия проверяются последовательно друг за другом, пока результат усло­вия не будет true. Тогда выполняется соответствующая этому усло­вию цепочка операторов и выполнение данного оператора if пре­кращается.

Оператор case

Этот оператор разрешает выполнение одной из цепочек последо­вательных операторов в зависимости от значения выражения селек­тора. Его синтаксис:

\оператор case\::=case \простое выражение\ is

when \альтернативы\ => {"^последовательный оператор\} {when \альтернативы\ => {"^последовательный оператор\}} end case; \альтернативы\:= \альтернатива\{ | \альтернатива\}

В выражении селектора \простое выражение\ должен вычисляться целый результат или значение перечисляемого или регулярного ти­па. Каждая из альтернатив \альтернатива\ должна быть такого же типа, что и \выражение\ и представлена статическим выражением или диапазоном, например, 0 to 4. Никакие два значения, получае­мые из выражений альтернатив, не должны быть равны друг другу, т.е. множества альтернатив не перекрываются. Последней альтерна­тивой может быть ключевое слово others, которое указывает на не перечисленные альтернативы. Если others не применяется, то в аль-


тернативах должны быть перечислены все возможные значения, принимаемые в селекторе \выражение\. Пример оператора case:

variable sel, a: integer 0 to 9;

case sel is

when 0 => a <= 0;

when 112 I 3 => a <= 1;

when 4 to 7 -> a <= 2;

when others => a <= 3;
end case;

Пустой оператор

Оператор null- не выполняет никаких действий и может быть вставлен в любом месте программы, как последовательный оператор. Например, если в операторе caseпо каким-то альтернативам не нужно ничего выполнять, то ставится этот оператор:

case sel is

when 0 => a <= 0; when 1 to 9 => a <= b; when others => null; end case;

Оператор цикла

Этот оператор несколько раз выполняет последовательность опе­раторов. Его синтаксис:

\оператор цикла\::=[\метка\:][\схема итерации\]1оор ^последовательный оператор\}

{next[\MeTKa\][when \условие\];} {ехЩ\метка\] [when \условие\];} end loop [\метка\]; \схема итерации\::=while \условие\

| for \переменная цикла \ in \диапазон\

Метка \метка\ необязательна, она отмечает начало цикла и с по­мощью ее во вложенных циклах указывается, в каком цикле начать новую итерацию по оператору nextили из какого цикла выйти по оператору exit.

По первой схеме итераций цикл, ограниченный ключевыми сло­вами loopи end loopбудет выполняться, пока условие \условие\ не примет значение false. Причем, это условие проверяется до выпол­нения цикла и если оно сразу равно false, то цикл не выполняется.


В примере:

variable vec: bit_vector(l to n); variable or_vec:bit; variable i:natural;

i:=l;

or_vec:='0'; while i<=n loop

or_vec:= or_vec or vec(i);

i: =i +1; end loop;

вычисляется переменная or_vec, равная функции ИЛИ от всех раз­рядов вектора vec длины п. Если п = 0, то цикл не вычисляется. Этот пример можно записать с помощью второй схемы итерации как:

variable vec: bit_vector(l to n); variable or_vec:bit;

or_vec:='0'; for i in 1 to n loop

or_vec:= or_vec or vec(i); end loop;

Здесь переменная цикла i последовательно принимает значения 1,2,... из диапазона 1 to п. Если необходим обратный порядок изме­нения переменной цикла: п, п-1,... то этот диапазон может быть за­дан как: n downto 1. Переменную цикла не нужно объявлять, как другие переменные и ей нельзя выполнять присваивания.