AHDL
AHDL | |
---|---|
Парадигма | паралельна |
Система типізації | сильна |
Під впливом від | Ada, VHDL, Verilog |
Звичайні розширення файлів | TDF (англ. Text Design File) |
AHDL (англ. Altera Hardware Definition Language) — комп'ютерна мова опису апаратних засобів, розроблена компанією Altera, що призначена для опису комбінаційних логічних пристроїв, цифрових автоматів і таблиць істинності з врахуванням архітектурних особливостей ПЛІС цієї фірми. Мова має Ada-подібний синтаксис; порівнюючи AHDL з Verilog можна зазначити, що це наче мова асемблера та мова високого рівня: перша має більше контролю, проте немає високорівневої підтримки.
AHDL, природно, сумісний з компіляторами фірми Altera: Quartus та Max PLUS та дає можливість створювати ієрархічні проєкти в рамках цієї мови чи комбінувати різні типи файлів в один проєкт.
Програма на мові AHDL має визначену структуру. Її розділи повинні слідувати в такому порядку:
Назва | Призначення | Особливості |
---|---|---|
Заголовок (англ. Title Statement) | Дає назву модулю | Починається з ключевого слова TITLE, за яким слідує назва модуля. |
Оператор включення (англ. Include Statement) | Включає вміст вказаного файлу в текст програми | Починається з ключевого слова INCLUDE, за яким слідує ім'я файлу, без шляху до нього. |
Оголошення константи (англ. Constant Statement) | Присвоює імені константи число | Починається з ключевого слова CONSTANT, за яким слідує ім'я, символ (=), а далі число чи арифметичний вираз. |
Оператор визначення (англ. Define Statement) | Присвоює арифметичним виразам символьні імена | Починається з ключевого слова DEFINE, за яким слідує ім'я зі списком аргументів, за яким ставиться символ (=), а далі арифметичний вираз. |
Оголошення параметрів (англ. Parameters Statement) | Оголошує параметри модуля | Починається з ключевого слова PARAMETERS, за яким слідує список параметрів. Значення параметру за замовчуванням вказується після символу (=). |
Опис прототипу (англ. Function Prototype Statement) | Описує параметри модулів, що використовуються | Починається з ключевого слова FUNCTION, за яким слідує ім'я, а потім список входів. Якщо модуль параметризований, далі йде ключове слово WITH і список параметрів. Потім вказується ключове слово RETURNS і список виходів модуля. |
Оператор опцій (англ. Options Statement) | Визначає елемент з меншим індексом | Починається з ключевого слова OPTIONS, за яким слідує ключове слово BITO, символ (=), а далі одне з ключевих слів: LSB (молодший розряд), MSB (старший розряд) чи ANY (будь-який). |
Оператор контролю (англ. Assert Statement) | Перевіряє істинність логічного виразу | Починається з ключевого слова ASSERT, за яким в дужках слідує арифметичний вираз. Якщо значення виразу false, на екран виводиться повідомлення, записане після ключевого слова REPORT. |
Опис модуля (англ. Subdesign Section) | Задає ім'я модуля й перераховує його порти | Починається з ключевого слова SUBDESIGN, за яким слідує назва модуля та список виводів в дужках. В кінці списку однотипних виводів вказується їх тип. |
Розділ змінних (англ. Variable Section) | Задає внутрішні змінні | Починається з ключевого слова VARIABLE, за яким слідують імена однотипних змінних, а далі тип змінних. Розділ може містити оператор IF GENERATE, що керує створення змінних залежно від результату арифметичного виразу. |
Опис логіки (англ. Logic Section) | Описує функціонал модуля | Починається з ключевого слова BEGIN, закінчується ключевим словом END. |
З усіх названих, лише розділи опису модуля та логіки є обов'язковими; заголовок, оператор опцій, розділи змінних, опису модуля та логіки можуть вживатися в програмі лише раз.
До множини символів мови відносять букви, цифри та спеціальні символи, призначення яких наведено в таблиці нижче.
Символ | Функція |
---|---|
-- | Коментар в стилі VHDL, що продовжується до кінця рядка |
% | Ставляться з обох боків коментаря в стилі AHDL |
() | Використовуються для підвищення пріоритету в операціях, оточують порти в іменах модуля та списки параметрів |
[] | Використовуються для створення діапазону значень |
'' | Використовуються для створення символічних імен |
"" | Використовуються в заголовку, для вказування файлу для включення, оточують цифри в недесяткових константах |
. | Відділяє ім'я файлу від розширення |
.. | Розділяє найбільші та найменші значення в діапазонах |
; | Закінчує розділи і секції мови |
, | Розділяє елементи списків та груп |
: | Відділяє символьні імена від типів |
= | Присвоює значення в операціях |
=> | Відділяє входи і виходи в таблицях істинності та операторі CASE |
З символів складаються імена, що в мові AHDL можуть даватися:
- портам, шинам;
- константам;
- змінним кінцевих автоматів, бітам та іменам станів;
- екземплярам;
- параметрам;
- функціям;
- іменованим операторам;
- сегментам пам'яті;
- підпроєктам.
Синтаксис імен в AHDL схожий на синтаксис імен в інших комп'ютерних мовах:
- ім'я може містити букви, цифри, символ підкреслення та не може бути зарезервованим словом;
- зарезервовані слова можна використовувати як символічні імена лише коли вони вживаються в одинарних лапках або в коментарях;
- великі та малі літери не розрізняються;
- ім'я повинне починатися з букви і не може закінчуватися знаком підкреслення.
В документації компанії Altera вказано, що для поліпшення прочитності програми зарезервовані слова варто писати великими літерами. До ключевих слів належать наступні:
AND | ASSERT | BEGIN | BIDIR | BITS | BURIED | CASE | CLIQUE | CONNECTED_PINS |
CONSTANT | DEFAULTS | DEFINE | DESIGN | DEVICE | DIV | ELSE | ELSEIF | END |
FOR | FUNCTION | GENERATE | GND | HELP_ID | IF | INCLUDE | INPUT | IS |
LOG2 | MACHINE | MOD | NAND | NODE | NOR | NOT | OF | OPTIONS |
OR | OTHERS | OUTPUT | PARAMETERS | REPORT | RETURNS | SEGMENTS | SEVERITY | STATES |
SUBDESIGN | TABLE | THEN | TITLE | TO | TRI_STATE_NODE | VARIABLE | VCC | WHEN |
WITH | XNOR | XOR |
До службових імен належать:
CARRY | CASCADE | CEIL | DFFE | DFF | EXP | FLOOR | GLOBAL | JKFFE | JKFF | LATCH | LCELL | MCELL | MEMORY | OPENDRN | SOFT |
SRFFE | SRFF | TFFE | TFF | TRI | USED | WIRE | X |
Змінні використовуються для збереження проміжних результатів обчислень. Допустимими типами змінних є:
- NODE;
- TRI_STATE_NODE;
- імена примітивів, мегафункцій, макрофункцій та машин станів.
Кілька провідників, що несуть однакове смислове навантаження можна об'єднати в шину. Кожна з них може мати до 255 біт і працює як одне ціле. Визначити шину можна наступними способами, після чого [] стануть еквівалентними звертанню до всієї шини:
a[1..5] b[7..0] (c, d, e)
Порт — це вхід чи вихід логічної функції. Може мати один з наступних типів:
- INPUT — вхід;
- OUTPUT — вихід;
- BIDIR — двонаправлений вивід;
- MACHINE INPUT — вхід станів автомата;
- MACHINE OUTPUT — вихід станів автомата.
Мова AHDL дає можливість описати двонаправлений порт, що корисно для зменшення кількості провідників. На прикладі нижче, двонаправлений сигнал io, що запускається примітивом TRI, використовується як вхід та вихід для D-тригера (DFF). Варто відмітити, що входи тригера clrn та prn не підключені, що видно з відділених комами місць.
SUBDESIGN bus_register ( clk, oe : INPUT; io : BIDIR; ) BEGIN io = TRI(DFF(io, clk, , ), oe); END;
Мова AHDL підтримує запис чисел в десятковій, двійковій, вісімковій та шістнадцятковій системах числення. Таблиця нижче ілюструє формат запису чисел.
Основа системи | Формат |
---|---|
10 | <послідовність цифр 0..9> |
2 | B"<послідовність цифр 0, 1, X>" |
8 | O"<послідовність цифр 0..7>" чи Q"<послідовність цифр 0..7>" |
16 | X"<послідовність цифр 0..9, A..F>" чи H"<послідовність цифр 0..9, A..F>" |
Константи можна використати для того, щоб надати конкретному числу більше інформативності. Окрім підвищення прочитності програми, їх застосування стає корисним тоді, коли це число неодноразово повторюється. Нижче наведено приклад селектора адреси, що забезпечує підключення певного пристрою до шини лише за умови подання на його вхід адреси 21 в шістнадцятковій системі числення.
CONSTANT io_address = H"21"; SUBDESIGN address_selector ( a[15..0] : INPUT; select : OUTPUT; ) BEGIN select = (a[15..0] == io_adress); END;
Арифметичні вирази — це засіб формування конструкцій мови, що обраховуються компілятором і не займають ресурсів ПЛІС. Їх результатом завжди є ціле додатне число, для його отримання є функції явного задання правил округлення: CEIL (до більшого цілого) та FLOOR (до меншого цілого).
Операції, що можуть використовуватись в арифметичних виразах наведені в таблиці:
Операція | Опис | Пріоритет |
---|---|---|
(унарний) | Плюс | 1 |
— (унарний) | Мінус | 1 |
! (NOT) | Заперечення | 1 |
^ | Степінь | 1 |
MOD | Залишок від ділення | 2 |
DIV | Ділення | 2 |
* | Множення | 2 |
LOG2 | Двійковий логарифм | 2 |
Додавання | 3 | |
— | Віднімання | 3 |
== (numeric) | Рівність чисел | 4 |
== (string) | Рівність рядків | 4 |
!= | Не рівно | 4 |
> | Більше | 4 |
>= | Більше рівно | 4 |
< | Менше | 4 |
<= | Менше рівно | 4 |
& (AND) | Кон'юнкція | 5 |
!& (NAND) | Штрих Шефера | 5 |
$ (XOR) | Виключна диз'юнкція | 6 |
!$ (XNOR) | Заперечення виключної диз'юнкції, еквівалентність | 6 |
# (OR) | Диз'юнкція | 7 |
!# (NOR) | Стрілка Пірса | 7 |
? | Умовна операція | 8 |
Булеві вирази — це операнди, розділені знаками арифметичних, логічних операцій та операторами порівняння, згруповані дужками. Варто зазначити, що порядок слідування булевих рівнянь в програмі не важливий, оскільки логічні стани встановлюються одночасно.
Операції, що можуть використовуватись в булевих виразах наведені в таблиці:
Операція | Опис | Пріоритет |
---|---|---|
— | Доповнення до 2 | 1 |
! | Інверсія | 1 |
Додавання | 2 | |
— | Віднімання | 2 |
== | Рівно | 3 |
!= | Не рівно | 3 |
> | Більше | 3 |
>= | Більше рівно | 3 |
< | Менше | 3 |
<= | Менше рівно | 3 |
& (AND) | Елемент «І» | 4 |
!& (NAND) | Елемент «І-НЕ» | 4 |
$ (XOR) | Елемент «ВИКЛЮЧНЕ АБО» | 5 |
!$ (XNOR) | Елемент «ВИКЛЮЧНЕ АБО-НЕ» | 5 |
# (OR) | Елемент «АБО» | 6 |
!# (NOR) | Елемент «АБО-НЕ» | 6 |
Комбінаційна логіка — це кінцеві автомати без пам'яті, що реалізуються за допомогою булевих виразів та таблиць істинності.
Таблична логіка в мові AHDL реалізується за допомогою наступного синтаксису:
- оператор починається ключевим словом TABLE, за яким йде заголовок таблиці;
- в заголовку перераховуються список входів, символ (=>) та список виходів;
- наступні рядки таблиці містять списки значень входів і виходів, розділені символом (=>). Вхідні значення можуть бути в неважливому стані X, проте варто слідкувати, щоб діапазони значень не перекривались в межах однієї таблиці;
- оператор закінчується ключевими словами END TABLE.
На прикладі нижче наведено контролер, що формує управляючі сигнали для відображення цифр в шістнадцятковій системі числення на семисегментному індикаторі.
% -a- % % f| |b % % -g- % % e| |c % % -d- % SUBDESIGN segment7 ( i[3..0] : INPUT; a, b, c, d, e, f, g : OUTPUT; ) BEGIN TABLE i[3..0] => a, b, c, d, e, f, g; H"0" => 1, 1, 1, 1, 1, 1, 0; H"1" => 0, 1, 1, 0, 0, 0, 0; H"2" => 1, 1, 0, 1, 1, 0, 1; H"3" => 1, 1, 1, 1, 0, 0, 1; H"4" => 0, 1, 1, 0, 0, 1, 1; H"5" => 1, 0, 1, 1, 0, 1, 1; H"6" => 1, 0, 1, 1, 1, 1, 1; H"7" => 1, 1, 1, 0, 0, 0, 0; H"8" => 1, 1, 1, 1, 1, 1, 1; H"9" => 1, 1, 1, 1, 0, 1, 1; H"A" => 1, 1, 1, 0, 1, 1, 1; H"B" => 0, 0, 1, 1, 1, 1, 1; H"C" => 1, 0, 0, 1, 1, 1, 0; H"D" => 0, 1, 1, 1, 1, 0, 1; H"E" => 1, 0, 0, 1, 1, 1, 1; H"F" => 1, 0, 0, 0, 1, 1, 1; END TABLE; END;
Умовна логіка в мові реалізується операторами IF та CASE.
Оператор CASE, як і в більшості комп'ютерних мовах, визначає вписок альтернативних варіантів, один з яких виконується при певному значенні селектора. Його синтаксис наступний:
- оператор починається ключевим словом CASE, за яким записується селектор, а потім — ключове слово IS;
- кожен альтернативний варіант починається ключевим словом WHEN, після якого йде константа, потім символ (=>) та набір операторів;
- на відміну від інших, останній альтернативний варіант може починатися з WHEN OTHERS;
- якщо селектор рівний одній з констант, виконується блок її операторів, якщо ж така константа не передбачена — виконується блок з WHEN OTHERS;
- завершується оператор ключевими словами END CASE.
Нижче наведено приклад дешифратора, що перетворює двохрозрядний код на вході в код «one hot» (чотири значення, кожне має одну одиницю):
SUBDESIGN decoder2x4 ( code[1..0] : INPUT; out[3..0] : OUTPUT; ) BEGIN CASE code[] IS WHEN 0 => out[] = B"0001"; WHEN 1 => out[] = B"0010"; WHEN 2 => out[] = B"0100"; WHEN 3 => out[] = B"1000"; END CASE; END;
Регістр необхідний для збереження інформації і створюється після його оголошення в розділі змінних. На прикладі нижче сформовано восьмирозрядний регістр, що використовує виходи як D-тригери, що дає економію ресурсів мікросхеми.
SUBDESIGN register8 ( clk, load, d[7..0] : INPUT; q[7..0] : OUTPUT; ) VARIABLE q[7..0] : DFFE; -- виводи оголошені тригерами BEGIN q[].clk = clk; q[].ena = load; q[] = d[]; END;
Лічильник зазвичай створюється з використанням оператора IF. Синтаксис його використання наступний:
- оператор починається з ключевого слова IF, за яким вказується булева умова, а потім ключеве слово THEN і список операторів, що виконуються при вірності умови;
- між ключевими словами ELSEIF та THEN може бути додатковий вираз, а за THEN — список операторів, що виконуються якщо цей вираз виконується;
- за цією конструкцією (що є необов'язковою, але може повторюватись багато разів), може слідувати ключове слово ELSE з списком операторів, що виконуються тоді, коли інші умови не вірні;
- оператор завершується ключевим словом END IF.
В наступному прикладі реалізовано чотирьохрозрядний лічильник зі скиданням.
SUBDESIGN counter4 ( clk, load, ena, clr, d[3..0] : INPUT; q[3..0] : OUTPUT; ) VARIABLE count[3..0] : DFF; BEGIN count[].clk = clk; count[].clrn = !clr; IF load THEN count[].d = d[]; ELSEIF ena THEN count[].d = count[].q 1; ELSE count[].d = count[].q; END IF; q[] = count[]; END;
Машина станів в AHDL — це мовна структура, що дозволяє описувати скінченний автомат в вигляді множини внутрішніх станів. Переходи між станами синхронізуються тактовим сигналом. Умова та напрямок переходу визначаються для кожного стану індивідуально. Кожному стану можна поставити у відповідність один чи кілька управляючих сигналів.
Машина станів описується як змінна в відповідному розділі, а її поведінка — у розділі логіки. Поведінку машини можна описати двома способами:
- за допомогою оператора CASE;
- за допомогою конструкції TABLE.
Нижче наведено приклади двох видів автоматів — автомата Мура та автомата Мілі. Відмінності між ними полягають в тому, що автомат Мура — машина станів з синхронними сигналами на виходах. Формування вихідного сигналу виконується синхронно з переходом до наступного стану по стробу синхросигналу.
SUBDESIGN moore ( clk, reset, y : INPUT; z : OUTPUT; ) VARIABLE ss: MACHINE WITH STATES (s0, s1, s2, s3); zd: NODE; BEGIN ss.clk = clk; ss.reset = reset; z = DFF(zd, clk, VCC, VCC); -- вихідний тригер, що синхронізує зміну сигналу TABLE -- поточний стан, вхідний сигнал, наступний стан, вихідний сигнал ss, y => ss, zd; s0, 0 => s0, 0; s0, 1 => s2, 1; s1, 0 => s0, 0; s1, 1 => s2, 1; s2, 0 => s2, 1; s2, 1 => s3, 0; s3, 0 => s3, 0; s3, 1 => s1, 1; END TABLE; END;
А от автомат Мілі — це машина станів з асинхронними сигналами на виходах. Формування вихідного сигналу здійснюється комбінаційною логікою. Після переходу до наступного стану, синхронізованого тактовим сигналом, зміна вихідного сигналу відбувається з затримкою, яку вносить комбінаційна логіка.
SUBDESIGN mealy ( clk, reset, y : INPUT; z : OUTPUT; ) VARIABLE ss: MACHINE WITH STATES (s0, s1, s2, s3); BEGIN ss.clk = clk; ss.reset = reset; TABLE -- поточний стан, вхідний сигнал, вихідний сигнал, наступний стан ss, y => z, ss; s0, 0 => 0, s0; s0, 1 => 1, s1; s1, 0 => 1, s1; s1, 1 => 0, s2; s2, 0 => 0, s2; s2, 1 => 1, s3; s3, 0 => 0, s3; s3, 1 => 1, s0; END TABLE; END;
- Бродин В. Б., Калинин А. В. Системы на микроконтроллерах и БИС программируемой логики. — М.: Издательство ЭКОМ, 2002. — 400 с.: илл. — ISBN 5-7163-0089-8. (рос.)
- Каршенбойм И., Косткин М. Шпаргалка для перехода от AHDL к VHDL. [Архівовано 18 жовтня 2011 у Wayback Machine.] — Компоненты и технологии № 1, 2003. (рос.)
- Стешенко В. Б. ПЛИС фирмы ALTERA: проектирование устройств обработки сигналов. — М.: ДОДЭКА, 2000. — 128 с. — ISBN 5-94020-001-X. (рос.)