/
Текст
П.Н. Бибило
ОСНОВЫ ЯЗЫКА
VHDL
“Солон-Р”
Москва 2007
П.Н. Бибило
Основы языка VHDL
Эффективная работа в современных САПР, разработанных
ведущими зарубежными фирмами в области микроэлектроники
(XILINX, Altera, Cadence, Synopsys, Mentor Graphics и др.), требует
знания языка VHDL – исходного языка описания проектов.
Книга доктора технических наук, профессора Бибило П.Н.
предназначена для первоначального ознакомления с языком
VHDL, являющимся международным стандартом в области
автоматизации проектирования микроэлектронных систем на
современной элементной базе сверхбольших интегральных схем
(СБИС) – как на заказных СБИС, так и на программируемых
логических интегральных схемах (ПЛИС).
Рецензенты:
доктор технических наук А.А. Петровский,
доктор технических наук А.А. Прихожий,
кандидат технических наук Д.И. Черемисинов
Приглашаем к сотрудничеству Авторов по тематике САПР:
E-mail: Solon.Pub@relcom.ru
тел.: (095) 254-44-10
(095) 252-36-96
ISBN 5-93455-056-X
©
“CОЛОН-P”, 2007
П.Н.Бибило, 2007
3
Оглавление
Оглавление
Оглавление
Предисловие
............................................. 5
Глава 1. Основные элементы языка VHDL............... 7
1.1. Структурное и поведенческое описание цифровой
системы .......................................... 7
1.2. Лексические элементы и типы данных.............. 19
1.3. Декларации ..................................... 33
1.4. Интерфейс и архитектура объекта ................. 35
1.5. Предопределенные атрибуты ..................... 38
1.6. Имена .......................................... 41
1.7. Операторы ...................................... 42
1.8. Понятие сигнала в языке VHDL ................... 49
1.9. Дельта-задержка ................................. 53
Упражнения .................................. 57
Глава 2. Последовательные и параллельные операторы .. 62
2.1. Последовательные операторы ..................... 62
2.2. Параллельные операторы......................... 78
Упражнения .................................. 99
Глава 3. Организация проекта
......................... 107
3.1. Подпрограммы ................................. 107
3.2. Функции ....................................... 108
3.3. Процедуры ..................................... 109
3.4. Разрешающие функции. Пакет std_logic_1164 ...... 111
3.5. Архитектура.................................... 117
3.6. Декларация интерфейса объекта.................. 118
3.7. Карта портов и карта настройки ................. 120
4
Оглавление
3.8. Конфигурация .................................. 121
3.9. Блоки проекта и VHDL-библиотеки .............. 124
Упражнения ................................. 126
Глава 4. Примеры проектирования на VHDL ........... 128
4.1. Стили описания поведения ....................... 128
4.2. Формы описания сигналов ....................... 131
4.3. Описание автоматов ............................ 135
4.4. Отладка VHDL-описаний........................ 155
4.5. Синтезируемое подмножество языка VHDL ....... 158
Упражнения ................................. 169
Литература .............................................. 171
Приложения ............................................ 172
1. Форма задания синтаксических конструкций
языка VHDL .................................... 172
2. Синтаксис языка VHDL’93 ........................ 173
3. Пакет STANDARD ............................... 197
4. Пакет STD_LOGIC_1164 .......................... 199
Предисловие
5
Предисловие
Предисловие
Язык VHDL (Very high speed integrated circuits Hardware Description
Language) является фактически международным стандартом в области
автоматизации проектирования цифровых систем, это входной язык
многих современных систем автоматизированного проектирования
(САПР) как заказных, так и программируемых логических интегральных
схем (ПЛИС) - Programmable Logic Devices (PLD) - и программируемых
пользователями вентильных матриц - Field-Programmable Gate Arrays
(FPGA). VHDL предназначен, в первую очередь, для спецификации точного описания проектируемых систем и их моделирования на
начальных этапах проектирования - алгоритмическом и логическом. С
помощью VHDL можно моделировать электронные схемы с учетом
реальных временных задержек.
В последнее время весьма успешно разрабатываются и системы
синтеза схем по спецификациям на этом языке. Например, используя
САПР Xilinx Foundation Series 2.1i, можно провести моделирование
исходного описания схемы на языке VHDL, а затем синтезировать схему и
получить файл настройки (конфигурации) микросхемы типа FPGA фирмы
Xilinx. Использование САПР MAX+PLUSII позволяет решать
аналогичные задачи для программируемых микросхем, выпускаемых
фирмой Altera. Для заказных СБИС могут быть использованы САПР
фирмы Mentor Graphics: система моделирования ModelSim позволяет
провести моделирование описаний, представленных на языке VHDL,
система синтеза Leonardo Spectrum Level 3 позволяет получать по
описаниям на языке VHDL схемы в заданных базисах логических
элементов. Такие крупнейшие фирмы – производители программного
обеспечения САПР в области микроэлектроники, как Cadence, Synopsys и
многие другие используют язык VHDL в качестве языка исходного
описания проектов.
VHDL - это мощный язык, он позволяет описывать поведение, т.е.
алгоритмы функционирования цифровых систем, а также проводить
иерархическое функционально-структурное описание систем, имеет
средства для описания параллельных асинхронных процессов, регулярных
(систолических) структур и в то же время имеет все признаки языка
программирования высокого уровня - позволяет создавать свои типы
6
Предисловие
данных, имеет широкий набор арифметических и логических операций и
т.д.
Язык VHDL был разработан в США по инициативе министерства
обороны этой страны. В 1987 г. VHDL был принят в качестве стандарта
ANSI/IEEE Std 1076-1987. Данный стандарт часто называют VHDL’87.
Затем язык был усовершенствован, новый стандарт ANSI/IEEE Std 10761993 (стандарт VHDL’93) появился в 1993 г. Книга [7] целиком посвящена
новому стандарту языка и его отличиям от стандарта VHDL’87.
В 1999 г. утвержден стандарт Std 1076.1-1999 (или более
распространенное наименование VHDL-AMS), который включает
расширения, дающие возможность описания моделей аналоговых и
смешанных (цифро-аналоговых) схем.
Язык VHDL развивается, ему посвящаются международные
конференции, выходят научные журналы, в которых изучаются проблемы
использования VHDL. Он стал языком разработки международных
проектов, в том числе осуществляемых с помощью всемирной
компьютерной сети Internet. Знакомство с этим языком необходимо для
эффективной работы по созданию самой разнообразной электронной
аппаратуры на современной элементной базе сверхбольших интегральных
схем.
Данная книга предназначена для первоначального ознакомления с
языком VHDL. Приводимые в ней определения синтаксических
конструкций языка базируются на стандарте VHDL’87. В приложении
дается синтаксис стандарта VHDL’93. Основной упор в книге делается на
применение языка VHDL на этапах алгоритмического и логического
проектирования цифровых систем, она оказалась незаменимой при
начальном изучении языка VHDL студентами Белгосуниверситета
(специализация “Математическая электроника”). При написании книги за
основу был взят материал лекционного курса, читаемого автором в этом
вузе на протяжении ряда лет. В конце каждой главы даются вопросы,
задачи и упражнения для самостоятельной работы. Книга будет полезна
как для студентов и аспирантов соответствующих специальностей, так и
для специалистов, занимающихся разработкой электронной аппаратуры с
помощью средств САПР.
Автор выражает благодарность О.В.Клачко за помощь в
подготовке рукописи к изданию.
Структурное и поведенческое описание цифровой системы
7
Глава 1
Основные элементы языка VHDL
Глава 1. Основные элементы языка VHDL
1.1. Структурное и поведенческое описание цифровой системы
Структурное и поведенческое описание цифровой системы
Цифровая система может быть описана на уровне поведения функций, реализуемых системой, и на структурном уровне.
Структурное описание - это описание системы в виде
совокупности компонент (подсхем, элементов) и связей между
компонентами.
Поведенческое описание - это описание системы при помощи
некоторых процедур на уровне зависимостей выходов от входов.
Иначе говоря, поведенческое описание задает алгоритм,
реализуемый системой.
Цифровая система может быть сложной, как, например,
СБИС, (микропроцессор) или весьма простой, как логический
элемент (вентиль).
Естественно, некоторые компоненты системы в структурном
описании могут состоять из нескольких частей - компонент более
низкого уровня иерархии описания. Представляя отношение
вхождения подсхем в схемы в виде графа, можно получить дерево
(граф) иерархии описания всей системы.
Например, пусть цифровая система S (рис. 1.1) реализует
следующий алгоритм. На входные полюсы системы S подаются два
двухразрядных числа a=(a2,a1), b=(b2,b1), где a2, b2 - старшие
разряды чисел a, b соответственно и x - управляющий сигнал [3].
Если x=1, система S должна перемножить числа a, b и выдать
четырехразрядное число d=(d4,d3,d2,d1), где d= a×b.
Если x=0, то числа a, b должны быть сложены, при этом в
разряде d4 всегда должен быть нуль, в разряде d3 - перенос c2, в
разряде d2 - старший разряд суммы s2, в разряде d1 - младший
разряд суммы s1.
Предполагается, что
8
Глава 1. Основные элементы языка VHDL
(a2,a1) + (b2,b1)= (с2,s2,s1).
Мы описали алгоритм, который должна реализовать система
S, на русском языке. Однако для автоматизированного
(компьютерного)
проектирования
требуется
формальная
спецификация.
a1
a2
d4
b2
d3
S
b1
d2
d1
Интерфейс
x
Рис.1.1. Система S и ее интерфейс
Формальные спецификации должны быть записаны на
соответствующем формальном языке. Позже будет показано, что
алгоритм, реализуемый системой S, может быть очень коротко
описан на языке VHDL. Если же рассматривать структурный
уровень описания системы S, то можно легко увидеть, что в систему
S входит двухразрядный сумматор и двухразрядный умножитель.
Двухразрядный сумматор - это устройство для сложения
двухразрядных чисел, двухразрядный умножитель - устройство для
перемножения двух чисел, каждое из которых имеет только два
9
Структурное и поведенческое описание цифровой системы
разряда. В систему S должно входить также простейшее устройство
управления и схема дизъюнктивного объединения выходных
сигналов.
Структура системы S изображена на рис. 1.2, где adder_2 двухразрядный сумматор, mult_2 - двухразрядный умножитель, yy устройство
управления,
dd
схема
дизъюнктивного
формирования
d4
d3
1
dd
t4 t3
t2
d2
d1
1
1
c2
t1
mult_2
b2
b1
s2
s1
adder_2
f2 f1
f4 f3 f6 f5
yy
x
a2 a1
Рис. 1.2. Структура цифровой системы S
выходных сигналов. Схему dd образуют три дизъюнктора.
Устройство управления yy является весьма простым и
функционирует следующим образом:
если x=0, то
(a2,a1)=(f4,f3),
(b2,b1)=(f6,f5),
10
Глава 1. Основные элементы языка VHDL
(f2,f1)=(0,0),
т.е. числа a, b подаются на вход сумматора adder_2.
Если же x=1, то
(f4,f3)=(0,0),
(f6,f5)=(0,0),
(a2,a1)=(f2,f1),
т.е. числа a, b подаются на вход умножителя mult_2.
Пусть описание системы S имеет имя VLSI_1. Тогда иерархия
структурного описания системы S будет иметь вид (рис.1.3)
VLSI_1
adder_2
mult_2
yy
dd
Рис. 1.3. Дерево иерархии структурного описания системы S
Рассмотрим двухразрядный умножитель mult_2. На вход
данной схемы (рис. 1.4) поступают сигналы r1, r0, s1, s0. Сигналы r1,
r0 интерпретируются как двухразрядное целое число r=(r1,r0),
сигналы s1, s0 - как двухразрядное целое число s=(s1,s0).
Выходные сигналы в t3, t2, t1, t0 представляют собой разряды
числа t=(t3, t2, t1, t0) - произведения чисел s, r:
(t3, t2, t1, t0) = (r1,r0)×(s1,s0).
В схему входят элементы двух типов - add1 и and2.
Элемент and2 представляет собой логический элемент И двухвходовый конъюнктор.
Заметим, что на языке VHDL знак & употребляется не для
обозначения логической операции "И" (конъюнкции), а для
операции конкатенации векторов.
Оператором логической конъюнкции служит оператор and,
поэтому описание функции элемента and2 на языке VHDL
выглядит следующим образом:
y <= x1 and x2;
11
Структурное и поведенческое описание цифровой системы
где x1, x2 - имена входных сигналов, у - имя выходного сигнала,
<= - оператор назначения сигнала (будет рассмотрен позже).
t3
t2
add1
t1
t0
circ2
add1
circ1
p3
p2
p4
and2
and2
el_4
el_3
pl
s1
r1
r0
and2
el_2
and2
el_1
s0
r1
r0
Рис. 1.4. Двухразрядный умножитель mult_2
Элемент
add1
представляет
собой
одноразрядный
полусумматор, функционирование которого описывается таблицей
истинности (табл. 1.1).
b1
0
0
1
1
Таблица 1.1
b2 c
s1
0
0
0
1
0
1
0
0
1
1
1
0
12
Глава 1. Основные элементы языка VHDL
В данном случае b1, b2 интерпретируются как одноразрядные
числа, s1 - сумма, c - перенос в следующий разряд.
В привычной математической записи булевы функции c, s1
могут быть представлены следующим образом:
s1 = b1 ⊕ b2 = (b1 ∧ b2 )∨( b1 ∧b2 ),
c=b1∧b2.
В языке VHDL функционирование
записывается следующим образом:
элемента
add1
s1<=((b1 and (not b2)) or (not b1) and b2));
c<=b1 and b2;
где or - оператор логической дизъюнкции;
and - оператор логической конъюнкции;
not - оператор отрицания.
Итак, в дерево проекта схемы умножителя, которую назовем
mult_2, входят элемент and2 и подсхема add1. Если использовать
логические элементы or2 (двухвходовый дизъюнктор) и inv
(инвертор) и and2 (двухвходовый конъюнктор) для реализации
подсхемы add1, то дерево проекта будет трехуровневым.
Элементы and2, or2, inv являются листьями проекта. Листья
проекта не имеют составных частей и называются примитивами
проекта. Примитив описывается только на поведенческом уровне.
Объектами проекта для двухразрядного умножителя
являются mult_2, add1, and2.
Обозначение корня дерева (mult_2) является именем проекта.
Каждый объект проекта имеет два различных типа описаний:
- описание объекта "в целом" (entity);
- описание архитектуры объекта (architecture).
Упрощенно можно сказать, что описание объекта "в целом"
состоит из имени объекта и описания портов (входов, выходов)
объекта. Описание объекта "в целом" в языке VHDL носит название
"интерфейс" объекта. Чтобы отличать один объект проекта от
другого, термин entity будет пониматься иногда и как объект
проекта.
Для сигналов, подаваемых, снимаемых с портов указывается
вид (режим, направление) сигнала: входной (in), выходной (out) и
его тип.
Структурное и поведенческое описание цифровой системы
13
Описание объекта проекта and2 имеет вид.
entity and2 is
port (x1,x2: in BIT;
y: out BIT);
end and2;
-- декларация имени объекта проекта
-- декларация входных портов
-- декларация выходного порта
architecture functional of and2 is -- декларация архитектуры
begin
y <= x1 and x2;
-- описание функции объекта
end functional;
В тексте данной программы имеются комментарии.
Комментарий начинается двумя смежными дефисами и
продолжается до конца строки.
В данном примере BIT - это тип сигнала. Архитектурное тело
может определять поведение объекта проекта непосредственно
(быть примитивом), либо представлять собой структурную
декомпозицию на более простые компоненты. Описание объекта
проекта add1 выглядит следующим образом:
entity add1 is
port (b1,b2 : in BIT;
c1,s1 : out BIT);
end add1;
architecture struct_1 of add1 is
begin
s1<= ((b1 and (not b2)) or ((not b1) and b2));
c1<= b1 and b2;
end struct_1;
Описание объекта проекта mult_2 выглядит следующим
образом:
entity mult_2 is
port (s1,s0,r1,r0 : in BIT;
t3,t2,t1,t0 : out BIT);
end mult_2;
architecture structure of mult_2 is
component
14
Глава 1. Основные элементы языка VHDL
add1
port (b1,b2: in BIT;
c1,s1: out BIT);
end component;
signal p1,p2,p3,p4 : BIT;
begin
t0 <= r0 and s0;
-p2 <= r0 and s1;
-p1 <= r1 and s0;
-p4 <= r1 and s1;
-circ1: add1
port map (p1, p2, p3,t1);
circ2: add1
port map (p3,p4,t3,t2);
end structure;
элемент el_1
элемент el_3
элемент el_2
элемент el_4
В описании архитектуры объявляются (декларируются) две
подсхемы (компоненты). После ключевого слова begin приводятся
экземпляры описаний. Каждый экземпляр имеет уникальную метку
(сirc1, сirc2 – метки). Каждый экземпляр имеет карту портов (port
map). Карта портов отражает связь между входами, выходами
описаний компонента и экземплярами компонента. Заметим, что в
данном описании мы использовали понятие компонента (подсхемы)
для add1, в то время как логические элементы И схемы мы описали
на функциональном уровне, не используя понятие компонента.
Возможность проведения таких смешанных описаний является
важной полезной особенностью языка VHDL. Данная гибкость
весьма удобна при проектировании на начальных этапах, когда
важно получить точное алгоритмическое описание, не вдаваясь в
детали структурной организации некоторых частей проекта.
Аналогично можно рассмотреть двухразрядный сумматор
adder_2 (рис. 1.5), состоящий из двух подсхем add1, add2, где add1 это уже известный нам одноразрядный полусумматор, а add2 одноразрядный
сумматор,
функционирование
которого
описывается следующей таблицей истинности (табл. 1.2):
Таблица 1.2
c1
0
0
a1
0
0
a2
0
1
c2
0
0
s2
0
1
Структурное и поведенческое описание цифровой системы
0
0
1
1
1
1
1
1
0
0
1
1
0
1
0
1
0
1
0
1
0
1
1
1
15
1
0
1
0
0
1
В дерево проекта для подсхемы adder_2 входят подсхемы
add1, add2, а VHDL-описание имеет вид
entity adder_2 is
port (a1, b1, a2,b2 : in BIT;
c2,s2,s1 : out BIT);
end adder_2;
architecture structure of adder_2 is
component
add1
port (b1,b2: in BIT;
c1,s1: out BIT);
end component;
component add2
port(c1, a1,a2:in BIT;
c2,s2:out BIT);
end component;
signal c1: BIT;
begin
circ1: add1
port map (b1,b2, c1,s1);
circ2: add2
port map (c1,a1,a2,c2,s2);
end structure;
16
Глава 1. Основные элементы языка VHDL
c2
s1 s2
adder_2
a)
a1 b1
a2 b2
s1
add1
s2
c1
add2
c2
б)
b1 b2
a1
a2
Рис. 1.5. Двухразрядный сумматор
(a1,b1)+(a2,b2)=(c2,s2,s1):
a - условное обозначение; б - схема в виде каскадного
соединения одноразрядного полусумматора add1 и
одноразрядного сумматора add2
Можно заметить, что в различные подсхемы входит add1, при
этом подсхема add1, входящая в сумматор adder_2, является листом
проекта и поэтому описана на поведенческом уровне. Подсхема
add1, входящая в умножитель mult_2, описана на структурном
уровне. Предлагаем читателю самостоятельно описать подсхему
add1 в виде объекта проекта, используя примитивы and2, or2, inv.
Итак, VHDL-код для структурного описания системы S
(см. рис. 1.2) выглядит следующим образом:
entity vlsi_1 is
port (a2, a1, b2,b1,x:in BIT;
d4,d3,d2,d1: out BIT);
end vlsi_1;
architecture structure of vlsi_1 is
component
-- декларация компонента
adder_2
port (a1,b1,a2,b2: in BIT;
Структурное и поведенческое описание цифровой системы
17
c2,s2,s1: out BIT);
end component;
component mult_2
port(s1,s0, r1,r0: in BIT;
t3,t2,t1,t0: out BIT);
end component;
component dd
port (x1,x2,x3,x4,x5,x6 : in BIT;
y1,y2,y3 : out BIT);
end component;
component yy
port( a2,a1,b2,b1,x : in BIT;
f6,f5,f4,f3,f2,f1 : out bit);
end component;
signal f1,f2,f3,f4,f5,f6,t4,t3,t2,t1,c2,s2,s1: BIT;
-- декларация внутренних сигналов
begin
circ1: yy
port map ( a2,a1, b2,b1, x, f6,f5,f4,f3,f2,f1);
circ2: mult_2
port map ( f2,f1, b2,b1, d4,t3,t2,t1);
circ3: adder_2
port map ( f4,f3, f6,f5,c2,s2,s1);
circ4: dd
port map ( s1,t1,s2,t2,c2,t3, d1,d2,d3);
end structure;
Дерево проекта для системы S изображено на рис. 1.6.
Приведем один из вариантов алгоритмического описания
системы S в целом. Следует обратить внимание на то, что входные
и выходные сигналы интерпретируются как целые числа, что
позволяет сделать алгоритмическое описание весьма компактным.
entity vlsi_1 is
port (a,b : in integer range 0 to 3;
x : in BIT;
D : out integer range 0 to 15);
end vlsi_1;
architecture functional of vlsi_1 is
18
Глава 1. Основные элементы языка VHDL
signal e: integer range 0 to 15;
begin
p0: process(a,b,x)
begin
if (x='0') then
e <= a + b;
elsif ( x = '1') then
e <= a * b ;
end if;
end process;
D <= e;
end functional;
VLSI_1
adder_2
add1
add2
mult_2
and2
yy
dd
add1
Рис.1.6. Дерево проекта цифровой системы S
Как видно, оно значительно компактнее структурного
описания. Очевидно, что переход от алгоритмического описания к
структурному представляет значительный практический интерес. К
сожалению, автоматический переход возможен только для
подмножества языка VHDL. Такое подмножество языка называется
синтезируемым.
Лексические элементы и типы данных
19
Получение функционально-структурной схемы по ее
алгоритмическому описанию называется высокоуровневым синтезом
в отличие от логического синтеза, когда по функциональноструктурному описанию цифровой системы надо получить
логическую схему из заданных базисных логических элементов.
Программу, осуществляющую по VHDL-описанию синтез схемы,
например схемы FPGA, часто называют компилятором. Однако в
системах моделирования VHDL-кодов под компиляцией также
понимается преобразование VHDL-кода в промежуточный язык, с
которым оперируют непосредственно программы моделирования.
Как и для языков программирования, сборку откомпилированных
модулей
осуществляет
программа
LINK.
Программа,
осуществляющая
проверку
синтаксической
корректности,
называется VHDL-анализатором.
Приведенное VHDL-описание системы S станет понятным
позже, когда будут введены типы данных и основные операторы
языка VHDL - операторы процессов, назначения сигналов и др.
Лексические элементы и типы данных
1.2. Лексические элементы и типы данных
Лексические элементы, разделители, операторы.
Текст на языке VHDL есть последовательность раздельных
лексических элементов, таких как
• идентификатор;
• разделитель;
• ключевое (зарезервированное) слово;
• абстрактный литерал;
• символьный литерал;
• строка литералов;
• битовая строка литералов;
• комментарий.
Смежные лексические элементы разделяются
• разделителями;
• концами строк;
• знаками форматирования.
Оператор есть один из следующих специальных символов:
& ( ) * + ? - . / : ; < = > |
20
Глава 1. Основные элементы языка VHDL
Составной
cпециальных символов
оператор есть композиция
двух смежных
=> ** := /= >= <= < >
Пример. VHDL-предложение
A <= B and C;
имеет шесть лексических элементов "A", "<=", "B", "and", "C", ";" .
Два из шести лексических элементов являются операторами:
" <= " (составной оператор назначения сигнала);
";"
В качестве разделителей в данном примере используются
пробелы, однако нет необходимости иметь разделитель между
оператором " ; " и лексическим элементом "C".
Комментарий начинается с двух смежных дефисов и
продолжается до конца строки. Комментарии не учитываются при
моделировании VHDL-описания.
Глава 1. Основные элементы языка VHDL
Идентификаторы
Определение.
identifier ::= letter { [ underline ] letter_or_digit }
Внимание! Здесь и далее формальная запись синтаксических
конструкций языка VHDL основывается на формах Бэкуса-Наура,
употребление которых разъясняется в Приложении 1. Далее важная
информация, на которую следует обратить особое внимание, будет
сопровождаться только восклицательным знаком.
Идентификаторы употребляются как пользовательские имена
и ключевые слова.
Идентификатор должен начинаться с буквы (не цифры).
Может употребляться кроме букв и цифр, знак подчеркивания.
Два подряд
идущих подчеркивания не допускаются.
! В VHDL-коде нет различия между прописными и строчными
буквами.
AbC7 эквивалентно aBC7,
A_3 не эквивалентно A3.
21
Лексические элементы и типы данных
Идентификатор не должен оканчиваться подчеркиванием.
Пример.
Правильные
Идентификаторы
carry_OUT
Dim_Sum
Count7SUB_2goX
AaBBb
Неправильные
Идентификаторы
7AB (начинается с цифры)
A@B (специальный символ @)
SUM_(кончается подчеркиванием)
PI_ _A (два подчеркивания подряд)
Зарезервированные (ключевые) слова
Как и многие другие языки программирования, VHDL имеет
ключевые (специальные) слова.
Список ключевых слов
abs
and
begin
case
access
architectur
e
block
component
after
array
Alias
Assert
all
attribute
body
configuratio
n
elsif
for
if
library
nand
null
others
process
report
subtype
units
when
Buffer
Constant
bus
disconnect
downto
else
End
entity
exit
file
Function
generate
generic
guarded
In
inout
is
label
Linkage
loop
map
mod
New
next
nor
not
Of
on
open
or
Out
package
port
procedure
range
record
register
rem
return
select
severity
signal
then
to
transport type
until
use
variable
wait
while
with
xor
В стандарт VHDL’93 добавлены следующие слова:
group
pure
sla
impure
reject
sll
inertial
rol
sra
literal
ror
srl
postponed
shared
unaffected
22
xnor
Глава 1. Основные элементы языка VHDL
Литералы
Классификация литералов языка VHDL приведена на рис. 1.7.
Literal
Abstract
Decimal
Character
String
BitString
Based
Рис. 1.7. Классификация литералов
Десятичный литерал может быть целым, вещественным или
вещественным с экспонентой.
Определение.
decimal_literal ::= integer [ . integer ] [ exponent ]
integer ::= digit { [ underline ] digit }
exponent ::= E [ + ] integer | E - integer
Примеры.
Целые литералы: 21, 0, 1Е2, 3e4, 123_000.
Вещественные литералы: 11.0, 0.0, 0.468, 3.141_592_6.
Вещественные литералы с экспонентой: 1.23E-11, 1.0E+4,
3.024E+23.
Знак экспоненты E может быть строчным либо прописным.
Подчеркивание в десятичном литерале не является значащим.
Экспонента для целого литерала не должна иметь знак минус.
Базовый литерал указывает на систему счисления: - от
двоичной
23
Лексические элементы и типы данных
до шестнадцатеричной:
2# 1111_1100#
16# fc#
016# 0FC#
7# 510#
Все эти
литералы
имеют
значение 252
Число 16#6#E1 означает 6*16**1 - это число 96 в десятичной
системе счисления: 96 = 6 × 161. Символ * - знак умножения, ** возведение в степень. Число 2E - 3 не является целым, 3e4 - это
число 3 × 104.
Символьный литерал формируется одним из символов (букв)
между апострофами:
'A','a','%', ''' (литерал - апостроф), ' ' (пробел);
'A' отличается от 'a' в случае символьного литерала.
Строковый литерал формируется как последовательность
букв (возможно пустая) между двумя кавычками, употребляемыми
как строковые скобки.
Строковый литерал должен располагаться в одной строке.
Для формирования "длинных" строковых литералов может быть
употреблена операция конкатенации & (напомним, что для
оператора логического И употребляется оператор AND).
Литерал "строка бит"
Определение.
bit_string_literal ::= base_specifier " bit_value "
base_specifier ::= B | O | X
bit_value ::= extended_digit { [ underline ] extended_digit }
Литерал "строка бит" формируется как последовательность
цифр 0, ... , 9, A, ... ,F (или a, ... , f) между двумя кавычками.
Подчеркивание в таком литерале не является значащим.
Литерал "строка бит" может быть
B - бинарным;
O - восьмеричным;
X - шестнадцатеричным.
Очевидно, вместо прописных букв B, O, X могут
употребляться строчные буквы b, o, x.
24
Глава 1. Основные элементы языка VHDL
Длина строкового битового литерала есть число бит в
последовательности, представляющей литерал. Для примера: все
литералы X"F_FF", O"7777", B"1111_1111_1111" имеют длину 12.
Примеры.
B"1010110"
-- длина 7
O"126"
-- эквивалентно B"001_010_110", длина 9
X"56"
-- эквивалентно B"0101_0110", длина 8
Пакеты
Базовым элементом в языке VHDL служит блок. Блок - это
ограниченный фрагмент текста, содержащий раздел описания и
исполняемый раздел. Само архитектурное тело есть блок. Более
подробно оператор "блок" будет рассмотрен далее.
Пакет (package) в VHDL - это блок, который может включать
множество деклараций:
• типов;
• подтипов;
• констант;
• процедур;
• функций.
Пример функции языка VHDL: функция NOW возвращает
текущее время системы моделирования.
Тело пакета есть одно из мест, где могут быть определены
тела функций, тела процедур и другие VHDL-описания (рис. 1.8).
Функции и процедуры иногда называют подпрограммами.
Приведем только пример декларации процедуры, более подробно
подпрограммы будут рассмотрены далее.
Пакет
multiplexer
показывает,
что
процедура
MX
декларируется в пакете и тело процедуры определяется в теле
пакета.
package multiplexer is
procedure MX(
signal SEL : in bit;
signal x0 : in bit;
signal x1 : in bit;
signal F : out bit);
end multiplexer;
package body multiplexer is
procedure MX(
25
Лексические элементы и типы данных
signal SEL : in bit;
signal x0 : in bit;
signal x1 : in bit;
signal F : out bit) is
begin
case SEL is
when '0' => F <= x0;
when others => F <= x1;
end case;
end MX;
end multiplexer;
entity
architecture
package
configuration
package body
Рис. 1.8. В пакете могут размещаться различные VHDL-описания
Типы
Большинство языков программирования предусматривает
различные типы данных, и язык VHDL не является в этом смысле
исключением. Однако, поскольку этот язык используется для
представления аппаратных проектов в самых разных вариантах,
средства типизации данных приобретают здесь особенно важное
значение. Например, они дают разработчику возможность
представить
группу линий (проводников) шины в виде
• массива битов;
• целого числа.
26
Глава 1. Основные элементы языка VHDL
В языке VHDL реализована
строгая типизация. Это
означает, что смешение различных типов в одной операции
является ошибкой. Средства строгого контроля типов играют
ответственную роль, поскольку позволяют уточнять намерения
разработчика [1].
Тип - поименованное множество значений с некоторыми
общими характеристиками.
Подтип - подмножество значений данного типа.
Например, тип NATURAL есть подтип типа INTEGER.
Классификация типов языка VHDL дана на рис. 1.9.
Types
Scalar
Integer
Real
Composite
Physical
File
Accsess
Enumerated
Типы определяются обычно в
Рис. 1.9. Классификация типов
• пакете;
• процессе;
• архитектурном теле.
Тип "целый"
Определение.
integer_type_definition ::= range_constraint
range_constraint ::= range range
range ::= simple_expression direction simple_expression
direction ::= to | downto
Примеры декларации целых типов.
type byte_int is range 0 to 255;
27
Лексические элементы и типы данных
type signed_word_int is range –32768 to 32767;
type bit_index is range 31 downto 0;
В табл. 1.3 приведены основные типы данных языка VHDL.
Логические
типы
BOOLEAN
(булев)
BIT
(битовый)
BIT_VECTOR
(битовый вектор)
-
Арифметические
типы
INTEGER
(целый)
POSITIV
(положительный)
NATURAL
(натуральный)
REAL
(вещественный)
Таблица 1.3
Символьные
типы
CHARACTER
(символьный)
STRING
(строковый)
-
В пакете STANDARD (см. приложение 3) декларируются типы
BOOLEAN, BIT, CHARACTER, INTEGER, NATURAL, TIME, STRING,
BIT_VECTOR.
Тип BOOLEAN состоит из значений TRUE (истина), FALSE
(ложь).
Все операторы IF (если) в языке должны проверять объекты
или выражения этого типа.
Тип BIT состоит из значений 0,1. Значение TRUE типа
BOOLEAN не эквивалентно значению 1 типа BIT, аналогично,
значение FALSE не эквивалентно значению 0.
Тип СHARACTER,
по сути дела, представляет набор
символов кода ASCII.
Числовые типы имеют диапазон (range), или область
значений.
Примеры.
type INDEX is range 0 to 9; -- тип целый,
type VOLTAGE is range 0.0 to 10.0; -- тип вещественный.
28
Глава 1. Основные элементы языка VHDL
Физический тип
Определение.
physical_type_definition ::= range_constraint
units
base_unit_declaration
{ secondary_unit_declaration }
end units
base_unit_declaration ::= identifier ;
secondary_unit_declaration ::= identifier = physical_literal ;
physical_literal ::= [ abstract_literal ] unit_name
Поскольку VHDL - это язык описания аппаратуры, в нем
предусмотрены физические типы. Например, тип TIME (время)
может быть описан следующим образом:
type TIME is range 0 to 1E20
units
fs;
ps
= 1000fs;
ns
= 1000ps;
us
= 1000ns;
ms
= 1000us;
s
= 1000ms;
min
= 60s;
nr
= 60min;
end units;
В качестве базовой выбрана фемтосекунда (10-15 с). Диапазон
(1E20) обеспечивает максимальный период времени 100 000 с (27,7
ч). Естественно, диапазон ограничивается длиной слова
инструментальной машины.
Перечислимые типы
Определение.
enumeration_type_definition ::= ( enumeration_literal { ,
enumeration_literal } )
Лексические элементы и типы данных
29
enumeration_literal ::= identifier | character_literal
Примеры перечислимых типов.
type logic_level is (unknown, low, undriven, high);
type alu_function is (disable, pass, add, subtract, multiply,
divide);
type octal_digit is ('0', '1', '2', '3', '4', '5', '6', '7');
Определения некоторых перечислимых типов:
type severity_level is (note, warning, error, failure);
type boolean is (false, true);
type bit is ('0', '1');
Составные типы - это тип "массив" (индексируемый тип) и
тип "запись" (структурный тип).
Массивы
Определение .
array_type_definition ::=
unconstrained_array_definition | constrained_array_definition
unconstrained_array_definition ::=
array ( index_subtype_definition { , index_subtype_definition })
of element_subtype_indication
constrained_array_definition ::=
array index_constraint of element_subtype_indication
index_subtype_definition ::= type_mark range <>
index_constraint ::= ( discrete_range { , discrete_range })
discrete_range ::= discrete_subtype_indication | range
Примеры декларации типа "массив".
type word is array (31 downto 0) of bit;
type memory is array (address) of word;
30
Глава 1. Основные элементы языка VHDL
type transform is array (1 to 4, 1 to 4) of real;
type register_bank is array (byte range 0 to 132) of integer;
Тип BIT_VECTOR определяет массив битов, например
BIT_VECTOR (0 to 7). Тип BIT_VECTOR есть тип массива, который
неявно описывается следующим образом:
type BIT_VECTOR is array (NATURAL range <>) of BIT;
BIT - базовый тип элементов массива, выражение "NATURAL
range" (диапазон натуральный) - это стандартный способ указать,
что длина массива будет задаваться диапазоном натуральных
чисел.
Пользователь должен задавать конкретный диапазон при
применении такого типа, например,
BIT_VECTOR (0 to 3) - возрастающий диапазон,
BIT_VECTOR (7 downto 0) - убывающий диапазон.
Примеры массивов, определяемых пользователем (рис. 1.10).
3
2
1
0
15
0
1
0
1
1022
1023
4094
4095
14
1k × 4
...
...
...
2
signal Mem4k16: array(0 to 4095)
of bit_vector(15 downto 0);
Пример.
Рис.
1.10.
Примеры
пользователем
массивов,
определяемых
signal DataBus: bit_vector (7 downto 0);
0
6
0
5
1
4
0
3
0
4k ×16
signal Mem1k4: array(0 to 1023)
of bit_vector(3 downto 0);
1
7
1
1
2
DataBus = "10010101"
0
1
1
0
номер разряда
Лексические элементы и типы данных
DataBus(7)=’1’
DataBus(6)=’0’
DataBus(5)=’0’
DataBus(4)=’1’
DataBus(3)=’0’
DataBus(2)=’1’
DataBus(1)=’0’
DataBus(0)=’1’
Записи
Определение.
record_type_definition ::=
record
element_declaration
{ element_declaration }
end record
element_declaration ::= identifier_list :
element_subtype_definition ;
identifier_list ::= identifier { , identifier }
element_subtype_definition ::= subtype_indication
Тип "запись" - это составной тип, состоящий из ряда полей.
Примеры декларации типа "запись".
type instruction is
record
op_code : processor_op;
address_mode : mode;
operand1, operand2: integer range 0 to 15;
end record;
type Instr_T is record
Mnemonic:
String;
Code:
Bit_vector (3 downto 0);
ExeCycles:
Integer;
end record;
31
32
Глава 1. Основные элементы языка VHDL
signal Instr1, Instr2, Instr3:
Instr_T;
Примеры сигналов типа Instr_T
Instr1.Mnemonic: "add reg1, reg2"
Instr1. Code:
"0010"
Instr1. ExeCycles:
2
Instr2.Mnemonic: "or reg1, reg2"
Instr2. Code:
"0001"
Instr2. ExeCycles:
1
Instr3.Mnemonic: "null reg1, reg2"
Instr3. Code:
"1110"
Instr3. ExeCycles:
8
Например, тип DATE (дата) можно описать как тип "запись"
следующим образом:
type DATE is
record
DAY: INTEGER range 1 to 31;
MONTH: MONT_NAME;
YEAR:INTEGER range 0 to 3000;
end record;
Здесь MONTH_NAME (имя месяца) - это перечислимый тип,
содержащий имена месяцев. VHDL предусматривает (см. рис. 1.9)
определенные типы файлов (FILE) и типы доступа (ACCSESS). В
данной книге они не рассматриваются.
Декларации
33
Глава 1. Основные элементы языка VHDL
1.3. Декларации
Декларации
Имеются три класса объектов языка VHDL:
• константы;
• сигналы;
• переменные.
С помощью объектов языка VHDL описываются объекты
проекта, т.е. различные подсистемы проектируемой (моделируемой)
цифровой системы. Поэтому, естественно, следует отличать
объекты проекта от объектов языка VHDL
Декларация константы.
Определение.
constant_declaration ::= constant identifier_list :
subtype_indication [ := expression ] ;
В VHDL константы подобны константам в других языках
программирования.
Примеры декларации констант.
constant PERIOD:
time:=100ns;
constant PI:
real:= 3.14159;
constant WIDTH:
integer:=32;
constant DEFAULT: bit_vector(0 to 3):= "0101";
Если символы ":=" следуют после выражения, то выражение
принимает значение объекта.
Если символов ":=" нет в декларации константы, то константа
называется задержанной. Такие константы могут быть в разделе
деклараций пакета. Соответствующая полная декларация
появляется в теле пакета.
Декларация переменной
Определение.
variable_declaration ::=
variable identifier_list : subtype_indication [ := expression
];
34
Глава 1. Основные элементы языка VHDL
Переменная
в
VHDL
подобна
идентификатору,
употребляемому в других языках программирования высокого
уровня. Значение переменной может быть инициализировано и
изменено
немедленно
после
выполнения
предложения,
присваивающего переменной новое значение.
Примеры декларации переменных.
variable ROM, COLUMN:
integer range 0 to 31;
variable COUNT
:
positive :=100;
variable MEMORY :
TWO_DIMENSION (0 to 15, 0 to 31);
Декларация сигнала
Определение.
signal_declaration ::=
signal identifier_list : subtype_indication [ signal_kind ]
[ := expression ] ;
signal_kind ::= register | bus
Концепция сигнала в VHDL является одной из самых важных.
Сигналы
подобны
(соответствуют)
физическим
линиям
(проводникам), которые соединяют элементы схемы. Сигналы и
переменные будут рассмотрены далее.
Примеры декларации сигналов.
signal CLK, RESETn: bit;
signal COUNTER:
integer range 0 to 31;
signal RAM :
TWO_DIMENSIONAL (0 to 15, 0 to 31);
signal INSTRUCTION: bit_vector (15 downto 0);
Декларация компонента
Определение.
component component_name
generic (generic_list);
port (port_list);
end component;
Список портов, начинающийся с ключевого слова port,
определяет имя, направление (режим - mode) и тип каждого порта.
Интерфейс и архитектура объекта
35
Тип порта - это тип сигнала, ассоциированного с данным портом.
Направление порта может быть: in - входной порт, out - выходной,
inout - двунаправленный.
Компоненты декларируются в архитектурном теле прежде
оператора begin. Для примера можно рассмотреть декларацию
компонента add1 в архитектурном теле mult_2.
Ключевое слово generic служит для передачи параметров,
чаще всего таких, как разрядность, число полюсов и других
настраиваемых параметров. Примеры настраиваемых параметров
будут даны позже.
Компонент является частью проекта. Его реализация
осуществляется соответствующим entity и одним либо несколькими
архитектурными телами.
! В entity и декларируемом компоненте должны совпадать
спецификации.
1.4. Интерфейс и архитектура объекта
Интерфейс и архитектура объекта
Понятие entity определяется как "интерфейс объекта проекта".
В entity
описывается интерфейс между объектом проекта и
окружением, в котором употребляется объект. "Внутренность"
объекта в entity не описывается и может быть уподоблена "черному
ящику".
Термин "архитектура" безотносительно к языку VHDL может
быть определен как распределение функций, реализуемых системой,
по отдельным ее уровням и точное определение границ между
этими уровнями.
К термину "архитектура" близок термин "структура",
понимаемый как совокупность элементов системы и связей между
ними.
Архитектура - это структура системы на функциональном
уровне ее описания.
Архитектурное тело (architecture) определяет тело объекта, т.е.
раскрывает внутренность "черного ящика". В архитектурном теле
описываются функции (поведение) либо структура объекта проекта.
В приведенном ниже примере архитектурные тела RTL1, RTL2,
RTL3 задают поведение схемы, представленной на рис. 1.11.
Архитектурные тела, в данном примере это RTL1, RTL2, могут быть
различными, задавая одно и то же поведение.
36
Глава 1. Основные элементы языка VHDL
x1
w
&
x2
1
f
x3
architecture
entity
Рис. 1.11. Комбинационная логическая схема
Пример.
entity ANDOR is
port (x1, x2, x3 :
f
:
end ANDOR;
in bit;
out bit);
architecture RTL1 of ANDOR is
begin
f <= (x1 and x2) or x3;
end RTL1;
architecture RTL2 of ANDOR is
signal w : bit;
begin
w <= x1 and x2;
p1 : process (w, x3)
begin
f <= w or x3;
end process p1;
end RTL2;
Интерфейс и архитектура объекта
37
В entity (в разделе деклараций) наряду с декларацией портов
могут быть декларированы параметры. Для декларации таких
параметров употребляется ключевое слово generic (настраиваемый).
С помощью generic могут передаваться такие параметры, как
ширина (разрядность) шины, число входных либо выходных
полюсов, задержки элементов и т.д.
Пример декларации объекта с настраиваемым (изменяемым)
параметром N.
entity Cate is
generic
(N:
Natural:=4);
port
(Inputs: in bit_vector ( 1 to N);
Result: out bit);
end Cate;
Изменяя параметр N, можно получать объект Cate с
различным числом входов. При этом вносить другие изменения в
VHDL-код нет необходимости.
Пример "минимальной" декларации объекта
entity TestBench is
end TestBench;
В гл.4. будет показано, что минимальная декларация объекта
проекта используется при отладке VHDL-описания.
Пример использования generic для описания объекта Processor
с переменной шириной шины (рис.1.12).
entity Processor is
generic (BusWidth: Integer:=3);
port (DataBus: inout bit_vector (BusWidth -1 downto 0);
. . . );
end Processor
38
Глава 1. Основные элементы языка VHDL
2
1
0
DataBus
a)
BusWidth=3
3
2
1
0
DataBus
б)
Processor
Processor
BusWidth=4
Рис. 1.12. Объект Processor с переменной шириной шины:
а - ширина шины равна 3; б - ширина шины
равна 4
1.5. Предопределенные атрибуты
Предопределенные атрибуты
Атрибуты - это значения, связанные с поименованным
элементом - объектом языка VHDL.
В VHDL имеются предопределенные (predefined) атрибуты и
определенные
пользователем
атрибуты.
Определенные
пользователем атрибуты в данной книге рассматриваться не будут.
Для построения моделей и моделирования важную роль
играют атрибуты сигналов. Например, предопределенный атрибут
event ассоциируется с каким-либо сигналом (например, с сигналом
CLK). Атрибут записывается CLK'event. Этот атрибут имеет тип
BOOLEAN cо значением TRUE, когда значение CLK изменилось.
Атрибут S'last_value (прошлое значение S) - предыдущее
значение, которое сигнал имел непосредственно перед последним
изменением S. Относится к тому же самому типу, что и S. Может
использоваться для того, чтобы проверить, не изменился ли данный
сигнал,
например
оператор
if(S/=S'last_value)
позволяет
контролировать изменение сигнала S.
Атрибут S'stable(T) имеет тип BOOLEAN. Атрибут имеет
истинное значение, если сигнал S стабилен в течение последних
T
39
Предопределенные атрибуты
единиц времени. Если Т=0, атрибут записывается S'stable.
Пример. В табл. 1.4 показано, как изменяются значения
атрибутов ex'transaction, ex'event, ex'last_value при изменении
сигнала ex
ex <= '0' after 2 s,
'1' after 5 s,
'0' after 6 s,
'1' after 8 s;
Таблица 1.4
Атрибут
t=0
false
false
0
0
Ex'transaction
Ex'event
Ex'last_value
Сигнал ex
t=1
false
false
0
0
t=2
true
false
0
0
t=3
false
false
0
0
Время
t=4
t=5
false true
false true
0
0
0
1
t=6
true
true
1
0
t=7
false
false
0
0
t=8
True
True
0
1
Временная диаграмма изменения сигнала ex показана на
рис. 1.13.
Время
0 1 2 3 4 5 6 7 8 9 10
Ex
1
0
Рис. 1.13. Изменение сигнала Ex
Полезный набор атрибутов относится к массивам, типам,
подтипам, например, атрибуты TS'left, TS'right, TS'low, TS'high
возвращают левую, правую, нижнюю
и верхнюю границу
соответственно (табл.1.5).
Пример.
Пусть тип type A_BYTE есть массив бит убывающего
диапазона (7 downto 0). Тогда
A_BYTE'left = A_BYTE'high= 7;
40
Глава 1. Основные элементы языка VHDL
A_BYTE'low = A_BYTE'right= 0;
В случае
type table is array (1 to 8) of bit;
variable array_1 : table := ''00001111'';
значением атрибута array_1'left является 1 - левая граница
возрастающего диапазона.
Атрибут TS'base возвращает базовый тип TS.
Атрибуты A'left(N), A'right(N), A'high(N), A'low(N) (табл.1.5)
ассоциируются с массивом объектов или конструируемым
массивом подтипов. Атрибуты возвращают значение N-го объекта
в массиве. Параметр N является необязательным и по умолчанию
равен 1.
Таблица 1.5
Атрибуты
Атрибут
T'left
T'right
T'low
T'high
T'pos(X)
Результат
Левая граница T
Правая граница T
Нижняя граница T
Верхняя граница T
T'val(N)
Значение позиции N в T
T'leftof(X)
Значение левой от X позиции в T
T'rightof(X)
Значение правой от X позиции в T
T'pred(X)
Значение нижней соседней с X позиции в T
T'succ(X
Значение верхней соседней с X позиции в T
Позиция объекта X в T
Пример.
signal RAM: TWO_DIMENSIONAL (0 to 10, 0 to 15);
Тогда RAM'left(2) = RAM'low(2) = RAM'low = RAM'low(1) =
RAM'left = RAM'left(1) = 0;
Имена
41
RAM'high(1)= RAM'right(1)=10;
RAM'high(2)= RAM'right(2)=15;
Пример. Пусть
Type new_values is (low, high, middle);
Тогда значением атрибута new_values'pred (high) является 'low'.
Пример. Для перечислимого типа new_values покажем VHDLкод, в котором определяются значения атрибутов "крайних"
элементов перечислимого типа.
entity TestAtr1 is
end TestAtr1;
architecture example of TestAtr1 is
type new_values is (a1, b1, a2, b2, a3, b3, w);
signal A : integer;
signal B,D,C,E,F: new_values;
begin
A<= new_values'pos(a1);
B <= new_values'val(4);
C <= new_values'leftof(a1);
D <= new_values'rightof(w);
E <= new_values'pred(b2);
F <= new_values'succ(w);
end example;
В результате моделирования: A = 0; B = 'a3'; C = 1; D = 7; E=
'a2'; F = 7. Обратите внимание на типы.
1.6. Имена
Имена
Имена употребляются для обозначения декларируемых
объектов.
Простые имена являются идентификаторами, такими как
COUNTER, CLK.
Индексированные имена употребляются для обозначения
массива элементов, например, RAM(1,3) и INSTRUCTION(5).
Интервал имен INSTRUCTION(7 downto 0).
42
Глава 1. Основные элементы языка VHDL
Выборка имен используется для выбора полей записи или
считывания, а также для выбора элемента библиотеки.
Пример.
DATE1.MONTH обозначает имя элемента, содержащегося в
поле MONTH записи DATE.
PACK.VDD может относиться к глобальному сигналу VDD в
пакете PACK.
WORK.DESIGN может обозначать объект проекта DESIGN в
библиотеке WORK.
Имена атрибутов могут употребляться для обозначения
предопределенных атрибутов или определенных пользователем
атрибутов.
1.7. Операторы
Операторы
Набор операторов (операций) в VHDL обеспечивает
возможность работы с предусмотренными типами данных.
Список операций приведен в табл. 1.6.
Строки табл. 1.7 располагаются в порядке старшинства (от
низшего к высшему) операторов. Операторы, находящиеся в одной
строке, обладают одинаковым старшинством (приоритетом). Таким
образом, операции нижней строки табл. 1.7 обладают наибольшим
приоритетом и выполняются первыми, в частности, логический
оператор not выполняется прежде других логических операторов.
Исходя из контекста VHDL-кода следует отличать оператор
<= (назначение сигнала) и оператор <= (меньше либо равно).
Следует также отличать унарные операции присвоения знака +, - от
соответствующих бинарных операций сложения и вычитания.
Замечание. Для устранения неоднозначностей трактовки
старшинства операций используются скобки.
Например, выражение "A nand B nand C" неверно
(синтаксическая ошибка). Данное выражение не представляет
трехвходовый элемент И-НЕ (трехвходовую NAND-ячейку).
Правильная запись "not (A and B and C) ". Запись "A nand (B nand C)"
не есть то же самое, что "(A nand B) nand C".
43
Операторы
Таблица 1.6
Операции языка VHDL
Обозначение
Название
not
логическое НЕ
and
логическое И
or
логическое ИЛИ
nand
логическое И-НЕ
nor
логическое ИЛИ-НЕ
xor
исключающее ИЛИ
xnor
эквивалентность (VHDL'93)
=
равно
/=
не равно
<
меньше
<=
меньше либо равно
>
больше
>=
больше либо равно
+
сложение, присвоение знака +
-
вычитание, присвоение знака -
&
конкатенация
*
умножение
/
деление
mod
модуль
rem
остаток
**
возведение в степень
abs
абсолютное значение
44
Глава 1. Основные элементы языка VHDL
Класс операций
Логические
Сравнения
Сложения и
конкатенации
Присвоение
знака
Умножения
Смешанные
Классификация операций
Операции
and or
nand
nor xor
=
+
/=
-
+
-
*
**
/
abs
<
&
<=
mod
not
rem
>
Таблица 1.7
Xnor
(VHDL’93)
>=
Примеры арифметических операторов.
Сложение (+)
RealX2+2.0
1us+3ns
Вычитание (-)
8.33-5
BusWidth-1
-- если RealX2 есть сигнал типа
-- вещественный, то число 2 должно
-- быть записано как вещественное
-- 1003ns
----
неправильно, оба числа должны
быть одного типа
допустимо, если BusWidth типа integer
-----
допустимо, если SomeVal
типа Integer или Time
результат типа Integer либо Real
в зависимости от типа Mult
---
тип CLK - Integer
результат - вещественное число 2.5
Умножение (*)
4*SomeVal
Mult*5ns
Деление (/)
CLK/2
5.0/2.0
45
Операторы
10ns/2ns
--
результат 5 типа Integer, но не Time
----
результат 2
результат -2
результат 2
Модуль (mod)
6 mod 4
6 mod (-4)
(-6) mod 4
Остаток деления (rem)
6 rem 4
6 rem (-4)
(-6) rem 4
----
результат 2
результат 2
результат -2
Экспонента (**)
с*0.5
-A**2
-B**3
--
неправильно в VHDL
эквивалентно A*A
эквивалентно B*B*B
Абсолютное значение (abs)
abs1
-результат 1
abs(-1)
-результат 1
abs(5*(-2))
-результат 10
Следует быть внимательным при переходе от битовых
векторов к числам:
bit_vector (0 to 7);
1
0
0
1
1
2
1
3
1
4
1
5
0
6
0
7
bit_vector (7 downto 0);
1
7
0
6
1
5
1
4
1
3
1
2
0
1
0
0
-- возрастающий
-- диапазон
число 61 (десятичное)
-- убывающий
-- диапазон
число 188 (десятичное)
Логические операторы выполняются для следующих типов
данных:
• boolean;
46
Глава 1. Основные элементы языка VHDL
• bit, bit_vector;
• std_logic, std_logic_vector;
• std_ulogic, std_ulogic_vector.
Логические операторы and, or, nand, nor, xor имеют
одинаковое старшинство и выполняются слева направо в
выражениях. Оператор not имеет более высокое старшинство и
выполняется прежде других операторов. В сложных логических
выражениях порядок выполнения операторов регулируется
скобками.
Рекомендуем
читателю
применять
скобки
в
затруднительных случаях. Например, для выражения
Z <= A and not B or C;
будет только отрицание B, в выражении
Z <= A and not (B or C);
будет отрицание подвыражения B or C, находящегося в скобках.
Операторы сдвига
Данные операторы поясним на примере семиразрядного
битового вектора MyBus.
signal MyBus: bit_vector(7 downto 0) := "01101001";
Логический сдвиг влево (Shift Left Logical)
оператор sll
<
0
1
1
0
1
0
0
1
<
0
начало
1
1
0
1
0
0
1
0
<
0
шаг1
1
0
1
0
0
1
0
0
<
0
шаг2
Логический сдвиг вправо (Shift Right Logical)
47
Операторы
Оператор srl
0
>
0
1
1
>
0
1
0
0
>
0
0
1
1
0
1
0
0
шаг1
0
>
0
0
0
1
1
0
1
0
шаг2
0
1
начало
Арифметический сдвиг влево (Shift Left Arithmetic)
оператор sla
0
1
<
1
0
1
0
0
1
начало
1
1
0
1
0
0
1
1
шаг 1
1
0
1
0
0
1
1
1
шаг 2
Арифметический сдвиг вправо (Shift Right Arithmetic)
оператор sra
>
0
1
1
0
1
0
0
1
начало
0
0
1
1
0
1
0
0
шаг1
0
0
0
1
1
0
1
0
шаг2
Вращение логическое влево (Rotate Left Logical)
48
Глава 1. Основные элементы языка VHDL
Оператор rol
0
1
1
0
1
0
0
1
начало
1
1
0
1
0
0
1
0
шаг 1
1
0
1
0
0
1
0
1
шаг 2
Вращение логическое вправо (Rotate Right Logical)
оператор ror
0
1
1
0
1
0
0
1
начало
1
0
1
1
0
1
0
0
шаг 1
0
1
0
1
1
0
1
0
шаг 2
Оператор конкатенации
Оператор конкатенации обозначается через &.
Пример.
Понятие сигнала в языке VHDL
49
BitOne:bit
1
Data2: bit_vector (0 to 7)
0 0 1 0 1 0 1 0
Data2 (3 to 5)
Data1: bit_vector (0 to 7)
1 0 1 1 0 0 1 0
Data1 (0 to 3)
AggVec:bit_vector(0 to 7)
1 0 1 1 0 1 0 1
AggVec<=(Data1(0 to 3)&Data (3 to 5)&BitOne);
Рис. 1.14. Конкатенация векторов
1.8. Понятие сигнала в языке VHDL
Понятие сигнала в языке VHDL
Логические сигналы в логических схемах передаются и
обрабатываются параллельно.
На схеме показаны три логических блока [1].
Если предположить, что входной набор 1 и входной набор 2
активизируются одновременно, то логические блоки 1, 2 будут
активизироваться также одновременно.
Логический блок 3 будет активизирован, а через блоки 1, 2
могут проходить измененные значения сигналов входного набора 1
и входного набора 2. Таким образом поток сигналов может
проходить через все блоки одновременно.
50
Глава 1. Основные элементы языка VHDL
x1
x2
Логический
блок 1
x3
z1
Логический
блок 3
z2
x2
x4
Логический
блок 2
Рис. 1.15. Логическому блоку схемы соответствует
процесс языка VHDL
Язык описания аппаратуры должен иметь средства для
отображения такой одновременности. В языке VHDL это
требование реализуется при помощи механизма процессов.
Каждый процесс представляет некоторый логический блок
моделируемой схемы, причем все процессы выполняются
параллельно (во времени).
Три параллельных процесса могут быть описаны следующим
образом.
BLOCK1: process(X1,X2,X3)
-- X1,X2,X3 список
-- чувствительности блока 1
begin
-- операторы процесса BLOCK1
end process BLOCK1;
BLOCK2: process(X2,X4)
-- операторы процесса BLOCK2
end process BLOCK2;
BLOCK3: process(Z1,Z2)
-- операторы процесса BLOCK3
end process BLOCK3;
51
Понятие сигнала в языке VHDL
В языке VHDL процесс активизируется, когда происходит
изменение какого-либо сигнала в списке сигналов запуска этого
процесса.
Список сигналов запуска - то же самое, что и список
чувствительности (sensitivity list). В общем случае список сигналов
запуска содержит входной набор сигналов соответствующего
логического блока.
Рассмотрим схему (рис. 1.16).
1
A
B
Y
C
D
&
Рис. 1.16. Сигнал Y, имеющий два
источника
Сигнал У ведет к двум источникам. Каждый источник сигнала
есть драйвер. В каждом процессе сигнал должен иметь только один
источник, иначе требуется специальная функция, которая будет
определять значения сигнала, определяемого из нескольких
драйверов. Подробнее эта проблема будет рассмотрена далее.
Каждый процесс может быть в одном из трех состояний:
• выполняющийся;
• активный;
• приостановленный.
Выполняющийся - когда система моделирования выполняет
процесс.
Активный - когда процесс является ожидающим, чтобы
система моделирования его выполнила.
Приостановленный - когда он не является выполняющимся
или активным.
Большинство ЭВМ, на которых работают системы
моделирования, являются однопроцессорными. Параллелизм
программно имитируется. Поэтому только один процесс из
нескольких параллельных процессов является "выполняющимся" по
существу. Реализация параллельных процессов происходит
следующим образом.
52
Глава 1. Основные элементы языка VHDL
Параллельные процессы, которые надо "одновременно"
выполнять, выстраиваются в очередь. Система моделирования
выбирает процесс из очереди активных процессов и выполняет
процесс, тем самым исполняет предложения языка VHDL,
относящиеся к данному процессу. Другие активные процессы
выбираются поочередно. Заметим, что выполненный процесс
является приостановленным. Когда очередь активных процессов
пуста, считается, что все параллельные процессы выполнились
"одновременно",
и
может
начаться
следующий
цикл
моделирования.
Приостановленный
процесс
может
стать
активным, когда изменился хотя бы один из драйверов сигналов из
списка чувствительности этого процесса.
Рассмотрим простую двухуровневую логическую схему
(см. рис. 1.11) и ее описание в языке VHDL в виде параллельных
процессов.
entity ANDOR is
port( x1, x2, x3 :
f:
end ANDOR;
in bit;
out bit);
architecture example of ANDOR is
signal w : bit;
begin
p0 : w <= x1 and x2 after 10 ns;
p1 : process (w, x3)
begin
f <= w or x3 after 20 ns;
end process p1;
end example;
Во время фазы инициализации каждый сигнал из множества
{x1,x2,x3} имеет значение 0. Процесс p0 вычислит w и
приостановится. Затем вычисляется значение f через 30ns, так как
10ns выполняется процесс p0 и 20ns - процесс p1. Цикл
моделирования начинается, когда
один из сигналов изменится.
Временная диаграмма изображена на рис. 1.17. Заметим, что
если сигнал x1 при декларации не имеет начального значения, то по
умолчанию он принимает значение левой границы
(x1'left)
декларируемого типа. Например,
53
Дельта-задержка
signal I : integer range 0 to 3;
-- при инициализации значение
0;
signal X : std_logic;
10 20
x1
-- при инициализации значение 'U'.
50
80
100 110
1
0
1
0
1
x3
0
x2
w
1
0
f
1
0
Рис. 1.17. Моделирование схемы ANDOR
1.9. Дельта-задержка
Дельта-задержка
Изменим архитектурное тело example для entity ANDOR,
удалив ключевые слова after и конкретные временные задержки тем самым логические операции and, or будут срабатывать
"мгновенно".
architecture DELTA of ANDOR is
signal w:bit;
begin
p0:
w<= x1 and x2; -- нет слова after
p1:
process(w, x3)
begin
f<=w or x3;
- - нет слова after
end process p1;
end DELTA;
54
Глава 1. Основные элементы языка VHDL
Рассмотрим временную диаграмму (рис. 1.18).
50
x1
80
100
1
0
1
0
1
x3
0
x2
w
1
0
f
1
0
Рис. 1.18. Временная диаграмма (architecture DELTA)
В 80ns входной сигнал x2 изменился, что послужило причиной
изменения сигнала w и причиной изменения сигнала f. Эта ситуация
очерчена лупой на временной диаграмме (рис.1.18). Все это
случилось точно в то же время. Рассмотрим более подробно, что же
произошло в момент времени 80 ns.
В 80ns входной сигнал x2 изменяется. Начинается цикл
моделирования. Активизируется процесс p0, выполняется,
приостанавливается. Сигнал w изменяется в 0. Резонно сказать, что
сигнал w изменился после сигнала x2. Мы будем ссылаться на это
время как на время дельта, или дельта-задержку (рис.1.19).
55
Дельта-задержка
80ns
x1
1
0
x2
1
0
x3
1
0
w
1
0
f
1
0
Дельта
Рис. 1.19. Временная диаграмма, иллюстрирующая
понятие "дельта-задержка"
Изменение сигнала w служит причиной для процесса p1,
который активизируется, выполняется, приостанавливается.
Сигнал f изменяется после изменения сигнала w. Появляется
другая дельта-задержка.
Понятие
дельта-задержки
есть
основное
понятие
моделирования в языке VHDL.
В одно и то же время (физическое) много сигналов могут
изменяться и много процессов могут быть активными.
После того как все процессы пришли в состояние
"приостановленный", система моделирования увеличивает время
моделирования.
Итак, ответом на вопрос "Что представляет собой
дельта-задержка, или просто дельта?" является следующее:
! Дельта есть один цикл прогона VHDL-модели.
VHDL-модель, имитирующая поведение цифровой системы,
состоит из множества процессов. Во время прогона модели в
данном цикле запускаются все процессы, входные параметры
которых изменились с момента выполнения последнего цикла.
После того как все процессы выполнены, данный цикл
моделирования считается завершенным. Следующий цикл начнется
после того, как в очередной раз произойдет изменение какого-то
входного сигнала для какого-то процесса. Этот период может
56
Глава 1. Основные элементы языка VHDL
составлять наносекунды времени моделирования или может просто
означать, что мы перешли на следующий цикл моделирования, т.е.
сделали временной шаг дельта.
Шаг величиной дельта образуется, например, при
выполнении операторов назначения сигналов (в рассмотренном
примере это сигналы w, f), не имеющих фразы after.
С точки зрения логической схемы дельта - это задержка на
одном уровне-каскаде логики, когда не задана конкретная задержка
логического элемента.
Параллельные выполнения операторов (назначение сигналов)
указываются при помощи символов <=. Символы := означают
процедурное выполнение и называются операторами присваивания
значения переменной.
Требует ответа еще один важный вопрос: "Где в описаниях на
языке VHDL могут быть использованы операторы присваивания
значений переменным и операторы назначения сигналов?"
Ответ: "Операторы присваивания значений переменным
разрешается использовать внутри процессов и в подпрограммах
(функциях или процедурах)".
Оператор назначения сигналов может встречаться в любом
месте выполняемого раздела архитектурного тела.
! Однако можно определять только по одному драйверу на
сигнал в процессе.
Природа
оператора
назначения
сигнала, оператора
присваивания переменной и блоков процессов дает разработчику
VHDL-моделей ряд возможностей выбора [1].
В начале проектирования разработчик может использовать
блок процесса, алгоритм которого реализуется при помощи
операторов присваивания значений переменным, а последний
оператор блока есть оператор назначения сигнала, вычисляющий
выходной сигнал блока. Такой подход применяется на этапе
алгоритмического проектирования, не ориентируясь на какую-то
конкретную схему. Другой подход заключается в том, чтобы
использовать операторы назначения сигналов. Этот подход
называется иногда реализацией "потока данных" (data flow), он
ориентирован на конкретную схему и более целесообразен на этапе
логического проектирования.
57
Упражнения
УПРАЖНЕНИЯ
Упражнения
1. Что такое язык VHDL?
2. Для чего предназначен язык VHDL? Выберите правильный
ответ.
a) только для проектирования заказных СБИС;
b)
только
для
проектирования
программируемых
пользователями вентильных матриц;
c) для спецификации аппаратурной части проектируемой
цифровой системы;
d) для спецификации системы перед разбиением ее на
аппаратную и программную части;
e) для всех случаев a - d.
3. Что такое VHDL-описание, VHDL-код?
4. Что такое проект, лист проекта, примитив проекта?
5. Что такое иерархия проекта?
6. Что такое высокоуровневый синтез?
7. Что такое логический синтез?
8. Что такое структура схемы, функция схемы, поведение
схемы?
9. Что такое IEEE?
10. Что такое VHDL-компилятор, VHDL-анализатор, система
моделирования VHDL-кода?
11. Опишите технологию проектирования цифровых систем с
использованием VHDL.
12. Можно ли на языке VHDL написать программу
нахождения факториала натурального числа?
13. Что такое "синтезируемое подмножество" языка VHDL?
14. Правильно ли утверждение: "VHDL имеет много
возможностей для моделирования аналоговых схем" ?
15. Когда были приняты стандарты языка VHDL?
16. Используя примитивы or2, and2, inv, составьте VHDL-код
объекта add1.
17. Какие из следующих операторов являются неправильными
и почему?
58
Глава 1. Основные элементы языка VHDL
А_А, А_, 9U, A%B, P8_3, e4, wait, in, OU_T
18. Какие из следующих литералов являются неправильными
и почему?
12_ _000, 1E-0, 2#1101#, 5#44#, #3#, 16# F#E3
19. Какие из следующих литералов c плавающей точкой
являются неправильными и почему?
1_ 0.00, 100_.0, 1.1Е-2, 2Н#10.11#, 16 #F #E2, 1_0.0.
20. Какие из следующих литералов типа "строка бит"
являются неправильными и почему?
2''110'', В ''1101'', О''047'', Н''ABcd'', 10''99'', ''0101''
21. Укажите правильные и неправильные идентификаторы
a) Decoder_1
b) _Decoder_1
c) 2FFT
d) sig_N
e) Not_Ack
f) Not-Ask
g) Sig_#N
h) FFT
22. Найдите ошибки в следующем VHDL-коде:
entity EXP is
end EXP;
architecture RTL of EXP is
signal A, B, C, D, E, F : bit;
signal X, Y, Z, S, T, R : bit;
begin
R <= A and B and C;
S <= B or C or D;
T <= A and B or D;
Y <= C nor E nor F;
X <= A and not B and not C;
Z <= F nand E nand B;
end RTL;
Исправьте их, проверьте результат с помощью VHDLанализатора.
23. Правильно ли утверждение: "Комментарий в языке VHDL
начинается и оканчивается двумя дефисами "?
Упражнения
59
24. Для каждого из утверждений ответьте, является оно
правильным или ложным:
a) все элементы массива должны быть одного и того же типа;
b) значение true типа boolean эквивалентно значению 0 типа
bit;
c) константы могут употребляться в выражениях.
25. Как специфицируются скалярные типы? Выберите
правиль-ный ответ:
a) употребляя только понятие диапазона значений;
b) употребляя только понятие перечисления элементов;
c) употребляя а) и b) одновременно.
26. Какой
тип
данных,
возвращаемых
операторами
сравнения?
27. Правильно ли, что в языке VHDL разрешено умножение
вещественного числа на целое? А если один из операндов имеет тип
time?
28. Какой из трех операторов отличается от двух других?
a) Z <= not X and not Y;
b) Z <= not (X and Y);
c) Z <= not X and Y;
29. Правильно ли утверждение: "Константе может быть
присвоено новое значение, если оно эквивалентно предыдущему
значению"?
30. Правильно
ли
утверждение:
"Когда
константа
декларируется, то достаточно специфицировать ее значение,
потому что тип константы косвенным образом определяется через
ее значение"?
31. Правильно ли, что логические операторы могут
употребляться только для типа bit ?
32. Как определяются арифметические операции для типа bit?
Правильно ли, что операторы всегда определяются для отдельных
(конкретных) типов данных языка VHDL ?
33. Можно ли в языке VHDL узнать (проверить) предыдущее
значение сигнала, предыдущее значение переменной ? Если "да", то
как это делается ?
34. Задан фрагмент VHDL-кода.
Variable TIME1, TIME2 : time;
a) TIME1 := TIME2 * 2,5;
b) TIME1:= TIME2/4;
60
Глава 1. Основные элементы языка VHDL
c) TIME1:= 3.6 ns + TIME2;
d) TIME1:= TIME2 * 6.62 ns;
Укажите правильные и неправильные строки.
35. Что такое сигнал в языке VHDL? Чему соответствует
сигнал в логической схеме?
36. Чем сигнал отличается от переменной? Как записывается
оператор присвоения значения переменной?
37. Что такое параллельный процесс?
38. В каких состояниях бывают параллельные процессы?
39. Что такое дельта-задержка?
40. В каких разделах VHDL-кода может встретиться:
- оператор назначения сигнала;
- оператор присвоения значения переменной?
41. В какой части VHDL-кода необходимо указывать тип
сигнала, который декларируется? Выберите правильный ответ:
a) когда сигнал декларируется;
b) когда сигнал употребляется первый раз в коде;
c) в пакете;
d) нет необходимости декларировать тип сигнала.
42. Когда (с точки зрения взаимодействия процессов) сигнал
корректируется, т.е. получает то новое значение, которое
приобретет в результате операции назначения сигнала,
находящейся внутри процесса?
43. Промоделируйте "вручную" параллельные процессы
A<=X∗Y;
B<=A+Z;
используя понятие дельта-задержки. Запишите VHDL-код и
промоделируйте его с помощью системы моделирования.
44. Рассмотрите рис. 1.20. Назовите внешние и внутренние
сигналы системы A. Ответьте, где декларируются внешние сигналы
системы A, где декларируются внутренние сигналы системы A.
Укажите интерфейсы для системы А и для подсистем B, C, D.
45. Рассмотрите систему, состоящую из телевизора и
переносного
кнопочного
пульта,
с
помощью
которого
осуществляется
управление телевизором. Укажите entity и
architecture для данной системы.
61
Упражнения
A
TL1
TL2
TL7
TL4
B
TL9
TL5
D
C
TL6
TL8
TL3
Рис. 1.20. Структура цифровой системы A
46. Рассмотрите персональный компьютер, как систему,
состоящую из системного блока, монитора и клавиатуры. Укажите
entity и architecture для данной системы.
62
Глава 2. Последовательные и параллельные операторы
Глава 2
Последовательные и параллельные операторы
Глава 2. Последовательные и параллельные операторы
2.1. Последовательные операторы
Последовательные операторы
В VHDL последовательные операторы подобны операторам
языков высокого уровня. На рис. 2.1 приведена общая структура
VHDL-описания, из которой следует, что
последовательные
операторы (sequential statement) могут появляться внутри
операторов процесса или внутри тел подпрограмм (функций,
процедур).
На данном рисунке указаны основные параллельные и
последовательные операторы.
Перечислим последовательные операторы:
1) оператор variable assignment (присвоения значения
переменной);
2) оператор signal assignment (назначения сигнала, т.е.
присвое-ния значения сигналу);
3) оператор if (если);
4) оператор case (случай);
5) оператор loop (цикл);
6) оператор next (следующий);
7) оператор exit (выход);
8) оператор null (нуль, пустой);
9) оператор procedure call (вызова процедуры);
10) оператор return (возврат);
11) оператор assertion (сообщение);
12) оператор wait (ожидать).
Оператор присваивания значения переменной
Определение.
variable_assignment_statement::=target:=expression;
63
Последовательные операторы
Данный оператор заменяет текущее значение переменной
новым значением, которое определяется выражением. Переменная
и выражение должны быть того же базового типа.
Package (optional)
Entity (I/O)
Architecture
Concurrent statements
Signal declaration
Component instantiation statement
Conditional signal assignment statement
Selected signal assignment statement
Generate statement
Process statement
Sequential statement
Variable declaration
Signal assignment
Variable assignment
Procedure call
If, case, loop, next, exit, return
Wait statement
Рис. 2.1. Структура VHDL-описания
Еще раз напомним, что присваивание значения переменным
не есть то же самое, что сигналам. Присваивание значений
сигналам мы обсудим в следующем разделе.
В VHDL локальные переменные могут быть только
декларированы в области операторов процессов и подпрограмм
(функций или процедур).
64
Глава 2. Последовательные и параллельные операторы
В следующем VHDL-коде приведены примеры присваивания
значений переменным. Слева указаны номера строк, не
относящиеся к тексту на языке VHDL.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
entity VAR is
end VAR;
architecture functional of VAR is
signal A, B, J : bit_vector(1 downto 0);
signal E, F, G : bit;
begin
p0 : process (A, B, E, F, G, J)
variable C, D, H, Y : bit_vector(1 downto 0);
variable W, Q
: bit_vector(3 downto 0);
variable Z
: bit_vector(0 to 7);
variable X
: bit;
variable DATA : bit_vector(31 downto 0);
begin
C
:= "11";
X
:= E and F;
Y
:= H nand J;
Z(0 to 3) := C & D;
-- конкатенация
Z(4 to 7) := (not A) & (A nor B); -- конкатенация
D
:= ('0', '0');
-- агрегат
W := (2 downto 1 => G, 3 => '1', others => '0'); -- агрегат
DATA
:= (others => '1');
-- агрегат
end process;
end functional;
В строке 15 переменная C получает константное значение.
Выражения в строке 16, 17 используют логические операторы.
В строке 18 в выражении употребляется оператор &
конкатенации, чтобы присвоить значения первым четырем битам
переменной Z.
В строке 19 употреблена комбинация логических операторов
и конкатенация.
Строка 20 показывает агрегат, в котором употребляется
позиционное отображение.
В строке 21 употребляется позиционное отображение и
ключевое слово others.
Последовательные операторы
65
В строке 22 всем компонентам битового вектора - переменной
DATA - присваивается значение нуль.
Заметим, что локальные переменные "видны" только внутри
процессов или подпрограмм, которые декларированы. VHDL‘93
определяет другой класс переменных, называемых shared
(совместно используемые, общие), которые могут совместно
использоваться (видны) с процессами и подпрограммами. Понятие
"видимости" будет рассмотрено далее.
Агрегаты и конкатенация могут использоваться не только при
присвоении значений переменным, но и при назначении сигналов
для таких типов данных, как массивы. Рассмотрим пример
агрегата.
Variable z_bus
: bit_vector (3 downto 0 );
Variable A,B,C,D : bit;
z_bus := (A,B,C,D);
-- агрегат
Запись (A,B,C,D) называется агрегатом. Агрегат заключается
в круглые скобки, входящие в агрегат элементы разделяются
запятой.
Присваивание значений сигналам (назначение сигналов)
Определение.
signal_assignment_statement::=
target <=[transport] waveform_element
{, waveform_element};
waveform_element::=
value_expression[after time_expression] |
null [after time_expression]
Ключевое слово transport определяет транспортную задержку.
В языке VHDL в операторах назначения сигналов используются
два вида задержек:
• инерционная задержка;
• транспортная задержка;
Пример.
X<=Y after 3 ns;
-- инерционная задержка,
X<= transport Y after 3ns;
-- транспортная задержка.
В случае инерционной задержки передача сигнала будет иметь
место, если и только если входной сигнал будет сохранять
66
Глава 2. Последовательные и параллельные операторы
соответствующий уровень в течение заданного отрезка времени. В
языке VHDL этот заданный отрезок времени и есть задержка,
указываемая во фразе after.
Таким образом, в первом примере изменение значения Y
подействует на значение X только в случае, если новый уровень Y
будет сохраняться в течение 3ns и более.
Во втором примере (транспортная задержка) все изменения Y
будут передаваться в X независимо от того, сколько времени будет
сохраняться новое значение Y.
! Если не используется ключевое слово transport, то
подразумевается инерционная задержка.
Как отмечено в [1], механизм инерционной задержки
позволяет отфильтровывать входные сигналы, которые меняются
слишком быстро. Данный механизм по существу имитирует работу
реальной схемы. Логический сигнал представляется на схемном
уровне напряжением узла. Ввиду наличия электрических емкостей
напряжения узлов не могут изменяться мгновенно, необходимо,
чтобы определенное качество энергии подавалось в течение
определенного отрезка времени, - только в этом случае напряжение
узла изменится настолько, чтобы вызвать переключение схемы,
управляемой этим напряжением. Поэтому при моделировании
реальных логических схем используется инерционная задержка.
Транспортная задержка чаще используется на этапе
алгоритмического проектирования.
Укажем различия между локальными переменными и
сигналами.
1. Локальные переменные декларируются и видны только
внутри процесса или подпрограммы. Сигналы не могут быть
декларированы внутри процесса или подпрограммы.
2. Новое значение локальной переменной немедленно
корректируется, когда выполняется оператор присваивания.
Понятие времени не ассоциируется с понятием переменной.
Оператор назначения сигнала корректирует сначала драйвер
сигнала. Когда процесс станет приостановленным, сигнал
корректируется. Поэтому использование сигналов ведет к
двухпроходному моделированию. С точки зрения системы
моделирования переменные применять "дешевле".
3. Только сигналы могут употребляться для связывания
параллельных операторов.
! Порты, декларируемые в entity, являются сигналами.
Аргументы подпрограмм могут быть сигналами или переменными.
67
Последовательные операторы
4. В VHDL-описаниях логических (цифровых) схем сигнал
употребляется для описания соединений элементов. Локальные
переменные обычно употребляются как временные значения в
алгоритме описания функции.
Пример. ( Различие между локальной переменной и сигналом).
Данный VHDL-код
Y<= A+(B*C+D*E*F+G);
Z<= A-(B*C+D*E*F+G);
эквивалентен следующему VHDL-коду
V:=(B*C+D*E*F+G);
Y<= A+V;
Y<= A- Y;
однако не эквивалентен приведенному ниже VHDL-коду
V<=(B*C+D*E*F+G);
Y<= A+V;
Z<= A - Y;
Замечание.
Запись
x <= y <= z
понимается
не
как
"конвейерное" назначение сигналов. Правильное понимание:
сигналу x присваивается значение, равное значению выражения
y<=z (у меньше либо равно z).
Назначение сигналов в случае массивов, например битовых
векторов, является позиционным.
Пример.
Signal z_bus : bit_vector (3 downto 0);
Signal c_bus : bit_vector (1 to 4);
z_bus <= c_bus;
эквивалентно
z_bus(3) <=c_bus(1);
z_bus(2) <=c_bus(2);
z_bus(1) <=c_bus(3);
z_bus(0) <=c_bus(4);
При назначении сигналов должно указываться то
направление диапазона (возрастающий диапазон - to, убывающий
диапазон - downto), которое было при декларации массива.
Для предыдущего примера
68
Глава 2. Последовательные и параллельные операторы
z_bus (3 downto 2) <= ''00''; -- правильно
c_bus (2 to 4) <= z_bus (3 downto 1); -- правильно
z_bus (0 to 1) <= ''11''; -неправильно, так как z_bus
декларирован
-- с убывающим диапазоном
Сигналы и переменные одного и того же типа могут быть
присвоены один другому.
Пример использования агрегатов при назначении сигналов.
Signal z_bus : bit_vector (3 downto 0 );
Signal A,B,C,D : bit;
z_bus <= (3 => '1', 1 downto 0 => '1', 2 => B); --
агрегат
Оператор if (если)
Определение.
if_statement::=if condition then
sequence of sequential statements
{elsif condition then
sequence of sequential statements}
[else
sequence of sequential statements]
end if;
Оператор if языка VHDL подобен операторам if в других
языках программирования.
Выражение условия (condition) должно иметь тип BOOLEAN.
В одном if операторе может быть одна (ни одной) либо более частей
elsif. Ключевое слово elsif следует отличать от слов else if. Часть else
может быть только одна (или ни одной). Должен быть разделитель
между ключевыми словами в заключительной фразе end if;
Следующая модель 5-битового счетчика употребляет if
операторы [9].
entity IFSTMT is
port (
RSTn, CLK, EN, PL : in bit;
DATA
: in integer range 0 to 31;
COUNT
: out integer range 0 to 31);
Последовательные операторы
69
end IFSTMT;
architecture RTL of IFSTMT is
signal COUNT_VALUE : integer range 0 to 31;
begin
p0 : process (RSTn, CLK)
begin
if (RSTn = '0') then
COUNT_VALUE <= 0;
elsif (CLK'event and CLK = '1') then
if (PL = '1') then
COUNT_VALUE <= DATA;
elsif (EN = '1') then
if (COUNT_VALUE = 31) then
COUNT_VALUE <= 0;
else
COUNT_VALUE <= COUNT_VALUE + 1;
end if;
end if;
end if;
end process;
COUNT <= COUNT_VALUE;
end RTL;
Как показано в разделе деклараций, 5-битовый счетчик имеет
порты RSTn, CLK, EN, PL, DATA. Выходной порт COUNT получает
значение счетчика, RSTn - асинхронная установка (в нуль), CLK входной сигнал синхронизации, PL - параллельное считывание,
DATA - порт данных.
Оператор case (случай)
Определение.
case_statement ::=
case expression is
when choice => sequence of sequential statements
[when choice => sequence of sequential statements]
end case;
Оператор case выбирает одну из альтернатив, избранная
альтернатива (случай) определяется значением выражения.
Выражение (expression) должно быть дискретного типа или типа
70
Глава 2. Последовательные и параллельные операторы
одноразмерного массива символов, значения которых могут быть
представлены как строки или строка битов. Выбор (choice) должен
быть такого же типа, как выражение. Все возможные выборы
(случаи) должны быть покрыты. Выбор "others" (другие) должен
быть покрыт значением, не покрываемым предыдущими
альтернативами.
Оператор case является подходящим для моделирования
конечных автоматов и программ микропроцессора. Используя
оператор case, приведем пример [9] VHDL-кода для вычисления
числа дней в каждом месяце.
package PACK is
type month_type is (JAN, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC);
end PACK;
use work.PACK.all;
entity CASESTMT is
port (
MONTH : in month_type;
LEAP : in boolean;
DAYS : out integer);
end CASESTMT;
architecture RTL of CASESTMT is
begin
p0 : process (LEAP, MONTH)
begin
case MONTH is
when FEB =>
if LEAP then
DAYS <= 29;
else
DAYS <= 28;
end if;
when APR | JUN | SEP | NOV =>
DAYS <= 30;
when JUL to AUG =>
DAYS <= 31;
when others =>
DAYS <= 31;
Последовательные операторы
71
end case;
end process;
end RTL;
Оператор loop (оператор цикла)
Определение.
loop_statement::=
[loop_label:][while condition |
for identifier in discrete_range]
loop sequence of sequential statements
end loop [loop_label];
Когда в записи цикла используется ключевое слово while, то
сначала вычисляется условие (condition). Если условие есть TRUE,
выполняется последовательность последовательных операторов,
иначе оператор цикла завершается.
Когда в записи цикла используется ключевое слово for, то
идентификатор (identifier) определяет цикловой параметр с базовым
дискретным типом. Параметр цикла употребляется как константа
внутри действия оператора цикла и он не может быть целью
оператора присваивания.
! Общая ошибка: употребление параметра цикла снаружи
оператора цикла.
Пример.
loop1: for i in 0 to 9 loop
exit loop1 when A(i)>20;
next when A(i)>10;
sum:=sum +A(i);
end loop loop1;
if i=20 then
-- ошибка! Параметр цикла снаружи цикла.
Оператор NEXT
Определение.
next _statement::=next [loop_label][when condition];
72
Глава 2. Последовательные и параллельные операторы
Пример дан выше. Оператор
завершения итераций цикла.
next
употребляется
для
Оператор EXIT
Определение.
exit_statement::=extit[loop_label][when condition];
Оператор EXIT употребляется, чтобы завершить выполнение
и закрыть оператор цикла. Если условие (condition) есть TRUE, то
осуществляется выход из цикла.
Оператор null
Определение.
null_statement::=null;
Оператор null не представляет действий. Он употребляется,
чтобы точно специфицировать, что нет действий. Типичное
применение - в операторе case, чтобы определить действия во всех
случаях.
Оператор вызова процедуры
Оператор вызова процедуры состоит из имени процедуры с
аргументами (если они есть) в скобках. Приведем пример
определения и вызова функции и процедуры.
entity CALL_PRO is
end CALL_PRO;
architecture RTL of CALL_PRO is
function bit_bool (inp_bit : in bit) return boolean is
begin
if (inp_bit = '1') then
return true;
else
return false;
end if;
end bit_bool;
procedure left_one (
Последовательные операторы
73
signal DATA : in bit_vector (1 to 8);
signal l_bit : out integer) is
variable temp : integer;
begin
temp := 0;
for i in 1 to 8 loop
if (DATA(i) = '1') then
temp := i;
end if;
if (temp /= 0) then exit;
end if;
end loop;
l_bit <= temp;
end left_one;
signal DIN : bit_vector (1 to 8);
signal bit_1 : bit;
signal bool_1 : boolean;
signal DOUT : integer;
begin
p0: process (bit_1,DIN)
begin
bool_1 <= bit_bool(bit_1);
-- вызов функции
LEFT_ONE(DIN, DOUT); -- вызов процедуры
end process;
p1: process
begin
bit_1 <= '1' after 20 ns, '0' after 40 ns;
DIN <= "01010000" after 20 ns,
"00000000" after 40 ns,
"00001100" after 60 ns,
"00000001" after 80 ns;
wait for 100 ns;
end process;
end RTL;
Функция bit_bool преобразует тип BIT в тип BOOLEAN.
Предлагаем читателю провести моделирование, проанализировать
временную диаграмму и определить функциональное назначение
процедуры left_one.
74
Глава 2. Последовательные и параллельные операторы
Оператор return
Определение.
return_statement::=return[expression];
Употребляется, чтобы завершить выполнение самой
внутренней функции или процедуры. Он используется только
внутри тела функции или процедуры. Оператор return не требуется
в теле процедуры, поэтому в архитектурном теле RTL (entity
RETURNSTMT) соответствующая строка может быть удалена.
Оператор
return
может
быть
употреблен
с
другими
последовательными операторами, такими как if, case для
управления возвратом функции или процедуры.
Оператор сообщений (assertion)
Определение.
assertion_statement::=assert condition
[report expression ]
[severity expression ];
Операторы сообщений проверяют, является ли условие
истинным (TRUE), и сообщают об ошибке, если условие является
ложным. По умолчанию сообщенное выражение есть "Assertion
violation" (нарушение). Выражение с ключевым словом severity
(severity - степень серьезности) имеет перечислимый тип: NOTE,
WARNING, ERROR, FAILURE.
Примеры.
assert (CLK'event and CLK='0') report "D hold error" severity
WARNING;
assert (CLK'last_event > HOLD) report "D hold error" severity
ERROR;
В данных примерах атрибут CLK'last_event имеет тип TIME и
возвращает время, пройденное с момента последнего изменения
сигнала
CLK,
HOLD
имеет
тип
TIME.
Условие
CLK'last_event>HOLD может быть либо истинным, либо ложным.
Последовательные операторы
75
Оператор wait (ждать)
Оператор wait является причиной временного прекращения
оператора процесса или процедуры.
Определение.
wait _statement::= wait [sensitivity_clause]
[condition_clause];
[timeout_clause];
sensitivity_clause::=
on sensitivity_list
condition_clause::=
until boolean_expression
timeout_clause ::=
for time_expression
Sensitivity_list - список чувствительности (список сигналов
запуска).
В цифровых системах логические процессы часто
приостанавливаются в своем выполнении, ожидая истечения
некоторого периода времени или наступления некоторого события.
После истечения указанного периода времени или наступления
ожидаемого события выполнение процесса возобновляется. Эта
ситуация иллюстрируется следующим образом
process ----------------------------------------------wait
------------------------------------------end process;
-- начало выполнения процесса
-- оператор ожидания
-- возобновление выполнения процесса
-- конец выполнения процесса
Общий вид оператора ожидания
wait on sensitivity_list until condition clause for timeout;
76
Глава 2. Последовательные и параллельные операторы
Оператор wait приостанавливает процесс до момента, пока не
изменится некоторый сигнал в списке чувствительности процесса
(sensitivity_list), в это время будет произведено вычисление условия
(condition). Фраза условия есть выражение типа BOOLEAN. Если
получается
истинное
значение,
выполнение
процесса
возобновляется.
Фраза
тайм-аута
(timeout)
устанавливает
максимальное время ожидания, после которого процесс возобновит
свое выполнение.
Пример.
WAIT on A, B until (C=0) for 50 ns;
Этот оператор приостановит процесс до момента изменения
A или B, после чего будет проверено выражение C=0 и, если
результатом проверки будет истина, процесс возобновится. Но
независимо от этих условий возобновление процесса произойдет
через 50ns.
Допустимо записывать одно или более условий в операторе
ожидания, например,
Условие 1.
Условие 2.
Условие 3.
WAIT on A, B;
WAIT until (C=0);
WAIT for 50 ns;
В условии 1 процесс будет возобновляться, когда изменится A
или B.
В условии 2 нет списка сигналов запуска, поэтому процесс
возобновится, когда C изменит свое значение из 1 в 0.
В условии 3 процесс возобновится через 50ns независимо от
любых других условий.
! Для оператора процесса мы можем иметь либо список
чувствительности после ключевого слова процесс, либо оператор
wait, но не оба вместе. Может быть более одного оператора wait
внутри оператора процесса.
Примеры оператора wait.
1. Оператор wait типа for
wait for 10ns;
wait for CLK_Period/2;
77
Последовательные операторы
2. Оператор wait типа until
wait until CLK='1';
wait until CE and (not RST);
wait until IntData>16;
3. Оператор wait типа on
wait on CLK;
wait on Enable, Data;
wait until Enable ='1';
эквивалентн
о
loop
wait on Enable;
exit when Enable = '1';
end loop;
4. Комбинированный оператор wait (комбинация двух или
трех предыдущих)
wait on Data until CLK='1';
wait until CLK='1' for 10ns;
78
Глава 2. Последовательные и параллельные операторы
2.2. Параллельные операторы
Глава 2. Последовательные и параллельные операторы
Параллельные операторы
Параллельные операторы (табл. 2.1) в VHDL определяют
параллельное (во времени) поведение схем.
! Порядок выполнения параллельных операторов не связан с
порядком их появления внутри архитектурного тела.
Параллельные операторы активизируются сигналами,
которые употребляются для связи параллельных операторов.
Последовательные операторы выполняются в порядке их появления
в VHDL-коде.
Таблица 2.1.
Параллельные операторы
Оператор процесса
process statement
Оператор
assert statement
параллельного
сообщения
Оператор
procedure call statement
параллельного
вызова процедуры
Условное назначение
conditional signal
сигнала
assignment statement
Выборочное
selected signal
назначение сигнала
assignment statement
Оператор
component instantiation
конкретизации
statement
(создания экземпляра)
компонента
Оператор генерации
generate statement
Оператор блока
block statement
Параллельный оператор процесса
(process statement)
Определение.
process_statement::= [process_label] process
[sensitivity_list]
process_declaration_part
begin
sequence of sequential statements
79
Параллельные операторы
end process [process_label];
Оператор процесса есть параллельный оператор, который
определяет независимое последовательное поведение некоторой
части проекта, описанное упорядоченной совокупностью
последовательных операторов.
Метка процесса необязательна, однако если она есть в конце
(после слов end process), то она должна быть и вначале перед
словом process.
В декларативной части процесса могут быть:
• тела подпрограмм;
• декларации подтипов;
• декларация констант;
• декларация файлов;
• декларация альтернативных точек входа в подпрограмму;
• декларация атрибутов;
• спецификации атрибутов.
Процесс может иметь список сигналов запуска и один (или
более) операторов ожидания, но не оба вместе.
! Сигналы не могут быть декларированы внутри процессов.
Структура процесса имеет вид
имя_процесса: process(список чувствительности)
декларации
begin
последовательные операторы
end process имя_процесса;
!
Ожидание (wait) в начале процесса не эквивалентно
ожиданию в списке чувствительности процесса.
process(signal_1)
statement_1;
statement_2;
...
statement_n;
end process;
эквивалентно
process
statement_1;
statement_2;
...
statement_n;
wait on signal_1;
end process;
80
Глава 2. Последовательные и параллельные операторы
process(signal_1)
statement_1;
statement_2;
...
statement_n;
end process;
не
эквивалентно
process
wait on signal_1;
statement_1;
statement_2;
...
statement_n;
end process;
Оператор параллельного сообщения
(assert statement)
Синтаксис оператора параллельного сообщения такой же, как и
у оператора последовательного сообщения.
"Параллельность" заключается в том, что оператор assert
может присутствовать в параллельных процессах.
Оператор параллельного вызова процедуры
(procedure call statement)
Определение.
concurrent_procedure_call::= [label] procedure_call_statement
Оператор параллельного вызова процедуры представляет
процесс, содержащий оператор последовательного вызова
процедуры. Его выполнение эквивалентно оператору процесса.
Пример.
1 entity call_parallel is
2
port (
3
data_inp : in bit_vector(5 downto 0);
4
data_out : out bit_vector(1 downto 0));
5 end call_parallel;
6 architecture RTL of call_parallel is
7
procedure N_XOR (
8
signal x1, x2, x3 : in bit;
9
signal f
: out bit) is
10
begin
11
f <= x1 xor x2 xor x3;
12
end N_XOR;
13 begin
Параллельные операторы
81
14
N_XOR (x1 => data_inp(5), x2 => data_inp(4), x3 =>
data_inp(3),
15
f => data_out(1));
16
p0 : N_XOR (data_inp(2), data_inp(1), data_inp(0),
data_out(0));
17 end RTL;
В строках 14, 16 осуществляется параллельный вызов
процедур. В строке 16 параметры передаются позиционным
сопоставлением, в строке 14 передача параметров осуществляется
сопоставлением имен: вместо параметра x1 передается data_inp(5),
вместо x2 передается data_inp(4) и т.д.
! Каждый формальный параметр процедуры должен быть
типа константы или сигнала.
Декларация процедур и тела процедур будут обсуждены
далее.
Параллельный оператор условного назначения сигнала
(conditional signal assignment statement)
Oператор параллельного назначения сигнала эквивалентен
оператору процесса, назначающему значения сигналам.
Определение.
concurrent_signal_assignment_statement::=
[label:] conditional_signal_assignment
[label:] selected_signal_assignment
conditional_signal_assignment::=[guarded][transport]
{waveform when condition else] waveform;
Могут быть употреблены опции guarded (охраняемый)
transport (транспортный).
Пример, показывающий эквивалентность параллельного
оператора условного назначения сигнала (архитектурное тело first)
и оператора процесса (архитектурное тело second).
entity example_condition is
port (
x1, x2, x3, x4 : in bit;
82
Глава 2. Последовательные и параллельные операторы
condition
: in bit_vector(1 downto 0);
F
: out bit);
end example_condition;
architecture first of example_condition is
begin
F <= x1 when condition = "00" else
x2 when condition = "01" else
x3 when condition = "10" else
x4;
end first;
architecture second of example_condition is
begin
process (x1, x2, x3, x4, condition )
begin
if (condition = "00") then
F <= x1;
elsif (condition = "01") then
F <= x2;
elsif (condition = "10") then
F <= x3;
else
F <= x4;
end if;
end process;
end second;
Параллельный оператор выборочного назначения сигнала
(selected signal assignment statement)
Определение.
selected_signal_assignment::=
with expression select
[label:] selected_signal_assignment
target<=[guarded][transport]
{waveform when choices, } waveform choices;
Данный оператор эквивалентен оператору процесса.
Пример, показывающий эквивалентность параллельного
оператора выборочного назначения сигнала (архитектурное тело
first) и оператора процесса (архитектурное тело second).
Параллельные операторы
83
entity example_selection is
port (
x1, x2, x3, x4 : in bit;
selection : in bit_vector(1 downto 0);
F : out bit);
end example_selection;
architecture first of example_selection is
begin
with selection select
F <= x1 when "00",
x2 when "01",
x3 when "10",
x4 when others;
end first;
architecture second of example_selection is
begin
process (x1, x2, x3, x4, selection)
begin
case selection is
when "00" => F <= x1;
when "01" => F <= x2;
when "10" => F <= x3;
when others => F <= x4;
end case;
end process;
end second;
Параллельный оператор конкретизации компонента
(component instantiation statement )
Определение.
component_instantiation_statement::=
instantiation_label: component_name
[generic_map_aspect]
[port_map_aspect];
Этот оператор употребляется для структурной организации
проекта. Часть схемы (подсхема) описывается как компонент
(component), имеющий имя (name). Одна и та же подсхема может
84
Глава 2. Последовательные и параллельные операторы
входить в схему несколько раз, однако при этом она имеет
различные связи. Чтобы описать эти связи, употребляется оператор
создания экземпляра компонента (оператор конкретизации
компонента), т.е. имеется в виду конкретизация связей данной
подсхемы.
Соответствие портов при создании экземпляров компонентов
может быть осуществлено
• позиционным сопоставлением;
• ключевым соответствием, с использованием оператора
"=>".
Пример ключевого соответствия портов при создании
экземпляров компонентов.
p1: A port map (x1 => x1, y1=>w) ;
p2: B port map (x2 => w, y2=>z) ;
p3: C port map (y3=>v, x3 => z) ;
Сделаем пояснения. При создании экземпляра компонента A
портам x1, y1 компонента A ставятся в соответствие сигналы x1, w.
При создании экземпляра компонента B портам x2, y2 компонента
B ставятся в соответствие сигналы w, z (рис. 2.2). При ключевом
соответствии порядок перечисления портов не играет роли,
поэтому при ключевом соответствии портов можно сначала указать
выходной порт, как это сделано при создании экземпляра
компонента C.
x1
x1
A
y1
w
x2
B
y2
z
x3
C
v
y3
Рис. 2.2. Конкретизация (создание экземпляров)
Рассмотрим 8-разрядный сдвиговый регистр (рис. 2.3), в
состав которого входит восемь подсхем - D-триггеров (элементов
памяти) [9]. D-триггер имеет имя DFF.
1
2
3
4
entity DFF is
port (
RSTn, CLK, D : in bit;
Q
: out bit);
Параллельные операторы
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
85
end DFF;
architecture RTL of DFF is
begin
process (RSTn, CLK)
begin
if (RSTn = '0') then
Q <= '0';
elsif (CLK'event and CLK = '1') then
Q <= D;
end if;
end process;
end RTL;
--------------------------------------------entity SHIFT is
port (
RSTn, CLK, SI : in bit;
SO
: out bit);
end SHIFT;
architecture RTL1 of SHIFT is
component DFF
port (
RSTn, CLK, D : in bit;
Q
: out bit);
end component;
signal T : bit_vector(6 downto 0);
begin
bit7 : DFF
port map (RSTn => RSTn, CLK => CLK, D => SI, Q => T(6));
bit6 : DFF
port map (RSTn, CLK, T(6), T(5));
bit5 : DFF
port map (RSTn, CLK, T(5), T(4));
bit4 : DFF
port map (CLK => CLK, RSTn => RSTn, D => T(4), Q => T(3));
bit3 : DFF
port map (RSTn, CLK, T(3), T(2));
bit2 : DFF
port map (RSTn, CLK, T(2), T(1));
bit1 : DFF
port map (RSTn, CLK, T(1), T(0));
bit0 : DFF
86
46
47
Глава 2. Последовательные и параллельные операторы
port map (RSTn, CLK, T(0), SO);
end RTL1;
Схема SHIFT задает сдвиговый регистр - каскадное
соединение D-триггеров (элементов памяти). D-триггер описан в
строках 1-16.
Сдвиговый 8-битовый региcтр специфицирован в строках 1822.
Строки 24-28 декларируют компонент DFF.
Строка 29 декларирует 7-битовый сигнал T, употребляемый
для связи между соседними триггерами.
Компонент DFF конкретизирован (упомянут) восемь раз,
чтобы получить сдвиговый регистр.
! Каждый оператор создания экземпляра компонента должен
иметь метку. Метки играют роль имен элементов схемы.
Карта портов дается в скобках после ключевых слов port map.
Назначение портов компонентов является как позиционным
(см. метки bit0, bit1, bit2, bit3, bit5, bit6), так и ключевым (см. метки
bit6, bit7).
! Для выходных неиспользуемых портов компонентов нужно
употребить ключевое слово open.
Следующий фрагмент VHDL-кода показывает, что при
создании экземпляра компонента add1 на вход b1 можно подать
константу 0 и выход c1 не использовать.
P1: add1 port map (b1 => '0', b2 =>x, s1 => s1, c1 => open);
Рассмотрим еще один пример - 7-разрядный сумматор,
являющийся каскадным соединением одного полусумматора add1 и
шести одноразрядных сумматоров add2. Схема данного сумматора
изображена на рис. 2.4,а.
entity adder_N_comp is
port (a,b : in bit_vector (0 to 6);
s : out bit_vector (0 to 6);
c : out bit);
end adder_N_comp;
Rst
Clk
SI
D
T(6)
D
T(5)
D
D
T(3)
D
Рис. 2.3. Сдвиговый регистр
T(4)
T(2)
D
T(1)
D
T(0)
D
SО
88
Глава 2. Последовательные и параллельные операторы
architecture structural of adder_N_comp is
component
add1
port (b1,b2: in BIT;
c1,s1: out BIT);
end component;
component add2
port(c1, a1,a2:in BIT;
c2,s2:out BIT);
end component;
signal c_in : bit_vector (0 to 5);
s(6) ;
begin
p0: add1
port map (b1 => a(0), b2 => b(0), c1 => c_in(0), s1 => s(0) );
p1: add2
port map (c1 => c_in(0), a1 => a(1), a2 => b(1), c2 => c_in(1),
s2 => s(1) );
p2: add2
port map (c1 => c_in(1), a1 => a(2), a2 => b(2), c2 => c_in(2),
s2 => s(2) );
p3: add2
port map (c1 => c_in(2), a1 => a(3), a2 => b(3), c2 => c_in(3),
s2 => s(3) );
p4: add2
port map (c1 => c_in(3), a1 => a(4), a2 => b(4), c2 => c_in(4),
s2 => s(4) );
p5: add2
port map (c1 => c_in(4), a1 => a(5), a2 => b(5), c2 => c_in(5),
s2 => s(5) );
p6: add2
port map (c1 => c_in(5), a1 => a(6), a2 => b(6), c2 => c, s2 =>
end structural;
б)
a)
c_in(0)
s(2)
c_in(1)
a(1) b(1) a(2) b(2)
adder_2p
s(1)
s(4)
adder_2p
adder_2p
s(3)
add2
s(4)
c_in(2)
add2
s(5)
adder_2p
a(5) b(5) a(6) b(6)
adder_2p
s(6)
add2
s(6)
c
a(6) b(6)
c_in(5)
a(5) b(5)
s(5)
c_in(4)
a(4) b(4)
c_in(3)
a(3) b(3)
add2
s(3)
a(3) b(3) a(4) b(4)
c_in(2)
a(2) b(2)
add2
s(2)
c
Рис. 2.4. 7-разрядный сумматор: а - в виде каскадного соединения одноразрядного полусумматора add1
и одноразрядных сумматоров add2; б - в виде каскадного соединения одноразрядного полусумматора add1
и двухразрядных сумматоров adder_2p
a(0) b(0)
add1
s(0)
adder_2p
a(1) b(1)
a(0) b(0)
c_in(1)
add2
c_in(0)
s(1)
add1
s(0)
90
Глава 2. Последовательные и параллельные операторы
Примеры, приведенные для пояснения оператора создания
экземпляров компонентов, понадобятся нам в дальнейшем. Схемы
сдвигового регистра и сумматора являются регулярными и могут
быть описаны более компактно с помощью оператора генерации,
рассматриваемого далее.
Параллельный оператор генерации
(generate statement)
Определение.
generate_statement::=
generate_label: for generate_parameter_specification
generate if condition
generate
concurrent statements
end generate [generate_label];
Параметр
генерации
(generate_parameter_specification)
константа дискретного типа в определенном диапазоне.
Параметром генерации не может быть декларированная
переменная или сигнал.
Структура регистра регулярна. Мы можем создать N
экземпляров компонента DFF (D-триггера) и сделать N-битный
сдвиговый регистр. Когда число N большое, значительно
возрастает длина VHDL-кода. Оператор генерации представляет
собой механизм для проектирования (описания) регулярных
(систолических) структур.
Следующий пример [9] показывает применение оператора
генерации к описанию 8-битового сдвигового регистра.
architecture RTL2 of SHIFT is
component DFF
port (
RSTn, CLK, D : in bit;
Q
: out bit);
end component;
signal T : bit_vector(6 downto 0);
begin
g0 : for i in 7 downto 0 generate
g1 : if (i = 7) generate
bit7 : DFF
Параллельные операторы
T(6));
91
port map (RSTn => RSTn, CLK => CLK, D => SI, Q =>
end generate;
g2 : if (i > 0) and (i < 7) generate
bitm : DFF
port map (RSTn, CLK, T(i), T(i-1));
end generate;
g3 : if (i = 0) generate
bit0 : DFF
port map (RSTn, CLK, T(0), SO);
end generate;
end generate;
end RTL2;
Проанализировав данное описание, можно заметить, что
некоторое "неудобство", связанное с установлением связей схемы в
целом с полюсами элементов, возникает при описании входного
(метка bit7) и выходного триггера (метка bit0). Избежать этого
неудобства можно, если увеличить размерность сигнала T .
T(i));
architecture RTL3 of SHIFT is
component DFF
port (
RSTn, CLK, D : in bit;
Q
: out bit);
end component;
signal T : bit_vector(8 downto 0);
-- декларация сигнала T
begin
T(8) <= SI;
SO <= T(0);
g0 : for i in 7 downto 0 generate
allbit : DFF
port map (RSTn => RSTn, CLK => CLK, D => T(i+1), Q =>
end generate;
end RTL3;
Имеются два способа употребления оператора генерации.
Способ 1 - (способ for), синтаксис такой же, как у
последовательного оператора for loop.
92
Глава 2. Последовательные и параллельные операторы
Способ 2 - (способ if) употребление подобно по синтаксису
последовательному оператору if.
В архитектуре RTL2 способ if употреблен внутри способа for.
Укажем различия параллельного оператора генерации от
последовательных операторов for, if.
1. Оператор генерации есть параллельный оператор, а if, for
loop есть последовательные операторы.
2. Оператор генерации не имеет фраз else, elsif.
3. Необходима метка для оператора генерации.
4. Только параллельные операторы могут появляться внутри
оператора генерации. Только последовательные операторы могут
появляться внутри последовательного for loop оператора и
последовательного if оператора.
Архитектура DFF может быть декларирована в пакете и
употреблена в архитектурах RTL1, RTL2, RTL3. Затем эта
компонента может быть удалена из этих архитектур.
! В архитектуре RTL3 параметр i не нуждается в декларации.
Все три архитектуры RTL1, RTL2, RTL3 описывают то же самое
поведение.
В следующем примере VHDL-кода оператор generate
употребляется для спецификации N-разрядного сумматора adder_N
(рис.2.5).
s(0)
add1
s(1)
c-in(0)
a(0) b(0)
add2
c-in(2)
...
a(1) b(1)
s(N-2)
s(N-1)
add2
add2
a(N-2) b(N-2) a(N-1) b(N-1)
Рис. 2.5. N-разрядный сумматор
entity adder_N is
generic (N : natural := 4);
port (a,b : in bit_vector (0 to N-1);
s : out bit_vector (0 to N-1);
c : out bit);
end adder_N;
c
Параллельные операторы
93
architecture functional of adder_N is
component
add1
port (b1,b2: in BIT;
c1,s1: out BIT);
end component;
component add2
port(c1, a1,a2:in BIT;
c2,s2:out BIT);
end component;
signal c_in : bit_vector (0 to N-1);
begin
adder: for i in 0 to N-1 generate
first_bit: if (i=0) generate
first_cell:
add1 port map (b1 => a(0), b2 => b(0),
c1 => c_in(0), s1 => s(0) );
end generate first_bit;
middle_bit: if (i>0) and (i < N-1) generate
middle_cell:
add2 port map (c1 => c_in(i-1), a1 => a(i), a2 => b(i),
c2 => c_in(i), s2 => s(i) );
end generate middle_bit;
end_bit: if (i=N-1) generate
end_cell:
add2 port map (c1 => c_in(i-1), a1 => a(i), a2 => b(i),
c2 => c, s2 => s(i) );
end generate end_bit;
end generate adder;
end functional;
Изменяя число N в строке с ключевым словом generic, можно
получать описание сумматора требуемой разрядности. В
представленном ниже архитектурном теле func_1 для N-разрядного
сумматора используется только подсхема одноразрядного
сумматора add2, при этом на вход переноса c1 подсхемы add2 (в
94
Глава 2. Последовательные и параллельные операторы
разряде с номером 0) подается нулевой сигнал, описание становится
более компактным.
architecture func_1 of adder_N is
component add2
port(c1, a1,a2:in BIT;
c2,s2:out BIT);
end component;
signal c_in : bit_vector (0 to N);
begin
c_in(0)<='0';
adder: for i in 0 to N-1 generate
add2 port map (c1 => c_in(i), a1 => a(i), a2 => b(i),
c2 => c_in(i+1), s2 => s(i) );
end generate adder;
c <= c_in(N);
end func_1;
Параллельный оператор блока
(block statement)
Определение.
block_statement::=block_label block[(guard_expression)]
block_header
block_declaration_part
begin
concurrent statements
end block[block_label];
Оператор блока определяет часть проекта (часть VHDLописания цифровой системы, схемы). Напомним, что блок - это
ограниченный фрагмент VHDL-кода, содержащий раздел описания
и исполняемый раздел.
Блоки могут быть иерархически вложены и поддерживать тем
самым декомпозицию проекта.
! Метка необходима в операторе блока.
В разделе деклараций блока размещаются
Параллельные операторы
•
•
•
•
•
•
•
•
•
•
95
декларации подпрограмм;
тела подпрограмм;
типы, подтипы;
константы;
сигналы;
альтернативные точки входа в подпрограмму;
декларации атрибутов;
декларации констант;
спецификации атрибутов;
конфигурации.
Параллельные операторы размещаются в теле блока.
Необязательные охранные выражения будут обсуждены
позднее.
Оператор блока обсудим на примере 7-разрядного сумматора,
составленного из одного полусумматора и трех полных
двухразрядных сумматоров.
Полный двухразрядный сумматор adder_2p есть каскадное
соединение двух полных одноразрядных сумматоров add2.
Структурное описание схемы adder_2p приведено ниже, в
данном описании a1, b1 - младшие разряды двухразрядных
складываемых чисел a = (a2, a1), b = (b2, b1); a2, b2 - старшие
разряды; c0 - перенос из предыдущего разряда. Таким образом
схема adder_2p реализует операцию сложения
(c0) + (a2, a1) + (b2, b1) = (c2, s2,s1)
одноразрядного числа c0 с двухразрядными числами a, b.
entity adder_2p is
port (a1, b1, a2,b2,c0 : in BIT;
c2,s2,s1 : out BIT);
end adder_2p;
architecture structural of adder_2p is
component add2
port(c1, a1,a2:in BIT;
c2,s2:out BIT);
end component;
signal c1:BIT;
begin
circ1: add2
96
Глава 2. Последовательные и параллельные операторы
port map (c1 => c0, a1 => b1,a2 =>b2,c2 =>c1,s2=>s1);
circ2: add2
port map (c1 => c1, a1 => a1,a2 =>a2,c2 =>c2,s2=>s2);
end structural;
В приводимом ниже описании две схемы adder_2p,
предназначенные для сложения разрядов 1 - 4, описываются в виде
блока. Подсхемы, входящие в блок, отмечены на рис. 2.4,б
штриховой линией.
entity adder_N_block is
port (a,b : in bit_vector (0 to 6);
s : out bit_vector (0 to 6);
c : out bit);
end adder_N_block;
architecture structural of adder_N_block is
component
add1
port (b1,b2: in BIT;
c1,s1: out BIT);
end component;
component adder_2p
port(a1,b1,a2,b2,c0:in BIT;
c2,s2,s1:out BIT);
end component;
signal c_in : bit_vector (0 to 2);
begin
p0: add1 port map (b1 => a(0), b2 => b(0),
c1 => c_in(0), s1 => s(0) );
block0:block
begin
stage1: adder_2p port map (c0 => c_in(0), a1 => a(1), b1 => b(1),
a2 => a(2), b2 => b(2),
c2 => c_in(1), s2 => s(2), s1 => s(1) );
stage2: adder_2p port map (c0 => c_in(1), a1 => a(3), b1 => b(3),
a2 => a(4), b2 => b(4),
c2 => c_in(2), s2 => s(4), s1 => s(3) );
97
Параллельные операторы
end block;
stage3: adder_2p port map (c0 => c_in(2), a1 => a(5), b1 => b(5),
a2 => a(6), b2 => b(6),
c2 => c, s2 => s(6), s1 => s(5) );
end structural;
В данном примере отсутствуют охранные
заголовок блока, раздел деклараций блока.
Блоки могут быть вложены.
выражения,
architecture XX of SYSTEM is
----- раздел описаний внешнего блока
------begin
-- выполнимые операторы внешнего блока
------A:
block
----- раздел описаний внутреннего блока A
---begin
-- выполнимые операторы внутреннего
блока A
------end block A;
B:
block
----- раздел описаний внутреннего блока B
---begin
-- выполнимые операторы внутреннего
блока B
------end block B;
end XX;
В данном примере блоки A, B вложены в блок XX.
Обсудим теперь охранные выражения блоков. Рассмотрим
архитектурное тело add1_e одноразрядного сумматора в виде
охраняемого блока.
98
Глава 2. Последовательные и параллельные операторы
entity add1_e is
port (b1,b2,enable : in BIT;
c1,s1 : out BIT);
end add1_e;
architecture struct_3 of add1_e is
begin
p0: block (enable = '1')
begin
s1<= guarded (b1 xor b2);
c1<= guarded (b1 and b2);
end block p0;
end struct_3;
Охранным выражением блока является выражение enable = 1.
Если это выражение принимает значение true (истина), то
охраняемые конструкции (назначения сигналов) выполняются, т.е.
одноразрядный сумматор складывает числа, если же значение
выражения является false (ложь), то охраняемые назначения
сигналов не выполняются, т.е. сумматор не складывает числа b1, b2.
Охрана назначения сигналов осуществляется указанием ключевого
слова guarded.
В качестве другого примера охраняемого блока приведем
пример [1] описания D-триггера с асинхронным сбросом в виде
блока с охранным выражением (clk = '1' or clr = '1').
D_LATCH : block (clk = '1' or clr = '1')
begin
Q <= guarded '0' when clr = '1'; else
D when clk = '1'; else
Q;
end block D_LATCH;
В данном примере clk - вход синхронизации, clr - асинхронный
сброс, D - вход данных, Q - выход триггера. Когда охранное
выражение имеет значение ложь, то сигнал Q в левой части
сохраняет свое прежнее значение. Легко видеть, что сигнал
асинхронного сброса имеет приоритет по отношению к сигналу clk.
99
Упражнения
Упражнения
УПРАЖНЕНИЯ
1. Перечислите последовательные операторы языка VHDL .
2. Какой порядок выполнения последовательных операторов?
3. Правильно ли утверждение: "Булево условие в цикле типа
while проверяется в начале каждой итерации"?
4. Правильно ли утверждение: "Счетчик в цикле типа for есть
переменная, которую нужно декларировать в начале процесса, в
котором цикл употребляется"?
5. Какой будет дельта-задержка после выполнения операторов
в случаях
a) X:=A+B+C+D;
b) Y:=A+B+C;
c) Z:=A+B;
d) W:=A;
6. Где в VHDL-коде может быть декларирована локальная
переменная?
7. Где в VHDL-коде может быть декларирован сигнал?
8. Перечислите различия между локальными переменными и
сигналами в языке VHDL .
9. Какие из последовательных операторов могут быть
помечены? Являются ли метки обязательными?
10. Может ли процесс иметь список сигналов запуска и
оператор wait внутри оператора процесса?
11. Может ли процесс иметь
- несколько списков сигналов запуска;
- несколько операторов wait внутри оператора процесса;
- несколько списков сигналов запуска и несколько операторов
wait внутри оператора процесса.
12. Правильно ли, что знак оператора назначения сигнала
может быть ориентирован как в левую сторону (<=), так и в
правую сторону (=>) по желанию проектировщика, пользующегося
языком VHDL?
13. Объясните, как Вы понимаете запись на языке VHDL
x <= y <= z
Является ли она корректной? Почему?
14. Какая часть VHDL-кода содержит последовательные
операторы. Выберите правильный ответ:
100
Глава 2. Последовательные и параллельные операторы
a) процесс (перед ключевым словом begin);
b) архитектурное тело;
c) процесс (после ключевого слова begin);
d) пакет.
15. Пусть имеется фрагмент VHDL-кода.
signal a_bus : bit_vector( 3 downto 0);
signal z_bus : bit_vector( 3 downto 0);
signal a_bit, b_bit, c_bit, d_bit : bit;
1) BYTE <= (OTHERS => '1');
2) z_bus <= a_bit & b_bit;
3) a_bus <= ('1', b_bit, '0', d_bit);
4) a_bus (0 to 1) <= (OTHERS => '0');
Какие строки корректны. Выберите правильный ответ.
Обоснуйте ответ.
a) только 2 и 4;
b) только 3 и 4;
c) только 1 и 2;
d) только 1 и 3.
16. Пусть имеется фрагмент VHDL-кода.
Type my_state is (RESET, IDLE, RW_CYCLE, INT_CYCLE);
signal STATE : my_state;
signal TWO_BIT : bit_vector (0 to 1);
1) STATE <= RESET;
2) STATE <= ''00'';
3) STATE <= TWO_BIT;
Какие строки корректны.
17. В какой части VHDL-кода можно употреблять операторы
if, case, for ... loop. Выберите правильный ответ:
a) architecture;
b) entity;
c) package;
d) process.
18. В данном фрагменте VHDL-кода осуществляется
инициализация массива z_bus четырьмя способами:
Signal z_bus : bit_vector (3 downto 0);
101
Упражнения
a) z_bus <= ''0000'' ;
b) z_bus <= (1 => '0' , others => '0' );
c) z_bus <= (others => '0' );
d) z_bus <= ('0' ,'0','0', '0' );
Укажите способ, который наиболее просто осуществляет
инициализацию массива независимо от его длины.
19. Что такое транспортная и инерционная задержка сигнала?
Какой тип задержки (транспортная, инерционная) принят по
умолчанию в языке VHDL?
20. В каком случае модель инерционной задержки сигнала и
модель транспортной задержки сигнала дают тот же результат?
21. Перечислите параллельные операторы языка VHDL.
22. Какая часть VHDL-кода
содержит параллельные
операторы назначения сигнала. Выберите правильный ответ:
a) entity;
b) process;
c) package;
d) architecture.
23. Какой параллельный оператор требуется внутри
параллельных операторов?
24. В
следующем
VHDL-коде
[9] имеются
четыре
параллельных вызова процедуры.
4),
entity PROCALL_EX is
end PROCALL_EX;
architecture RTL of PROCALL_EX is
procedure ANDOR (
signal A, B, C, D : in bit_vector(1 downto 0);
signal Y
: out bit_vector(1 downto 0)) is
begin
Y <= (A and B) or (C and D);
end ANDOR;
signal DIN, DOUT : bit_vector(7 downto 0);
signal X, Y, Z : bit_vector(1 downto 0);
begin
call0 : ANDOR (A => DIN(7) & DIN(6), B => DIN(5 downto
C => DIN(3 downto 2), D => DIN(1 downto 0),
Y => DOUT(1 downto 0));
102
4),
Глава 2. Последовательные и параллельные операторы
call1 : ANDOR (A => DIN(7 downto 6), B => DIN(5 downto
C => DIN(3 downto 2), D => DIN(1 downto 0),
Y => DOUT(3 downto 2));
call2 : ANDOR (A => DIN(7 downto 6) and DIN(5 downto 4),
B => DIN(5 downto 4),
C => DIN(3 downto 2), D => DIN(1 downto 0),
Y => DOUT(5 downto 4));
call3 : ANDOR (A => X nand Y, B => Z,
C => DIN(3 downto 2), D => DIN(1 downto 0),
Y => DOUT(7 downto 6));
end RTL;
Является ли каждый вызов корректным или нет, почему?
25. Может ли локальная переменная употребляться как
фактический
параметр
оператора
параллельного
вызова
процедуры? Составьте соответствующий VHDL-код, проверьте его
с помощью VHDL-анализатора.
26. Каким параллельным операторам требуются метки?
27. Для
каких
параллельных
операторов
метки
необязательны?
28. Что такое компонент в языке VHDL? Чему соответствует
компонент в логической схеме? Какие средства языка VHDL
употребляются для соединения компонент?
29. Могут ли декларироваться компоненты внутри раздела
декларации процесса?
30. Требуется ли декларировать сигналы внутри процесса?
31. Допустимо ли декларировать любые объекты внутри
процесса?
32. Правильно ли, что все операторы внутри процесса
выполняются один за другим?
33. Правильно ли, что все процессы внутри архитектурного
тела выполняются один за другим?
34. Должен ли каждый процесс иметь имя (метку)?
Рекомендуется ли именовать процессы? Если "да", то почему?
35. Правильно ли, что имя процесса специфицируется после
ключевого слова process?
36. Правильно ли, что как сигналы, так и переменные могут
употребляться для хранения временных данных внутри процесса?
103
Упражнения
37. Перепишите следующий VHDL-код
оператор выборочного назначения сигнала.
[9],
используя
entity IFCASE is
port (
HEX : in bit_vector(3 downto 0);
LED : out bit_vector(6 downto 0));
end IFCASE;
architecture RTL of IFCASE is
begin
p0 : process (HEX)
begin
case HEX is
when "0000" => LED <= "1111110";
when "0001" => LED <= "1100000";
when "0010" => LED <= "1011011";
when "0011" => LED <= "1110011";
when "0100" => LED <= "1100101";
when "0101" => LED <= "0110111";
when "0110" => LED <= "0111111";
when "0111" => LED <= "1100010";
when "1000" => LED <= "1111111";
when "1001" => LED <= "1110111";
when "1010" => LED <= "0111001";
when "1011" => LED <= "0111101";
when "1100" => LED <= "0011001";
when "1101" => LED <= "1111001";
when "1110" => LED <= "1011111";
when others => LED <= "0001111";
end case;
end process;
end RTL;
Проведите моделирование, сравните результаты.
38. Правильно ли, что оператор выборочного назначения
сигнала и оператор условного назначения сигнала представляют то
же действие, только записанное по-разному?
39. Правильно ли утверждение "Условное назначение сигнала
может употребляться как в архитектурном теле (как параллельный
оператор), так и в процессе (как последовательный оператор)"?
104
Глава 2. Последовательные и параллельные операторы
40. Для чего служит оператор generate? Структуру каких схем
удобно описывать с его помощью?
41. Допустимо
ли
при
конкретизации
компонентов
использовать оба направления (=>, <=) в зависимости от того,
является порт входным либо выходным?
42. Разработайте логическую схему и, употребляя оператор
generate,
запишите
VHDL-код
структурного
описания
мультиплексора с двумя, тремя, четырьмя и n управляющими
входами.
43. Разработайте функциональное описание схемы для
перемножения двух матриц A, B размерностью 4×4, элементами
которых являются целые числа. Используйте двухразмерные
массивы для входных и выходных данных.
Примените операторы generic, generate, запишите VHDL-код
для общего случая, когда матрицы имеют размерность N×N.
Разработайте структурные описания для случаев N=2, N=3,
используя умножители и сумматоры и полагая, что элементами aij,
bij матриц A,B являются целые числа, не большие числа 3.
Примените битовое представление входных и выходных данных.
Приведите моделирование, убедитесь в корректности VHDL-кода.
Введите соответствующие типы данных и разработайте
поведенческое VHDL-описание схемы для умножения матрицы A
на вектор c.
Разработайте структурное описание, используя битовое
представление входных данных для случая, когда элементы
матрицы A и компоненты вектора c являются целыми числами, не
большими 7, а матрица A имеет размерность N× N, вектор с имеет
размерность N, N=2,3,4. Используйте функции преобразования
типов integer, bit_vector.
105
Упражнения
44. На рис. 2.6 изображена схема 4-разрядного умножителя.
Введите имена сигналам, соединяющим элементы схемы:
одноразрядные полусумматоры add1, одноразрядные сумматоры
add2, двухвходовые конъюнкторы.
t7
t6
t5
t4
t3
add2
add2
add2
add1
&
&
s3
&
s2
add2
&
s1
add2
&
s0
add2
&
s3
add1
add1
&
s2
&
s1
add2
&
s0
add2
&
s3
r3
t2
add1
&
s2
r2
t1
&
s1
r1
s0
t0
&
&
s3
&
s2
&
s1
s0
r0
Рис. 2.6. Четырехразрядный умножитель
Опишите схему, используя операторы создания экземпляров
компонентов. Составьте более компактное описание, используя
другие операторы языка VHDL. Проведите моделирование,
сравните результаты. Введите задержки элементам: add1 - 10ns, add2
-15 ns, элементам И - 5 ns. Проведите моделирование. Определите
задержку схемы..
106
Глава 2. Последовательные и параллельные операторы
45. На рис. 2.7 дана схема D-триггера. Введите задержки
элементам и составьте структурное описание. Модифицируйте
функциональное описание, введя задержку в оператор назначения
сигнала, проведите моделирование в обоих случаях. Сравните
результаты.
T
D
C
Q
Q
a)
D
&
DD1
C
A
&
Y1
DD3
&
&
DD2
DD4
Y2
Q
Q
б)
Рис. 2.7. D-триггер (защелка): a - условное обозначение;
б - схема D-триггера на элементах И-НЕ
46.
Опишите
функционирование
RS-триггера
использованием конструкции "охраняемый блок".
с
Подпрограммы
107
Глава 3
Организация проекта
Г
л
а
в
а
3
.
Организация проекта
3.1. Подпрограммы
Подпрограммы
Декларация подпрограммы
Определение.
subprogram_declaration::=
procedure identifier [(formal_parameter_list)]|
function designator [(formal_parameter_list)]
return type_mark;
Подпрограммы имеют две формы - функции и процедуры.
Вызов процедуры есть оператор, в то время как вызов функции
возвращает значение в выражении. Указателем функции
(операторным символом) может быть идентификатор или
строковый литерал. Заметим, что строковый литерал не может
быть именем процедуры. Список формальных параметров
(formal_parameter_list) - список интерфейса (interface_list), который
состоит
из
одной
или
более
деклараций
интерфейса
(interface_declaration).
interface_list ::= interface_declaration {; interface_declaration}
interface_declaration ::=
interface_constant_declaration
| interface_signal_declaration
| interface_variable_declaration
interface_constant_declaration ::=
[ constant ] identifier_list : [ in ] subtype_indication
[:=static_expression ]
108
Глава 3. Организация проекта
interface_signal_declaration ::=
[signal] identifier_list : [ mode ] subtype_indication [ bus ]
[ :=static_expression ]
interface_variable_declaration ::=
[variable] identifier_list : [ mode ] subtype_indication
[ := static_expression ]
mode ::= in | out | inout | buffer | linkage
Подпрограммы могут быть декларированы в пакете,
интерфейсе объекта (entity), архитектурном теле (architecture),
процессе, процедуре или функции.
Тело подпрограммы
Определение.
subprogram_body::= subprogram_declarations is
subprogram_declarative_part
begin
sequential statements
end [procedure identifier or function designator];
Примеры подпрограмм уже приводились и будут даны далее.
3.2. Функции
Функции
Функция имеет только входные параметры. Следующий
пример показывает функцию BOOL_TO_SL, преобразующую тип
BOOLEAN в тип STD_ULOGIC.
Пример.
function BOOL_TO_SL(X : boolean)
return std_ulogic is
begin
if X then
return '1';
else
return '0';
end if;
end BOOL_TO_SL;
Процедуры
109
Функция может содержать последовательные операторы,
исключая операторы ожидания и назначения сигналов. В теле
функции могут декларироваться локальные переменные. Например,
в теле функции PARITY декларируется локальная переменная TMP.
Пример.
function PARITY (X : std_ulogic_vector)
return std_ulogic is
variable TMP : std_ulogic := '0';
begin
for J in X'range loop
TMP := TMP xor X(J);
end loop;
return TMP;
end PARITY;
теле.
Пример использования функции PARITY в архитектурном
architecture FUNCTIONS of PAR is
begin
-- вызов функции
PARITY_BYTE <= PARITY(DATA_BYTE);
PARITY_WORD <= PARITY(DATA_WORD);
end FUNCTIONS;
3.3. Процедуры
Процедуры
Процедура может иметь входные (in), выходные (out) и
вход/выходные (inout) параметры. Это могут быть сигналы,
переменные или константы. По умолчанию входные параметры константы, выходные и вход/выходные - переменные. Процедуры
могут вызываться последовательно или параллельно. При
параллельном вызове происходит выполнение процедуры, когда
какой-нибудь входной вход/выходной параметр изменился.
Следующий пример процедуры PARITY показывает отличия
процедуры от функции: функция имеет только входные параметры,
режим (mode) которых не специфицируется, в процедуре могут
содержаться операторы назначения сигналов.
Пример.
110
Глава 3. Организация проекта
procedure PARITY
(signal X : in std_ulogic_vector;
signal Y : out std_ulogic) is
variable TMP : std_ulogic := '0';
begin
for J in X'range loop
TMP := TMP xor X(J);
end loop;
Y <= TMP;
-- в процедуре могут быть операторы
-- назначения сигналов
end PARITY;
Следующий пример показывает процедуру DISPLAY_MUX и
ее вызов в архитектурном теле SUBPROG.
procedure DISPLAY_MUX
(ALARM_TIME, CURRENT_TIME : in digit;
SHOW_A
: in std_ulogic;
signal DISPLAY_TIME : out digit) is
begin
if (SHOW_A = '1') then
DISPLAY_TIME <= ALARM_TIME;
else
DISPLAY_TIME <= CURRENT_TIME;
end if;
end DISPLAY_MUX;
architecture SUBPROG of DISP_MUX is
...
begin
-- вызов процедуры
DISPLAY_MUX (ALARM_TIME, CURRENT_TIME,
SHOW_A, DISPLAY_TIME);
end SUBPROG;
Если подпрограмма определена в
подпрограммы должен быть в теле пакета.
пакете,
то
текст
3.4. Разрешающие функции. Пакет std_logic_1164
Разрешающие функции. Пакет std_logic_1164
Когда сигнал имеет один драйвер (иногда драйвер называют
контейнером), то значение сигнала легко определить, потому что,
Разрешающие функции. Пакет std_logic_1164
111
когда процесс приостанавливается, значение сигнала из драйвера
передается сигналу. Однако во многих практических ситуациях
один и тот же сигнал может назначаться в различных (нескольких)
процессах. Например, шина данных в персональном компьютере
может получать данные из процессора, памяти (ОЗУ), жесткого
диска и других устройств. Сигнал от многих источников называется
в языке VHDL разрешаемым (resolved), т.е. требующим решения
проблемы разрешения - определения значения результирующего
сигнала по значениям сигналов из различных источников. Сигнал,
не требующий решения проблемы разрешения, называется
неразрешаемым (unresolved) - это сигнал из одного источника.
Функция разрешения - это функция определения значения
сигнала по его значениям из различных источников. Далее будем
рассматривать два источника и для этого случая изучать функции
разрешения в электронных схемах. Для моделирования процессов
прохождения сигналов в реальных электронных схемах
используется многозначная логика. Тип bit обобщается на случай
девяти значений сигнала
'U'
'X'
'0'
'1'
'Z'
'W'
'L'
'H'
'-'
----------
не инициализировано;
неизвестное значение (сильный источник сигнала);
логический 0 (сильный источник сигнала);
логическая 1 (сильный источник сигнала);
высокий импеданс (цепь не подключена к источнику);
неизвестное значение (слабый источник сигнала);
логический 0 (слабый источник сигнала);
логическая 1 (слабый источник сигнала);
неопределенное значение (don't care).
На практике чаще всего используется шестизначный алфавит
{U, X, 0,1,Z,-}. Заметим, что неизвестное значение 'X' не
эквивалентно неопределенному значению '-'. Неопределенное
значение эффективно используется при логическом синтезе схемы и
логической оптимизации. Читатель, знакомый, например, с
методами минимизации не полностью определенных булевых
функций, может вспомнить о том, что некоторые неопределенные
значения '-' функции заменяются при минимизации определенными
(0,1) с целью получения лучшего результата.
Расширение типа bit на случай девяти значений сигнала
привело к понятию типа std_logic.
112
Глава 3. Организация проекта
Основное назначение типа std_logic - это дать "легальную"
возможность разработчику делать многократные присваивания
одному и тому же сигналу.
Пример.
Signal FlagC : std_logic := 'Z';
ALU: process
begin
if Carry then FlagC <= '1'; end if;
end process ALU;
COMM: process
begin
FlagC <= '0';
end process COMM;
В данном примере для сигнала FlagC требуется разрешающая
функция, так как операторы назначения данного сигнала имеются в
двух процессах (рис. 3.1).
Тип std_logic будем называть разрешаемым. Тип std_logic
является подтипом типа std_ulogic. Тип std_ulogic является не
разрешаемым перечислимым типом с множеством значений {'U', 'X',
'0','1','Z','W', 'L','H','-'}. Для сигналов этого типа запрещено
использовать
много
источников
сигнала,
поэтому
нет
необходимости указывать разрешающую функцию. Буква u в
названии типа std_ulogic сигнализирует о термине (unresolved).
Итак, типы std_logic, std_ulogic - это перечислимые типы. Их
определение содержится в пакете std_logic_1164 (см. приложение 4).
113
Разрешающие функции. Пакет std_logic_1164
process ALU
FlagC<='1';
process Comm
FlagC<='0';
Драйвер
сигнала
FlagС
Функция
разрешения
F
Сигнал
FlagC
Драйвер
сигнала
FlagС
Рис. 3.1. Функция разрешения F для сигналов с многими драйверами
В пакете std_logic_1164 содержатся определения типов,
подтипов, функций на случай многозначной логики:
• тип std_ulogic - неразрешаемый логический тип с
девятизначным алфавитом;
• тип std_logic_vector;
• подтип std_logic типа std_ulogic;
• "перегружаемые" логические функции and, nand, or, xor, not
для операндов std_ulogic и др.
Заметим, что для преобразования типа bit в тип std_logic (и
наоборот) требуются соответствующие функции.
Табл. 3.1, по существу, есть табличное задание разрешающей
функции F для сигнала из двух источников. Рис. 3.2 иллюстрирует
смысл таблицы, т.е. получение значения сигнала с помощью
функции разрешения F.
Фактически типы std_logic, std_ulogic стали промышленным
стандартом и доступны во всех системах моделирования с языком
VHDL, поставляющихся вместе с пакетом std_logic_1164. Чтобы
использовать пакет std_logic_1164, необходимо указать следующее:
Library IEEE;
use IEEE. std_logic_1164.all;
Опишем схему (рис.3.3), используя для сигналов тип
std_logic.
114
Глава 3. Организация проекта
Чтобы описать
являющийся
а)
б)
в)
монтажное
X
'U'
'X'
'X'
'X'
'X'
'X'
'X'
'X'
'X'
0
'U'
'X'
'0'
'X'
'0'
'0'
'0'
'0'
'X'
Драйвер 1
a)
введем
тип
resolved_bit,
Таблица 3.1
U
'U'
'U'
'U'
'U'
'U'
'U'
'U'
'U'
'U'
U
X
0
1
Z
W
L
H
-
ИЛИ,
1
'U'
'X'
'X'
'1'
'1'
'1'
'1'
'1'
'X'
Z
'U'
'X'
'0'
'1'
'Z'
'W'
'L'
'H'
'X'
W
'U'
'X'
'0'
'1'
'W'
'W'
'W'
'W'
'X'
L
'U'
'X'
'0'
'1'
'L'
'W'
'L'
'W'
'X'
'U' (столбец)
(столбец)
F
Драйвер 2
H
'U'
'X'
'0'
'1'
'H'
'W'
'W'
'H'
'X'
'U'
'X'
'X'
'X'
'X'
'X'
'X'
'X'
'X'
'U'
'1' (строка)
Драйвер 1
'Z'
'U' (столбец)
(столбец)
F
б)
Драйвер 2
'W'
'W' (строка)
Драйвер 1
в)
'L'
'U' (столбец)
(столбец)
F
Драйвер 2
'W'
'H' (строка)
Рис. 3.2. Иллюстрация табличного задания функции
разрешения F
для сигналов типа std_logic с двумя драйверами
115
Разрешающие функции. Пакет std_logic_1164
подтипом типа std_logic, и определим в пакете wire, находящемся в
рабочей библиотеке work, разрешающую функцию res_func для
сигнала типа resolved_bit. Разрешающая функция определяет
значение сигнала по значениям сигналов из нескольких источников.
В данном примере разрешающая функция назначит сигналу
out_wire значение '1', если хотя бы один из выходных сигналов
логических элементов И первого уровня схемы (рис. 3.3) будет
иметь значение '1', в противном случае сигнал out_wire примет
значение '0'. В VHDL-коде используются следующие имена: схема,
изображенная на рис. 3.3, имеет имя circuit_wire, двухвходовый
элемент И - имя cc.
x1
&
x2
x3
&
x4
x5
out_wire
&
x2
&
x6
Рис. 3.3. Схема circuit_wire
library IEEE;
use IEEE.std_logic_1164.all;
library work;
use work.wire.all;
entity circuit_wire is
port (x1,x2,x3,x4,x5,x6 : in std_logic;
out_circ : out std_logic);
end circuit_wire;
out_circ
116
Глава 3. Организация проекта
architecture structure of circuit_wire is
component cc
port (x1,x2 : in std_logic; y : out std_logic);
end component;
signal out_wire : resolved_bit;
begin
p1: cc
port map (x1 => x1, x2 => x2, y => out_wire);
p2: cc
port map (x1 => x3, x2 => x4, y => out_wire );
p3: cc
port map (x1 => x5, x2 => x6, y => out_wire );
p4: cc
port map (x1 => out_wire, x2 => x2, y => out_circ);
end structure;
library IEEE;
use IEEE.std_logic_1164.all;
entity cc is
-- описание логического элемента И
port (x1,x2: in std_logic;
y: out std_logic);
end cc;
architecture functional of cc is
begin
y <= x1 and x2;
end functional;
Ниже приведен пакет wire и тело (body) этого пакета.
library IEEE;
use IEEE.std_logic_1164.all;
package wire is
function RES_FUNC(DATA: in std_logic_vector) return std_logic;
subtype RESOLVED_BIT is RES_FUNC std_logic;
end;
package body wire is
-- описание разрешающей
функции
function RES_FUNC(DATA: in std_logic_vector) return std_logic is
begin
for I in DATA'range loop
Архитектура
117
if DATA(I) = '1' then
return '1';
end if;
end loop;
return '0';
end;
end;
В тексте функции RES_FUNC используется атрибут
DATA'range - диапазон сигнала DATA. Аналогичным образом
можно ввести разрешающую функцию для монтажного И.
3.5. Архитектура
Архитектура
Ранее в общем виде была представлена архитектура объекта
проекта и интерфейс объекта проекта. Приведем определение
архитектуры.
Определение.
architecture_body::=architecture identifier of
entity_name is
architecture_declaration_part
begin
[concurrent statements]
end [architecture_simple_name]
В разделе деклараций архитектуры могут быть
• декларации подпрограмм;
• тела подпрограмм;
• спецификации конфигурации;
• декларации типов, подтипов, констант, сигналов, файлов,
альтернативных точек входа, компонентов и др.
! В разделе деклараций архитектуры не могут быть
декларированы локальные переменные.
! Только параллельные операторы размещаются в теле
архитектуры
между
ключевыми
словами
begin,
end.
Последовательные операторы могут быть внутри оператора
процесса или подпрограммы.
Допустимо, чтобы параллельных операторов не было внутри
архитектурного тела.
118
Глава 3. Организация проекта
3.6. Декларация интерфейса объекта
Декларация интерфейса объекта
Определение.
entity_declaration::=
entity identifier is
[generic (generic_list);]
[port (port_list);]
entity_declaration port
[begin
entity_statement_port]
end [entity_simple_name];
Необязательный раздел операторов entity может иметь только
параллельные вызовы процедур, параллельные операторы
сообщения, операторы процесса. Все они должны быть
пассивными, так чтобы не было присваивания значений сигналам.
Список портов (port_list) и список настройки (generic_list)
такие же, как и в подпрограммах.
Если специфицировать объект другого класса, а не сигнал
после ключевого слова port, то это является ошибкой. Ошибкой
будет также, если специфицировать не константу после ключевого
слова generic.
В entity ключевое слово port является необязательным.
Список
после
ключевого
слова
generic
(общий,
настраиваемый) есть хороший способ проведения (передачи)
параметров в интерфейс объекта проекта, таких как параметры
временной задержки, ширина шины (число проводников) и т.д.
Употребляя
настройку
(слово
generic),
можно
специфицировать регулярную структуру переменной длины.
Приведем пример [9] entity для сдвигового регистра
переменной длины N, определив сперва модификацию D-триггера c
предустановкой (очисткой).
library IEEE;
use IEEE.std_logic_1164.all;
entity DFF is
-- D-триггер
generic (
PRESET_CLRn : in integer);
port (
RSTn, CLK, D : in std_logic;
Декларация интерфейса объекта
119
Q
: out std_logic);
end DFF;
architecture RTL of DFF is
begin
process (RSTn, CLK)
begin
if (RSTn = '0') then
if (PRESET_CLRn = 0) then
Q <= '0';
else
Q <= '1';
end if;
elsif (CLK'event and CLK = '1') then
Q <= D;
end if;
end process;
end RTL;
Тогда архитектурное тело сдвигового регистра переменной
длины N будет иметь вид
library IEEE;
use IEEE.std_logic_1164.all;
entity SHIFTN is
-- сдвиговый регистр длины N
generic (
PRESET_CLRn : in integer;
N
: in integer);
port (
RSTn, CLK, SI : in std_logic;
SO
: out std_logic);
signal T : std_logic_vector(N downto 0);
begin
assert (N > 3) and (N < 33) report
"N outside of range 3 to 32";
end SHIFTN;
architecture RTL1 of SHIFTN is
component DFF
generic (
PRESET_CLRn : in integer);
port (
RSTn, CLK, D : in std_logic;
120
T(i));
Глава 3. Организация проекта
Q
: out std_logic);
end component;
begin
T(N) <= SI;
SO <= T(0);
g0 : for i in N-1 downto 0 generate
allbit : DFF
generic map (PRESET_CLRn => PRESET_CLRn)
port map (RSTn => RSTn, CLK => CLK, D => T(i+1), Q =>
end generate;
end RTL1;
Обращаем внимание на то, что спецификация компонента
DFF в архитектурном теле RTL1 совпадает с его определением в
entity DFF.
3.7. Карта портов и карта настройки
Карта портов и карта настройки
Соединение VHDL-описаний осуществляется с помощью карт
(map).
Для иерархического проекта порты низкоуровневых
компонент (уровня i-1) могут быть отображены в порты
высокоуровневого объекта (уровня i) сигналами с учетом
следующих ограничений.
Сигнал порта, имеющий режим (mode) in, может быть
соединен с портом, имеющим режим in, inout, buffer (рис. 3.4). На
рис. 3.4 изображены только некоторые возможные соединения
портов компонента с портами той подсхемы, в которую компонент
входит.
Сигнал порта режима out может быть соединен с портом,
имеющим режим out или inout, buffer. Сигнал порта режима inout,
buffer может быть отображен (соединен) с портом, имеющим режим
вида inout, buffer соответственно.
Сигнал порта режима linkage может быть соединен с сигналом
порта любого режима. С точки зрения проектирования аппаратуры
вид связи linkage не является естественным, данный тип связи более
подходит для алгоритмических описаний.
121
Конфигурация
out
запрещен
in
in
разрешен
in
Компонент
(уровень i-1)
out
out
разрешен
разрешен
out
inout
Объект проекта уровня i
Рис. 3.4. Связи портов компонента с портами
объектаinout употребляется чаще всего для двунаправленных
Режим
контактов, которые находятся снаружи кристалла СБИС. Для
внутренних сигналов режим не указывается.
3.8. Конфигурация
Конфигурация
Один и тот же объект проекта (entity) может иметь много
архитектурных тел. Как при моделировании выбрать то или другое
архитектурное тело?
Формальное определение (синтаксис) понятия конфигурации
довольно сложное.
Начнем с простейших случаев
Пусть мы определили компоненту goose.
entity goose is
port (a, b: in bit; c : out bit);
end goose;
architecture struct_1 of goose is
begin
c <= a xor b;
end struct_1;
122
Глава 3. Организация проекта
Мы можем употребить данную компоненту стандартным
образом, употребляя имя goose.
entity flock is
port (a, b: bit; c: out bit);
end flock;
architecture three_geese of flock is
signal w, r: bit;
component goose
-- декларация компонента
port (a, b: bit; c: out bit);
end component;
begin
one: goose port map (a, b, w); -создание экземпляра
компонента
two: goose port map (a, w, r);
three: goose port map (a, r, c);
end three_geese;
Архитектурное тело содержит три экземпляра компонента
goose. По умолчанию предполагается, что это тот же самый
компонент goose, который был определен ранее и который
содержится в рабочей библиотеке (Work - имя рабочей
библиотеки).
Пусть у нас имеется другое архитектурное тело для
компонента goose.
architecture struct_2 of goose is
begin
c <= ((a and (not b)) or ((not a) and b)) ;
end struct_2;
Мы можем не действовать "по умолчанию", а "явно"
определить употребление того или другого архитектурного тела
для конкретного компонента на основе конфигурации.
configuration bird of flock is -- bird - имя конфигурации
for three_geese
for one: goose
use entity work.goose(struct_2);
end for;
for two: goose
Конфигурация
123
use entity work.goose(struct_1);
end for;
for three: goose
use entity work.goose(struct_1);
end for;
end for;
end bird;
Мы указали, что для компонента goose, имеющего имя
(метку) one, необходимо использовать (use) из рабочей библиотеки
архитектурное тело struct_2, аналогично - для компонентов с
метками two, three необходимо использовать архитектурное тело
struct_1.
Рассмотрим немного более сложный пример конфигурации на
примере схемы vlsi_1 (см. рис. 1.2). Представим, что в схемах
сумматора adder_2 и умножителя mult_2 мы хотим использовать
различные архитектурные тела для одноразрядного полусумматора
add1. Итак, в умножителе будем использовать для подсхемы add1
архитектурное тело struct_2, а в сумматоре - архитектурное тело
struct_1. Архитектурное тело struct_2 отличается от архитектурного
тела struct_1 только назначением сигнала: вместо
s1<=((b1 and (not b2)) or (not b1) and b2));
можно использовать
s1<= (b1 xor b2);
Конфигурация example выглядит следующим образом:
configuration example of vlsi_1 is
for struct_1
-- имя архитектурного тела схемы
vlsi_1
for circ2: mult_2
use entity work.mult_2(structure);
for structure
for all: add1
use entity work.add1(struct_2);
end for;
end for;
124
Глава 3. Организация проекта
end for;
for circ3: adder_2
use entity work.adder_2(structure);
for structure
for all: add1
use entity work.add1(struct_1);
end for;
for all: add2
use entity work.add2(struct_1);
-- вместо struct_1
end for;
-- можно указать
end for;
-- другую архитектуру
end for;
end for;
end example;
В данной конфигурации предполагается, что подсхемы
сумматора и умножителя находятся в рабочей библиотеке work.
Использование библиотек в языке VHDL рассматривается в
следующем разделе.
При записи конфигурации могут быть использованы другие
конфигурации для подсхем, входящих в схему, таким образом
описание конфигурации может быть организовано иерархически,
наподобие иерархической организации описания проектируемой
цифровой системы. Большое число примеров конфигураций для
сдвигового регистра можно найти в [9].
3.9. Блоки проекта и VHDL-библиотеки
Блоки проекта и VHDL-библиотеки
Файл проекта может содержать один или более блоков
проекта. Имеются первичные и вторичные блоки проекта.
Первичные блоки проекта:
• декларация объекта в целом (интерфейса entity);
• декларация конфигурации;
• декларация пакета.
Первичный блок может быть связан с многими вторичными
блоками проекта, которые включают:
• архитектурное тело;
• тело пакета.
125
Блоки проекта и VHDL-библиотеки
! Каждый первичный блок в данной библиотеке должен иметь
уникальное простое имя. Каждое архитектурное тело, связанное с
entity, должно быть уникальным.
Блоки проекта (первичные и вторичные) размещаются в
библиотеках (рис.3.5). Рабочая библиотека может быть только
одна.
Библиотека
ресурсов
VHDL-код
(файлы)
...
VHDL-анализатор
Библиотека
ресурсов
Рабочая
библиотека
В рабочей библиотеке размещаются файлы (блоки),
анализируемые
VHDL-анализатором.
Рис. 3.5.
VHDL-библиотеки и VHDLВ библиотеках
анализатор ресурсов размещаются блоки, на которые
ссылаются анализируемые блоки.
Ресурсной библиотеки может не быть во время анализа.
Ссылка на библиотеку осуществляется указанием ключевого слова
library.
Например, ссылка на библиотеку STD, содержащую пакет
STANDARD, и на библиотеку WORK, содержащую пакет FXP,
осуществляется следующим образом:
library STD, WORK;
use STD.STANDARD.all
use WORK.FXP.all
VHDL-анализатор читает файлы исходного VHDL-кода,
читает ссылки на ресурсные библиотеки и генерирует базу данных
моделирования в рабочей библиотеке.
Область видимости библиотеки - от начальной ссылки до
конца декларативной области, связанной с блоком проекта, где
ссылка появилась.
126
Глава 3. Организация проекта
Видимость сигналов: сигнал, декларированный в пакете,
является видимым во всех объектах проекта, которые употребляют
ссылку (use) на данный пакет. Сигнал, декларированный в entity как
порт, является видимым во всех архитектурных телах, связанных с
данным entity. Сигнал, декларированный в разделе деклараций
архитектурного тела, видим только внутри данного архитектурного
тела.
Упражнения
УПРАЖНЕНИЯ
1. В какой части VHDL-кода должны быть декларированы
локальные сигналы архитектурного тела? Выберите правильный
ответ:
a) в списке портов архитектурного тела;
b) в конфигурации;
c) в архитектурном теле после ключевого слова begin;
d) в архитектурном теле перед ключевым словом begin.
2. Как должны быть подобны компонент (component) и
соответствующий интерфейс (entity)? Выберите правильный ответ:
a) entity и component должны иметь одно и то же имя, но
порты могут различаться;
b) имена entity и component могут различаться, но имена
портов должны быть одинаковы;
c) entity и component должны иметь одинаковые имена и
должны иметь одинаковые имена портов.
3. Правильно ли, что компоненты, декларируемые в
архитектурном теле, должны специфицироваться полностью, т.е.
вместе с их интерфейсом и выполняемыми функциями?
4. Как много архитектурных тел может быть связано с одним
entity? Выберите правильный ответ:
a) одно или более;
b) более одного;
c) только одно;
d) ни одного.
5. Правильно ли утверждение: "Каждый порт должен быть
специфицирован с его режимом (mode)"?
6. Правильно ли утверждение: "Режим порта специфицирует
направление потока данных через порт"?
7. Являются ли порты сигналами?
127
Упражнения
8. Правильно ли утверждение: "Описание каждого порта с
комментарием в конце строки является необходимым согласно
стандарту языка VHDL"?
9. Разрешается ли специфицировать начальное значение
порта?
10. Может ли настраиваемый параметр (generic) динамически
изменяться во время моделирования?
11. Правильно
ли
утверждение:
"Все
процессы
в
архитектурном теле являются активными, когда архитектура
активна "?
12. Могут ли употребляться переменные для передачи
информации между процессами?
13. Напишите VHDL-код для схемы 4-разрядного сумматора,
представляющей
каскадное
соединение
одноразрядных
сумматоров. Напишите VHDL-код для одноразрядного сумматора
add2 в виде
а) логической схемы элементов И, ИЛИ, НЕ;
б) логических функций.
Запишите различные конфигурации, используя различные
архитектурные тела для одноразрядных сумматоров add1, add2.
14. Рассмотрите предыдущую задачу для случая 4-разрядного
умножителя (см. рис. 2.6). Запишите различные конфигурации.
15. Разработайте логическую схему для вычисления функции
f = ( p + q) + w × d ,
где p = ( p2 , p1 ) ,
q = (q 2 , q1 ) ,
w = ( w 2 , w1 ) ,
d = ( d2 , d1 )
-
двухразрядные числа.
Опишите ее на языке VHDL. Запишите различные
конфигурации, употребляя различные архитектурные тела для
сумматоров и умножителя.
16. Что из перечисленного ниже не является блоком проекта.
Выберите правильный ответ:
a) architecture;
b) entity;
c) process;
d) package.
128
Глава 4. Примеры проектирования на VHDL
Глава 4
Примеры проектирования на VHDL
Г
л
а
в
а
4
.
Примеры проектирования на VHDL
4.1. Стили описания поведения
Стили описания поведения
Рассмотрим различные стили описания одного и того же
поведения на примере дешифратора DC(2), который имеет два входных
полюса и четыре выходных ( рис. 4.1) .
x(0)
y(0)
y(1)
y(2)
y(3)
DС
x(1)
Рис. 4.1. Дешифратор
На рис. 4.1 слева и справа указаны имена входных и выходных
полюсов, употребляемых в VHDL-описании. Функции дешифратора
имеют следующий вид:
y0=x0 ∧
y1=x0 ∧
y2= x0 ∧
y3= x0 ∧
x1;
x1;
x1;
x1;
Интерфейс дешифратора
entity Decoder is
port
(X: in Bit_vector (0 to 1);
Y: in Bit_vector (0 to 3));
end Decoder;
Стили описания поведения
129
Представим различные стили описания функционирования
дешифратора: "чисто" структурное описание, описание в виде потока
данных, процедурное описание. Заметим, что при спецификации
цифровых систем допустим смешанный стиль, что весьма удобно при
проектировании.
Структурное описание архитектурного тела в виде схемы в
базисе инверторов (Inverter) и двухвходовых элементов И (AND_Gate)
имеет вид
architecture structure of Decoder is
signal S: bit_vector (0 to 1);
component AND_Gate port
(A, B: in Bit; D: out Bit);
end component;
component Inverter port (A: in Bit; B: out Bit);
end component;
Inv1: Inverter port map (A=>x(0), B=>s(0));
Inv2: Inverter port map (A=>x(1), B=>s(1));
A1:AND_Gate port map (A=>s(0), B=>s(1), D=>y(0));
A2:AND_Gate port map (A=>s(0), B=>x(1), D=>y(1));
A3:AND_Gate port map (A=>x(0), B=>s(1), D=>y(2));
A4:AND_Gate port map (A=>x(0), B=>x(1), D=>y(3));
end structure;
Описание поведения дешифратора в виде потока данных (data
flow).
architecture Data_flow of Decoder is
begin
y(0) <= (not x(0) and (not x(1));
y(1) <= (not x(0) and x(1));
y(2) <= x(0) and (not x(1));
y(3) <= x(0) and x(1));
end Data_flow;
Процедурное описание дешифратора выглядит следующим
образом:
architecture Procedural of Decoder is
130
Глава 4. Примеры проектирования на VHDL
signal s: bit_vector (0 to 3);
begin
process (x, s)
case x is
when "00"=> s<= "1000";
when "01"=> s<= "0100";
when "10"=> s<= "0010";
when "11"=> s<= "0001";
end case;
y<=s;
end process;
end Procedural;
Смешанное описание, использующее элементы структурного
описания и элементы описания "поток данных", приведено ниже.
architecture Mixed of Decoder is
component Inverter port (A: in Bit; B: out Bit);
end component;
signal S: bit_vector (o to 1);
begin
Inv1: Inverter port map (A=>x(0), B=>s(0));
Inv2: Inverter port map (A=>x(1), B=>s(1));
p: process (s, x)
begin
y(0) <= s(0) and s(1);
y(1) <= s(0) and x(1);
y(2) <= x(0) and s(1);
y(3) <= x(0) and x(1));
end process;
end Mixed;
В данном примере структурное описание и описание типа "поток
данных" весьма схожи, так как происходит замена логических
элементов (компонентов) логическими выражениями. Однако для более
сложных схем такая замена может быть совершенно не очевидной.
4.2. Формы описания сигналов
Формы описания сигналов
131
Формы описания сигналов
Битовое представление сигналов может быть громоздким. На
начальных этапах проектирования могут быть использованы другие
типы данных [1].
Устройство
управления
COUT
Component UU
C
Операционное
устройство
OUIN
Component OU
Рис. 4.2. Сигнал С может быть описан как
bit_vector и как перечислимый тип
Пусть устройство управления (UU) посылает четырехбитовый
код в операционное устройство (OU). Четырехбитовый код определяет
операцию, подлежащую выполнению. На рис. 4.2 выходной порт
устройства управления имеет имя COUT, входной порт операционного
устройства – имя OUIN.
Можно описать сигнал C на битовом уровне
signal C: BIT_VECTOR(0 to 3);
или же как перечислимый тип
type CONTROL is (AND, OR, XOR, ADD, SUB, ..., TCOMP);
signal C: CONTROL;
Таким образом, если использовать перечислимый тип, то
управляющую информацию можно представлять в мнемоническом
виде, т.е. именовать команды UU. При этом в архитектурном теле
устройства управления можно было бы использовать операторы
назначения сигнала, такие как
COUT <= ADD;
а в архитектурном теле операционного устройства
if (OUIN = ADD) then ...
При таком подходе разработчик модели освобождается от
необходимости беспокоиться о низкоуровневых деталях [1].
Другой вариант описания сигнала C выглядит следующим
образом:
subtype CONTROL is INTEGER range 0 to 15;
signal C: CONTROL;
132
Глава 4. Примеры проектирования на VHDL
Подтип CONTROL ограничивает диапазон значений, которые
могут быть присвоены сигналу C, тем самым обеспечивается
некоторый контроль ошибок.
В некоторых случаях может понадобиться как битовый уровень,
так и более высокий уровень - типа INTEGER. Для преобразования
типов нужны функции. Ниже описаны две функции.
Функция BIN4_TO_INT преобразует битовые векторы в целые
числа путем суммирования соответствующих степеней двойки.
Функция INT_TO_BIN4 выполняет обратную операцию.
Функция INT_TO_BIN4 приведена ниже в пакете vv_vls.
Предоставляем читателю самостоятельно написать VHDL-код функции
BIN4_TO_INT, для образца можно воспользоваться VHDL-кодом
функции BIN2_TO_INT, находящемся в теле пакета vv_vls.
С использованием функций BIN2_TO_IN, INT_TO_BIN4 легко
описывается (на алгоритмическом уровне) поведение схем mult_2,
adder_2, входящих в схему VLSI_1 (см. гл. 1). Определим функции
BIN2_TO_INT, INT_TO_BIN4 в пакете vv_vls.
package vv_vls is
function bin2_to_int (signal w2,w1: bit)
return integer;
function int_to_bin4
(signal INPUT : integer)
return bit_vector;
end vv_vls;
package body vv_vls is
function bin2_to_int
(signal w2,w1: bit)
return integer is
variable sum : integer :=0;
begin
if w1 ='1' then
sum :=1;
else
sum :=0;
end if;
if w2 ='1' then
-- функция преобразования битового
-- вектора в число
Формы описания сигналов
sum := sum+2;
else
sum := sum;
end if;
return sum;
end bin2_to_int;
function int_to_bin4
-- функция преобразования числа
(signal INPUT : integer)
-- в битовый вектор
return bit_vector is
variable fout: bit_vector(0 to 3);
variable temp_a: integer:=0;
variable temp_b: integer:=0;
begin
temp_a:=INPUT;
for i in 3 downto 0 loop
temp_b:=temp_a/(2**i);
temp_a:=temp_a rem (2**i);
if (temp_b=1) then
fout(i):='1';
else
fout(i):='0';
end if;
end loop;
return fout;
end int_to_bin4;
end vv_vls;
architecture functional of mult_2 is
-- функциональное описание
use std.vv_vls.all;
-- умножителя
signal ss, rr : integer range 0 to 3;
signal tt : integer range 0 to 9;
signal tt_sig : bit_vector (0 to 3);
begin
ss <= bin2_to_int(s1,s0);
rr <= bin2_to_int(r1,r0);
tt <= ss*rr;
-- функция умножителя
tt_sig <= int_to_bin4(tt);
t0 <= tt_sig(0);
-- формирование выходных сигналов
133
134
Глава 4. Примеры проектирования на VHDL
t1 <= tt_sig(1);
t2 <= tt_sig(2);
t3 <= tt_sig(3);
end functional;
entity adder_2 is
port (a1,b1,a2,b2 : in BIT;
c2,s2,s1 : out BIT);
end adder_2;
architecture functional of adder_2 is
-- функциональное описание
-- сумматора
use std.vv_vls.all;
signal aa, bb : integer range 0 to 3;
signal cc : integer range 0 to 7;
signal cc_sig : bit_vector (0 to 3);
begin
aa <= bin2_to_int (a1,b1);
bb <= bin2_to_int (a2,b2);
cc <= aa+bb;
-- функция сумматора
cc_sig <= int_to_bin4(cc);
s1 <= cc_sig(0);
-- формирование выходных сигналов
s2 <= cc_sig(1);
c2 <= cc_sig(2);
end functional;
Предлагаем читателю провести моделирование схемы VLSI_1,
используя архитектурные тела functional (алгоритмические описания)
для объектов проекта mult_2, adder_2 вместо архитектурных тел
structure, представленных в гл. 1.
Вернемся к схеме VLSI (разд. 1.1). Чтобы заменить
алгоритмическое описание структурным, необходимо использовать
функцию преобразования типа INTEGER в тип BIT_VECTOR.
Предоставляем читателю сделать это самостоятельно.
135
Описание автоматов
4.3. Описание автоматов
Описание автоматов
Схема с обратной связью
Рассмотрим схему, изображенную на рис. 4.3. В нее входит
элемент памяти (D-триггер) и комбинационный элемент И. Данная
схема описывается в виде двух процессов, причем для описания
функционирования D-триггера вводится функция rising_edge.
&
a
B
D
C
clk
Q
C
R
reset
Рис. 4.3. Схема с обратной связью
(architecture circ_feedback)
architecture circ_feedback of some_entity is
signal b: bit;
function rising_edge (signal s : bit ) return boolean is
begin
return s = '1' and s'event;
end;
begin
process (clk, reset)
begin
if reset = '1' then
c <= '0';
elsif rising_edge(clk)
c <= b;
end if;
end process;
process (a, c)
-- комбинационный процесс
136
Глава 4. Примеры проектирования на VHDL
begin b <= a and c;
end process;
end circ_feedback ;
Глава 4. Примеры проектирования на VHDL
Конечный автомат
Широкое распространение в практике проектирования
дискретных устройств получила модель конечного (абстрактного)
автомата.
Конечный автомат K определяется как набор
K = (A, Z, W, δ , λ , a1 ),
где A = { a1 ,..., aQ } - множество (алфавит) состояний (имеются в
виду внутренние состояния автомата);
Z = { z1 ,..., zN } - множество входных сигналов (входной
алфавит);
W = { w1 ,..., wM } - множество выходных сигналов (выходной
алфавит);
δ - функция переходов, определяющая состояние автомата в
момент времени t+1 в зависимости от состояния автомата и входного
сигнала в момент времени t, иначе говоря,
as = δ (am , z),
(4.1)
где am - состояние автомата в момент времени t; z - входной сигнал в
момент времени t; as - состояние автомата в момент времени t+1;
λ - функция выходов. Если функция λ по состоянию автомата
am и входному сигналу zn определяет значение выходного сигнала wm
wm = λ (aq , zn ),
(4.2)
то конечный автомат называется автоматом Мили , если же
wm = λ (aq),
(4.3)
то конечный автомат называется автоматом Мура;
a1 - начальное состояние автомата в момент времени t =0, a1 ∈A.
Функционирование автомата происходит следующим образом: в
дискретные моменты времени t = 0, 1, 2, 3,... на вход устройства
поступает входной сигнал - один из элементов множества Z, а на
137
Описание автоматов
выходе появляется выходной сигнал - один из элементов множества W,
в этот же момент времени t автомат из состояния am переходит в
состояние as, в котором он будет находиться в момент времени t+1.
Разработаны различные формы задания конечных автоматов.
Например, в табл. 4.1 задан конечный автомат с четырьмя внутренними
состояниями [2].
Таблица 4.1
Входные
сигналы
z1
z2
a1
a2/w1
a4/w5
Состояния
a2
a3
a2/w1
a1/w2
a3/w3
a4/w4
a4
a1/w4
a3/w5
Алфавит состояний A = {a1, a2, a3, a4}, q = 1,...,4. Входной алфавит
Z образуют сигналы z1, z2, т.е. Z = {z1 , z2 }, n = 1,2. Выходной алфавит
W образуют сигналы w1, ..., w5, т.е. W = {w1, w2 ,w3 ,w4,w5}, m = 1,...,5.
На пересечении строки zn и столбца aq в таблице находится состояние as
, в которое должен перейти автомат из состояния aq под воздействием
сигнала zn. После косой черты в этой же графе таблицы указывается
выходной сигнал, выдаваемый автоматом в состоянии aq при
поступлении на его вход сигнала zn . Иначе говоря, табл. 4.1 является
таблицей задания функций δ , λ и называется совмещенной таблицей
переходов и выходов.
Следующий VHDL-код реализует поведение конечного автомата,
заданного в табл. 4.1. Поведение автомата представляется в виде
совокупности двух взаимодействующих процессов (рис. 4.4).
Процесс NS определяет выходной сигнал w и внутренний сигнал
NEXT_state, который является входным для процесса REG. Заметим,
однако, что в списке чувствительности процесса REG имеется только
сигнал clk, который соответствует моментам времени срабатывания
автомата.
Для входных сигналов автомата в пакете vv_vls определяется
перечислимый тип
fsm_in_type is (z1, z2);
138
Глава 4. Примеры проектирования на VHDL
state
z
state
w
Процесс
NS
NEXT_state
clk
Процесс
REG
Рис. 4.4. Описание функционирования конечного автомата в виде
совокупности двух процессов (entity FSM_A)
для выходных сигналов в том же пакете определяется перечислимый
тип
fsm_out_type is (w1 , w2 ,w3 ,w4 ,w5);
Для задания состояний автомата в архитектурном теле
определяется перечислимый тип t_state. Предполагается, что начальное
состояние автомата равно a1. Начальное состояние явно не
указывается, так как при инициализации будет взят элемент нижней
границы перечислимого типа - это и будет элемент a1.
use work.vv_vls.all;
entity FSM_A is
port (z : in fsm_in_type;
clk : in bit;
w : out fsm_out_type);
end FSM_A;
architecture rtl_a of fsm_a is
type T_state is (a1,a2,a3,a4);
signal NEXT_state : T_state;
signal state : T_state;
begin
NS : process (state, z)
Описание автоматов
begin
NEXT_state <= state;
case state is
when a1 =>
if (z=z1) then NEXT_state <= a2; w <= w1;
elsif (z=z2) then NEXT_state <= a4; w <= w5;
end if;
when a2 =>
if (z=z1) then NEXT_state <= a2; w <= w1;
elsif (z=z2) then NEXT_state <= a3; w <= w3;
end if;
when a3 =>
if (z=z1) then NEXT_state <= a1; w <= w2;
elsif (z=z2) then NEXT_state <= a4; w <= w4;
end if;
when a4 =>
if (z=z1) then NEXT_state <= a1; w <= w4;
elsif (z=z2) then NEXT_state <= a3; w <= w5;
end if;
end case;
end process;
REG : process(clk)
begin
if clk = '1' then
state <= NEXT_state;
end if;
end process;
end rtl_a;
Сделав следующие назначения сигналов z, clk
z <= z1,
z2 after 50 ns,
z1 after 100 ns,
z2 after 150 ns,
z1 after 200 ns,
z2 after 250 ns;
clk <= '1',
139
140
Глава 4. Примеры проектирования на VHDL
'0' after 25 ns,
'1' after 50 ns,
'0' after 75 ns,
'1' after 100 ns,
'0' after 125 ns,
'1' after 150 ns,
'0' after 175 ns,
'1' after 200 ns,
'0' after 225 ns,
'1' after 250 ns;
"снаружи" объекта FSM_A, получим соответствующую временную
диаграмму (рис. 4.5) функционирования автомата.
Многократное изменение синхросигнала clk можно более
компактно описать в виде процесса generator. Переменная number
задает число тактов. В данном случае число тактов равно 5.
generator : process
variable number : integer := 5;
begin
for i in 1 to number loop
clk <= transport '1'; wait for 25 ns;
clk <= transport '0'; wait for 25 ns;
end loop;
end process;
При схемной реализации автомата обычно поступают
следующим образом. Выделяют комбинационную часть автомата и
память. Как же детализировать описание поведения автомата на случай
элементов памяти того или иного типа? В случае нашего примера
будем реализовывать элементы памяти на D-триггерах. Заметим, что в
архитектурном теле rtl_a для entity FSM_A не указывается, как будут
функционировать элементы памяти. Так как поведение D-триггера нам
известно, можем использовать соответствующий VHDL-код для
описания процесса REG. Описание поведения конечного автомата в
виде совокупности двух взаимодействующих процессов - процесса NS
и детализированного процесса REG - показано на рис. 4.6.
1
100
w2
a1
a3
z1
125
150
w5
a4
a1
z2
175
200
w4
a1
a4
z2
225
250
Рис. 4.5. Временная диаграмма функционирования конечного автомата
w3
w1
w
0
a3
a2
Next_state
clk
a2
a1
State
75
z2
50
z1
z1
25
z
0
w5
a4
a1
z2
Время
142
Глава 4. Примеры проектирования на VHDL
use work.vv_vls.all;
entity FSM is
port (z : in fsm_in_type;
clk, rst : in bit;
w : out fsm_out_type);
end FSM;
architecture rtl of fsm is
type T_state is (a1,a2,a3,a4);
signal NEXT_state, state : T_state;
begin
NS : process (state, z)
-- комбинационный процесс
...
-- описание процесса NS дано в архитектурном теле
-- rtl_a для entity FSM_A
end process NS;
REG: process (clk, rst)
-- процесс REG для D-триггера
begin
if (rst = '1') then state <= a1;
elsif clk'event and clk = '1' then
state <= NEXT_state;
end if;
end process REG;
end rtl;
z
Процесс
NS
w
NEXT_state
Процесс
REG
clk
rst
Рис. 4.6. Структура конечного автомата
(entity FSM)
state
Описание автоматов
143
Дальнейшая детализация поведения автомата связана с
кодированием значений перечислимых типов булевыми векторами,
описанием функций комбинационной части схемы и формированием
регистра триггеров. В качестве упражнения можно составить VHDLкод для структурной схемы автомата, для этого можно использовать
приведенную в [2] структуру: булевы функции для комбинационной
части и регистр D-триггеров.
Далее рассмотрим различные способы структурной организации
автоматов Мура и Мили и приведем общие планы описания их на языке
VHDL, не конкретизируя функции комбинационных частей и регистров
элементов памяти.
Автомат Мура
Рассмотрим схему moore1, изображенную на рис. 4.7. Не будем
конкретизировать типы сигналов a, d. Может быть дано следующее
описание поведения схемы moore1:
entity system is
port (clock: boolean; a: some_type;.d: out some_type);
end system;
architecture moore1 of system is
signal b, c: some_type;
begin process (a, c)
begin b <= F1(a, c);
end process;
process (c)
begin d <= F2(c);
end process;
process
begin
wait until clock;
c <= b;
end process;
end moore1;
144
Глава 4. Примеры проектирования на VHDL
b
F1
c
Регистр
d
F2
a
clock
Рис. 4.7. Схема moore1
Для схемы moore1 более компактное описание представлено
архитектурным телом moore1_1.
architecture moore1_1 of system is
signal c: some_type;
begin
process (c)
-- процесс для комбинационной логики
begin
d <= F2(c);
end process;
process -- процесс для последовательностной логики
begin
wait until clock;
c <= F1(a, c);
end process;
end moore1_1;
В литературе автоматом Мура называют также схему с памятью,
у которой выходные функции равны состояниям элементов памяти.
Например, для схемы moore2 (рис. 4.8 ) описание поведения имеет вид
architecture moore2 of system is
begin
process
begin wait
until clock;
d <= F(a,d);
end process;
end moore2;
145
Описание автоматов
Выходной
регистр d
F
a
clock
Рис. 4.8. Схема moore2
Автомат Мили
Схема mealy, реализующая некоторый автомат Мили, изображена
на рис. 4.9, а ниже представлено описание ее поведения.
architecture mealy of system is
signal c: some_type;
begin
process (a, c)
-- процесс для комбинационной логики
begin
d <= F2(a, c);
end process;
process
-- процесс для последовательностной логики
begin
wait until clock;
c <= F1(a, c);
end process;
end mealy;
F1
b
Регистр
a
clock
Рис. 4.9. Схема mealy
c
F2
d
146
Глава 4. Примеры проектирования на VHDL
Параллельный автомат
Все шире в практике проектирования цифровых систем
используются языки и формальные модели, позволяющие описывать
параллелизм и асинхронность логического управления. Одной из таких
моделей является модель параллельного автомата. Отличительной
особенностью параллельного автомата является то, что он может
одновременно находиться в нескольких состояниях, называемых
частичными [4]. В работе [4] для описания функционирования
параллельного автомата используется язык ПРАЛУ. Язык ПРАЛУ [4]
предназначен для описания параллельных алгоритмов логического
управления. Его характерными особенностями являются логическая
стройность,
простота,
компактность
получаемых
описаний,
использование двоичных (булевых) переменных для входных и
выходных
переменных
устройства
управления,
алгоритм
функционирования которого задан на языке ПРАЛУ. Полное описание
языка ПРАЛУ содержится в [4].
Дадим некоторые сведения по языку ПРАЛУ, касающиеся
параллельных автоматов.
Будем считать исходным ПРАЛУ-описание, состоящее из
элементарных цепочек. Согласно [4] элементарной называется цепочка
вида
µi : -ki′ →ki" →νi ,
(4.4)
где операция -ki′ или →ki" или обе вместе в ней могут отсутствовать.
В общем случае элементарная цепочка состоит из четырех частей:
µi - множество начальных меток цепочки;
-ki′ - операция ожидания события ki′ ;
→ki" - операция действия;
νi - множество заключительных меток цепочки.
Двоеточие служит разделителем, а стрелка перед νi играет роль
операции внесения элементов в текущее множество запуска цепочек.
Множество M, называемое множеством запуска цепочек, получается в
результате объединения множеств начальных и заключительных меток
всех цепочек. Поясним сначала, что представляют собой операции
ожидания и действия, а затем объясним, каким образом выполняется
алгоритм в целом, т.е. как выполняются цепочки, как они
взаимодействуют друг с другом и какова роль в этом множества M.
147
Описание автоматов
В записи (4.4) ki′, ki" представляют собой элементарные
конъюнкции булевых переменных. Конъюнкции ki′ образуются из
литералов булевых переменных множества X, конъюнкции ki"
образуются из литералов переменных множества Y. Если конъюнкция
ki′, ( ki" ) отсутствует в (4.4), то предполагается, что она тождественно
равна 1. Множество X представляет собой множество входных
переменных устройства управления (УУ), множество Y - выходных
переменных (рис. 4.10). Предполагается, что алгоритм, представленный
ПРАЛУ-описанием, реализует поведение (функции) УУ.
z1
Устройство
управления
(ПРАЛУ-алгоритм)
X
Y
Объект
управления
z_end
Рис.4.10. ПРАЛУ-описание реализует функции
устройства управления
Операция -ki′ представляет собой операцию ожидания события ki′.
Выполнение этой операции сводится к ожиданию события, когда
переменные, входящие в конъюнкцию ki′, примут значения,
обращающие ki′ в единицу.
Операция действия →ki" означает присвоение таких значений
переменным конъюнкции ki" , при которых ki" обращается в единицу.
Цепочка (4.4) срабатывает, если в текущем множестве запуска
содержится множество µi и если выполнилась операция ожидания -ki′ .
Срабатывание цепочки заключается в немедленном удалении
множества µi из текущего множества запуска, после чего выполняется
операция действия →ki" , а затем немедленно добавляются элементы
множества νi в текущее множество запуска. В начале работы алгоритма
в текущее множество запуска включается метка 1, алгоритм
заканчивает работу, если множество запуска содержит заключительную
метку. В процессе работы алгоритма некоторые цепочки могут
выполняться одновременно (параллельно), поэтому такой формализм
148
Глава 4. Примеры проектирования на VHDL
позволяет
описывать
параллельные
алгоритмы
логического
управления. В [4] показано, что множество элементарных цепочек
представляет собой параллельный автомат. При этом множество таких
цепочек должно удовлетворять определенным требованиям, например,
цепочки i, j, имеющие одинаковые множества начальных меток,
должны иметь ортогональные конъюнкции в операциях ожидания.
Другие требования к корректности исходных ПРАЛУ-описаний
изложены в [4].
Будем предполагать, что исходное ПРАЛУ-описание является
корректным.
Рассмотрим вопрос о преобразовании ПРАЛУ-описаний в VHDLкоды.
Естественно, сначала нужно, если потребуется, изменить
идентификаторы языка ПРАЛУ в соответствии с требованиями языка
VHDL. После этого преобразование ПРАЛУ-описаний в VHDL-коды
может быть полностью автоматизировано. Покажем, как это может
быть сделано.
Рассмотрим ПРАЛУ-описание [4], в котором X = {a, b, c, d}, Y =
={u, v, w}. В элементарных конъюнкциях ki′ , ki" отрицательный
литерал x i булевой переменной xi будем записывать в виде xi′.
Номер цепочки
1
(начало)
1: -u →ab →9
2
9: -u′ →2.3
3
2: -v′w →b′c →10
4
10: -w′ →b →11
5
11: →c′ →2
6
2: -v →a′c →4.5
7
3: -uw →d →6
8
4: -u′v′ →a →12
9
12: -u →a′ →4
10
4: -u →ab′ →7
11
5: -v′w →c′ →8
149
Описание автоматов
12
6.7.8: →a′d →13
13
13: -w′ →. (конец)
В данном примере идентификаторы u, v, w, a, b, c, d ПРАЛУописания являются однобуквенными и проблем с их изменением не
возникает.
Отдельное ПРАЛУ-описание переводится в объект проекта языка
VHDL. Именем entity будет имя ПРАЛУ-описания. Обозначим через
behavior имя архитектурного тела для формируемого объекта проекта.
Формирование интерфейса объекта осуществляется следующим
образом.
1. Имя ПРАЛУ-описания становится именем объекта проекта в
языке VHDL. Пусть в нашем примере example будет именем ПРАЛУописания.
2. По спискам входных (INP) и выходных (OUT) переменных
формируется раздел port VHDL-кода, при этом переменные языка
ПРАЛУ специфицируются на языке VHDL как битовые сигналы (bit).
В список входных переменных добавляется битовый сигнал z1, в
список выходных переменных - битовый сигнал z_end. Назначение
сигналов z1, z_end поясним позже.
В нашем примере интерфейс объекта проекта будет иметь вид
entity example is
port ( u,v,w,z1 : in bit;
a,b,c,d, z_end : out bit);
end example;
Для ПРАЛУ-описания формирование архитектурного тела
объекта проекта осуществляется в виде совокупности процессов языка
VHDL.
Каждой элементарной цепочке ПРАЛУ-описания взаимно
однозначно соответствует процесс языка VHDL.
В архитектурном теле декларируются внутренние сигналы типа
bit. Каждый такой сигнал взаимно однозначно соответствует элементу
множества запуска M, за исключением первого и последнего элемента
множества M. Будем считать, что элемент 1 из множества M является
входным сигналом z1, разрешающим работу алгоритма в целом.
Единичное значение выходного сигнала z_end будет сигнализировать о
том, что алгоритм закончил свою работу (см. рис. 4.10). Сигналы z1,
150
Глава 4. Примеры проектирования на VHDL
z_end могут быть использованы для записи VHDL-кодов тех ПРАЛУописаний, которые устроены иерархически (рис.4.11).
ПРАЛУ-алгоритм
Головной блок
z1_1
z_end_1
Подчиненный
блок 1
z1_n
.. .. ..
z_1
z_end_n
Подчиненный
блок n
z_end
Объект управления
Рис. 4.11. Взаимодействие головного и подчиненных блоков иерархического
ПРАЛУ-алгоритма осуществляется с помощью сигналов z1, z_end
В примере элементу 1 множества M будет соответствовать сигнал
z1, заключительной метке (точке) будет соответствовать сигнал z_end.
Таким образом, меткам 2, 3, ..., 11, 12, 13 будут соответствовать
внутренние сигналы z2, z3,..., z11, z12, z13 архитектурного тела.
Покажем теперь, каким образом элементарная цепочка
переводится в процесс языка VHDL. Пронумеруем цепочки, как это
показано в примере. Номера цепочек не следует путать с номерами
начальных меток. Номер j цепочки будет соответствовать процессу pj в
архитектурном теле.
151
Описание автоматов
Все процессы, соответствующие цепочкам, будут ожидающими,
т.е. не будут иметь списков сигналов запуска. Срабатывание цепочки на
языке VHDL записывается с помощью оператора wait (ждать).
Рассмотрим, например, цепочку 3
2: -v′w →b′c →10 ,
которой будет соответствовать процесс p3. Фрагмент VHDL-кода
приведен ниже. Заметим, что комментарии на языке VHDL начинаются
с двух смежных знаков дефиса и продолжаются до конца строки.
p3 : process
-- процесс, соответствующий цепочке 3
begin
wait until ( (v='0') and (w = '1') and (z2 = '1')); -- оператор ожидания
z2 <= transport '0';
-- изымание метки 2 из текущего множества
запуска
b<= transport '0'; c<= transport '1';
-- операция действия
z10 <= transport '1';
-- занесение заключительной метки 10 в
-- текущее множество запуска
end process p3;
Процесс p3 является ожидающим, операторы назначения сигналов,
записанные после оператора wait, будут выполняться, если будет
истинным булево выражение
(v='0') and (w = '1') and (z2 = '1'),
записанное после ключевого слова until. Оно будет истинным (примет
значение true), если битовые переменные y, w, z2 примут значение 0,1,1
соответственно. В процессе p3 в операторе назначения сигнала
использовано ключевое слово transport, т.е. используется транспортная
задержка. Транспортная задержка предполагает, что все изменения
сигналов будут передаваться независимо от того, сколько времени
будет сохраняться новое значение сигнала.
Заметим, что записанные после оператора wait операторы
назначения сигналов, представляющие собой изымание меток из
текущего множества запуска, операцию действия и внесение
заключительных меток в текущее множество запуска, будут
выполняться параллельно. Поэтому, чтобы определить временной
152
Глава 4. Примеры проектирования на VHDL
интервал их выполнения, в практических ситуациях можно вносить
конкретные временные задержки. Пусть требуется, чтобы перед
операцией действия была задержка 20 ns, а сигналы, устанавливающие
значение 0 для переменной b и значение 1 для переменной c, были
стабильными в течение 10 ns, а сигналы z2, z10 были стабильны 5 ns. В
этом случае процесс p3 будет иметь вид
p3 : process
begin
wait until ( (v='0') and (w = '1') and (z2 = '1'));
z2 <= transport '0'after 5 ns;
wait for 20 ns;
-- ожидание перед операцией действия
b<= transport '0' after 10 ns;
c<= transport '1' after 10 ns;
z10 <= transport '1' after 5 ns;
end process p3;
Ниже представлен VHDL-код архитектурного тела behavior
объекта проекта для примера ПРАЛУ-описания, составленного из 13
элементарных цепочек.
architecture behavior of example is
-- декларация внутренних сигналов
signal z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13 : bit;
begin
p1 : process
begin
wait until ((u='1') and (z1 = '1'));
a<= transport '1'; b<= transport '1' ;
z9 <= transport '1' ;
end process p1;
p2 : process
begin
wait until ((u='0') and (z9 = '1'));
z9 <= transport '0' ;
z2 <= transport '1'; z3 <= transport '1';
end process p2;
p3 : process
Описание автоматов
begin
wait until ( (v='0') and (w = '1')
and (z2 = '1'));
z2 <= transport '0' ;
b<= transport '0'; c<= transport '1';
z10 <= transport '1';
end process p3;
p4 : process
begin
wait until((w = '0') and (z10 = '1'));
z10 <= transport '0';
b <= transport '1';
z11 <= transport '1';
end process p4;
p5 : process
begin
wait until (z11 = '1');
z11 <= transport '0';
c<= transport '0';
z2 <= transport '1' ;
end process p5;
p6 : process
begin
wait until ((v='1') and (z2 = '1'));
z2 <= transport '0';
a <= transport '0'; c <= transport '1' ;
z4 <= transport '1';
z5 <= transport '1';
end process p6;
p7 : process
begin
wait until ((u='1') and (w = '1') and (z3 = '1'));
z3 <= transport '0';
d <= transport '1';
z6 <= transport '1';
end process p7;
p8 : process
begin
wait until ((u='0') and (v = '0') and (z4 = '1'));
z4 <= transport '0';
153
154
Глава 4. Примеры проектирования на VHDL
a <= transport '1';
z12 <= transport '1';
end process p8;
p9 : process
begin
wait until ((u='1') and (z12 = '1'));
z12 <= transport '0';
a <= transport '0';
z4 <= transport '1';
end process p9;
p10 : process
begin
wait until ((u='1') and (z4 = '1'));
z4 <= transport '0';
a <= transport '1'; b<= transport '0';
z7 <= transport '1';
end process p10;
p11 : process
begin
wait until ((v='0') and (w = '1') and (z5 = '1'));
z5 <= transport '0';
c <= transport '0';
z8 <= transport '1';
end process p11;
p12 : process
begin
wait until ((z6='1') and (z7 = '1') and (z8 = '1'));
z6 <= transport '0'; z7 <= transport '0'; z8 <= transport '0';
a <= transport '0'; d <= transport '1';
z13 <= transport '1';
end process p12;
p13 : process
begin
wait until ((w='0') and (z13 = '1'));
z13 <= transport '0';
z_end <= '1';
end process p13;
end behavior;
Отладка VHDL-описаний
155
Очевидно, что преобразование ПРАЛУ-описания в VHDL-код
может быть автоматизировано.
При
автоматизированном
проектировании
совместное
использование языков ПРАЛУ и VHDL может быть организовано
следующим образом. Так как в существующих системах
моделирования VHDL-кодов проводится только проверка правильности
синтаксических конструкций языка VHDL, то в качестве исходного
описания параллельного алгоритма целесообразно взять ПРАЛУописание, семантическая корректность которого может быть проверена
с помощью хорошо развитых формальных методов верификации, когда
параллельный алгоритм проверяется на живость, безопасность, наличие
тупиковых состояний и т.д. [4]. После семантической отладки
алгоритма осуществляется автоматическое преобразование ПРАЛУописания в VHDL-код, который может быть аппаратно реализован в
виде СБИС типа FPGA.
4.4. Отладка VHDL-описаний
Отладка VHDL-описаний
Отладка VHDL-кодов происходит путем подачи входных
сигналов в объект проекта, после чего происходит сравнение
полученных реакций с ожидаемыми. Этот процесс, по существу,
аналогичен отладке программ. С точки зрения "отладки" аппаратуры
этот процесс напоминает тестирование схемы на предмет установления
правильности ее функционирования.
Пример тестирования VHDL-кода схемы VLSI_1.
entity test_vlsi_1 is
end test_vlsi_1;
architecture test of test_vlsi_1 is
component vlsi_1
port (a2,a1,b2,b1,x : in BIT;
d4,d3,d2,d1 : out BIT);
end component;
signal a2, a1, b2, b1, x, d4, d3,d2,d1 : BIT;
begin
p:component vlsi_1
port map (a2 => a2, a1=>a1, b2=>b2,b1=>b1,x=>x,
d4=>d4, d3=>d3,d2=>d2,d1=>d1);
b2 <= '1'; b1 <= '1'; a2 <= '1'; a1 <= '0', '1' after 50 ns;
156
Глава 4. Примеры проектирования на VHDL
x <= '0', '1' after 30 ns, '0' after 70 ns ;
end test;
Временная диаграмма показана на рис. 4.12. В табл. 4.2 дано
функционирование схемы во времени.
0
30ns 50ns
70ns
100ns
Время
a2
1
0
a1
1
0
b2
1
0
b1
1
0
x
1
0
d4
1
0
d3
1
0
d2
1
0
d1
1
0
Рис. 4.12. Временная диаграмма
157
Отладка VHDL-описаний
Таблица 4.2
Сигналы
a=(a2, a1)
b=(b2,b1)
x=(x)
d=(d4,d3,d2,d1)
t=[0ns, 30ns]
2
3
0 (сложение)
5
Время
t=[30ns, 50ns] t=[50ns, 70ns]
2
3
3
3
1(умножение) 1(умножение)
6
9
t=[70ns,100ns]
3
3
0 (сложение)
6
В данном примере объект проекта test_vlsi_1 представляет собой
"оболочку" (рис. 4.13) объекта проекта vlsi_1 с единственной целью организовать подачу входных сигналов в объект vlsi_1, так как внутри
архитектурного тела объекта vlsi_1 нельзя назначить входные сигналы.
Входные сигналы для entity должны быть назначены "снаружи"!
a2
a1
d4
b2
b1
d3
S
d2
d1
x
entity VLSI 1
entity test_VLSI_1
Рис. 4.13. При тестирование объекта VLSI_1
entity test_VLSI_1 не имеет портов
158
Глава 4. Примеры проектирования на VHDL
4.5. Синтезируемое подмножество языка VHDL
Глава 4. Примеры проектирования на VHDL
Синтезируемое подмножество языка VHDL
После того как проектировщик убедился в корректности VHDLмодели цифровой системы, возникает проблема программной либо
схемной реализации данной модели. Схемные реализации, как правило,
являются более быстродействующими, поэтому важной задачей
является задача синтеза схемы, функции которой реализуют поведение
VHDL-модели. На практике, однако, переход к соответствующей
логической схеме осуществляется не для всего языка VHDL, а только
для
некоторого
подмножества
этого
языка,
называемого
синтезируемым подмножеством. Для VHDL-модели цифровой
системы, описанной на синтезируемом подмножестве языка VHDL,
можно получить схему. Обычно это интегральная схема типа ПЛИС
либо схема программируемой пользователем вентильной матрицы [5].
Общий метод получения такой схемы является компилятивным операторы языка VHDL заменяются компилятами. Компилят - это
подсхема, реализующая вполне определенный оператор языка,
например оператор сложения. При синтезе схемы типы данных bit
отражаются при синтезе в проводники (полюса) схем, типы данных
bit_vector - в шины (жгуты проводников). Перечислимые типы данных
при синтезе кодируются булевыми векторами. Кодирование обычно
ведется с использованием минимального числа кодирующих
переменных. Например, для перечислимого типа
type my_state is (RESET, IDLE, RW_CYCLE, INT_CYCLE);
может быть проведено кодирование
RESET = ''00'',
IDLE = ''01'',
RW_CYCLE = ''10'',
INT_CYCLE = ''11''.
Очевидно, в кодах 00, 01, 10, 11 используются только две
кодирующие булевы переменные.
Переменные языка VHDL, мгновенно передающие свои значения,
исчезают при схемной реализации. В приведенном ниже примере
проследите за переменной W в VHDL-коде и в соответствующей схеме
(рис. 4.14).
Пример схемной "реализации" переменных языка VHDL.
Синтезируемое подмножество языка VHDL
159
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity xor_var is
port (A,B,C : in std_logic;
X,Y : out std_logic);
end xor_var;
architecture example of xor_var is
begin
P : process (A,B,C)
variable W: std_logic;
begin
W := A;
X < = C xor W;
W := B;
Y <= C xor D;
end process;
end example;
C
A
C
B
⊕
X
⊕
Y
Рис. 4.14. Исчезновение переменных
при схемной реализации
Для логических операторов and, or, nand, nor, xor, xnor, not,
имеющих тип bit, boolean, arrays, bit_vector, компиляция в схему
осуществляется прямым преобразованием логических выражений в
соответствующие логические вентили (элементы).
Пример схемной реализации логических выражений.
160
Глава 4. Примеры проектирования на VHDL
entity logical_ops_1 is
port (a, b, c, d: in bit; m: out bit);
end logical_ops_1;
architecture example of logical_ops_1 is
signal e: bit;
begin
m <= (a and b) or e;
-- оператор назначения сигнала
e <= c xor d;
end example;
Схема, реализующая поведение объекта logical_ops_1, приведена
на рис. 4.15.
a
b
c
d
&
1
m
⊕
Рис. 4.15. Схемная реализация логического
выражения для типа bit
Пример схемной реализации логических выражений типа
bit_vector.
entity logical_ops_2 is
port (a, b: in bit_vector (0 to 3); m: out bit_vector (0 to 3));
end logical_ops_2
architecture example of logical_ops_2 is
begin
m <= a and b;
end example;
Соответствующая схема приведена на рис. 4.16.
Синтезируемое подмножество языка VHDL
a(0)
b(0)
a(1)
b(1)
a(2)
b(2)
a(3)
b(3)
&
m(0)
&
m(1)
&
m(2)
&
m(3)
161
Рис. 4.16. Схемная реализация логического
выражения для типа bit_vector
Схемная реализация операторов отношения
Операторами отношения являются следующие операторы
= (равно);
/= (не равно)
> (больше);
< (меньше);
>= (больше или равно);
<= (меньше или равно).
Операторы = , /= определяются в языке VHDL для всех типов.
Операторы (>=, <=, >, < ) определяются для числовых типов,
перечислимых типов и некоторых массивов. Результирующий тип для
всех операторов boolean. Следующие два примера показывают схемную
реализацию для операторов a=b, a>=b.
entity relational_ops_1 is
port (a, b: in bit_vector (0 to 3); m: out boolean);
end relational_ops_1;
architecture example of relational_ops_1 is
begin
162
Глава 4. Примеры проектирования на VHDL
m <= a = b;
end example;
Схема, реализующая оператор равенства для типа bit_vector,
приведена на рис. 4.17.
a(0)
b(0)
a(1)
b(1)
⊕
⊕
1
m
a(2)
b(2)
a(3)
b(3)
⊕
⊕
Рис. 4.17. Схемная реализация оператора a=b
для типа bit_vector (0 to 3)
entity relational_ops_2 is
port (a, b: in integer range 0 to 3; m: out boolean);
end relational_ops_2;
architecture example of relational_ops_2 is
begin
m <= a >= b;
end example;
Схема, реализующая оператор >= для типа integer, показана на
рис. 4.18.
163
Синтезируемое подмножество языка VHDL
b0
1
a0
&
1
b1
a1
&
⊕
&
1
b2
a2
&
⊕
&
1
b3
a3
&
⊕
m
&
Рис. 4.18. Схемная реализация оператора отношения а>=b для
целых чисел a =(a3,a2,a1,a0), b =(b3,b2,b1,b0)
164
Глава 4. Примеры проектирования на VHDL
Схемная реализация арифметических операторов
Арифметические операторы
+ (сложение);
- (вычитание);
* (умножение);
/ (деление);
mod (модуль);
rem (остаток );
abs (абсолютное значение);
** (возведение в степень)
определяются для числовых типов.
Операторы ( +, - ) являются достаточно "дорогостоящими"
(дающими сложные схемы). Операторы (*, / , mod, rem) являются
очень дорогостоящими. Обычно при синтезе делается специальная
оптимизация, если справа от оператора находится константа или число,
не большее 2. Реализация оператора (abs) не является сложной.
Оператор (**) поддерживается только для констант.
Примеры схем, реализующих операторы сложения и умножения,
уже рассматривались в данной книге.
Схемная реализация операторов управления
Схемным "аналогом" оператора if является, по существу,
мультиплексор (рис. 4.19) с одним управляющим входом, где b, c
выступают в качестве настроечных входов, вход a - в качестве
управляющего. Функционирование мультиплексора описывается
следующей формулой: m = a& c ∨ a& b .
entity control_if is
port (a, b, c: boolean; m: out boolean);
end control_if;
architecture example of control_if is
begin
process (a, b, c)
variable n: boolean;
begin
if a then n := b;
165
Синтезируемое подмножество языка VHDL
else n := c;
end if;
m <= n;
end process;
end example;
Схема, реализующая оператор if, изображена на рис. 4.19: если
a=1, то m=b, если a=0, то m=c. Предлагаем читателю сравнить
функцию, реализуемую процедурой MX, содержащейся в пакете
multiplexer (разд.1.2), с функцией объекта проекта control_if.
Однако не всегда очевидна та логическая схема, которая
соответствует оператору языка VHDL. В качестве примера укажем на
тот факт, что в компиляторах, осуществляющих схемную реализацию
VHDL-кода, оператор if, у которого после ключевого слова else не
производится никаких действий, интерпретируется как D-триггер
(задержка). Поэтому получение нужных логических схем по VHDLкодам с помощью САПР требует тщательного изучения библиотеки
компилятов.
a
1
&
с
1
a
b
m
&
Рис. 4.19. Схемная реализация оператора управления if
(entity control_if)
Схемная реализация оператора case
entity control_case is
port (sel: in bit_vector (0 to 1); a,b,c,d : in bit; m: out bit);
end control_case;
architecture example of control_case is
begin
166
Глава 4. Примеры проектирования на VHDL
process (sel,a,b,c,d)
begin
case sel is
when
"00" => m <= c;
when
"01" => m <= a;
when
"10" => m <= d;
when others => m <= b;
end case;
end process;
end example;
Схема, реализующая оператор case, изображена на рис. 4.20.
sel (1)
sel (0)
a
1
&
&
b
&
&
&
c
&
1
&
d
&
Рис.4.20. Схемная реализация оператора case
(entity control_case)
m
Синтезируемое подмножество языка VHDL
167
Схемная реализация подпрограмм и циклов
Операторы generate, loop, for loop, while loop, function, procedure
также могут быть схемно реализованы.
Для каждого вызова подпрограммы и для каждой итерации цикла
создается соответствующая схема.
entity control_loop is
port (a: bit_vector (0 to 3); m: out bit_vector (0 to 3));
end control_loop;
architecture example of control_loop is
begin
process (a)
variable b: bit;
begin
b := '1';
for i in 0 to 3 loop
b:= a(3-i) and b;
m( i ) <= b;
b := b + 1;
end loop;
end process;
end example;
entity subprograms is
port (a: bit_vector (0 to 2); m: out bit_vector (0 to 2));
end subprograms;
architecture example of subprograms is
function simple (w, x, y: bit) return bit is
begin
return (w and x) or y;
end;
begin
process (a)
begin
m(0) <= simple(a(0), a(1), a(2));
m(1) <= simple(a(2), a(0), a(1));
m(2) <= simple(a(1), a(2), a(0));
end process;
end example
168
Глава 4. Примеры проектирования на VHDL
Например, для цикла (entity loop_stmt) и для подпрограммы
(entity subprograms) соответствующие схемы приведены ниже (рис.
4.21, 4.22).
a (0)
&
a (1)
m (3)
&
a (2)
m (2)
&
m (1)
a (3)
m (0)
Рис. 4.21. Схемная реализация оператора loop
(entity control_loop)
a (0)
1
&
m (2)
a (1)
1
&
m (1)
a (2)
1
&
m (0)
Рис. 4.22. Схемная реализация оператора "подпрограмма"
(entity
subprograms)
В заключение можно
сказать,
что мир VHDL большой и
достаточно сложный, так как сложны те электронные схемы и системы,
169
Упражнения
инструментом описания, моделирования, верификации и синтеза
которых он является. За чертой остались еще такие аспекты языка
VHDL, как типы файлов и типы доступа, инородные подпрограммы,
группы, разделяемые переменные и другие вопросы. Автор надеется,
что провести их изучение можно будет, базируясь на материалах,
представленных в данной книге.
Упражнения
УПРАЖНЕНИЯ
1. Правильны ли утверждения
a) структурное VHDL-описание может быть иерархичным;
b) поведенческое VHDL-описание может быть иерархичным;
c) смешанное (структурно-поведенческое) VHDL-описание не
может быть иерархичным.
2. Правильно ли, что структурное описание состоит из компонент
и сигналов?
3. Правильно ли, что все компоненты должны быть
специфицированы на поведенческом уровне?
4. Какие компоненты проекта не имеют структурного описания?
5. Какое устройство реализует поведение, представленное VHDLкодом?
entity EX is
port (A : in std_ulogic_vector(0 to 15);
SEL : in integer range 0 to 15;
Z : out std_ulogic);
end EX;
architecture RTL of EX is
begin
WHAT: process (A, SEL)
begin
for I in 0 to 15 loop
if SEL = I then
Z <= A(I);
end if;
end loop;
end process WHAT;
170
Глава 4. Примеры проектирования на VHDL
end RTL;
Выберите правильный ответ.
a) дешифратор;
в) счетчик;
с) мультиплексор.
Укажите разрядность устройства.
6. Опишите
поведение
конечного
автомата,
используя
двухразмерные массивы для задания совмещенной таблицы переходов
и выходов.
7. Используя информацию о структурной схеме, приведенную в
[2, с. 20-21], составьте VHDL-код и проведите моделирование
конечного автомата, поведение которого задано в архитектурном теле
rtl_a (entity FSM_A).
8. Составьте VHDL-код для генерации синхроимпульсов (см. рис.
4.5) в виде процесса с использованием оператора wait.
9. Как должен быть написан VHDL-код, чтобы с помощью
существующих средств САПР можно было автоматически получить
схему? Выберите правильный ответ.
a) код должен быть написан на поведенческом уровне;
b) код должен быть написан на уровне регистровых передач;
c) код должен быть написан на уровне логических вентилей;
d) средства САПР могут синтезировать схему для любого уровня
VHDL-описания.
10. В данной книге даны различные архитектурные тела для
Dтриггера. Рассмотрите особенности их функционального и
структурного описания. Проведите моделирование.
171
Литература
Литература
Литература
1. Армстронг Дж.Р. Моделирование цифровых систем на
языке VHDL/Пер с англ. - М.: Мир, 1992. - 175 с.
2. Баранов С.И., Скляров В.А. Цифровые устройства на
программируемых БИС с матричной структурой. - М.: Радио и связь,
1986. - 279 с.
3. Бибило П.Н. Кремниевая компиляция заказных СБИС. Минск: Ин-т техн. кибернетики АН Беларуси, 1996. - 268 с.
4. Закревский А.Д. Параллельные алгоритмы логического
управления. - Минск: Ин-т техн. кибернетики НАН Беларуси, 1999. 202 с.
5. Соловьев В.В., Васильев А.Г. Программируемые логические
интегральные схемы и их применение. - Минск: Беларуская навука,
1998. - 270 с.
6. VHDL для моделирования, синтеза и формальной
верификации аппаратуры/Пер с англ. - М: Радио и связь, 1995. - 360с.
7. VHDL’92. Новые свойства языка описания аппаратуры
VHDL/Пер с англ. - М.: Радио и связь, 1995. -256 с.
8. Asheden P.J. The VHDL Cookbook. University of Adelaide,
South Australia. -1990.
9. Chang K.C. Digital design and modeling with VHDL and
synthesis. IEEE Computer Society Press. 1997.
172
Приложения
Приложения
Приложения
1. Форма задания синтаксических конструкций языка VHDL
Форма задания синтаксических конструкций языка VHDL
Для задания синтаксических конструкций языка VHDL
используются так называемые формы Бэкуса-Науэра, служащие для
описания грамматик формальных языков. Для определения
синтаксической конструкции используется выражение
<синтаксическая конструкция>::=<определение>
Используемые фигурные скобки служат для обозначения
повторения выражения, заключенного в них. Выражение может
повторяться k раз (k=0,1,2, ...). При k=0 выражение отсутствует.
Вертикальная черта служит для обозначения альтернативных
случаев. Например,
letter_or_digit ::= letterdigit,
т.е. синтаксическая конструкция символ_или_число определяется как
символ (letter) или цифра (digit).
В случае, например,
choices::=choice{choise},
когда в фигурных скобках стоит то же выражение (с символом
«вертикальная черта»), это означает повторение того же выражения. В
данном примере повторяется выражение «choice».
Квадратные скобки служат для обозначения необязательного
выражения или необязательного слова.
Например, запись
return_statement::=return[expression];
эквивалентна записи
return_statement::=return;return[expression];
Если элемент синтаксической конструкции начинается с курсива,
то выделяемая курсивом часть конструкции несет смысловую нагрузку
(семантическую информацию). Выделяемое курсивом слово может не
приниматься во внимание.
Например, элементы type_name и subtype_name могут
рассматриваться просто как name (имя). В случае type_name
подчеркивается, что это имя типа, в случае subtype_name, что это имя
подтипа.
Синтаксис языка VHDL’93
Синтаксис языка VHDL’93
173
2. Синтаксис языка VHDL’93
Синтаксические
конструкции,
приводимые
в
данном
приложении, можно найти по следующему адресу сети Internet:
http://tech-www.informatik.uni-hamburg.de/vhdl/tools/vhdl-93.bnf
abstract_literal ::= decimal_literal | based_literal
access_type_definition ::= access subtype_indication
actual_designator ::=
expression
| signal_name
| variable_name
| file_name
| open
actual_parameter_part ::= parameter_association_list
actual_part ::=
actual_designator
| function_name ( actual_designator )
| type_mark ( actual_designator )
adding_operator ::= + | - | &
aggregate ::=
( element_association { , element_association } )
alias_declaration ::=
alias alias_designator [ : subtype_indication ] is name [ signature ] ;
alias_designator ::= identifier | character_literal | operator_symbol
allocator ::=
new subtype_indication
| new qualified_expression
architecture_body ::=
architecture identifier of entity_name is
174
Приложения
architecture_declarative_part
begin
architecture_statement_part
end [ architecture ] [ architecture_simple_name ] ;
architecture_declarative_part ::=
{ block_declarative_item }
architecture_statement_part ::=
{ concurrent_statement }
array_type_definition ::=
unconstrained_array_definition | constrained_array_definition
assertion ::=
assert condition
[ report expression ]
[ severity expression ]
assertion_statement ::=
[ label : ] assertion ;
association_element ::=
[ formal_part => ] actual_part
association_list ::=
association_element { , association_element }
attribute_declaration ::=
attribute identifier : type_mark ;
attribute_designator ::= attribute_simple_name
attribute_name ::=
prefix [ signature ] ' attribute_designator [ ( expression ) ]
attribute_specification ::=
attribute attribute_designator of entity_specification is expression ;
base ::= integer
Синтаксис языка VHDL’93
base_specifier ::= B | O | X
base_unit_declaration ::= identifier ;
based_integer ::=
extended_digit { [ underline ] extended_digit }
based_literal ::=
base # based_integer [ . based_integer ] # [ exponent ]
basic_character ::=
basic_graphic_character | format_effector
basic_graphic_character ::=
upper_case_letter | digit | special_character| space_character
basic_identifier ::=
letter { [ underline ] letter_or_digit }
binding_indication ::=
[ use entity_aspect ]
[ generic_map_aspect ]
[ port_map_aspect ]
bit_string_literal ::=
base_specifier " bit_value "
bit_value ::= extended_digit { [ underline ] extended_digit }
block_configuration ::=
for block_specification
{ use_clause }
{ configuration_item }
end for ;
block_declarative_item ::=
subprogram_declaration
| subprogram_body
| type_declaration
| subtype_declaration
175
176
Приложения
| constant_declaration
| signal_declaration
| shared_variable_declaration
| file_declaration
| alias_declaration
| component_declaration
| attribute_declaration
| attribute_specification
| configuration_specification
| disconnection_specification
| use_clause
| group_template_declaration
| group_declaration
block_declarative_part ::=
{ block_declarative_item }
block_header ::=
[ generic_clause
[ generic_map_aspect ; ] ]
[ port_clause
[ port_map_aspect ; ] ]
block_specification ::=
architecture_name
| block_statement_label
| generate_statement_label [ ( index_specification ) ]
block_statement ::=
block_label :
block [ ( guard_expression ) ] [ is ]
block_header
block_declarative_part
begin
block_statement_part
end block [ block_label ] ;
block_statement_part ::=
{ concurrent_statement }
case_statement ::=
Синтаксис языка VHDL’93
[ case_label : ]
case expression is
case_statement_alternative
{ case_statement_alternative }
end case [ case_label ] ;
case_statement_alternative ::=
when choices =>
sequence_of_statements
character_literal ::= ' graphic_character '
choice ::=
simple_expression
| discrete_range
| element_simple_name
| others
choices ::= choice { | choice }
component_configuration ::=
for component_specification
[ binding_indication ; ]
[ block_configuration ]
end for ;
component_declaration ::=
component identifier [ is ]
[ local_generic_clause ]
[ local_port_clause ]
end component [ component_simple_name ] ;
component_instantiation_statement ::=
instantiation_label :
instantiated_unit
[ generic_map_aspect ]
[ port_map_aspect ] ;
component_specification ::=
177
178
Приложения
instantiation_list : component_name
composite_type_definition ::=
array_type_definition
| record_type_definition
concurrent_assertion_statement ::=
[ label : ] [ postponed ] assertion ;
concurrent_procedure_call_statement ::=
[ label : ] [ postponed ] procedure_call ;
concurrent_signal_assignment_statement ::=
[ label : ] [ postponed ] conditional_signal_assignment
| [ label : ] [ postponed ] selected_signal_assignment
concurrent_statement ::=
block_statement
| process_statement
| concurrent_procedure_call_statement
| concurrent_assertion_statement
| concurrent_signal_assignment_statement
| component_instantiation_statement
| generate_statement
condition ::= boolean_expression
condition_clause ::= until condition
conditional_signal_assignment ::=
target <= options conditional_waveforms ;
conditional_waveforms ::=
{ waveform when condition else }
waveform [ when condition ]
configuration_declaration ::=
configuration identifier of entity_name is
configuration_declarative_part
block_configuration
Синтаксис языка VHDL’93
end [ configuration ] [ configuration_simple_name ] ;
configuration_declarative_item ::=
use_clause
| attribute_specification
| group_declaration
configuration_declarative_part ::=
{ configuration_declarative_item }
configuration_item ::=
block_configuration
| component_configuration
configuration_specification ::=
for component_specification binding_indication ;
constant_declaration ::=
constant identifier_list : subtype_indication [ := expression ] ;
constrained_array_definition ::=
array index_constraint of element_subtype_indication
constraint ::=
range_constraint
| index_constraint
context_clause ::= { context_item }
context_item ::=
library_clause
| use_clause
decimal_literal ::= integer [ . integer ] [ exponent ]
declaration ::=
type_declaration
| subtype_declaration
| object_declaration
179
180
Приложения
| interface_declaration
| alias_declaration
| attribute_declaration
| component_declaration
| group_template_declaration
| group_declaration
| entity_declaration
| configuration_declaration
| subprogram_declaration
| package_declaration
delay_mechanism ::=
transport
| [ reject time_expression ] inertial
design_file ::= design_unit { design_unit }
design_unit ::= context_clause library_unit
designator ::= identifier | operator_symbol
direction ::= to | downto
disconnection_specification ::=
disconnect guarded_signal_specification after time_expression ;
discrete_range ::= discrete_subtype_indication | range
element_association ::=
[ choices => ] expression
element_declaration ::=
identifier_list : element_subtype_definition ;
element_subtype_definition ::= subtype_indication
entity_aspect ::=
entity entity_name [ ( architecture_identifier) ]
| configuration configuration_name | open
entity_class ::=
Синтаксис языка VHDL’93
entity
| architecture | configuration
| procedure | function
| package
| type
| subtype
| constant
| signal | variable
| component
| label
| literal
| units
| group
| file
entity_class_entry ::= entity_class [ <> ]
entity_class_entry_list ::=
entity_class_entry { , entity_class_entry }
entity_declaration ::=
entity identifier is
entity_header
entity_declarative_part
[ begin
entity_statement_part ]
end [ entity ] [ entity_simple_name ] ;
entity_declarative_item ::=
subprogram_declaration
| subprogram_body
| type_declaration
| subtype_declaration
| constant_declaration
| signal_declaration
| shared_variable_declaration
| file_declaration
| alias_declaration
| attribute_declaration
| attribute_specification
| disconnection_specification
| use_clause
| group_template_declaration
| group_declaration
entity_declarative_part ::=
{ entity_declarative_item }
181
182
Приложения
entity_designator ::= entity_tag [ signature ]
entity_header ::=
[ formal_generic_clause ]
[ formal_port_clause ]
entity_name_list ::=
entity_designator { , entity_designator }
| others
| all
entity_specification ::=
entity_name_list : entity_class
entity_statement ::=
concurrent_assertion_statement
| passive_concurrent_procedure_call_statement
| passive_process_statement
entity_statement_part ::=
{ entity_statement }
entity_tag ::= simple_name | character_literal | operator_symbol
enumeration_literal ::= identifier | character_literal
enumeration_type_definition ::=
( enumeration_literal { , enumeration_literal } )
exit_statement ::=
[ label : ] exit [ loop_label ] [ when condition ] ;
exponent ::= E [ + ] integer | E - integer
expression ::=
relation { and relation }
| relation { or relation }
| relation { xor relation }
| relation [ nand relation ]
Синтаксис языка VHDL’93
| relation [ nor relation ]
| relation { xnor relation }
extended_digit ::= digit | letter
extended_identifier ::=
\ graphic_character { graphic_character } \
factor ::=
primary [ ** primary ]
| abs primary
| not primary
file_declaration ::=
file identifier_list : subtype_indication file_open_information ] ;
file_logical_name ::= string_expression
file_open_information ::=
[ open file_open_kind_expression ] is file_logical_name
file_type_definition ::=
file of type_mark
floating_type_definition := range_constraint
formal_designator ::=
generic_name
| port_name
| parameter_name
formal_parameter_list ::= parameter_interface_list
formal_part ::=
formal_designator
| function_name ( formal_designator )
| type_mark ( formal_designator )
full_type_declaration ::=
type identifier is type_definition ;
183
184
Приложения
function_call ::=
function_name [ ( actual_parameter_part ) ]
generate_statement ::=
generate_label :
generation_scheme generate
[ { block_declarative_item }
begin ]
{ concurrent_statement }
end generate [ generate_label ] ;
generation_scheme ::=
for generate_parameter_specification
| if condition
generic_clause ::=
generic ( generic_list ) ;
generic_list ::= generic_interface_list
generic_map_aspect ::=
generic map ( generic_association_list )
graphic_character ::=
basic_graphic_character | lower_case_letter |
other_special_character
group_constituent ::= name | character_literal
group_constituent_list ::= group_constituent { , group_constituent }
group_template_declaration ::=
group identifier is ( entity_class_entry_list ) ;
group_declaration ::=
group identifier : group_template_name ( group_constituent_list ) ;
guarded_signal_specification ::=
guarded_signal_list : type_mark
185
Синтаксис языка VHDL’93
identifier ::=
basic_identifier | extended_identifier
identifier_list ::= identifier { , identifier }
if_statement ::=
[ if_label : ]
if condition then
sequence_of_statements
{ elsif condition then
sequence_of_statements }
[ else
sequence_of_statements ]
end if [ if_label ] ;
incomplete_type_declaration ::=
type identifier ;
index_constraint ::= ( discrete_range { , discrete_range } )
index_specification ::=
discrete_range
| static_expression
index_subtype_definition ::= type_mark range <>
indexed_name ::= prefix ( expression { , expression } )
instantiated_unit ::=
[ component ] component_name
| entity entity_name [ ( architecture_identifier ) ]
| configuration configuration_name
instantiation_list ::=
instantiation_label { , instantiation_label }
| others | all
integer ::= digit { [ underline ] digit }
186
Приложения
integer_type_definition ::= range_constraint
interface_constant_declaration ::=
[ constant ] identifier_list : [ in ] subtype_indication [ :=
static_expression ]
interface_declaration ::=
interface_constant_declaration
| interface_signal_declaration
| interface_variable_declaration
| interface_file_declaration
interface_element ::= interface_declaration
interface_file_declaration ::=
file identifier_list : subtype_indication
interface_list ::=
interface_element { ; interface_element }
interface_signal_declaration ::=
[signal] identifier_list : [ mode ] subtype_indication [ bus ] [ :=
static_expression ]
interface_variable_declaration ::=
[variable] identifier_list : [ mode ] subtype_indication [ :=
static_expression ]
iteration_scheme ::=
while condition
| for loop_parameter_specification
label ::= identifier
letter ::= upper_case_letter | lower_case_letter
letter_or_digit ::= letter | digit
library_clause ::= library logical_name_list ;
Синтаксис языка VHDL’93
library_unit ::=
primary_unit
| secondary_unit
literal ::=
numeric_literal
| enumeration_literal
| string_literal
| bit_string_literal
| null
logical_name ::= identifier
logical_name_list ::= logical_name { , logical_name }
logical_operator ::= and | or | nand | nor | xor | xnor
loop_statement ::=
[ loop_label : ]
[ iteration_scheme ] loop
sequence_of_statements
end loop [ loop_label ] ;
miscellaneous_operator ::= ** | abs | not
mode ::= in | out | inout | buffer | linkage
multiplying_operator ::= * | / | mod | rem
name ::=
simple_name
| operator_symbol
| selected_name
| indexed_name
| slice_name
| attribute_name
next_statement ::=
[ label : ] next [ loop_label ] [ when condition ] ;
187
188
null_statement ::= [ label : ] null ;
numeric_literal ::=
abstract_literal
| physical_literal
object_declaration ::=
constant_declaration
| signal_declaration
| variable_declaration
| file_declaration
operator_symbol ::= string_literal
options ::= [ guarded ] [ delay_mechanism ]
package_body ::=
package body package_simple_name is
package_body_declarative_part
end [ package body ] [ package_simple_name ] ;
package_body_declarative_item ::=
subprogram_declaration
| subprogram_body
| type_declaration
| subtype_declaration
| constant_declaration
| shared_variable_declaration
| file_declaration
| alias_declaration
| use_clause
| group_template_declaration
| group_declaration
package_body_declarative_part ::=
{ package_body_declarative_item }
package_declaration ::=
package identifier is
Приложения
Синтаксис языка VHDL’93
package_declarative_part
end [ package ] [ package_simple_name ] ;
package_declarative_item ::=
subprogram_declaration
| type_declaration
| subtype_declaration
| constant_declaration
| signal_declaration
| shared_variable_declaration
| file_declaration
| alias_declaration
| component_declaration
| attribute_declaration
| attribute_specification
| disconnection_specification
| use_clause
| group_template_declaration
| group_declaration
package_declarative_part ::=
{ package_declarative_item }
parameter_specification ::=
identifier in discrete_range
physical_literal ::= [ abstract_literal ] unit_name
physical_type_definition ::=
range_constraint
units
base_unit_declaration
{ secondary_unit_declaration }
end units [ physical_type_simple_name ]
port_clause ::=
port ( port_list ) ;
port_list ::= port_interface_list
189
190
Приложения
port_map_aspect ::=
port map ( port_association_list )
prefix ::=
name
| function_call
primary ::=
name
| literal
| aggregate
| function_call
| qualified_expression
| type_conversion
| allocator
| ( expression )
primary_unit ::=
entity_declaration
| configuration_declaration
| package_declaration
procedure_call ::= procedure_name [ ( actual_parameter_part ) ]
procedure_call_statement ::=
[ label : ] procedure_call ;
process_declarative_item ::=
subprogram_declaration
| subprogram_body
| type_declaration
| subtype_declaration
| constant_declaration
| variable_declaration
| file_declaration
| alias_declaration
| attribute_declaration
| attribute_specification
| use_clause
191
Синтаксис языка VHDL’93
| group_template_declaration
| group_declaration
process_declarative_part ::=
{ process_declarative_item }
process_statement ::=
[ process_label : ]
[ postponed ] process [ ( sensitivity_list ) ] [ is ]
process_declarative_part
begin
process_statement_part
end [ postponed ] process [ process_label ] ;
process_statement_part ::=
{ sequential_statement }
qualified_expression ::=
type_mark ' ( expression )
| type_mark ' aggregate
range ::=
range_attribute_name
| simple_expression direction simple_expression
range_constraint ::= range range
record_type_definition ::=
record
element_declaration
{ element_declaration }
end record [ record_type_simple_name ]
relation ::=
shift_expression [ relational_operator shift_expression ]
relational_operator ::= = |
report_statement ::=
[ label : ]
/= | < | <=
| > | >=
192
Приложения
report expression
[ severity expression ] ;
return_statement ::=
[ label : ] return [ expression ] ;
scalar_type_definition ::=
enumeration_type_definition | integer_type_definition
| floating_type_definition
| physical_type_definition
secondary_unit ::=
architecture_body
| package_body
secondary_unit_declaration ::=
identifier = physical_literal ;
selected_name ::= prefix . suffix
selected_signal_assignment ::=
with expression select
target <= options selected_waveforms ;
selected_waveforms ::=
{ waveform when choices , }
waveform when choices
sensitivity_clause ::= on sensitivity_list
sensitivity_list ::= signal_name { , signal_name }
sequence_of_statements ::=
{ sequential_statement }
sequential_statement ::=
wait_statement
| assertion_statement
| report_statement
| signal_assignment_statement
| variable_assignment_statement
| procedure_call_statement
Синтаксис языка VHDL’93
| if_statement
| case_statement
| loop_statement
| next_statement
| exit_statement
| return_statement
| null_statement
shift_expression ::=
simple_expression [ shift_operator simple_expression ]
shift_operator ::= sll | srl | sla | sra | rol | ror
sign ::= + | signal_assignment_statement ::=
[ label : ] target <= [ delay_mechanism ] waveform ;
signal_declaration ::=
signal identifier_list : subtype_indication [ signal_kind ] [ :=
expression ] ;
signal_kind ::= register | bus
signal_list ::=
signal_name { , signal_name }
| others
| all
signature ::= [ [ type_mark { , type_mark } ] [ return type_mark ] ]
simple_expression ::=
[ sign ] term { adding_operator term }
simple_name ::=
identifier
slice_name ::= prefix ( discrete_range )
string_literal ::= " { graphic_character } "
193
194
Приложения
subprogram_body ::=
subprogram_specification is
subprogram_declarative_part
begin
subprogram_statement_part
end [ subprogram_kind ] [ designator ] ;
subprogram_declaration ::=
subprogram_specification ;
subprogram_declarative_item ::=
subprogram_declaration
| subprogram_body
| type_declaration
| subtype_declaration
| constant_declaration
| variable_declaration
| file_declaration
| alias_declaration
| attribute_declaration
| attribute_specification
| use_clause
| group_template_declaration
| group_declaration
subprogram_declarative_part ::=
{ subprogram_declarative_item }
subprogram_kind ::= procedure | function
subprogram_specification ::=
procedure designator [ ( formal_parameter_list ) ]
| [ pure | impure ] function designator [ ( formal_parameter_list ) ]
return type_mark
subprogram_statement_part ::=
{ sequential_statement }
subtype_declaration ::=
subtype identifier is subtype_indication ;
Синтаксис языка VHDL’93
195
subtype_indication ::=
[ resolution_function_name ] type_mark [ constraint ]
suffix ::=
simple_name
| character_literal
| operator_symbol
| all
target ::=
name
| aggregate
term ::=
factor { multiplying_operator factor }
timeout_clause ::= for time_expression
type_conversion ::= type_mark ( expression )
type_declaration ::=
full_type_declaration
| incomplete_type_declaration
type_definition ::=
scalar_type_definition
| composite_type_definition
| access_type_definition
| file_type_definition
type_mark ::=
type_name
| subtype_name
unconstrained_array_definition ::=
array ( index_subtype_definition { , index_subtype_definition } )
of element_subtype_indication
use_clause ::=
use selected_name { , selected_name } ;
196
Приложения
variable_assignment_statement ::=
[ label : ] target := expression ;
variable_declaration ::=
[ shared ] variable identifier_list : subtype_indication [ := expression
];
wait_statement ::=
[ label : ] wait [ sensitivity_clause ] [ condition_clause ] [
timeout_clause ] ;
waveform ::=
waveform_element { , waveform_element }
| unaffected
waveform_element ::=
value_expression [ after time_expression ]
| null [ after time_expression ]
Пакет STANDARD
3. Пакет STANDARD
package STANDARD is
type BOOLEAN is (FALSE, TRUE);
type BIT
is ('0', '1');
type CHARACTER is (
NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL,
BS, HT, LF, VT, FF, CR, SO, SI,
DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB,
CAN, EM, SUB, ESC, FSP, GSP, RSP, USP,
' ', '!', '"', '#', '$', '%', '&', ''',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
Пакет STANDARD
197
'X', 'Y', 'Z', '[', '\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', DEL);
type SEVERITY_LEVEL is (NOTE, WARNING, ERROR, FAILURE);
type INTEGER is range -214748 to +214748;
type TIME is range -9 to +9
units
fs;
-- femtosecond
ps = 1000 fs; -- picosecond
ns = 1000 ps; -- nanosecond
us = 1000 ns; -- microsecond
ms = 1000 us; -- millisecond
sec = 1000 ms; -- second
min = 60 sec; -- minute
hr =
60 min; -- hour
end units;
function NOW return TIME;
subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;
subtype POSITIVE is INTEGER range 1 to INTEGER'HIGH;
type STRING is array ( POSITIVE range <> ) of CHARACTER;
type BIT_VECTOR is array ( NATURAL range <> ) of BIT;
end STANDARD;
198
Пакет STD_LOGIC_1164
Приложения
4. Пакет STD_LOGIC_1164
package PACK1164 is
type std_ulogic is ( 'U', -- Uninitialized
'X', -- Forcing Unknown
'0', -- Forcing 0
'1', -- Forcing 1
'Z', -- High Impedance
'W', -- Weak Unknown
'L', -- Weak 0
'H', -- Weak 1
'-'); -- Don't care
type std_ulogic_vector is array ( NATURAL RANGE <> ) of std_ulogic;
function resolved ( s : std_ulogic_vector ) RETURN std_ulogic;
subtype UX01 is resolved std_ulogic RANGE 'U' TO '1';
subtype std_logic is resolved std_ulogic;
type std_logic_vector is array ( NATURAL RANGE <>) of std_logic;
function "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01;
function "and" ( l, r : std_logic_vector ) RETURN std_logic_vector;
function "and" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector;
end PACK1164;
package body PACK1164 is
type stdlogic_1d is array (std_ulogic) of std_ulogic;
type stdlogic_table is array (std_ulogic, std_ulogic) of std_ulogic;
constant resolution_table : stdlogic_table := (
----
--------------------------------------------------------| U
X
0
1
Z
W
L
H
|
|
--------------------------------------------------------( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U |
( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X |
( 'U', 'X', '0', 'X', '0', '0', '0', '0', 'X' ), -- | 0 |
( 'U', 'X', 'X', '1', '1', '1', '1', '1', 'X' ), -- | 1 |
( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X' ), -- | Z |
( 'U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X' ), -- | W |
( 'U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X' ), -- | L |
( 'U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X' ), -- | H |
( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - |
);
function resolved ( s : std_ulogic_vector ) RETURN std_ulogic IS
variable result : std_ulogic := 'Z'; -- weakest state default
199
Пакет STD_LOGIC_1164
begin
if (s'LENGTH = 1) then
RETURN s(s'LOW);
else
for i in s'RANGE loop
result := resolution_table(result, s(i));
end loop;
end if;
RETURN result;
end resolved;
constant and_table : stdlogic_table := (
----
---------------------------------------------------| U
X
0
1
Z
W
L
H
---------------------------------------------------( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' )
--
|
|
|
|
|
|
|
|
|
|
|
U
X
0
1
Z
W
L
H
-
|
|
|
|
|
|
|
|
|
);
function "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 is
begin
RETURN (and_table(l, r));
end "and";
function "and" (l,r : std_logic_vector ) RETURN std_logic_vector is
alias lv : std_logic_vector ( 1 TO l'LENGTH ) is l;
alias rv : std_logic_vector ( 1 TO r'LENGTH ) is r;
variable result : std_logic_vector ( 1 TO l'LENGTH );
begin
if ( l'LENGTH /= r'LENGTH ) then
assert FALSE report
"arguments of 'and' operator are not of the same length"
severity FAILURE;
else
for i in result'RANGE loop
result(i) := and_table (lv(i), rv(i));
end loop;
200
end if;
RETURN result;
end "and";
-----------------------------------------------------------------function "and" ( l,r : std_ulogic_vector )
RETURN std_ulogic_vector is
alias lv : std_ulogic_vector ( 1 TO l'LENGTH ) is l;
alias rv : std_ulogic_vector ( 1 TO r'LENGTH ) is r;
variable result : std_ulogic_vector ( 1 TO l'LENGTH );
begin
if ( l'LENGTH /= r'LENGTH ) then
assert FALSE report
"arguments of 'and' operator are not of the same length"
severity FAILURE;
else
for i in result'RANGE loop
result(i) := and_table (lv(i), rv(i));
end loop;
end if;
RETURN result;
end "and";
end PACK1164;
Приложения