Компоненты и технологии, № 7'2002
Проектирование в системе Max+Plus II:
VHDL против AHDL
Разработчики, замкнувшиеся в рамках ДИОЬ, уподобляются программистам, пишущим на ассемблере.
Глеб Варфоломеев
gleb@schemes.spb.ru
Языки описания аппаратуры завоевывают все большую популярность среди российских разработчиков. В немалой степени этому способствует популярность пакета Max+Plus II фирмы Altera, который поддерживает создание описаний аж на трех языках: AHDL, VHDL и Verilog. С момента появления Max+Plus II из этих трех языков именно язык AHDL захватил и по сей день удерживает абсолютное первое место по популярности у отечественных инженеров-разработчиков. На взгляд автора, причин тому две. Первая — это чрезвычайная простота и превосходная документированность в справочной системе, что особенно привлекает инженеров старшего поколения. Вторая важная причина — это неплохой ассортимент литературы по языку AHDL, включая замечательный практический курс [3]. С литературой же по языку VHDL ситуация зеркально противоположная. Если посмотреть на список литературы в конце статьи, то видно, что доступные сейчас в продаже книги по языку VHDL, такие как, например, первые две, изданы в 2000-2001 годах. Причем все известные автору книги по VHDL скорее напоминают краткие справочники по языку, а о наличии практического курса типа того, что написан для AHDL [3], и говорить не приходится.
На практике всегда, когда одну и ту же задачу можно решить разными способами, возникает естественный вопрос о том, какой способ эффективнее и в каких ситуациях. Однако в доступной автору литературе (не только на русском языке) не содержится сравнения эффективности языков AHDL и VHDL.
На взгляд автора, разработчики, замкнувшиеся в рамках AHDL, уподобляются программистам, пишущим на ассемблере. Обоснуем это утверждение путем сравнения языков на ряде примеров, используя многолетний опыт практической работы с системой MAX+Plus II. Кроме того, данная статья ставит целью в некоторой мере компенсировать отсутствие практического курса по проектированию на VHDL в Max+Plus II. Впрочем, материалы статьи не заменят собой справочников по VHDL и справочную систему Max+Plus II. Материалы статьи относятся не только к САПР Max+Plus II, но во многом и к другой популярной САПР фирмы Altera — Quartus.
AHDL (AlteraHDL) является внутренним языком пакета Max+Plus II. Это означает, что в каком бы виде вы не выполняли свой проект (графический, AHDL, VHDL, Verilog или в виде временных диа-
грамм в Waveform Editor), компилятор Max+Plus II сначала переведет ваш проект на язык AHDL. Затем компилятор превратит AHDL-файл в файл прошивки с расширением .pof. Если проводить параллели между языками описания аппаратуры и языками программирования, то здесь напрашивается аналогия (рис. 1).
Какой же среди языков описания аппаратуры является аналогом языков программирования высокого уровня? Как отмечает известный специалист по ПЛИС из Петербургского университета аэрокосмического приборостроения Р. А. Мяльк: «Аналогом языков программирования высокого уровня является язык VHDL». Для иллюстрации справедливости этого утверждения приведем пример.
Начнем с языков программирования. Рассмотрим простую подпрограмму перемножения двух целых 32-разрядных чисел, написанную на языке высокого уровня C:
long MULT(int a, int b)
{
А вот та же подпрограмма, переведенная на язык низкого уровня Macro Assembler.
push ebp
mov ebp,esp
mov eax,[ebp+0x08]
imul [ebp+0x0c]
pop ebp
ret
Сравним эти две подпрограммы. Что сразу бросается в глаза? Во-первых, компактность записи первой подпрограммы по сравнению со второй. Если не
return a*b
Компоненты и технологии, № 7'2002
Таблица 1
Таблица 2
Имя группы Тип группы Назначение Комментарии
dataa[] Вход Множимое Ширина равна LPM_WIDTHA
datab[] Вход Множитель Ширина равна LPM_WIDTHB
result[] Выход result = dataa[] * datab[] Ширина равна LPM_WIDTHP
Имя параметра Тип Описание
LPM_WIDTHA Integer Ширина порта dataa[]
LPM_WIDTHB Integer Ширина порта datab[]
LPM_WIDTHP Integer Ширина порта гаЫ^]
LPM_WIDTHS Integer Ширина порта sum[]*
* Примечание: хотя в минимальной конфигурации порт sum не используется, этот параметр следует установить равным LPM_WIDTHP
считать строк с фигурными скобками, то подпрограмма на Си состоит из двух строк — заголовка подпрограммы и собственно умножения. Подпрограмма на ассемблере занимает 6 строк. Во-вторых, — и это свойство даже более важно, чем компактность, — наглядность первой подпрограммы по сравнению со второй. Даже если вы не знаете языка Си, но имеете маломальский опыт программирования, взглянув на первый листинг вы наверняка поймете, что происходит перемножение двух переменных а и Ь. А вот со вторым листингом гораздо сложнее: даже опытный программист на ассемблере, посмотрев на этот текст сможет лишь сказать, что перед ним часть подпрограммы, которая перемножает некие 32-разрядные числа.
А какую программу легче отлаживать и в какой программе сложнее сделать ошибку? Ответ очевиден! Любопытный пример из личного опыта: в 1997 году автору этой статьи было заказано устройство на базе только что появившихся ЛУИ-микроконт-роллеров фирмы ЛШе1. Никаких других инструментальных средств, кроме бесплатно распространяемого компилятора с языка ассемблера wavrasm не существовало. Выхода не было — пришлось писать программу на ассемблере. В принципе несложная программа, занимавшая в памяти менее 3 кбайт, при распечатке занимала около 30 страниц, а на ее доведение «до ума» ушло почти полгода. Впоследствии эта программа, переписанная на языке С под компилятор ImageCraft была полностью закончена и отлажена за полторы недели!
Аналогичная ситуация с языками описания аппаратуры. Опять возьмем для реализации перемножитель. Только для простоты уменьшим разрядность операндов до 8 (32-разрядный перемножитель просто не поместится в большинство микросхем, да и компиляция такого проекта будет длиться неприлично долго). Вот как можно описать такой пере-множитель на УИБЬ:
ENTITY MULT IS
PORT ( a, b : IN INTEGER RANGE 0 TO 2**8-1;
ret : OUT INTEGER RANGE 0 TO 2**16-1 );
END MULT;
ARCHITECTURE a OF MULT IS
BEGIN
ret <= a*b;
END a;
Если не считать декларативной части (ENTITY), архитектурная часть описания полностью эквивалентна функции MULT. И достоинства те же: краткость и наглядность. А теперь давайте посмотрим, как выглядит функция MULT, написанная на AHDL. Самый простой способ получить AHDL-представле-
ние — это скомпилировать вышеприведенную программу в MAX+Plus II. Предварительно только нужно, переключившись в окно компилятора, войти в меню «Processing» и щелкнуть по позиции «Generate AHDL TDO File». Теперь после компиляции будет создан файл с тем же именем, что и исходный проект, но с расширением .tdo. Этот файл будет содержать описание вашего проекта на языке AHDL, причем на самом «нижнем» уровне, то есть без макрофункций и c разбиением групп проводников на отдельные проводники. Откроем этот файл. Уверен, то, что вы увидели на экране, привело к непроизвольному возгласу удивления. Перед вами листинг объемом около сотни машинописных страниц, пестрящий логическими выражениями длиной до пяти строчек! Небольшой отрывок из этого файла выглядит так:
-- Node name is 'ret12'
ret12 = LCELL ( _EQ019 $ _EQ020);
_EQ019 = _LC088 & _X009 & _X011 & _X013 & _X015
# _LC238;
_EQ020 = _X016 & _X017;
_X016 = EXP ( _LC253 & _LC255);
_X017 = EXP (!_LC253 & !_LC255);
Даже не верится, что несколько строк, написанных на VHDL, могли превратиться в несколько сотен строк в AHDL. Правда, следует отметить, что этот листинг действительно является самым низким уровнем. Язык AHDL позволяет получить и более высокоуровневое описание, но его придется сделать вручную. Единственный способ перемножить целые числа в AHDL — это воспользоваться готовой функцией, в данном случае «мегафункцией» (параметризованным модулем) LPM_MULT. Но это сделать не так просто. Посмотрим на заголовок этой функции, описание которой находится в справке по AHDL:
FUNCTION lpm_mult (dataa[(LPM_WIDTHA-1 )..0],
datab[(LPM_WIDTHB-1)..0], sum[(LPM_WIDTHS-1)..0], aclr, clock) WITH (LPM_WIDTHA, LPM_WIDTHB, LPM_WIDTHP, LPM_WIDTHS, LPM_REPRESENTATION, LPM_PIPELINE, LATENCY, INPUT_A_IS_CONSTANT, INPUT_B_IS_CONSTANT, USE_EAB, MAXIMIZE_SPEED) RETURNS (result[LPM_WIDTHP-1..0]);
В минимальной «комплектации» эта функция имеет две группы входных сигналов, группу выходных сигналов и четыре обязательных параметра (см. табл. 1-2).
Для того чтобы не вписывать все эти параметры вручную, можно воспользоваться помощью утилиты «MegaWizard Plug-In Manager» (автор затрудняется с адекватным перевести это словосочетание на русский) для создания собственной функции MULT на базе LPM_MULT. Утилита запускается из меню
е
Компоненты и технологии, № 7'2002
«File». После запуска нужно пройти последовательно несколько окон, в которых следует ввести требуемую информацию (рис. 2-7).
После всех этих манипуляций функция MULT, написанная на AHDL, будет выглядеть следующим образом:
INCLUDE «lpm_mult.inc»;
SUBDESIGN MULT
dataa[7..0] datab[7..0] result[15..0]
INPUT;
INPUT;
OUTPUT;
«NO»,
«UN-
(или запустить его из меню «Max+Plus II», если он не был запущен), щелчком установить галочку в позиции «VHDL Netlist Writer» меню «Interface», скомпилировать проект и загрузить выходной код на языке VHDL с расширением .vho в редактор.
Язык AHDL тоже имеет возможности поведенческого описания, аналогично тому, как в языке ассемблера можно использовать макрокоманды или вызовы стандартных функций. Но AHDL допускает только статическое поведенческое описание. Для динамических (синхронных) систем AHDL допускает только один метод описания — структурный. Посмотрим для примера следующий код на VHDL:
lpm_mult_component : lpm_mult WITH ( LPM_WIDTHA = В, LPM_WIDTHB = В, LPM_WIDTHP = 16, LPM_WIDTHS = 16, INPUT_B_IS_CONSTANT LPM_REPRESENTATION
USE_EAB = «OFF»
result[15..0] = lpm_mult_component.result[15..0]; lpm_mult_component.dataa[7..0] = dataa[7..0]; lpm_mult_component.datab[7..0] = datab[7..0];
Согласитесь, разница по сравнению с УИБЬ-описанием очевидна.
Если говорить об аналогии с языками программирования, то она все-таки не будет полной. Создавая программу на языке программирования высокого уровня, вы думаете в основном о том, «что она должна делать» (поведенческое описание [1, 4-5]), а не о том, «как это сделать» (структурное описание). Программирование на ассемблере заставляет вас думать больше о том, «как это сделать». Структурное описание за исключением простейших ситуаций всегда гораздо более громоздкое, чем поведенческое описание. К тому же поведенческое описание намного «естественнее» для восприятия человеком. Однако иногда не удается избежать структурного описания. В этом случае в программы на языках высокого уровня вставляют ассемблерные вставки или подгружают внешние ассемблерные модули. У языков описания аппаратуры такой аналогии нет. Хотя диалект языка УИБЬ пакета Мах+Р1ш II позволяет вызывать функции (компоненты), написанные на ЛИБЬ, делать это совсем не обязательно. УИБЬ позволяет создавать структурное описание проекта без каких-либо ограничений. И вообще вы можете писать на УИБЬ в стиле «как на ЛИБЬ». На языке УИБЬ можно писать и очень низкоуровневые проекты. Чтобы в этом убедиться, достаточно переключиться на компилятор
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY EVENT IS
PORT( d : IN STD_LOGIC;
c : OUT STD_LOGIC);
END EVENT;
ARCHITECTURE a OF EVENT IS
BEGIN
PROCESS (d)
BEGIN
IF (d'event AND d = ' 1') THEN
c <= NOT(d);
END IF;
END PROCESS;
END a;
А вот как компилятор перевел этот код на AHDL:
SUBDESIGN 'event'
( d : INPUT;
) c : OUTPUT;
BEGIN
c = DFFE( d S GND, GLOBAL( d), VCC, VCC, VCC);
END;
Из-за отсутствия в AHDL конструкций, аналогичных PROCESS, WAIT и 'EVENT, реализующих поведенческое описание динамических проектов, компилятор MAX+Plus II был вынужден прибегнуть к структурному описанию проекта. При этом он использовал единственный в языке AHDL динамический элемент — триггер. Кстати, в данном случае описание на AHDL оказалось компактнее, чем на VHDL. Но зато понять сходу по AHDL-листингу, какую логическую функцию выполняет данное устройство, практически невозможно. А вот VHDL-описание дает нам вполне наглядную информацию.
Еще один существенный недостаток языка AHDL — невозможность перенести с платформы на платформу проект на языке AHDL. В конце концов, на продукции фирмы Altera свет клином не сошелся! Сегодня на российском рынке труда, к сожалению, спрос на квалифицированных инженеров-разработчиков намного ниже предложения. И если вы хотите претендовать на высокооплачиваемую работу, то просто обязаны иметь опыт работы с несколькими семействами ПЛИС разных фирм. По крайней мере, кроме Altera, автор настоятельно рекомендует знакомство с не менее популярной продукцией фирмы Xilinx. Реальный случай из жизни одного знакомого разработчика. Он создал достаточно интересный проект на ПЛИС семейства
MAX7000. Проект был сделан в графическом формате, а отдельные блоки были написаны на AHDL. Об этом проекте узнал главный инженер одной достаточно известной питерской фирмы. Разработчику было предложено выкупить у него проект за хорошую цену. Но вот беда: эта фирма работала исключительно на элементной базе фирмы Xilinx, а о переходе на другие ПЛИС и слышать не хотела. Фирма Xilinx принципиально не поддерживала язык AHDL, так как фирма Altera — ее главный конкурент на рынке ПЛИС. В результате весь проект пришлось переписывать. Ничего подобного бы не случилось, если бы проект был выполнен на языке VHDL, поскольку VHDL, в отличие от AHDL, де-факто является международным стандартом языка описания и моделирования аппаратуры.
Например, часто встает задача моделирования устройства, в состав которого входят несколько микросхем, в том числе ПЛИС. Симулятор Max+Plus II способен моделировать только ПЛИС. Для моделирования всего устройства следует использовать внешние симуляторы, такие, как ModelSim, Orcad Express и др. Наиболее удобен, по мнению автора, симулятор Orcad Express, входящий в популярный пакет сквозного проектирования электронной аппаратуры Orcad. Orcad Express осуществляет моделирование проектов, написанных на VHDL [2]. Удобство заключается в том, что пакеты Orcad и Max+Plus II осуществляют полноценную поддержку друг друга (рис. 8).
Последний аргумент, который обычно приводят в пользу AHDL: «AHDL — это родной язык Max+Plus II, поэтому проекты, выполненные на AHDL, лучше оптимизируются компилятором и занимают гораздо меньше места в ПЛИС, нежели проекты на языке VHDL». Это совершенно неверное утверждение, поскольку между языками описания аппаратуры и языками программирования нет полной аналогии. Доказать это очень просто. Выберите в меню «Assign/Device...» семейство MAX3000. Теперь попробуйте скомпилировать оба варианта умножителя MULT. Файл MULT.vhd успешно скомпилируется для ПЛИС EPM3256ATC144. Скомпилировать же проект MULT.tdf удастся, если только разрешить упаковщику компилятора (Fitter) использовать две микросхемы. В одну микросхему проект MULT.tdf просто не помещается!
На взгляд автора, у языка AHDL лишь одно преимущество перед VHDL — крайняя простота. В AHDL, если не считать машин состояния, существует только один тип данных — группы (или массивы) логических уровней. При этом отсутствуют проблемы с приведением типов данных. Практически нет разницы между одиночным сигналом и группой сигналов. Поэтому, если уж вы настроены использовать язык AHDL, то лучше всего он подходит для небольших проектов, в которых не предполагаются какие-либо арифметические действия или сложная обработка сигналов.
Общий же вывод следующий: если вы еще не имели опыта использования языков описания аппаратуры и размышляете о выборе языка, то выбирайте VHDL! Если же вы уже
SIGNED»
BEGIN
END
Компоненты и технологии, № 7'2002
Исправления
Рис. 8
работаете на ЛИБЬ, но собираетесь выходить на проекты более сложные, чем компаратор 4-разрядных чисел без знака, то вам, несомненно, тоже следует изучить и пользоваться языком УИБЬ. В чем, надеюсь, вам поможет данная статья. ММ
Литература
1. Бибило П. Н. Основы языка VHDL. М. Солон-Р. 2000.
2. Суворова Е. А., Шейнин Ю. Е. Язык VHDL для проектирования систем на СБИС, СПб.: СПбГУАП. 2001.
3. Антонов А. П. Язык описания цифровых устройств AlteraHDL. Практический курс. М. РадиоСофт. 2001.
4. Армстронг Дж. Р. Моделирование цифровых систем на языке VHDL. Пер. с англ. М. Мир. 1992.
5. An Introductory VHDL Tutorial. Green Mountain Computing Systems, Inc. http://www.gmvhdl.com/VHDL.html.