Кафедра "Вычислительная техника"
курсовая работа
На тему: Основы языка
VHDL
Москва, 2009
Содержание
1.1 Введение
1.2 Идентификаторы в языке VHDL
1.3 Объекты языка VHDL
1.4 Типы данных
1.5 Операции языка VHDL
1.6 Последовательные операторы
1.7 Параллельные операторы
1.8 Описание интерфейса устройства
1.9 Архитектура
1.10 Особенности синтеза схем по описаниям на языке VHDL
Литература
1.1 Введение
Язык VHDLслужит для описания модели цифрового устройства (прибора, системы). Описание на языке VHDLопределяет внешние связи устройства (“вид снаружи” или интерфейс) и один или несколько “видов изнутри” (см. рис. 1.1). Вид снаружи задает интерфейс устройства, набор сигналов, которыми устройство обменивается с внешним миром. Этот вид описывает абстрактное представление устройства “в целом” и обозначается английским термином entity, что в дословном переводе означает «сущность» и наиболее точно отражает смысл представления. Однако в литературе термин «сущность» не нашел широкого распространения, для обозначения внешнего описания объекта используются термины «интерфейс объекта», «декларативная часть» и другие. В настоящем пособии будет использоваться термин «интерфейс объекта» или просто «интерфейс».
Рис. 1.1. Цифровое устройство и его модель
Вид изнутри определяет функциональные возможности устройства или его структуру. Внутреннее строение объекта определяет архитектура (architecturebody).
Как и в языках программирования, язык VHDLимеет свои правила, в том числе правила описания имен переменных, объектов, типов данных и других параметров. Основные правила языка VHDLописаны в последующих разделах.
1.2 Идентификаторы в языке VHDL
Идентификаторы - это последовательность букв и цифр произвольной длины. Легальными символами являются прописные (A…Z), строчные (a…z), цифры (0…9), знак подчеркивания. Первый символ должен быть буквой, а последний символ не может быть знаком подчеркивания. Строчные и прописные буквы считаются идентичными, например, Count, COUNT и CouNTрассматриваются как один идентификатор. Знаки подчеркивания не должны следовать друг за другом. Комментарии начинаются с двойного дефиса и следуют до конца строки, например,
- это комментарий, он продолжается до конца строки
- это продолжение комментария
entityUARTisend -- это комментарий, который следует за декларацией интерфейса устройства.
Следующие идентификаторы зарезервированы для использования в качестве ключевых слов и не могут быть использованы иначе:
Abs | Access | after | alias | All |
And | architecture | array | begin | Block |
Body | Buffer | case | component | Configu-ration |
Constant | disconnect | downto | else | Elsif |
End | Entity | file | for | function |
generate | Generic | guarded | if | In |
inout | Is | label | library | linkage |
loop | Map | mod | nand | New |
next | Nor | not | null | Of |
on | Open | or | others | Out |
package | Port | procedure | process | Range |
record | Register | rem | select | severity |
signal | Subtyupe | then | to | Transport |
type | Units | until | use | vriable |
wait | When | while | with | Xor |
1.3 Объекты языка VHDL
Объекты это область хранения данных определенного типа. Создаются объекты посредством декларации объекта, например:
variableCOUNT: INTEGER;
В результате порождается объект с именем COUNT, который хранит целочисленную величину. Кроме того, COUNTдекларируется как класс variable.
Объекты – данные могут быть трех классов:
- сonstant(константа) - может хранить отдельное значение определенного типа. Это значение присваивается объекту в начале моделирования и не может изменяться в процессе моделирования.
- variable(переменная) - объект этого класса может хранить отдельное значение определенного типа, однако, в процессе моделирования ему могут присваиваться различные значения. Для этого используются выражения присваивания (variableassignmentstatement).
- signal(сигнал) – объект данного класса имеет предыдущее значение, имеет текущее значение и набор последующих значений.
Объекты класса signalмоделируют проводные соединения в схемах, в то время как переменные (variable) и константы (constant) используются для моделирования поведения схемы, они аналогичны объектам, используемым в языках программирования Cи Pascal.
Декларация констант
Декларации объектов (objectdeclaration) имеют целью дать имя объекту, объявить его тип, класс и даже присвоить значение. Примеры деклараций констант описаны ниже:
constantRISE_TIME: TIME:= 10ns;
constantBUS_WIDTH: INTEGER:= 8:
В первом случае объявляется объект RISE_TIME, который хранит значение типа TIME, объекту в начале моделирования присваивается величина 10 наносекунд. Во втором случае объявляется, что BUS_WIDTH(ширина шины) типа INTEGER(целое) и ей присвоено значение 8.
Декларация переменных
Примеры деклараций объектов класса variableприведены ниже:
variable CTRL_STATUS: BIT_VECTOR(10 downto 0);
variable SUM: INTEGER range 0 to 100 := 10;
variableFOUND, DONE: BOOLEAN;
В первом случае декларируется переменная CTRL_STATUSкак массив из 11 элементов, причем, каждый элемент типа BIT. Во втором случае переменная SUMдекларируется как целое, лежащее в диапазоне от 0 до 100, в начале моделирования переменной присваивается значение 10. Если переменной в начале моделирования не задано значение, то используется значение по умолчанию. Им служит самое “левое” значение в наборе значений данного типа. Например, переменная типа BOOLEANимеет набор значений (FALSE, TRUE) и в третьем примере начальное значение переменных FOUNDи DONEбудет взято по умолчанию, т.е. FALSE.
Декларация сигналов
Декларации объектов класса signalсхожи с декларациями переменных:
signal CLOCK: BIT;
signal DATA_BUS: BIT_VECTOR(0 to 7);
signal GATE_DELAY: TIME := 10 ns;
В первом примере декларируется объект CLOCKтипа BIT, начальное значение при моделировании будет взято по умолчанию, т.е. 0 (набор значений типа BIT: 0,1 и крайнее левое значение 0).
Не все объекты в языке VHDLсоздаются путем декларирования, например, входные/выходные порты всегда считаются объектами класса signal.
1.4 Типы данных
Каждый объект в языке VHDLможет хранить значения, относящиеся к определенному набору. Это множество значений декларируется с помощью объявления типа (typedeclaration). Тип – это имя, которое связывается с определенным набором значений и набором операций. Некоторые типы предопределены языком VHDL. Например, BOOLEANимеет набор значений FALSE, TRUEи набор операторов: and, or, nor, nand, not. В языке имеется возможность создавать новые типы с использованием деклараций и задания набора операций.
Все возможные типы в VHDLраспадаются на четыре больших категории:
- scalar(скалярные),
- composite(композитные) – они состоят из элементов одного типа (массивы) или различного типа (записи),
- accesstype(типы доступа) – обеспечивают доступ к данному типу через указатели,
- filetypes(тип – файл) – обеспечивает доступ к объектам, содержащим последовательности значений данного типа.
В свою очередь скалярные типы подразделяются на четыре вида:
-enumeration(перечислимый тип),
-integer(целый тип),
-physical(физический тип),
-floatingpoint(тип “с плавающей запятой”).
Перечислимый тип
В декларации определяется набор определенных пользователем значений, например:
type MVL is ('U','0','1','Z);
type MICRO_OP is (LOAD, STORE, ADD, SUB, MUL, DIV);
MVL – перечислимый тип с упорядоченным набором значений: 'U', '0', '1', и 'Z'. MICRO_OP имеетнаборзначений: LOAD, STORE, ADD, SUB, MUL, DIV. Порядок записи значений в декларации определяет лексику, т.е. значение справа всегда больше значения слева: STORE<DIVistrue, SUB> MULisfalse. Значения в перечислимых типах имеют позиционный номер. Позиционный номер самого левого элемента 0. Значения в перечислимых типах еще называют enumerationliterals(литералы перечислимого типа). Например, вдекларации:
type CAR_STATE is (STOP, SLOW, MEDIUM, FAST);
литералами являются STOP, SLOW, MEDIUM, FASTи только они могут присваиваться переменной CAR_STATE.
Целый тип
Integer– целое, задает тип, набор значений которого находится в заданном целочисленном диапазоне, например:
type INDEX is range 0 to 15;
type WORD_LENGTH is range 31 downto 0;
subtype DATA_WORD is WORD_LENGTH range 15 downto 0;
type MY_WORD is range 4 to 6;
INDEX– это переменная целочисленного типа, набор значений которой размещен в диапазоне целых от 0 до 15. DATA_WORD– подтип WORLD_LENGTHв диапазоне от 15 до 0. В отличие от перечислимых в целочисленных типах позиционный номер равен величине значения, например, для значения 31 переменной WORD_LENGTHпозиция равна 31.
Тип “с плавающей запятой”
Тип floatingpointобладает набором значений в заданном диапазоне вещественных чисел, например:
type TTL_VOLTAGE is range 1.4 to 5.5
type REAL_DATA is range 0.0 to 31.9;
Литералы типа floatingpointотличаются от целочисленных присутствием точки ( . ). В результате 0 – это целочисленный литерал, а 0.0 – это литерал типа с плавающей запятой.
Физический тип
Physicaltypeхранит значения, которые представляют собой результаты измерений физических величин: времени, длины, напряжения, тока и т.п. Значения этого типа выражаются целыми, умноженными на базовую единицу, например:
type CURRENT is range 0 to 1 E9
units
nA; -- (base unit) nano-ampere
uA = 1000 nA; -- micro-ampere
mA = 1000mA; --milli-ampere
Amp = 1000 mA; -- ampere
end units;
subtype FILTER_CURRENT is CURRENT range 10mA to 5 mA;
Здесь CURRENTопределен как физический тип, имеющий значения в диапазоне от 0 nAдо 10^9 nA. Базовой единицей является наноАмпер, а все остальные являются производными. Позиционный номер значения равен числу базовых единиц, представленных данным значением, например, 2 mAимеют позиционный номер 2000, в то время как 100 nAзанимают позицию 100. Физический литерал записывается как целое, за которым следует название единицы измерения (пробел обязателен).
Тип “массив”
Объект типа arrayсостоит из элементов одного типа. Нижеданыпримерымассивов:
type ADDRESS_WORD is array (0 to 63) of BIT;
type DATA_WORD is array (7 downto 0) of MVL;
type ROM is array (0 to 125) of DATA_WORD;
ADDRESS_WORD– одноразмерный массив из 64 элементов типа BIT. DATA_WORD– одноразмерный массив из 8 элементов типа MVL. ROM– массив из 126 элементов типа DATA_WORD, т.е. в данном случае имеем дело с массивом массивов.
Доступ к элементам массива осуществляется с помощью индексов, например, ADDRESS_WORD(26) ссылается на 27-ой элемент массива ADDRESS_WORD.
1.5 Операции языка VHDL
В языке VHDLимеются операции следующих категорий:
1. Логические операции
2. Операции отношений
3. Операции сложения/вычитания
4. Операции умножения/деления
5. Прочие
Приоритет операций возрастает от категории 1 к категории 5. Операции одной категории имеют одинаковый приоритет и выполняются в последовательности: слева направо. Скобки используются для изменения последовательности исполнения.
Операции логические
Существует шесть логических операций: and, or, nand, nor, xor, not.
Операции применимы к типам BIT, BOOLEAN, к одноразмерным массивам BITи BOOLEAN. При выполнении битовые значения ‘0’ и ‘1’ интерпретируются как булевские FALSEи TRUE. Результат имеет тот же тип, что и операнды. Операция not– унарная операция, она имеет приоритет категории 5.
Операции отношений
В языке VHDLимеются следующие операции отношений:
=, /=, <, <=, >, >=
Результатом выполнения любой операции отношений является булевское выражение BOOLEAN. Операции равенства ( = ) и неравенства ( /= ) допустимы со всеми типами, за исключением типа “файл”. Остальные четыре операции допустимы над скалярными типами (целочисленными, перечислимыми) или над массивами дискретного типа. Когда операндами являются массивы, то сравнение выполняется слева направо по одному элементу, например при следующем сравнении:
BIT_VECTOR'('0', '1', '1') < BIT_VECTOR'('1', '0', '1')
получен результат TRUE, т.к. первый элемент вектора слева меньше первого элемента вектора справа. Другой пример, если декларирован тип:
typeMVLis('U', '0', '1', 'Z' );
то результат сравнения:
MVL'( 'U' ) <MVL'( 'Z' )
будет TRUE, т.к. ‘U’ находится левее ‘Z’.
Операции суммирования, вычитания, конкатенации
Операции имеют обозначения:
+, -, &.
Операнды, участвующие в операциях сложения ( + ) и вычитания ( - ) должны быть одного числового типа, результат оказывается того же типа. Операндами в конкатенации ( & ) могут быть или отдельные элементы или одномерные массивы. Результат выдается в виде массива, например при выполнении конкатенации:
‘0’ & ‘1’
образуется массив символов “01”, или еще пример:
‘C’ & ‘A’ & ‘T’
дает“CAT”.
Операции умножения, деления
К этой группе оператций относятся: *, /, mod, rem.
Операнды умножения ( * ) и деления ( / ) должны быть одновременно либо целочисленного типа (integer) либо типа с плавающей запятой (floatingpoint). Результат всегда того типа, что и операнды. Операция умножения может иметь один операнд физического типа, а другой – либо целочисленного, либо натурального типа. Результат выдается в виде физического типа.
В операции деления допустимо делить объект физического типа на целочисленный или натуральный. Результат - всегда физического типа. Деление физического типа на физический дает целочисленный результат.
Операции остатка ( rem) и “деления по модулю” ( mod) в качестве операндов могут иметь целочисленные типы и результат - целочисленного типа. Результат remимеет знак первого операнда и определяется следующим образом:
AremB= A- ( A/ B) * B
Результат mod имеет знак второго операнда и определяется следующим образом:
AmodB= A– B* N,
где N– некоторое целое.
Прочие операции
К их числу следует отнести: Abs, ** и другие. Операция выделения абсолютного значения ( abs ) совместима с любым числовым типом операнда. Операция возведения в степень ( ** ) операндом слева имеет целое или тип с плавающей точкой, а в качестве правого операнда (степень) - только целое.
1.6 Последовательные операторы
К последовательным операторам (SequentialStatements) относятся операторы присваивания (AssignmentStatements), условные операторы if(ifStatements) и case(caseStatements), операторы цикла (loop - next Statements) и другие. Рассмотрим некоторые из операторов этого типа
Оператор присваивания
Эти операторы делятся на операторы присваивания переменной (обозначается знаком :=) и операторы назначения сигнала (<=). В обоих случаях снаала вычисляется значение выражения, стоящее справа от знака равенства, а затем полученное значение присваивается переменной или сигналу, стоящим слева от знака. Например, оператор
abar:= nota;
задает новое значение переменной abar, а именно – инверсное значение a.
Оператор
z <= not (a and b);
задает новое значение сигнала z, которое получается справа от знака <=.
Оператор if
В общем случае ifпредставляет собой последовательность выражений, оговаривающих условия. В качестве условий применимы любые выражения, при вычисление которых получается булевская величина (FALSEи TRUE).
ifбулевское_выражение then
последовательностные_выражения
[elsifбулевское_выражение then
последовательностные_выражения ]
[else
последовательностные_выражения]
endif;
Выражение ifвычисляется путем просмотра условий одного за другим, пока не будет найдено истинное. Затем вычисляется набор последовательностных выражений, связанных с этим условием. Предложений вида elsifв выражении ifможет быть от 0 и более. Может использоваться и предложение else. Выражения ifмогут вкладываться одно в другое без ограничений.
Рассмотрим простой пример.
ifCTRL= '1' then
MUX_OUT<= "10";
else
MUX_OUT<= "01";
endif;
Если управляющий сигнал CTRL1 равен ‘1’, то выходной сигнал MUX_OUTпринимает значение "10", иначе MUX_OUTпримет значение "01". На этом оператор ifзавершается.
Рассмотрим более сложный пример.
ifCTRLI= '1' then
if CTRL2 = '0' then
MUX_OUT<= "0010";
else
MUX_OUT<= "0001";
end if;
else
if CTRL2 = '0' then
MUX_OUT <= "1000";
else
MUX_OUT <= "0100";
end if;
endif;
Если управляющий сигнал CTRL1 равен ‘1’, тогда при условии (открывается вложенное if) CTRL2=’0’ выходной сигнал MUX_OUT<= "0010", иначе (т.е. при любых других значениях сигнала CTRL2) MUX_OUT<= "0001". Здесь завершается внутренний (вложенный) оператор if. Иначе (т.е. при любых других значениях сигнала CTRL1), если (открывается новый вложенный оператор if) CTRL2=’0’, тогда MUX_OUT<= "1000", иначе (т.е. при любых других значениях сигнала CTRL2) MUX_OUT<= "1000". Здесь завершается внутренний (вложенный) оператор if, а также завершается и наружный.
Оператор case
Операторcaseимеет следующий формат:
caseвыражение is
whenвариант выбора => последовательностные_выражения
whenвариант выбора => последовательностные_выражения
-- произвольное число вариантов выбора.
whenothers=> последовательностные_выражения]
endcase;
При вычислении выражения caseвыбирается одна из ветвей в соответствии со значением выражения. Выражение может иметь значения типа перечислимого или типа одномерного массива. Рассмотримпример:
type WEEK_DAY is (MON, TUE, WED, THU, FRI, SAT, SUN);
type DOLLARS is range 0 to 10;
variable DAY: WEEK_DAY;
variable POCKET_MONEY: DOLLARS;
case DAY is
when TUE => POCKET_MONEY := 6; -- ветвь 1
when MON I WED => POCKET_MONEY := 2; -- ветвь 2
when FRI to SUN => POCKET_MONEY := 7; -- ветвь 3
when others => POCKET_MONEY := 0; -- ветвь 4
endcase;
Переменная WEEK_DAYимеет значения перечислимого типа (дни недели). Переменная DOLLARSимеет целочисленные значения в диапазоне от 0 до 10. Ветвь 1 выбирается, когда день недели TUE. Ветвь 2 выбирается в случае когда дни недели MONили WED(вертикальная черта означает ИЛИ). Ветвь 3 покрывает значения от FRIдо SUN, т.е. FRI, SATи SUN. Ветвь 4 покрывает все оставшиеся значения, т.е. THU.
Оператор loop
Оператор loopиспользуется для задания итерации набора последовательных выражений.
[ярлык для loop: ] итерационная схема loop
последовательностные_выражения
endloop[ярлык для loop] ;
Существует три итерационных схемы. Первая имеет форму:
forидентификатор inдиапазон
Пример использования схемы:
FACTORIAL := 1;
for NUMBER in 2 to N loop
FACTORIAL := FACTORIAL * NUMBER;
end loop;
Тело loopисполняется N-1 раз, при этом идентификатор NUMBERв конце каждой итерации увеличивается на 1. Подразумевается, что идентификатор целочисленного типа и значения его лежат в диапазоне от 2 до N.
Второй итерационной схемой является следующая:
whileбулевскоe_выражение
Пример использования схемы:
J:=0;SUM:=10;
WH-LOOP: while J<20 loop -- loop имеет ярлык WH_LOOP
SUM := SUM * 2;
J:=J+3;
end loop;
Выражения в теле loopвыполняются одно за другим и эта последовательность повторяется, пока условие J<20 истинно.
Третьей cхемой является конструкция, в которой итерационная схема не задается и выход из loopосуществляется с использованием выражений: exit, nextили return, например:
SUM:=1;J:=0;
L2: loop--loopимеет ярлык
J:=J+21;
SUM := SUM* 10;
exit when SUM > 100;
endloopL2;
В этом примере выражение exitзаставляет выходить из петли L2 когда SUMстановится больше 100. При отсутствии выражения exitloopбудет исполняться бесконечно.
1.7 Параллельные операторы
К параллельным операторам (Concurrent Statements) оператор process, оператор параллельного вызова процедуры, оператор конкретизаци компонента, оператор генерации (generate) и другие. Параллельные операторы определяют параллельное поведение схем, порядок их выполнения не зависит от их появления внутри блока.
Рассмотрим кратко оператор process. В общем виде он может быть записан следующим образом.
[имя процесса:][postponed] process [(список)]
раздел деклараций
begin
операторы
endprocess[имя процесса];
Имя процесса и ключевое слово [postponed] являются необязательными и часто отсутствуют. Список, находящийся после ключевого слова process, хотя и является необязательным, на практике используется достаточно часто для указания сигналов запуска. Перед ключевым словом могут находиться различного рода декларации типов, констант атрибутов и т. д.
Хотя процесс является параллельным оператором, он может содержать последовательные операторы. Внутри процессов не мегут быть декларированы сигналы.
1.8 Описание интерфейса устройства
В начале главы уже говорилось, что на моделируемое устройство в первую очередь следует посмотреть со стороны (“вид снаружи”) и для этого “черного ящика” определить интерфейс с внешним миром. Такая задача решается в VHDL декларацией интерфейса entity. Она задает имя описания, имена интерфейсных портов, направление передачи, тип портов. Порт – это сигнальная линия (шина), с помощью которой устройство (модель) взаимодействуют с окружающей средой. Например, для полусумматора (рис. 1.2) декларация будет выглядеть следующим образом:
Рис. 1.2. Полусумматор
entity half_adder is
port(a, b: in BIT; sum, cur: out BIT);
endhalf_adder;
Здесь описание с именем half_adderимеет два входных порта, aи b(in– означает входной порт), и два выходных порта, sumи carry(out– означает выходной порт). Тип портов определен как BIT– означает, что сигналы на линиях портов могут принимать значения: ‘0’ или ‘1’.
Другим примером может послужить дешифратор, показанный на рис. 1.3.
entity dec2x4 is
port(a, b, enable: in BIT; z: out BIT_VECTOR (0 to 3));
enddec2x4;
Здесь описание с именем dec2x4 имеет три входных порта и четыре выходных. Выходные порты описаны как массив. BIT_VECTOR– это одномерный массив, диапазон задается параметром Z(0 to3).
Рис. 1.3. Декодер 2х4
Каждый интерфейсный порт может функционировать в следующих режимах:
in– значение порта только считывается для использования внутри модели,
out– значение порта может только обновляться моделью, но не считывается,
inout– двунаправленный порт, значение считывается и обновляется моделью,
buffer– буферный порт, значение считывается и обновляется моделью, но источником сигнала может быть либо буфер, либо одиночный источник.
1.9 Архитектура
Архитектура (architecturebody) моделирует взгляд на устройство “изнутри”. Устройство может рассматриваться под разными углами и описываться по-разному. Оно может предстать либо как композиция более простых модулей (структурный стиль моделирования), либо как набор параллельно исполняемых алгоритмов (стиль dataflow), либо описано как процесс последовательного исполнения операций (стиль “поведенческий”), либо может быть раскрыто сочетанием указанных стилей.
С одним интерфейсом типа entity может быть связано несколько архитектур. Рассмотрение архитектурных стилей начнем с поведенческого (behavioralstyle).
Поведенческое описание
Функционирование устройства рассматривается как процесс последовательного вычисления выражений, входящих в process. Толчком к запуску процесса является изменение (event-событие) какого либо сигнала, из входящих в список “воспринимаемых” сигналов (sensitivitylist). Этот список внешне очень похож на список параметров в других языках высокого уровня. Рассмотрим поведенческую модель декодера dec2х4 (рис.1.3). Декларация интерфейса его уже приводилась, а теперь она будет пополнена архитектурой поведенческого типа.
entity dec2x4 is
port(a, b, enable: in BIT; z: out BIT_VECTOR (0 to 3));
end dec2x4;
architecture dec_seq of dec2x4 is
begin
process (a, b, enable)
variable abar, bbar: BIT;
begin
abar:= not a; --выражение 1
bbar:= not b; -- выражение 2
If enable = ‘1’ then -- выражение 3
z(3) <= not (a and b); -- выражение 4
z(2) <= not (a and bbar); -- выражение 5
z(1) <= not (abar and b); -- выражение 6
z(0) <= not (abar and bbar); -- выражение 7
else z <= “1111”;
end if;
end process;
enddec_seq;
Архитектура имеет свое имя dec_seq. О принадлежности архитектуры к описанию интерфейса dec2х4 говорит выражение: dec_seqofdec2x4. Список сигналов, которыми запускается процесс, дан в скобках: process(a, b, enable). До начала процесса, если необходимо, декларируются переменные variableabar, bbar: BIT. Зона действия их ограничена данным процессом (от beginдо endprocess). Предположим, что в момент Tпроизошло изменение сигнала а. Новое значение переменной abar(выражение 1) вычисляется и присваивается без задержки – мгновенно (в качестве знака присваивания в данном случае используется =). Без задержки будут вычислены выражения 2 и 3.
Далее в ходе процесса одно за другим вычисляются выражения от 4 до 7, а новые значения сигналам z(0), z(1), z(2), z(3) будут присвоены (в качестве символа оператора присвоения используется <= ) лишь через некоторую, пусть даже фиктивную (бесконечно малую), задержку D. Это существенное отличие процедур присвоения для переменных и для сигналов.
Рассмотрим пример мультиплексора 4х1 (рис.1.4). Четыре входных сигнала A, B, Cи Dвыводятся через один порт Z. Коммутация осуществляется сигналом CTRL.
Рис. 1.4. Мультиплексор4х1.
entity MUX is
port (A, B, C, D: in BIT; CTRL: in BIT_VECTOR(0 to 1);
Z: out BIT);
end MUX;
architecture MUX_BEHAVIOR of MUX is
begin
PMUX: process (A, B, C, D, CTRL)
variable TEMP: BIT;
begin
case CTRL is
when "00" => TEMP := A:
when "01" => TEMP := B;
when "10" => TEMP := C;
when "11" => TEMP := D;
end case;
Z <= TEMP;
end process PMUX;
end MUX_BEHAVIOR;
АрхитектураполучиланазваниеMUX_BEHAVIOR, процессимеетярлыкPMUX. Переменной TEMPв зависимости от значения сигнала CTRLприсваивается значение одного из входных портов: A, когда CTRLимеет значение “00”; B, когда CTRLимеет значение “01”; A, когда CTRLимеет значение “10”; D, когда CTRLимеет значение “11”.
Для описания синхросигналов обычно используется атрибу EVENT. Он истинен когда происходит “событие” - изменение сигнала. Например, поведение D-триггера, показанного на рис.1.5, можно описать так:
Рис.1.5. D-триггер
entity dff is
port (data, clk: in BIT
q, notq: out BIT);
end dff;
architecture behav of dff is
begin
process (clk)
begin
if (clk’event and clk = ‘1’) then
q <= data;
notq <= not data;
end if;
end process;
end behav;
Выражение (clk’eventandclk= ‘1’) задает условие: если сигнал clk меняется с ‘0’ на ‘1’
Потоковое описание (dataflow)
Dataflow- означает поток данных. Описание в стиле dataflowиспользует в архитектуре параллельно вычисляемые выражения. Количество параллельно вычисляемых выражений может быть любым. Так как вычисления происходят параллельно, то порядок записи выражений не имеет значения. Толчком к началу вычислений является изменение любого из сигналов, входящих в выражения. Рассмотрим модель одноразрядного сумматора, показанного на рис.1.6.
Рис.1.6. Одноразрядныйсумматор
entity full_adder is
port (a, b, cin: in BIT; sum, cout: out BIT);
end full_adder;
architecture full_ad_conc of full_adder is
begin
sum <= (a xor b) xor cin after 15 ns;
cout <= (a and b)or(b and cin)or(cin and a) after 10ns;
endfull_ad_conc;
Для описания потока данных здесь используются два выражения. Всегда, когда происходят изменения сигналов a, bили cin, оба выражения вычисляются и сигналам sumи cout присваиваются новые значения через 15nsи 10ns, соответственно. Знак <= оператор присваивания. Выражение after15nsозначает задержку, вносимую логикой, реализующей вычисление выражения для sum. Если задержка не введена явно, то предполагается наличие бесконечно малой задержки D. Такой прием позволяет упорядочить события модели dataflow. Рассмотрим схему рис. 1.7 и ее модель.
Рис. 1.7. Цепочкаинверторов
entity fast_inverter is
port (a: in BIT; z: out BIT);
end fast_inverter;
architecture delta_delay of fast_inverter is
signal b,c: BIT;
begin
z <= not c; -- выражение1
c<= notb; --выражение 2
b<= nota; --выражение 3
enddelta_delay;
В выражениях 1, 2 и 3, присваивающих значения переменным z, c, b, подразумевается задержка D. Например, в момент Tпроисходит изменение сигнала a. Запускается процесс вычисления выражения 3 и через задержку D переменной bбудет присвоено новое значение (в момент T+D). В свою очередь изменение сигнала bзапустит процесс вычисления выражения 2 и значение сигнала с будет обновлено в момент T+2D. Изменение сигнала с приведет к запуску процесса вычисления выражения 1 и значение сигнала zбудет изменено в момент T+3D. Временные соотношения в схеме иллюстрирует рис. 1.8.
Рис. 1.8. Временные соотношения в цепочке инверторов.
Структурное описание.
Структурное описание интерпретирует устройство как набор компонентов, связанных между собой сигналами. Грубо говоря - это таблица соединений (netlist). Рассмотрим простую схему управления (рис.1.8) и ее структурную модель.
Рис. 1.9. Устройство местного управления
entityctr_lckis
port (data, mr, clk, din: in BIT; rdy, ctrla:out Bit);
end ctr_lck;
architecture str_view of ctr_lck is
component AND2 -- декларируетсякомпонентAND2
port (x,y in BIT; z: out BIT);
end component;
component DFF -- декларируется компонент DFF
port (d, clock: in BIT; Q,NOTQ: out BIT);
end component;
component NOR2 -- декларируется компонент NOR2
port (a,b: in BIT; z: out BIT);
end component;
signal s1,s2: BIT;
begin
D1: DFF port map (data, clk, s1,s2); -- выражение 1
A1: AND2 port map (s2, din, ctrla); -- выражение 2
N1: NOR2 port map (s1, mr, rdy); -- выражение 3
endstr_view;
Здесь декларируются три компонента: AND2, DFFи NOR2. В тело архитектуры экземпляры компонентов вводятся с помощью выражений 1, 2 и 3. Компоненты связаны между собой сигналами s1 и s2. В декларации называется имя компонента и его интерфейс, что очень схоже с декларацией интерфейса устройства. Выражение для экземпляра компонента должно в первую очередь дать имя экземпляру или ярлык. Например, D1 – это ярлык для экземпляра триггера DFF. Далее следует список связей (associationlist). Он устанавливает связь между портами компонента и портами и сигналами устройства. Существует два варианта связи: позиционный и поименный. В позиционном списке первый порт декларации (слева направо) компонента соответствует первому порту экземпляра компонента (слева направо), второй – второму и так далее. Именно такой вариант списка был использован в приведенном выше примере. Вместо этого можно было использовать поименный вариант списка связей, например, выражение 3 можно было бы записать так:
N1: NOR2 port map (a=>s1, b=> mr, z=>rdy);
Рассмотрим еще пример. На рис.1.2 была приведена схема полусумматора.Его структурная модель должна предстать как набор следующих компонентов: XORна два входа (например, 7486 или отечественный аналог ЛП5) и ANDна два входа (например, 7408 или отечественный аналог ЛИ1 ).
entity half_adder is
port(a, b: in BIT; sum, cur: out BIT);
end half_adder;
architecture h_a_str of half_adder is
component a_7486
port (a_2: in BIT;
a_3: in BIT;
a_1: out BIT);
end component;
component a_7408
port (a_2: in BIT;
a_3: in BIT;
a_1: out BIT);
end component;
begin
X1: a_7486 port map (a, b, sum);
A1: a_7408 port map (a, b, cur);
endh_a_str;
Названия компонентов и их портов приведены такими, какими они даны в библиотеке фирмы ALTERA– известного производителя программируемых логических схем.
Декларации компонентов, использованные в архитектуре h_a_strполусумматора half_adder, можно упаковать в отдельный файл, например, maxplus2.vhd:
package maxplus2 is
component a_7486
port (a_2: in BIT;
a_3: in BIT;
a_1: out BIT);
end component;
component a_7408
port (a_2: in BIT;
a_3: in BIT;
a_1: out BIT);
endmaxplus2;
Файл maxplus2 при компиляции может быть помещен в библиотеку, например, с названием altera. Ссылка на библиотеку позволит не декларировать компоненты в архитектуре:
libraryaltera;
use altera.maxplus2.all;
entity half_adder is
port(a, b: in BIT; sum, cur: out BIT);
end half_adder;
architecture h_a_str of half_adder is
begin
X1: a_7486 port map (a, b, sum);
A1: a_7408 port map (a, b, cur);
endh_a_str;
Комбинированное описание архитектуры
В едином теле архитектуры можно комбинировать все рассмотренные выше стили моделирования. В качестве примера рассмотрим одноразрядный полный сумматор (рис.1.5).
Сумматор представлен выражением 1, создающим экземпляр X1 компонента а_7486 (из библиотеки altera.maxplus2), и задающим отображение портов и сигнала сущности (сумматора) на порты компонента. Это структурный стиль.
Выражение 2 - это process, поведенческий стиль, и выражение 3 – это стиль dataflow.
Рис.1.10. Одноразрядный сумматор
libraryaltera;
use altera.maxplus2.all;
entity full_adder is
port (a, b, cin: in BIT; sum, cout: out BIT);
end full_adder;
architecture fa_mix of full_adder is
signal s1:BIT;
begin
X1: a_7486 port map (a,b,s1); --выражение 1
process (a, b, cin) --выражение 2
variable t1, t2, t3: BIT;
begin
t1:= a and b;
t2:= b and cin;
t3:= a and cin;
cout <= t1 or t2 or t3;
end process;
sum <= s1 xor cin; --выражение 3
endfa_mix;
1.10 Особенности синтеза схем по описаниям на языке VHDL
Между процессами моделирования (имитации поведения схемы) синтеза схем с использованием языка VHDLесть существенные различия. Рассмотрим некоторые из них.
В отличие от системы моделирования система проектирования преобразует проектную информацию в заданный формат. Среди них выделяются широко распространенный формат EDIF, специализированные форматы различных фирм-изготовителей микросхем, а также языки Verilog, VHDL и другие. Формат EDIFявляется своеобразным стандартом де-факто, он имеется в большинстве современных систем проектирования и может использоваться для обмена информацией. Среди специализированных форматов можно выделить формат XNFфирмы Xilinx, который широко использовался в ранних версиях САПР этой фирмы. При преобразовании исходного модуля в промежуточный текст на языке VHDLобычно осуществляется преобразование в структурные конструкции этого языка, в которых используются схемотехнические особенности используемой элементной базы.
Система моделирования обычно использует все конструкции языка VHDL, в то время, как система проектирования использует не все его возможности. Обычно при синтезе не поддерживаются операции над типом Real(в этом случае при синтезе выдается ошибка), игнорируются ключевое слово After, не поддерживается также ряд других второстепенных конструкций языка. В системах проектирования атрибут eventможет использоваться только для указания фронтов синхросигналов в условных операторах, преимущественно в операторах if.
В современных системах проектирования для описания схем используется тип std_logic, который заменяет тип bit. Тип std_logicимеет следующие значения:
· 0 – логический ноль;
· 1 – логическая единица;
· U– значение не инициализировано;
· X– неизвестное значение;
· Z– высокое выходное сопротивление;
· W– неизвестное значение при слабом источнике сигнала;
· L– логический ноль при слабом источнике сигнала;
· H– логическая единица при слабом источнике сигнала;
· ‘-‘– неопределенное значение.
ЛИТЕРАТУРА
1. Бибило П.Н. Синтез логических схем с использованием языка VHDL. М.: Солон-Р, 2002.
2. Суворова Е. А., Шейнин Ю. Е. Проектирование цифровых систем на VHDL. - СПб.: БХВ-Петербург. 2003.