Проектирование цифровых систем на языках описания аппаратуры/Лекция 3
- Заголовок
- Основы языка VHDL. часть 2
- Автор
- Ланкевич Ю.Ю.
- Нижний колонтитул
- Проектирование цифровых систем на языках описания аппаратуры/Лекция 3
- Дополнительный нижний колонтитул
- Ланкевич Ю.Ю., 11:30, 21 сентября 2020
Слайд:Логические элементы
В алгебре логики известны три основные логические операции:
- Логическое умножение (конъюнкция или операция И). Записывается как F = A Λ B, F = A & B, F = A·B, F = AB, читается – A и B.
- Логическое сложение (дизъюнкция или операция ИЛИ). Записывается как F = A V B, F = A | B, F = A+B, читается – F = A или B.
- Логическое отрицание (инверсия или операция НЕ). Записывается F = A , читается – F = “не” A.
Слайд:Таблица истинности логических элементов

Аргументы | Логические операции (булевы функции) | ||||
---|---|---|---|---|---|
А | В | И | ИЛИ | НЕ | |
A·B | A+B | A | B | ||
0 | 0 | 0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 0 | 1 |
1 | 1 | 1 | 1 | 0 | 0 |
Операторы VHDL | A and B | A or B | not A | not B |
Комментарий
Таким образом, выполнение сколь угодно сложной логической операции может быть сведено к трем вышеперечисленным операциям. Следовательно, имея некоторые технические устройства, реализующие операции И, ИЛИ, НЕ, можно построить сколь угодно сложное цифровое устройство. Такие устройства называются соответственно логическими элементами И, ИЛИ, НЕ и образуют основной базис или функционально полную систему логических элементов.
Слайд:Арифметические и логические операции
Набор операторов (операций) в VHDL обеспечивает возможность работы с предусмотренными типами данных. Список операций приведен в таблице ниже. Строки таблице располагаются в порядке приоритетов (от низшего к высшему) операторов. Операторы, находящиеся в одной строке, обладают одинаковым приоритетом. Таким образом, операции нижней строки обладают наибольшим приоритетом и выполняются первыми.
Исходя из контекста VHDL-кода следует отличать оператор <= (назначение сигнала) и оператор <= (меньше либо равно). Следует также отличать унарные операции присвоения знака +, - от соответствующих бинарных операций сложения и вычитания. Для устранения неоднозначностей трактовки старшинства операций используются скобки. Например, выражение "A nand B nand C" неверно (синтаксическая ошибка). Данное выражение не представляет трехвходовый элемент И-НЕ (трехвходовую NAND-ячейку). Правильная запись "not (A and B and C) ". Запись "A nand (B nand C)" не есть то же самое, что "(A nand B) nand C".
Операции языка VHDL:
Приоритет | Классы операторов |
Обозначение | Название |
---|---|---|---|
0 (низкий) | Логические | and or nand nor xor xnor |
логическое И логическое ИЛИ логическое И-НЕ логическое ИЛИ-НЕ исключающее ИЛИ эквивалентность |
1 | Отношения | = < > <= >= /= |
равно меньше больше меньше либо равно больше либо равно не равно |
2 | Сдвиги (VHDL 2008, определены для std_logic_vector) | sll srl sla sra rol ror |
логический сдвиг влево логический сдвиг вправо арифметический сдвиг влево арифметический сдвиг вправо циклический сдвиг влево циклический сдвиг вправо |
3 | Сложение | + – & |
сложение + вычитание - конкатенация |
4 | Унарные | +, – | присвоение знака + присвоение знака - |
5 | Умножение | * / mod rem |
умножение деление модуль остаток |
6 (высокий) | Вспомогательные | ** abs not |
возведение в степень абсолютное значение логическое НЕ |
Слайд:Арифметические и логические операции/ Примеры
Примеры арифметических операторов
Сложение (+)
RealX2+2.0 -- если RealX2 есть сигнал типа -- вещественный, то число 2 должно -- быть записано как вещественное1us+3ns -- 1003ns
Вычитание (–)
8.33–5 -- неправильно, оба числа должны -- быть одного типаBusWidth – 1 -- допустимо, если BusWidth типа integer
Умножение (*)
4*SomeVal -- допустимо, если SomeVal -- типа Integer или TimeMult*5ns -- результат типа Integer либо Real -- в зависимости от типа Mult
Деление (/)
CLK/2 -- тип CLK – Integer5.0/2.0 -- результат – вещественное число 2.510ns/2ns -- результат 5 типа Integer, но не Time
Модуль (mod)
6 mod 4 -- результат 26 mod (–4) -- результат –2(–6) mod 4 -- результат 2
Слайд:Арифметические и логические операции/ Примеры
Остаток деления (rem)
6 rem 4 -- результат 26 rem (–4) -- результат 2(-6) rem 4 -- результат –2
Возведение в степень (**)
с**0.5 -- неправильно в VHDLB**3 -- эквивалентно B*B*B
Абсолютное значение (abs)
abs 1 -- результат 1abs(–1) -- результат 1abs(5*(–2)) -- результат 10
Логические операторы выполняются для следующих типов данных:
- boolean;
- bit, bit_vector;
- std_logic, std_logic_vector;
- std_ulogic, std_ulogic_vector.
Логические операторы and, or, xor имеют одинаковый приоритет и выполняются слева направо.
Оператор not имеет более высокий приоритет и выполняется прежде других операторов.
В сложных логических выражениях порядок выполнения операторов регулируетсяскобками.
Например, для выражения
Z <= A and not B or C;
будет только отрицание B, в выражении
Z <= A and not (B or C);
будет отрицание подвыражения B or C, находящегося в скобках.
Слайд:Арифметические и логические операции/ Примеры/ Конкатенация
Оператор конкатенации обозначается через &, пример приведен на рисунке ниже

Слайд:Структура VHDL описания
Слайд:Пример параллельных процессов в логической схеме
На схеме ниже показаны три логических блока. Если предположить, что входной набор 1 (для логического блока 1) и входной набор 2 (для логического блока 2) изменяются одновременно, то выходы логических блоков 1, 2 будут изменяться также одновременно. Выход логического блока 3 будет изменяться чуть позже, в то время как через блоки 1, 2 могут проходить (конвейерным способом) измененные значения сигналов других входных наборов. Таким образом, поток сигналов может проходить через все блоки одновременно.
Слайд:Параллельные процессы и параллельные операторы
В языке VHDL процесс активизируется, когда происходит изменение какого-либо сигнала в списке сигналов запуска этого процесса (или в списке чувствительности (sensitivity list)). В общем случае список сигналов запуска содержит входной набор сигналов соответствующего логического блока.
Рассмотрим схему с монтажным соединением выходных полюсов элементов.
! Можно определять только по одному драйверу на сигнал в процессе.
Так как в каждом процессе сигнал должен иметь только один источник, то, в случае, если имеется несколько источников сигнала, требуется специальная (разрешающая) функция, которая будет вычислять значение сигнала по значениям этого сигнала из нескольких драйверов.
Например, сигнал Y имеет два источника, и, соответственно, два драйвера. Для такого сигнала требуется разрешающая функция. Подробнее эта проблема будет рассмотрена далее.
Слайд:Параллельные процессы и параллельные операторы
Параллельные операторы в VHDL определяют параллельное (во времени) поведение схем.
! Порядок выполнения параллельных операторов не связан с порядком их появления внутри архитектурного тела.
Параллельные операторы активизируются сигналами, которые употребляются для связи параллельных операторов. Последовательные операторы выполняются в порядке их появления в VHDL-коде.
Параллельные операторы: 1. оператор process (процесс); 2. оператор параллельного сообщения; 3. оператор параллельного вызова процедуры; 4. оператор условного назначения сигнала; 5. оператор select выборочного назначения сигнала; 6. оператор конкретизации (создания экземпляра) компонента; 7. оператор generate (генерации); 8. оператор block (блок).
Слайд:Параллельный оператор process
Оператор процесса есть параллельный оператор, который определяет независимое последовательное поведение некоторой части проекта, описанное упорядоченной совокупностью последовательных операторов.
Метка процесса необязательна, однако если она есть в конце (после слов end process), то она должна быть и вначале перед словом process.
Общий вид оператора process (процесс)
[имя процесса :] [postponed] process [(список чувствительности)] раздел деклараций begin упорядоченное множество последовательных операторов end process [имя процесса];
В декларативной части процесса могут быть:
- тела подпрограмм;
- декларации подтипов;
- декларация констант;
- декларация файлов;
- декларация альтернативных точек входа в подпрограмму;
- декларация атрибутов;
- спецификации атрибутов.
! Процесс может иметь список сигналов запуска и один (или более) операторов ожидания, но не оба вместе.
! Сигналы не могут быть декларированы внутри процессов.
! Ожидание (wait) в начале процесса не эквивалентно ожиданию в списке чувствительности процесса.
Слайд:Оператор assert (сообщение)
Операторы сообщений проверяют, является ли условие истинным (TRUE), и сообщают об ошибке, если условие является ложным. По умолчанию сообщенное выражение есть "Assertion violation" (нарушение).
Выражение с ключевым словом severity (severity – степень серьезности) имеет перечислимый тип: NOTE, WARNING, ERROR, FAILURE.
Оператор assert может быть использован как в качестве параллельного оператора, так и в качестве последовательного оператора
Общий вид оператора assert
assert условие [report выражение ] [severity выражение ];
Примеры:
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 может быть либо истинным, либо ложным.
Слайд:Оператор параллельного вызова процедуры
Оператор параллельного вызова процедуры представляет процесс, содержащий оператор последовательного вызова процедуры. Его выполнение эквивалентно оператору процесса. Иначе говоря, процедуры могут вызываться параллельно.
Общий вид оператора
[метка:] оператор вызова процедуры
Пример:
6 architecture RTL of call_parallel is 7 procedure N_XOR ( signal x1, x2, x3 : in bit; 8 signal f : out bit) is 9 begin 10 f <= x1 xor x2 xor x3; 11 end N_XOR; 12 begin 13 N_XOR (x1=> data_inp(5), x2 => data_inp(4), x3 => data_inp(3), f => data_out(1)); 14 p0 : N_XOR (data_inp(2), data_inp(1), data_inp(0), data_out(0)); 15 end RTL;
! Каждый формальный параметр процедуры должен быть типа константы или сигнала.
Слайд:Параллельный оператор условного назначения сигнала
Oператор параллельного назначения сигнала эквивалентен оператору процесса, назначающему значения сигналам.
Могут быть употреблены опции guarded (охраняемый) transport (транспортный).
Общий вид оператора
[guarded][transport] {назначение сигнала when условие else} сигнал;
Пример, показывающий эквивалентность параллельного оператора условного назначения сигнала (архитектурное тело first) и оператора процесса (архитектурное тело second).
entity example_condition is port ( x1, x2, x3, x4 : in bit; 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;
Выполняться назначение для первого выполненного условия.
Слайд:Параллельный оператор select выборочного назначения сигнала
Общий вид оператора select (выбирать)
with выражение select имя сигнала <= [guarded][transport] {имя сигнала when условие выбора, } имя сигнала условие выбора;
Пример, показывающий эквивалентность параллельного оператора выборочного назначения сигнала (архитектурное тело first) и оператора процесса (архитектурное тело second)
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), имеющий имя (name).
Одна и та же подсхема может входить в схему несколько раз, однако при этом она имеет различные связи.
Чтобы описать эти связи, употребляется оператор создания экземпляра компонента (оператор конкретизации компонента), т.е. имеется в виду конкретизация связей данной подсхемы.
Общий вид оператора конкретизации компонента (оператора создания экземпляра компонента)
метка : имя компонента [generic (список параметров);] [port map (список портов)];
Соответствие портов при создании экземпляров компонентов может быть осуществлено позиционным сопоставлением и ключевым соответствием, с использованием оператора "=>"
Пример
p1: A port map (x1 => x1, y1 => w) ; -- ключевое соответствие p2: B port map (w, z) ; -- позиционное соответствие p3: C port map (y3 => v, x3 => z) ; -- ключевое соответствие
Слайд:Параллельные процессы, их выполнение на ЭВМ
Каждый параллельный процесс может быть в одном из трех состояний:
- выполняющийся – когда система моделирования выполняет процесс;
- активный – когда процесс является ожидающим, чтобы система моделирования его выполнила;
- приостановленный – когда он не является выполняющимся или активным.
В реальной системе процессы могут протекать параллельно (одновременно в различных элементах). В ЭВМ общего назначения параллелизм имитируется программно.
Поэтому только один процесс из нескольких параллельных процессов является "выполняющимся" по существу. Реализация параллельных процессов происходит следующим образом.
Параллельные процессы, которые надо выполнять "одновременно", выстраиваются в очередь. Система моделирования выбирает процесс из очереди активных процессов и выполняет процесс,
тем самым исполняет предложения языка VHDL, относящиеся к данному процессу. Другие активные процессы выбираются поочередно. Заметим, что выполненный процесс является приостановленным.
Когда очередь активных процессов пуста, считается, что все параллельные процессы выполнились "одновременно", и может начаться следующий цикл моделирования.
Приостановленный процесс может стать активным, когда изменился хотя бы один из драйверов сигналов из списка чувствительности этого процесса.
Слайд:Пример моделирования схемы, описанной на языке VHDL
Рассмотрим простую двухуровневую логическую схему и ее описание в языке VHDL в виде параллельных процессов.
entity ANDOR is port( x1, x2, x3 : in bit; f : out bit); end ANDOR; 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. Затем, если в начальный момент времени сигналы x1, x2 и x3 изменятся, то начнёт выполняться процесс p0, поскольку цикл моделирования начинается, когда хотя бы один из сигналов изменится.
В процессе p0 будет вычислено w и процесс p0 приостановится. Затем вычисляется значение f через 30ns, так как 10ns выполняется процесс p0 и 20ns – процесс p1.
Временная диаграмма изображена на рисунке ниже.

Заметим, что если сигнал x1 при декларации не имеет начального значения, то по умолчанию он принимает значение левой границы (x1'left) декларируемого типа. Например,
signal I: integer range 0 to 3; -- при инициализации значение 0; signal X : std_logic; -- при инициализации значение 'U'.
Слайд:Дельта-задержки сигналов
Изменим архитектурное тело example для entity ANDOR, удалив ключевые слова after и конкретные временные задержки, – тем самым логические операции and, or будут срабатывать "мгновенно".
architecture DELTA_example 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_example;
![]() |
![]() |
---|
В 80 ns входной сигнал x2 изменился, что послужило причиной изменения сигнала w и причиной изменения сигнала f. Эта ситуация очерчена лупой на временной диаграмме выше.
Все это случилось точно в то же время. Рассмотрим более подробно, что же произошло в момент времени 80 ns. В 80ns входной сигнал x2 изменяется.
Начинается цикл моделирования. Активизируется процесс p0, выполняется, приостанавливается. Сигнал w изменяется в 0. Резонно сказать, что сигнал w изменился после сигнала x2.
Мы будем ссылаться на время между изменениями этих сигналов как на время дельта, или дельта-задержку.
Изменение сигнала w служит причиной для процесса p1, который активизируется, выполняется, приостанавливается. Сигнал f изменяется после изменения сигнала w.
Появляется другая дельта-задержка. В системах моделирования обычно на временных диаграммах дельта-задержки не показываются.
Например, в системе моделирования ModelSim их можно видеть в специальном окне текстового (табличного) представления результатов моделирования.
Слайд:Дельта-задержки сигналов
Понятие дельта-задержки есть основное понятие моделирования в языке VHDL.
В одно и то же время (физическое) много сигналов могут изменяться и много процессов могут быть активными.
После того как все процессы пришли в состояние "приостановленный", система моделирования увеличивает время моделирования.
Итак, ответом на вопрос "Что представляет собой дельта-задержка, или просто дельта?" является следующее:
! Дельта – это один цикл прогона VHDL-модели.
VHDL-модель, имитирующая поведение цифровой системы, состоит из множества процессов.
Во время прогона модели в данном цикле запускаются все процессы, входные параметры которых изменились с момента выполнения последнего цикла.
После того как все процессы выполнены, данный цикл моделирования считается завершенным.
Следующий цикл начнется после того, как в очередной раз произойдет изменение какого-то входного сигнала для какого-то процесса.
Этот период может составлять наносекунды времени моделирования или может просто означать, что мы перешли на следующий цикл моделирования, т.е. сделали временной шаг дельта.
Шаг величиной дельта образуется, например, при выполнении операторов назначения сигналов (в рассмотренном примере это сигналы w, f), не имеющих фразы after.
С точки зрения логической схемы дельта – это задержка на одном уровне (каскаде) логики, когда не задана конкретная задержка логического элемента.
Слайд:Параллельный оператор block
Оператор блока определяет часть проекта (часть VHDL-описания цифровой системы, схемы).
Блок – это ограниченный фрагмент VHDL-кода, содержащий раздел описания и исполняемый раздел.
Блоки могут быть иерархически вложены и поддерживать тем самым декомпозицию проекта.
Общий вид оператора block (блок)
имя блока (метка): block[(охранное выражение)] заголовок блока раздел деклараций begin параллельные операторы end block[имя блока];
! Метка необходима в операторе блока.
В разделе деклараций блока размещаются
- декларации подпрограмм;
- тела подпрограмм;
- типы, подтипы;
- константы;
- сигналы;
- альтернативные точки входа в подпрограмму;
- декларации атрибутов;
- декларации констант;
- спецификации атрибутов;
- конфигурации.
Параллельные операторы размещаются в теле блока. Блоки могут быть вложены.
architecture XX of SYSTEM is - - - - -- раздел описаний внешнего блока - - - - - - - - begin -- выполнимые операторы внешнего блока - - - - - - - - A: block - - - - -- раздел описаний внутреннего блока A - - - - begin -- выполнимые операторы внутреннего блока A - - - - - - - - end block A; B: block - - - - -- раздел описаний внутреннего блока B - - - - begin -- выполнимые операторы внутреннего блока B - - - - - - - - end block B; end XX;
Слайд:Параллельный оператор block / охранное выражение
Обсудим теперь охранные выражения блоков. Рассмотрим архитектурное тело add1_e одноразрядного сумматора в виде охраняемого блока.
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.
Слайд:Последовательные операторы
В VHDL последовательные операторы подобны операторам языков высокого уровня. На рисунке приведена общая структура VHDL-описания, из которой следует, что последовательные операторы (sequential statement) могут появляться внутри операторов процесса или внутри тел подпрограмм (функций, процедур).
На данном рисунке указаны основные параллельные и последовательные операторы.
Перечислим последовательные операторы:
- оператор присвоения значения переменной;
- оператор назначения сигнала, т.е. присвоения значения сигналу;
- оператор if (если);
- оператор case (случай);
- оператор loop (цикл);
- оператор next (следующий);
- оператор exit (выход);
- оператор null (нуль, пустой);
- оператор вызова процедуры;
- оператор return (возврат);
- оператор assert (сообщение);
- оператор wait (ожидать).
Слайд:Оператор присваивания значения переменной
Определение
variable_assignment_statement::=[label] target := expression ;
Данный оператор заменяет текущее значение (target) переменной новым значением, которое определяется выражением (expression). Переменная и выражение должны быть того же базового типа. Еще раз напомним, что присваивание значения переменным не есть то же самое, что сигналам. Присваивание значений сигналам мы обсудим в следующем разделе. В VHDL локальные переменные могут быть только декларированы в области операторов процессов и подпрограмм (функций или процедур). В следующем VHDL-коде приведены примеры присваивания значений переменным. Слева указаны номера строк, не относящиеся к тексту на языке VHDL.
1 entity VAR is 2 end VAR; 3 4 architecture functional of VAR is 5 signal A, B, J : bit_vector(1 downto 0); 6 signal E, F, G : bit; 7 begin 8 p0 : process (A, B, E, F, G, J) 9 variable C, D, H, Y : bit_vector(1 downto 0); 10 variable W, Q : bit_vector(3 downto 0); 11 variable Z : bit_vector(0 to 7); 12 variable X : bit; 13 variable DATA : bit_vector(31 downto 0); 14 begin 15 C := "11"; 16 X := E and F; 17 Y := H nand J; 18 Z(0 to 3) := C & D; -- конкатенация 19 Z(4 to 7) := (not A) & (A nor B); -- конкатенация 20 D := ('0', '0'); -- агрегат 21 W := (2 downto 1 => G, 3 => '1', others => '0'); 22 DATA := (others => '1'); -- агрегат 23 end process; 24 end functional; |
В строке 15 переменная C получает константное значение. Выражения в строке 16, 17 используют логические операторы. В строке 18 в выражении употребляется оператор & конкатенации, чтобы присвоить значения первым четырем битам переменной Z. В строке 19 употреблена комбинация логических операторов и конкатенация. Строка 20 показывает агрегат, в котором употребляется позиционное отображение (соответствие). Запись ('0', '0') называется агрегатом. Агрегат заключается в круглые скобки, входящие в агрегат элементы разделяются запятой. В строке 21 употребляется позиционное отображение и ключевое слово others. В строке 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) является агрегатом.
Слайд:Присваивание значений сигналам (назначение сигналов)/ Инцерционная и транспортная задержка
В языке VHDL в операторах назначения сигналов, т. е. в операторах присваивания значений сигналам используются два вида задержек:
- инерционная задержка;
- транспортная задержка;
Ключевое слово inertial определяет инерционную задержку, ключевое слово transport определяет транспортную задержку.
Пример
X<= inertial Y after 3 ns; -- инерционная задержка X<= transport Y after 3 ns; -- транспортная задержка.
В случае инерционной задержки передача сигнала будет иметь место, если и только если входной сигнал будет сохранять соответствующий уровень в течение заданного отрезка времени.
В языке VHDL этот заданный отрезок времени и есть задержка, указываемая во фразе after. Таким образом, в первом примере изменение значения Y подействует на значение X только в случае,
если новый уровень Y будет сохраняться в течение 3ns и более. Во втором примере (транспортная задержка) все изменения Y будут передаваться в X независимо от того,
сколько времени будет сохраняться новое значение Y.
! Если не используется ключевое слово transport, то подразумевается инерционная задержка.
Пример
X<= Y after 3 ns; -- инерционная задержка
Механизм инерционной задержки позволяет отфильтровывать входные сигналы, которые меняются слишком быстро, т. е. если длительность сигнала Y меньше 3 ns, то его значение не будет передано сигналу X. Данный механизм по существу имитирует работу реальной схемы. Уровень напряжения определяет значение логического сигнала. Ввиду наличия электрических емкостей напряжения узлов не могут изменяться мгновенно, необходимо, чтобы определенное количество энергии подавалось в течение определенного отрезка времени, – только в этом случае напряжение узла изменится настолько, чтобы вызвать переключение схемы, управляемой этим напряжением. Поэтому при моделировании реальных логических схем используется инерционная задержка. Транспортная задержка чаще используется на этапе алгоритмического проектирования.
Слайд:Присваивание значений сигналам (назначение сигналов)/ Сигналы и переменные
Порты, декларируемые в entity, являются сигналами. Аргументы подпрограмм могут быть сигналами или переменными.
Пример. ( Различие между локальной переменной и сигналом).
Данный 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- V;
однако не эквивалентен приведенному ниже VHDL-коду
V <= (B*C+D*E*F+G); Y <= A+V; Z <= A - V;
Замечание. Запись 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), которое было при декларации массива. Для предыдущего примера
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
if условие then упорядоченное множество последовательных операторов {elsif условие then упорядоченное множество последовательных операторов} [else упорядоченное множество последовательных операторов] end if;
Оператор if языка VHDL подобен операторам if в других языках программирования.
Выражение, представляющее собой “условие” должно иметь тип BOOLEAN. В одном if операторе может быть одна (ни одной) либо более частей elsif.
Ключевое слово elsif следует отличать от слов else if. Часть else может быть только одна (или ни одной).
Должен быть разделитель между ключевыми словами в заключительной фразе end if;
Следующая модель 5-битового счетчика употребляет if операторы.
entity IFSTMT is port ( RSTn, CLK, EN, PL : in bit; DATA : in integer range 0 to 31; COUNT : out integer range 0 to 31); 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
case выражение is when выбор => упорядоченное множество последовательных операторов {when выбор => упорядоченное множество последовательных операторов} end case;
Оператор case выбирает одну из альтернатив, избранная альтернатива (случай) определяется значением выражения. Выражение должно быть дискретного типа или типа одноразмерного массива символов, значения которых могут быть представлены как строки или строка битов. Выбор должен быть такого же типа, как выражение. Все возможные выборы (случаи) должны быть перебраны. Для случая "others" (другие) должно быть такое значение, которое не соответствует предыдущим альтернативам. Оператор case является подходящим для моделирования конечных автоматов и программ микропроцессора. Используя оператор case, приведем пример 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; end case; end process; end RTL;
Слайд:Оператор loop (цикл)
Общий вид оператора loop
[метка цикла:][while условие | for идентификатор in диапазон дискретного типа] loop упорядоченное множество последовательных операторов end loop [метка цикла];
Когда в записи цикла используется ключевое слово while, то сначала вычисляется условие (condition).
Если условие есть TRUE, выполняется последовательность последовательных операторов, иначе оператор цикла завершается.
Когда в записи цикла используется ключевое слово for, то идентификатор определяет цикловой параметр с базовым дискретным типом.
Параметр цикла употребляется как константа внутри действия оператора цикла и он не может быть целью оператора присваивания.
! Общая ошибка: употребление параметра цикла снаружи оператора цикла.
Пример
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
next [метка цикла ][when условие];
Пример дан выше. Оператор next употребляется для завершения итераций цикла.
Оператор exit (выход)
Общий вид оператора exit
exit [метка цикла ] [when условие];
Оператор EXIT употребляется, чтобы завершить выполнение и закрыть оператор цикла. Если условие (condition) есть TRUE, то осуществляется выход из цикла.
Оператор null (пустой)
Общий вид оператора null (нуль, пустой)
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 ( 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.
Слайд:Оператор return (возврат)
Общий вид оператора return
return [выражение];
Употребляется, чтобы завершить выполнение самой внутренней функции или процедуры. Он используется только внутри тела функции или процедуры. Оператор return не требуется в теле процедуры, поэтому в архитектурном теле RTL (entity RETURNSTMT) соответствующая строка может быть удалена. Оператор return может быть употреблен с другими последовательными операторами, такими как if, case для управления возвратом функции или процедуры.
Слайд:Оператор assert (сообщение)
Общий вид оператора assert
assert условие [report выражение ] [severity выражение ];
Операторы сообщений проверяют, является ли условие истинным (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 может быть либо истинным, либо ложным. Следующие два оператора (две строки) эквивалентны:
report "NEW YEAR 3003" severity ERROR; assert FALSE report "NEW YEAR 3003" severity ERROR;
также, как и следующие:
report "NEW YEAR 2002"; assert FALSE report "NEW YEAR 2002" severity NOTE;
Так как FALSE всегда является ложным, то данные сообщения всегда выдаются – это примеры безусловно выдаваемых сообщений.
Слайд:Оператор wait (ожидать)
Общий вид оператора wait
wait on список чувствительности until условие for тайм-аут ;
Оператор wait является причиной временного прекращения оператора процесса или процедуры. Оператор ожидания wait приостанавливает процесс до момента, пока не изменится некоторый сигнал в списке чувствительности процесса, в это время будет произведено вычисление условия. Фраза “условие” есть выражение типа BOOLEAN. Если получается истинное значение, выполнение процесса возобновляется. Фраза “тайм-аут” устанавливает максимальное время ожидания, после которого процесс возобновит свое выполнение. Пример.
WAIT on A, B until (C=0) for 50 ns;
Этот оператор приостановит процесс до момента изменения A или B, после чего будет проверено выражение C=0 и, если результатом проверки будет истина, процесс возобновится. Но независимо от этих условий возобновление процесса произойдет через 50ns. Допустимо записывать одно или более условий в операторе ожидания, например,
Условие 1. WAIT on A, B; Условие 2. WAIT until (C=0); Условие 3. 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;
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;