2.5.3. Язык проектирования электронных устройств VHDL VHDL - язык моделирования дискретных электронных устройств, утвержденный в 1987 г. в качестве международного стандарта IEEE 1076. Основная версия языка IEEE 1076 VHDL предназначена для моделирования дискретных устройств преимущественно на уровнях вентильном, RTL и корпусов микросхем. Язык VHDL успешно используется и при синтезе устройств. В дальнейшем стандарт корректировался и расширялся, новые версии приняты в 1993 и 1999 гг. Так, версия 1999 г., получившая индекс ШЕЕ 1076.1, содержит средства описания аналоговых и смешанных моделей. Эти описания вместе с базовым вариантом языка VHDL образуют язык VHDL-AMS. VHDL - не единственный язык проектирования радиоэлектронной аппаратуры. Так, для проектирования интегральных схем широко применяется Verilog, находят применение языки Cupl, Palasm и другие, но для сквозного проектирования на всех требуемых для СБИС уровнях функционального проектирования (выше схемотехнического) предназначены только VHDL и Verilog. В VHDL имеются средства для поведенческих и структурных описаний [10]. Описание схемы на языке VHDL включает две части. Первая часть - описание схемы как компонента некоторой над-системы, т.е. это прежде всего описание интерфейсов схемы с внешней средой. Вид этой части, называемой сущностью - entity (здесь и далее принято выделение служебных слов языка VHDL полужирным шрифтом, а нетерминальных символов - курсивом): entity имя_сущности isдекларацииend имя_сущности; Назначение второй части- описание внутренних свойств схемы (структуры или функций), она называется архитектурным телом:architecture имя_ахитектурного_тела of имя_сущности is[декларации]beginописание _схемы_или_алгоритма end имя_архитектурного_тела; У одной схемы (сущности) может быть несколько архитектурных тел, так как могут быть описаны разные аспекты (структура или алгоритмы) и версии объекта, причем на разных иерархических уровнях. Различают структурное и поведенческое описания сущностей. В декларации структурного описания перечисляются сигналы на входах и выходах схемы в виде следующего предложения:port (список_идентификаторов_входных_сигналов: in тип; списокидентификаторов_ выходных_ сигналов: out тип); Фактически списки идентификаторов - это списки сигналов или, что то же самое, имен цепей, соединяющих схему с внешним окружением. Словом in отмечен список входных сигналов, словом out - список выходных сигналов, словом inout помечается список цепей, которые могут быть как входными, так и выходными. Но кроме сигналов связь с внешним окружением может характеризоваться и рядом других величин, примерами которых могут служить такие параметры, как температура, количество выводов компонента схемы, временные задержки и т.п. Для их описания используется декларация generic: generic (список_параметров); Конкретные значения параметров могут быть заданы непосредственно в этой декларации, например: generic (Tl: Time := 20 ns; T2: Time := 5 ns; numb: integer := 12); где Time и integer - типы соответствующих данных. В декларациях архитектурного тела объявляются типы, фигурирующие в данном архитектурном теле. Ими могут быть используемые типы компонентов (объекты), параметры и сигналы. В декларации могут входить также описания процедур, функций, типов данных. В качестве примера рассмотрим структурное описание схемы, представленной на рис. 2.26: entity schema is port (a,b,c,d,e: in BIT; y: out BIT); end schema; Рис. 2.26. Фрагмент логической схемыarchitecture str of schema is component AND_OR generic (delay 1: Time); port (i1,i2,i3,i4: in BIT; a: out BIT); end component AND_OR; component OR2 generic (delay2: Time); port (i1,i2: in BIT; a: out BIT); end component OR2; signal zl,z2: BIT; begin El: AND_OR generic map (delay 1 := 4ns); port map (a,c,b,c,zl); ^ E2: AND_OR ; generic map (delayl := 5 ns); port map (d,c,e,c,z2); E3:OR2 generic map (delay2 := 3 ns); port map (zl,z2,y); end str; Из примера следует, что в декларации port перечисляются формальные сигналы, а в port map - фактические сигналы, причем последовательность перечисления в обоих местах должна быть согласованной. Допускается и произвольный порядок перечисления при использовании в port map списка с ключевой записью. Например, для ЕЗ последнего примера такой список имеет вид port map (a=>y, 11 =>zl, i2=>z2); Аналогична роль деклараций generic map, используемых в том случае, если конкретные значения параметров различны для разных экземпляров компонентов. Сигналы в цепях, не являющихся входными или выходными для описываемой схемы, должны быть перечислены в декларации архитектурного тела после слова signal. Структурные описания для сложных объектов являются иерархическими. Только структурных описаний недостаточно для задания объекта, нужно описывать также поведение (функции объекта). Поведенческое описание, как минимум, должно быть задано для сущностей нижнего иерархического уровня. Однако в практике проектирования СБИС превалирует нисходящий стиль, следовательно, проектирование начинается с разработки алгоритмов (поведенческих описаний) верхнего иерархического уровня. В описаниях поведения фигурируют типы данных, операторы, процессы, процедуры, функции и т.п. Семантика простых типов данных понятна уже из их названий: INTEGER (целые числа), REAL (действительные числа, их нужно записывать с десятичной точкой), BIT (со значениями 0 и 1), BOOLEAN (со значениями TRUE и FALSE), BIT_VECTOR (строка битов), POSITIVE (положительные целые числа), NATURAL (натуральные числа), CHARACTER ( символы кода ASCII), STRING (строка символов). Отметим, что после символа «--»(двойной дефис) следует примечание. Константы в VHDL описываются следующим образом:constant имя: тип : = значение; Например:constant numb: integer := 1025; или constant col: string := "black"; Переменные декларируются следующим образом:variable имя: тип; Начальные значения переменных могут быть заданы в декларациях, например:signal reg: BIT_VECTOR := "1001100101"; variable vol: real := 5.4; Значения величин типа BIT и CHARACTER, так же как и отдельных элементов массивов BIT_VECTOR и STRING, обрамляются апострофами, а сочетания из более чем одного значения этих массивов заключаются в кавычки. Типы могут быть введены разработчиком модели с помощью описаний следующего вида:type идентификатор is (список значений); (2.8) Например, конечное множество значений задается в виде перечислимого типаtype octal_digits is ('О1, Т, '2', '3', '4', '5', '6', 7');type color is («red», «green», «blue»); Список значений в (2.8) может иметь одну из следующих форм. • В случае скалярных величин - диапазон возможных значений в видеrange минимальное ^значение to максимальное _значение; Например: range 1 to 10; или range 10 downto 1; Другой пример - задание часто используемого типа Time:type Time is range -1E9 to 1E9 units fs; ps= 1000 fs; ns=1000ps; us=1000ns; ms=1000us; sec= 1000 ms; min=60sec; hr=60min;end units; Аналогично с помощью конструкции units задаются измерения других физических величин. • В случае массиваarray (диапазон_индексов) of тип_элементов_массива; Например, вектор из 16 действительных чисел: array (0 to 15) of real; Отметим, что границы диапазонов значений величин или индексов могут быть представлены не только конкретными числовыми значениями, но и в параметрическом виде, если предварительно определены их значения с помощью декларации generic. • В случае записиrecordсписок_идентификаторов_и_их_типов;end record; Например:recordDay: INTEGER range 1 to 31; Month: month_list; - - month_list-ранее описанный тип; Year: ^ INTEGER range 1900 to 2100; end record; В VHDL применяются операторы присваивания, назначения сигнала, управления, вызова процедур и ряд других. В арифметических выражениях, встречающихся в операторах, используются знаки операций «+» (сложение), «-» (вычитание), «*» (умножение), «/»(деление), mod (деление по модулю), rem (остаток), «**> (возведение в степень), abs (абсолютная величина); в логических выражениях - not (НЕ - отрицание), and (И -конъюнкция), or (ИЛИ -дизъюнкция), nand (И-НЕ), nor (ИЛИ-НЕ), хог (исключающее ИЛИ). Знак «&» использован для указания операции конкатенации. Знаки отношений составляют множество {=, /=, ,>=}. Прежде всего рассмотрим, в чем состоит различие между оператором присваивания :=, известным из других алгоритмических языков, и оператором назначения сигнала у 0; у Поэтому использование операторов присваивания и назначения сигналов в одной и той же ситуации может дать разные результаты. Например: A: = B or X; С:= A and Z; (2.10) Пусть В = 0, Z=l и в рассматриваемый момент времени X переключается из 0 в 1. После выполнения этих двух операторов С становится равным 1. В случае АС в (2.11) используется старое значение А. Поэтому поскольку старое значение А есть 0, то сигнал С в данный момент времени остается равным 0. Другими словами, в случае (2.10) имеем последовательное выполнение операторов, а в случае (2.11) - параллельное, не зависящее от того, в каком порядке операторы записаны. Следует различать понятия инерционной и транспортной задержек. В (2.9) подразумевается инерционная задержка, т.е. у примет после 200 нc новое значение xl and x2, равное 1 только в том случае, если значение xl and x2 оставалось равным 1 в течение этих 200 нc. При транспортной задержке, которая указывается в видеу сигнал проходит на выход независимо от его длительности. ?*» Ш»Примеры других операторов. • Условный оператор:if условие then операторы;else операторы;end if; По отношению к сигналам можно использовать и параллельные формы условного оператора. Форма when:сигнал где каждая строка списка имеет вид выражение when условие else причем в последней строке else отсутствует, a when может отсутствовать. Например:у al and not a2 when J = 2 else al when J= 3; Форма select:with переменная select сигнал где каждая строка списка имеет видвыражение when значение переменной В том же примере имеемwith J select у al and а2 when 1, al and not a2 when 2, al when 3; • Оператор выбора:case выражение is список_действий end case; В списке действий столько строк, сколько имеется альтернативных действий. Каждая строка имеет видwhen значение_ выражения —> оператор; Например:case J is when 1 => у when 2 => у when 3 => у end case; • Оператор цикла: for переменная in диапазон_переменной loop операторы end loop; или: метка while отношение loop операторы end loop метка; • Оператор ожидания: wait on список сигналов until условие for значение времени; Возможны сокращенные формы: wait on список сигналов; wait until условие; wait for значение времени; т.е. подразумевается задержка до изменения какого-либо сигнала го списка, до выполнения условия или до исчерпания времени соответственно. • Оператор generate. Структурные описания сложных схеммогут стать чрезмерно громоздкими, если все экземпляры компонентов описывать по отдельности. Чтобы устранить этот недостаток, в язык введен оператор generate, порождающий копии компонентов. Например, если схема состоит го 10 экземпляров двухвходового компонента Device, то ее архитектурное тело может выглядеть следующим образом: architecture example of schema is component Device port (il,i2: in BIT; y: out BIT); end component; signal X1 ,X2,Y: BIT_VECTOR (0 to 9); begin for i in 0 to 9 generate En: Device port map (il=>Xl(i),i2=>X2(i),y=>Y(i)); end generate; end example; Моделирование в VHDL осуществляется событийным методом. Реализуется этот метод благодаря не только учету задержек, но и специальным механизмам, таким, как оператор processили охраняемые блоки. Process - это блок, выполняемый только тогда, когда происходи изменения его входных параметров. Структура этого блока:[метка:] process [(список параметров)] тело_процесса — здесь описываются вложенные в процесс -- типы и операторы end process [метка]; Охраняемый (guarded) блок имеет видметка: block (охранное выражение) begin операторы end block метка; Операторы блока выполняются только при истинном значении охранного выражения. При поведенческом описании сущностей архитектурное тело представляет собой алгоритмы, реализуемые в схеме. Подразумевается, что все операторы в архитектурном теле выполняются параллельно (последовательное выполнение имеет место внутри процессов и подпрограмм). Рассмотрим пример поведенческого описания схемы, приведенной на рис. 2.26. Первый вариант: architecture alg of schema is signal zl,z2: BIT; begin zl z2 у end alg; Второй вариант с использованием оператора process: architecture alg of schema is signal zl,z2: BIT; begin process (a,b,d,e,c) begin zl z2 у end process; end alg; Третий вариант, в котором сигналы a, b, d, е представлены в виде элементов двоичного вектора X: entity schema is port (с: in BIT; X: in BIT_VECTOR (1 to 4); y: out ВIT); end schema; architecture alg of schema is signal zl,z2: BIT; begin zl z2 yend alg; Приведенный ниже пример D-триггера - это пример использования охраняемого блока. D-триггер при R = ‘1’ переходит в состояние '0', иначе, если С =’1’Г, на выходе Q устанавливается значение входного сигнала S. D:block(C =’1’or R =’1’) beginQ end block D; В языке VHDL допускаются смешанные описания, имеющие место в том случае, если в архитектурном теле одновременно присутствуют как операторы поведенческого моделирования, так и элементы структурного описания. Например:architecture unit of schema is component addport (xl,x2: in BIT; у: out BIT);end component;signal b: BIT; begin b El: add port map (a,b,d); end unit; При моделировании структурное описание компонента El заменяется его поведенческим описанием, которое также должно быть разработано. Форма представления процедур и функций в VHDL аналогична формам, используемым во многих алгоритмических языках. Вид описания процедуры:procedure имя (список_параметров) is описания _типов; begin телоend имя; Описание функции:function имя (список параметров) return тип функции is begin тело end имя; (2.12) В теле функции имеется оператор return выражение, это выражение и задает возвращаемое значение функции. В пакеты оформляются части описаний, используемые неоднократно в разных местах VHDL-модели. Пакет имеет форму:package имя is описание _типов_и/или_функций end имя; При этом код функций помещается в тело пакета: package body имя isописание _процедур_и/или_функций end имя; Описание функций имеет вид (2.12). Если описываются только типы, тело пакета не требуется. Если пакет нужно использовать в некоторой сущности, то перед ее описанием (перед фразой entity) достаточно сделать ссылку на пакет в виде use имя_пакета; Например, в следующей записи отражено использование библиотек компонентов IEEE, DW03 и широко распространенных пакетов IEEE. std_logic_l 164. all, IEEE. std_logic_arith. all и DW03.DW03_components.all: library IEEE, DW03; useIEEE.std_logic_1164.all; useIEEE..std_logic_arith.all; use DW03.DW03_components. all;entity unitl is port (.... В VHDL имеются стандартные (предопределенные) атрибуты:S'LAST_VALUE - предыдущее (перед последним изменением) значение сигнала S;S'STABLE (Т) - принимает значение true, если сигнал S не изменялся в течение времени Т;S'DELAYED (Т) - значение сигнала S в момент времени t -Т, где t - текущее время; S'EVENT - принимает значение true, если с сигналом S произошло событие (сигнал изменился);^ A'RANGE, A'LEFT, A'RIGHT - диапазон, нижняя и верхняя границы массива А; и некоторые другие. В частности, эти стандартные значения позволяют лаконично описывать некоторые важные ситуации. Например, выраженияХ= ‘1’ and not X'STABLE илиХ= ‘1’ and X'EVENT , оказываются истинными в момент положительного фронта сигнала X, и, следовательно, с помощью любого из этих выражений можно представлять события, происходящие по положительному фронту сигнала. Если вместо X =’1’ записать X = '0', то эти выражения будут соответствовать отрицательному фронту сигнала X. Как уже отмечалось, в программах моделирования на VHDL используется событийный метод. Можно выделить две фазы моделирования. На первой из них устанавливаются исходные значения переменных и сигналов, настраиваются внешние сигналы, модельное время устанавливается в нуль. Вторая фаза - моделирование до истечения установленного времени Т. Рассмотрим примеры моделей схем на языке VHDL. Пример 1. Генератор синхросигналов. entity clock is generic (tl: Time:=10ns;t2:Time:=10ns); port (c: out BIT := '0'); --tl и t2 в сумме составляют период синхросигналов, ~ начальное значение сигнала с есть низкий уровень, т.е. ‘0’. end clock; architecture gen of clock is generic (N:integer:=1000); -- N есть число периодов колебаний на отрезке -- моделирования; .begin A: process beginfor i in 1 to N loop с cend loop; end process A; end gen; Пример 2. Возможный вариант описания D-триггера (сигнал R - установка в 0, при С = 1 на выходе Q устанавливается значение входа S):entity FF isport (R,S,C: in BIT; Q: out BIT); end FF; architecture func of FF is begin work: process (R,C) begin if R=’1’ thenQ end if;end process work; end func; П p и м e p 3. Повторение примера 2, но установка состояния S происходит по положительному фронту сигнала С. В этом случае можно сохранить предыдущую модель, лишь заменив второе условие в операторе if на выражение not C'STABLE and С = ' 1’ П р и м е р 4. Требуется описать операции записи данных в восьмиразрядный регистр 1 со входа А по переднему фронту тактового сигнала С и далее данных из регистра 1 в регистр 2 по заднему фронту того же сигнала (в этом примере иллюстрируется представление сигналов битовыми векторами):entity REG is port(A: in BIT_VECTOR(0 to 7); C: in BIT; Z: out BIT_VECTOR(0 to 7)); end REG;architecture alg of REG issignal B: BIT_VECTOR(0 to 7); begin m: block((C = 'I1 and not C'STABLE) or (C= '0' and notC'STABLE))В Z end block m; end alg; П p и m e p 5. Конвертор параллельного кода в последовательныйentity converter is generic (tact: Time); port (paral: in BIT_VECTOR (0 to 7); clock: in BIT; seq: out BIT); end converter; architecture alg of converter is begin ,,A: process variable delay: Time := tact; ~ описывается переменная delay типа Time с начальным -- значением tact.begin wait until clock =’1’; for iinparal'range loop seq delay:= delay+tact; end loop; seq end process A;end alg; П p и m e p 6. Автомат Мура (рис. 2.27), где П - память (12-разрядный регистр), КС - комбинационная схема. entity Moore is generic (Т: Time:=25 ns; N: integer:=12; M: integer:=9); port (X: in BIT_VECTOR (1 to N); C: in BIT; F: out BIT_VECTOR (1 to M)); end Moore; XFCРис.2.27. Автомат МураArchitecture cont of Moore issignal Rl, R2: BIT_VECTOR (1 to N); begini; process (R2) begin F end process; -- Идентификаторами СС1 и СС2 обозначены функции, -- описывающие поведение -- соответствующих КС, описания функций здесь не приведены process (С) begin R2end process; end cont; П p и m e p 7. Мультиплексор, схема и таблица функционирования которого приведены на рис. 2.28 [68]. entity mpx is port (X: in BIT_VECTOR (1 to 4); A: in BIT_VECTOR (1 to 2); y: out BIT); end mpx; -- архитектурное тело algl - первоначальное поведенческое -- описание, выражающее алгоритм функционирования -- устройства.X1X2X3X4A1A2MUX4YРис. 2.28. Изображение мультиплексора и его функциональностьarchitecture alg of mpx is begin process beginwith A select у end; end algl; -- архитектурное тело alg2 - поведенческое описание в стиле ~ потока данных, полученное после выбора элементщй базы и -- определенной конкретизации схемных решений. architecture alg2 of mpx issignal mal,ma2: ^ BIT_VECTOR (1 to 2); signal: my: BIT_VECTOR (1 to 4);beginfor i in 1 to 2 loop mal(i) ma2(i) end loop; my(l) my(2) my(3) my(4) у end alg2; ~ архитектурное тело schema - структурное описание, ~ выражающее логическую схему устройства.architecture schema of mpx is component ANDN3 port (a.b.c: in BIT; z: out BIT);end component; component ANDN4port (a,b.c,d: in BIT; z: out BIT); end component;Рнс. 2.29. Логическая схема мультиплексораcomponent INV port (x: in BIT; у: out BIT);end component;signal mal,ma2: BIT_VECTOR (1 to 2);signal: my: BIT_VECTOR(1 to 4); el: ANDN3 port map (x(l),mal(l),ma2(l),my(l)); e2:ANDN3 port map (x(2),mal(l),ma2(2),my(2)); e3:ANDN3 port map (x(3),mal(2),ma2(l),my(3)); e4: ANDN3 port map (x(4),mal(2),ma2(2),my(4)); e5:ANDN4 port map (my(l),my(2),my(3),my(4),y); e6:INV port map (A(l),mal(l)); e7:INV port map (mal(l),ma2(l)); e8:INV port map (A(2),mal(2)); e9:INV ' port map (mal(2),ma2(2)); end schema; Пример8.В этом примере рассматривается возможный вариант модели двоичного сумматора, на входы которого подаются двухразрядные двоичные слагаемые А и В, на выходе получается трехразрядное двоичное число Y. Главное назначение примера - иллюстрация применения пакета (package). В примере используется операция сложения целых десятичных чисел, что требует перевода слагаемых А и В из двоичной системы в десятичную, а полученной суммы из десятичной системы в двоичную. Для перевода используются функции tran2_10 и tranlO_2. Эти функции объединены в пакет tran.entity add isport (A: in BIT_VECTOR (0 to 1); ^ B: in BIT_VECTOR (0 to 1); Y: out BIT_VECTOR (0 to 2));end add;package tran isfunction tran2_l0 (signal X1, X2: BIT) return integer;function tranlO_2 (signal X: integer) return BIT_VECTOR;end tran; package body tran isfunction tran2_10 (signal XI, X2: BIT) return integer is variable Z: integer := 0; — функция преобразования двухразрядных двоичных чисел в ~ десятичные; -- аргументы XI и Х2 соответственно ~ младший и старший разряды двоичного числаbeginif XI = ' 1 ’ then X:=1;else X := 0;end if;if X2 = ' 1 ’ then X:=X+2;else X := X;end if;return X;end tran2_10; .function tranlO_2 (signal X: integer) return BIT_VECTOR is variable Y: BIT_VECTOR (0 to 2); variable tl: integer := 0; variable t2: integer := 0; --функция преобразования десятичных чисел в диапазоне от 0 до 7 в трехразрядные двоичные числаbegint1:=X;for i in 2 downto 0 loop t2:=tl/(2**i); tl:=tlrem(2**i); ift2=l then Y(i) :=' 1 '; else Y(i) := '0' ; end if; end loop; return Y;end tranlO_2; end tran;architecture sum of add is use tran.all;signal aint, bint: integer range 0 to 3;signal yint: integer range 0 to 7;begin aint bmt yint Y end sum; Пример9. В этом примере рассматривается важная особенность языка VHDL, заключающаяся в возможности использования в одном архитектурном теле смешанных структурных и поведенческих (structure and dataflow) описаний. Смешанные описания удобны, когда проектируется сложная схема из компонентов, для которых уже определены VHDL-модели в виде сущностей (entities). Пусть требуется разработать VHDL-модель восьмиразрядного комбинационного сумматора. Логика работы схемы одного разряда сумматора задана в виде табл. 2.12. Тогда модель одноразрядного сумматора может быть представлена в следующем виде:Таблица 2.12 А В С1 SUM С2 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 1 1 entity adder is port (А, В, С1: in BIT; SUM, C2: out BIT); end adder; - А и В - слагаемые, С1 - перенос из соседнего младшего разряда, — SUM - сумма, С2 - перенос в соседний старший разрядarchitecture opr of adder is begin SUM C2 end opr; Теперь модель восьмиразрядного сумматора получается со ссылкой на компонент adder и с помощью оператора generate:entity add_8 is port (X, Y: in BIT_VECTOR (7 downto 0);CO: in BIT;C7: out BIT; RES: out BIT_VECTOR (7 downto 0); end add_8; -- X и Y - слагаемые, RES - сумма architecture cont of add 8 iscomponent adder SUM, C2: out BIT); end component; signal C: BIT_VECTOR (7 downto);beginfor i in 7 downto 0 loop if i = 0 generate FF: adderport map (X(0), Y(0), C0, RES(0), C(0)); end generate;if i /= 0 generate FF: adderport map (X(i), Y(i), C(i-l), RES(i), C(i));end generate;end loop; C7end cont;