Поливариантные параллельные тексты в рамках Национального корпуса русского языка
ПАРАЛЛЕЛЬНЫЕ ОПЕРАТОРЫvhdl2u.weebly.com/uploads/2/0/5/8/20589250/vhdl_4.pdf ·...
Transcript of ПАРАЛЛЕЛЬНЫЕ ОПЕРАТОРЫvhdl2u.weebly.com/uploads/2/0/5/8/20589250/vhdl_4.pdf ·...
1
ПАРАЛЛЕЛЬНЫЕ ОПЕРАТОРЫ.
VHDL – это язык параллельного программирования.
Параллелизм в программе задается явным образом в
параллельных операторах. Параллельным операторам
соответствуют виртуальные процессорные элементы в
программистской модели вычислителя VHDL. Параллельные
операторы образуют исполнительную часть тела архитектуры.
Оператор процесса - это основной параллельный оператор.
Оператор вставки компонента - также важный оператор,
наиболее встречаемый в проектах. В этом разделе рассмотрены
эти и другие параллельные операторы.
2
Все параллельные операторы, кроме оператора блока и
вставки компонента, могут быть заменены на эквивалентные
операторы процесса, в которых список чувствительности
содержит все входные сигналы выражений исходного оператора
и у которых оператор wait стоит последним в цепочке
последовательных операторов.
Оператор параллельного присваивания.
Этот оператор имеет такой же синтаксис, как и оператор
присваивания сигналу в процессе. Такой оператор эквивалентен
оператору процесса, в котором этот оператор повторен в его
исполнительной части, а последним оператором стоит оператор
3
wait со списком чувствительности. Например, следующие
два оператора эквивалентны:
ADDER:A<=B+C;
ADDER_P:processprocessprocessprocess beginbeginbeginbegin
A<=B+C;
waitwaitwaitwait onononon B,C;
endendendend processprocessprocessprocess;
Оператор условного параллельного присваивания.
Оператор условного параллельного присваивания имеет
синтаксис:
\условное параллельное присваивание\::= \имя\<= [\способ
задержки\]
4
{\график\ when \булевское выражение\
else }
\график\[when \булевское выражение\];
где определение способа задержки и графика представлено выше
при описании оператора присваивания сигналу.
Любой оператор условного параллельного присваивания имеет
эквивалентное представление в виде процесса, как например,
оператор:
cntrl<= one whenwhenwhenwhen st=1 elseelseelseelse
two whenwhenwhenwhen st=2 orororor st=3 elseelseelseelse
5
three;
эквивалентен оператору
processprocessprocessprocess(st,one,two,three)
beginbeginbeginbegin
ifififif st=1 thenthenthenthen
cntrl<= one;
elsifelsifelsifelsif st=2 orororor st=3 thenthenthenthen
cntrl<= two;
else else else else
cntrl<=three;
endendendend ifififif;
endendendend processprocessprocessprocess;
6
Пример:Оператор условного назначения сигнала
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
7
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;
8
Оператор селективного параллельного
присваивания.
Оператор селективного параллельного присваивания имеет
синтаксис:
\селективное параллельное присваивание\::= with
\выражение\ select
{\имя\<= [\способ задержки\]{\график\ when
\альтернативы\,}
\график\[when others ];
9
где \альтернативы\ имеют то же значение, что и в
операторе case. Этот оператор эквивалентен соответствующему
процессу, как например, оператор:
withwithwithwith st select
cntrl<= one wwwwhen hen hen hen 1,
two when when when when 2 to to to to 3,
three when otherswhen otherswhen otherswhen others;
выполняет такие же действия, что и процесс:
processprocessprocessprocess(st,one,two,three)
beginbeginbeginbegin
case case case case st is is is is
when when when when 1 => cntrl<= one;
10
when when when when 2 to to to to 3 => cntrl<= two;
when otherswhen otherswhen otherswhen others => cntrl<= three;
endendendend casecasecasecase;
endendendend processprocessprocessprocess;
Требования к выражению селектора и альтернативам оператора
такие же, как у оператора casecasecasecase. Так, каждая из альтернатив
должна быть такого же типа, что и \выражение\ и представлена
статическим выражением или диапазоном. Никакие два
значения, получаемые из выражений альтернатив, не должны
быть равны друг другу.
Пример: Оператор селективного параллельного присваивания
(Оператор выборочного назначения сигнала)
11
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;
12
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;
13
Параллельный оператор assert.
Этот оператор имеет такой же синтаксис, как и
соответствующий ему последовательный оператор. Он
выполняется точно также, как и процесс, в исполнительной
части которого стоит последовательный оператор assertassertassertassert с
таким же содержанием.
Параллельный вызов процедуры.
Параллельный вызов процедуры имеет такой же синтаксис, как
у последовательного вызова процедуры. Он исполняется точно
так же, как процесс, который имеет в своей исполнительной
части такой же вызов процедуры с такими же параметрами и
14
оператор wait ожидания прихода сигналов - входных
параметров. Поэтому каждый параллельный вызов процедуры
соответствует некоторому виртуальному процессорному
элементу, исполняющему алгоритм этой процедуры.
Если программа предназначена для синтеза, то процедура,
вызываемая параллельно, не должна иметь операторов wait.
Такая процедура отображается в комбинационную схему или
комбинацию шин, т.е. некоторый специализированный
процессорный элемент.
15
Отложенные параллельные операторы.
Так как всем вышеперечисленным параллельным операторам
ставится в соответствие оператор процесса, то поскольку
процесс бывает отложенным, то и эти параллельные операторы
могут быть отложенными. Такие операторы, как и отложенный
процесс, обозначаются ключевым словом postponed, которое
ставится перед оператором.
16
ПРОЦЕДУРЫ И ФУНКЦИИ.
Процедуры и функции относятся к числу подпрограмм. Здесь
рассмотрены правила и особенности составления и объявления
процедур и функций, а также их вызова.
Спецификация процедуры.
Спецификация процедуры описывает действия при вызове
процедуры и имеет следующий синтаксис:
\спецификация процедуры\::=procedure \имя
процедуры\[(\список параметров\)] is
{\объявление в подпрограме\}
17
begin
{\последовательный оператор\}
end [procedure][\имя процедуры\];
\список параметров\::=(\элемент списка\ {; \элемент
списка\})
\элемент списка\::=[constant | variable | signal ]
\идентификатор\{,\идентификатор\}: [in | out |
inout] \тип параметра\
[ := \статическое выражение\]
18
Здесь \имя процедуры\ - идентификатор процедуры. В
списке параметров указывается информация о формальных
параметрах процедуры. Вместо формальных параметров
подставляются фактические параметры во время вызова
процедуры. В каждом из элементов списка параметров может
объявляться какой это параметр (константа, переменная или
сигнал) направление передачи параметра (in, out или inout)
его тип или подтип и его значение по умолчанию, равное
статическому выражению.
Список параметров может отсутствовать, т.е. он тогда задан
неявно. При этом имена фактических параметров совпадают с
19
именами формальных параметров, объявленных в
процедуре. Обычно трудно понять программу с процедурами без
списков параметров. Поэтому в соответствии с условиями
повторного использования проектов, не рекомендуется
программирование процедур без списка параметров.
Объявленными в процессе могут быть: объявление и тело
другой процедуры или функции, объявление типа и подтипа,
объявление константы, переменной, файла, псевдонима,
объявление и спецификация атрибута, объявление группы,
описание use.
20
Рассмотрим пример программирования и использования
процедуры в процессе для сортировки трех целых чисел.
processprocessprocessprocess(a1,a2,a3)
variablevariablevariablevariable b1,b2,b3:integer;
procedureprocedureprocedureprocedure sort2(variablevariablevariablevariable x1,x2:inout inout inout inout
integer) is is is is
variable variable variable variable t:integer;
begin begin begin begin
ifififif x1>x2 thenthenthenthen
returnreturnreturnreturn;
elseelseelseelse
t:=x1; x1:=x2; x2:=t;
21
end ifend ifend ifend if;
end procedureend procedureend procedureend procedure;
begin begin begin begin
b1:=a1; b2:=a2; b3:=a3;
sort2(b2,b3);
sort2(b1,b2);
sort2(b2,b3);
c1<=b1; c2<=b2; c3<=b3;
end processend processend processend process;
Здесь процедура sort2 выполняет сортировку двух переменных
х1, х2, которые являются входными – выходными формальными
22
параметрами процедуры. Вызов процедуры выполняется с
позиционным связыванием.
Оператор return досрочно прерывает исполнение
процедуры. Последовательный оператор return -оператор
возврата из подпрограммы – немедленно прерывает
выполнение процедуры или вызова функции и возвращает
управление в программу, вызвавшую процедуру.
23
Спецификация функции.
Спецификация функции имеет следующий синтаксис:
\спецификация функции\::=[pure | impure] function \имя
функции\ |\знак функции\
[(\список параметров\)] return
\тип параметра\ is
{\объявление в подпрограме\}
begin
{\последовательный оператор\}
return \выражение\;
24
end [function][\имя функции\];
В ней знак функции – символ в кавычках, например, "+",
список параметров – такой же, как в процедуре за исключением
того, что режимы параметров out и inout не допускаются.
После ключевого слова return в объявлении функции
указывается тип возвращаемого параметра. Объявления в
функции могут быть такими же, как в процедуре. Выполнение
функции должно оканчиваться оператором return,
вычисляющим выражение возвращаемого параметра.
Объявление процедур и функций.
25
Объявление подпрограмм вставляется в части объявлений
в процессов, блоков, объявлениях объектов и пакетов, если эти
подпрограммы используются в этих программных единицах.
Оно представляет собой часть спецификации процедуры и
функции до слова is :
\объявление процедуры\::= procedure \имя
процедуры\[(\список параметров\)];
\объявление функции\::=[pure | impure] function \имя
функции\ |\знак функции\
[(\список параметров\)] return
\тип параметра\;
26
Вызов процедуры.
Вызов процедуры представляет собой последовательный
или параллельный оператор, в зависимости от того, стоит
ли он внутри или снаружи процесса. Упрощенный
синтаксис последовательного вызова процедуры:
\вызов процедуры\::=\имя процедуры\[([\имя параметра
=>\] \выражение\
{,[\имя параметра\ => ] \выражение\})];
Здесь \имя процедуры\ - имя ранее определенной
процедуры. Связывание формальных и фактических
27
параметров выполняется аналогично как в вызове
функции. Выражение - параметр функции - должно давать
результат типа, соответствующего имени параметра \имя
параметра\. Параметры можно задавать с поименованным
или позиционным связыванием. При позиционном
связывании параметры-выражения подставляются в
порядке, определенном порядком следования имен
параметров в определении функции. При поименованном
связывании каждое имя, параметра связывается с
соответствующим параметром с помощью символов "=>",
28
причем порядок следования параметров может быть
произвольным.
В пакете IEEE.Math_Real определена процедура
генерации случайных чисел:
procedure procedure procedure procedure UNIFORM(variable SEED1,SEED2:inout
POSITIVE; variable X:out real);
Она может быть вызвана со связыванием
параметров:
variablevariablevariablevariable s1,s2:natural:=12345;
variable variable variable variable Random:real;
29
…
UNIFORM(X=> Random, SEED1=>s1,SEED2=>s2);
или без связывания параметров:
UNIFORM(s1,s2, Random);
Следующий пример представляет использование процедуры со
связыванием не всех формальных параметров.
procedureprocedureprocedureprocedure and4(variablevariablevariablevariable x1,x2,x3,x4:in in in in bit
:='1'; signal signal signal signal y:out out out out bit) is is is is
begin begin begin begin
y<=x1 and and and and x2 and and and and x3 andandandand x4;
endendendend procedureprocedureprocedureprocedure;
30
При вызове этой процедуры:
and4(a1,a2,a3, openopenopenopen, b);
четвертый входной параметр отсутствует, на что указывает
ключевое слово open и вместо него подставляется начальное
значение '1'.
Вызов процедуры без параметров – это просто
написанное ее имя.
При вызове процедуры входные параметры переменных
копируются внутрь процедуры. После исполнения процедуры
31
выходные параметры записываются на место
соответствующих переменных.
Входные параметры сигналов представляются как ссылки на
сигналы. Параметру сигнала нельзя присваивать начальное
значение, так как источник этого сигнала недоступен. Поэтому
нельзя также использовать такие атрибуты сигнала, как
'delayed, 'stable, 'quiet или 'transaction. Выходной параметр
сигнала передается в процедуру вместе с источником сигнала, в
котором происходит присваивание сигналу. Это эквивалентно
тому, что цепочка последовательных операторов тела процедуры
копируется в процесс на место вызова процедуры с
32
соответствующей подстановкой параметров. В отличие от
вызова процедуры в обычных алгоритмических языках, в
которых используется одно тело процедуры, в VHDL каждый
вычислительный процесс, вызывающий процедуру, использует
свой собственный экземпляр тела процедуры.
Параллельный вызов процедуры имеет такой же синтаксис, как
у последовательного вызова процедуры. Он исполняется точно
так же, как процесс, который имеет в своей исполнительной
части такой же вызов процедуры с такими же параметрами и
оператор wait ожидания прихода сигналов - входных
параметров. Поэтому каждый параллельный вызов процедуры
33
соответствует некоторому виртуальному процессорному
элементу, исполняющему алгоритм этой процедуры.
Если программа предназначена для синтеза, то процедура,
вызываемая параллельно, не должна иметь операторов wait.
Такая процедура отображается в комбинационную схему или
комбинацию шин, т.е. некоторый специализированный
процессорный элемент.
34
Вызов функции.
При вызове функции выполняется функция с заданными
значениями параметров. Упрощенный синтасис вызова
функции:
\вызов функции\::=\имя функции\ ([\имя параметра\ =>]
\выражение\
{,[\имя параметра\ => ]
\выражение\});
35
где \имя функции\ - имя функции, определяемой
ранее, \имя параметра\ - не обязательный формальный
параметр этой функции. Выражение-параметр функции -
должно давать результат типа, соответствующий имени
параметра. Параметры можно задавать с поименованным
или позиционированным связыванием. При
позиционированном связывании параметры-выражения
подставляются в порядке, определенном порядком
следования имен параметров в определении функции. При
поименованном связывании каждое имя, параметра
связывается с соответствующим параметром с помощью
36
символов "=>", причем порядок следования
параметров может быть произвольным.
В отличие от процедуры, вызов функции возвращает только
один параметр, зато он может участвовать как операнд в
выражениях. В языке VHDL очень мало встроенных функций.
Большинство функций реализовано в виде подпрограмм. Для
преобразования типов чаще всего используются функции.
Например, функция
functionfunctionfunctionfunction BIT_TO_INT(x:bit_vector) returnreturnreturnreturn
natural isisisis
variablevariablevariablevariable t, j:integer:=0;
37
begin begin begin begin
for for for for I inininin x'reverse_range loop loop loop loop
if if if if ( x(I)='1') thenthenthenthen
t:=t + 2**j;
end ifend ifend ifend if;
j:=j+1;
end loopend loopend loopend loop;
returnreturnreturnreturn t;
end functionend functionend functionend function BIT_TO_INT;
преобразует вектор битов в целое. При этом атрибут
x'reverse_range возвращает диапазон, обратный диапазону
38
представления входного параметра. Например, если входной
параметр – bit_vector(7 downto 0), то в оператор цикла
подставится диапазон 0 to 7. Таким образом, получается
функция, универсальная для множества различных параметров –
операндов.
Ключевые слова pure и impure обозначают идеальную и
неидеальную функции. В отличие от идеальной функции,
неидеальная функция может возвращать различные результаты
для одинаковых наборов входных параметров. Например, если
входной параметр – глобальная переменная, то она может
измениться в момент вызова функции и результат будет
39
отличаться от ожидаемого. Поэтому глобальные
переменные не могут быть операндами в идеальных функциях.
Примером неидеальной функции является функция Now из
пакета STANDARD, которая при вызове возвращает
переменную предопределенного типа delay_length, равную
текущему моменту времени моделирования. Естественно, что
при различных вызовах этой функции она возвращает различные
значения.
40
Перезагрузка процедур и функций.
В языке VHDL допускается определять несколько процедур и
функций с одинаковыми названиями. При вызове функции или
процедуры из числа функций или процедур с одинаковым
названием выбирается такая, которая подходит по типам и числу
входных и выходных параметров. Такая функция перезагружает
(overloads) остальные функции. Перезагрузка процедур и
функций удобна при вычислениях с различными типами.
Например, над типами integer, real, подтипами signed,
41
unsigned определены одни и те же арифметические
функции, но имеющие различное сочетание типов аргументов и
результатов.
Примером перезагрузки служит следующая функция, которая
не входит ни в один стандартный пакет:
functionfunctionfunctionfunction "andandandand"(x1,x2:bit) returnreturnreturnreturn boolean is is is is
begin begin begin begin
returnreturnreturnreturn (x1 andandandand x2) ='1';
endendendend;
42
Если эта функция объявлена, то теперь транслятор не
выдаст сообщения об ошибке при выполнении оператора if,
вызывающего эту функцию:
variablevariablevariablevariable a,b,c: bit;
…
if if if if (a andandandand b andandandand c) thenthenthenthen
…
endendendend ifififif;
так как выражение в скобках будет иметь правильный тип
boolean.
43
ОПЕРАТОР ПРОЦЕССА.
Оператор процесса – это параллельный оператор,
представляющий основу языка VHDL. Его упрощенный
синтаксис:
\оператор процесса\ ::=[postponed] process [(\имя
сигнала\ {,\имя сигнала\})] [is]
{\объявление в процессе\}
begin
{\последовательный оператор\}
end process;
44
Объявленными в процессе могут быть: объявление и тело
подпрограммы, объявление типа и подтипа, объявление
константы, переменной, файла, псевдонима, объявление и
спецификация атрибута, объявление группы, описание use. То,
что объявлено в процессе, имеет область действия (видимость),
ограниченную данным процессом.
Все процессы в программе выполняются параллельно.
Процессы обмениваются сигналами, которые выполняют
синхронизацию процессов и переносят значения между ними.
Если над сигналами определена функция разрешения, то выходы
источников сигнала могут объединяться. Сигналы нельзя
45
объявлять в процессах. Процесс невозможно поместить в
процесс, так как там есть место только для последовательных
операторов.
В круглых скобках заголовка процесса указывается множество
сигналов, по которым процесс запускается – список
чувствительности. Это форма оператора процесса,
альтернативная процессу с оператором wait on, стоящим
последним в цепочке последовательных операторов тела
процесса. Любой процесс со списком чувствительности может
быть преобразован в эквивалентный процесс с оператором wait
on, стоящим последним в списке последовательных операторов.
46
В операторе процесса со списком чувствительности ставить
операторы wait не допускается.
Об отложенных процессах, отмеченных ключевым словом
postponed, уже говорилось, когда шла речь об архитектуре
симулятора VHDL. Здесь следует добавить, что, так как
отложенный процесс запускается последним в цепочке
процессов с дельта-задержкой, то он сам должен исполняться с
ненулевой задержкой, т.е. в нем должен быть оператор wait for.
Процесс представляет собой маленькую программу, которая
выполняется на виртуальном процессорном элементе.
47
Рассмотрим процесс, вычисляющий функцию синуса y от
аргумента x по аппроксимирующей формуле:
sin(x) = c1x+c2x3+c3x
5+c4x7.
Процесс выглядит следующим образом:
48
process process process process
type type type type tabl is arrayis arrayis arrayis array(0 to to to to 3) of real; of real; of real; of real;
constant constant constant constant c:tabl:=(0.99999, -0.16666,
0.00831, -0.00019);
variable variable variable variable xtmp, p: real:=0.0;
beginbeginbeginbegin
xtmp:=x;
p:=c(0)*xtmp;
for for for for i in in in in 1 to to to to 3 loop loop loop loop
p:=p+c(i)*xtmp*x*x;
end loop; end loop; end loop; end loop;
y<=p;
wait on wait on wait on wait on x;
49
endendendend processprocessprocessprocess;
При моделировании логических схем в список
чувствительности процесса необходимо вносить все входные
сигналы, иначе моделирование схемы будет отличаться от
ожидаемого. Например, процесс
processprocessprocessprocess(A) beginbeginbeginbegin
c<= A orororor B;
end processend processend processend process;
при моделировании дает графики как на рис. Из графиков
видно, что изменение результирующего сигнала С происходит
только в моменты изменения сигнала A, т.е. процесс
моделирует некоторую триггерную схему, а не схему ИЛИ.
50
51
ОПЕРАТОР ВСТАВКИ КОМПОНЕНТА.
Оператор вставки компонента - это любимый оператор
начинающих программистов. Он играет основную роль для
реализации иерархического проектирования. Его синтаксис:
\оператор вставки компонента\::= \метка экземпляра
элемента\ :
\вставляемый
элемент\
[genericgenericgenericgeneric mapmapmapmap(\связывание
настроечной константы\
52
{, \связывание
настроечной константы\});]
[portportportport mapmapmapmap (\связывание порта\
{,\связывание
порта\})];
\вставляемый элемент\ ::= [componentcomponentcomponentcomponent] \имя
компонента\
| entityentityentityentity \имя
объекта\[идентификатор архитектуры]
| configurationconfigurationconfigurationconfiguration \имя
конфигурации\
53
Действие этого оператора заключается в подстановке
вместо себя одного экземпляра компонента (вставляемый
элемент - компонент) или объекта (вставляемый элемент -
объект проекта), или компонента, указанного в конфигурации.
Если вставляется компонент, то он должен быть объявлен в
данной архитектуре.
Сколько раз встречается имя вставляемого компонента –
столько копий объекта вставляется в странслированную
программу. При этом каждая копия имеет уникальное имя,
указанное в метке компонента. Таким образом, при
многократной вставке компонента в странслированном проекте
54
дублируются несколько раз все параллельные операторы
указанного компонента, а, следовательно, дублируются
сответствующие им виртуальные процессорные элементы
программистской модели.
Фраза \связывание порта\ указывает порядок
подключения сигналов данного тела архитектуры к портам
– сигналам компонента. Связывание может быть как
позиционным, так и ассоциативным (поименованным), а
также комбинированным. При позиционном связывании
параметры-выражения подставляются в порядке,
определенном порядком следования имен параметров в
55
объявлении компонента. При поименованном
связывании каждое имя порта связывается с
соответствующим сигналом с помощью символов "=>",
причем порядок следования портов может быть произволь-
ным. Второй способ связывания предпочтителен, так как
поименованное связывание более понятно при чтении и
меньше вероятность допустить ошибку при записи.
Неподключенные порты с режимом outoutoutout или inoutinoutinoutinout
допускается не указывать в списке связывания портов. Но
более понятным и правильным считается связывание
56
таких портов с условным сигналом, обозначенным
ключевым словом openopenopenopen.
В поименованном связывании допускается связывать
вырезку порта с сигналом. Например, вставка компонента
регистра, выходы которого подключены к различным
сигналам, имеет вид:
U_RG: RG16 portportportport mapmapmapmap (CLK => CLK,
E => \разр_зп_рг\,
DI => D,
DO(15)=> openopenopenopen,
57
DO(14)=> \знак_D\,
DO(13 downtodowntodowntodownto
0)=>\мантисса_D\ );
Более полный синтаксис допускает связывать порт и
сигнал в виде статического выражения с использованием
вызовов функций, например:
DI => Conv_Integer(D(n-1 downto downto downto downto 0));
To_Bit(DO(14)) => \знак_D\,
58
т.е. здесь для совмещения типов порта DI в режиме inininin
и сигнала D, разряда DO(14) порта в режиме outoutoutout и
сигнала \знак_D\ используются функции
преобразования типа.
Следует отметить, что компиляторы – синтезаторы, как
правило, не допускают связывание порта с функцией
преобразования типа. Если выход компонента не
подключен, как, например, DO(15)=>openopenopenopen или если
выхода нет в списке связываний, то компилятор-
синтезатор может минимизировать в компоненте цепи и
59
логику, относящиеся к этому выходу, в примере –
удалить триггер, подключенный к DO(15).
Синтаксис связывания настроечной константы
аналогичен синтаксису связывания порта. При таком
связывании настроечная константа, обозначающая,
например, разрядность шин, объем памяти, задержку
элемента, передается из объекта проекта более высокого
уровня в объект более низкого уровня, который становится
компонентом. Другими словами, при связывании
настроечных констант выполняется настройка в некотором
60
смысле обобщенного объекта до компонента с
конкретными параметрами.
Все компиляторы – синтезаторы поддерживают настроечные
константы целого типа.
Пусть на нижнем уровне иерархии описана модель
синхронного регистра разрядности n, который принимает данное
DI по фронту синхросигнала CLK:
entityentityentityentity RGn isisisis
genericgenericgenericgeneric(n: integer);
61
portportportport(CLK:bit; DI, DO: bit_vector(n-1
downto downto downto downto 0));
endendendend entityentityentityentity;
architecture architecture architecture architecture behav of of of of RGn is beginis beginis beginis begin
processprocessprocessprocess(CLK)
beginbeginbeginbegin
if if if if CLK='1' and and and and CLK'event thenthenthenthen
DO<=DI ;
endendendend processprocessprocessprocess;
endendendend architecture architecture architecture architecture behav;
62
Тогда следующий оператор в теле архитектуры более
высокого уровня иерархии выполняет вставку компонента
этого регистра и настраивает его разрядность равной n =
8:
U_RG8: entityentityentityentity RGn(proc) genericgenericgenericgeneric mapmapmapmap(8),
portportportport mapmapmapmap (CLK,
DI=>DATA_IN, DO=>DATA_OUT);
ОПЕРАТОР GENERATE.
63
Если необходимо неоднократно повторить один или
несколько параллельных операторов, то используют оператор
generategenerategenerategenerate. Его синтаксис:
\оператор generate\::= \метка\: forforforfor
\идентификатор\ inininin \диапазон\ generategenerategenerategenerate
[{\объявление в
блоке\}
beginbeginbeginbegin]
{ \параллельный
оператор\}
endendendend generategenerategenerategenerate
[\метка\];
64
Метка оператора generate необходима для обозначения
сгенерированной структуры, \идентификатор\ - это
параметр оператора generategenerategenerategenerate, а фраза \диапазон\ -
диапазон его изменения. Они имеют такие же синтаксис и
семантику, как и в операторе looplooplooploop. В операторе могут быть
вставлены такие же объявления, как в декларативной части тела
архитектуры.
В отличие от оператора looplooplooploop, который повторяет в цикле один
или несколько последовательных операторов, оператор
generategenerategenerategenerate делает несколько копий параллельных операторов,
65
когда параметр оператора пробегает все значения из
заданного диапазона.
В следующем примере с помощью оператора generategenerategenerategenerate
запрограммирована схема сдвигового регистра длиной n на
триггерах FD из библиотеки компонентов ПЛИС Xilinx,
описанного в пакете UNISIM.unisim_VITAL с входом DI и
выходом DO, тактируемого синхросерией CLK.
signal signal signal signal t: std_logic_vector(1 to to to to n+1);
…
t(1)<=DI;
FIFO: for for for for i in in in in 1 to to to to n generategenerategenerategenerate
66
U_ TT: FD(C=>CLK, D=>t(i),
Q=>t(i+1));
endendendend generategenerategenerategenerate;
DO<=t(n+1);
Для того чтобы управлять структурой проектируемого
устройства используется условный оператор generategenerategenerategenerate. Его
синтаксис:
\условный оператор generate\::= \метка\: ifififif
\булевское выражение\ generategenerategenerategenerate
[
{\объявление в блоке\}
beginbeginbeginbegin]
67
{
\параллельный оператор\}
endendendend gengengengenerateerateerateerate
[\метка\];
В зависимости от условия, заданного булевским выражением,
оператор вставляет или нет в структуру устройства узлы,
представленные параллельными операторами. Так как это
булевское выражение влияет на структуру устройства, оно
должно быть статическим.
В примере:
RESn: if if if if \подключить_PULLUP\=1 generategenerategenerategenerate
RES1:for for for for i in in in in DATA_BUS'range generategenerategenerategenerate
68
U_ RES:
PULLUP(DATA_BUS(i));
endendendend generategenerategenerategenerate;
end end end end generategenerategenerategenerate;
если целое значение \подключить_PULLUP\ равно 1, то к
шине DATA_BUS подключаются компоненты нагрузочных
резисторов PULLUP из библиотеки UNISIM.
Направлением научной деятельности автора является синтез
структур вычислительных устройств. Поэтому язык VHDL
нравится именно тем, что с помощью таких средств, как
оператор generategenerategenerategenerate можно программировать структуру
устройства в зависимости от параметров ее настройки.
69
Например, можно создать проект универсального цифрового
фильтра, число ступеней которого изменяется в зависимости от
заданного качества фильтрации.
К сожалению, в языке Verilog нет операторов, аналогичных
generategenerategenerategenerate. . . . И только поэтому не рекомендуется в проектах
для синтеза использовать этот оператор, так как такой проект
трудно перевести на Verilog, если возникнет такая
необходимость. В этом случае прийдется написать столько
Verilog - программ, сколько вариантов настройки структуры.
Или на каком-то алгоритмическом языке, например, Java, Perl,
70
VHDL написать программу, генерирующую Verilog - файл,
соответствующий заданной настройке.
71
ОПЕРАТОР BLOCK.
В языке VHDL блок представляет собой выделенное множество
параллельных операторов. Этот оператор, как и оператор
процесса является основным операторам языка VHDL. Все
операторы вставки компонента в проекте можно заменить на
эквивалентные операторы блока. Большой иерархический объект
проекта можно представить одним объектом, в котором
компоненты заменены эквивалентными блоками. Синтаксис
этого оператора:
\оператор blockblockblockblock\::=[\метка\]: blockblockblockblock [\выражение
сдерживания\] [isisisis]
72
[genericgenericgenericgeneric(\объявление
настроечной константы\
{; \объявление настроечной
константы\});]
[genericgenericgenericgeneric mapmapmapmap(\связывание
настроечной константы\
{, \связывание
настроечной константы\});]
[portportportport (\объявление порта\
{;\объявление порта\});]
[portportportport mapmapmapmap (\связывание порта\
73
{,\связывание
порта\})];
{\объявление в блоке\}
beginbeginbeginbegin
{\параллельный
оператор\ }
endendendend blockblockblockblock [\метка\];
В описании блока фраза genericgenericgenericgeneric объявляет типы внутренних
настроечных констант блока, фраза genericgenericgenericgeneric mapmapmapmap, описывает
список связывания настроечных констант, поступающих извне с
внутренними настроечными константами, объявления порта
описывают входные и выходные сигналы блока, а список
74
связываний портов задает соответствие внешних сигналов и
сигналов портов. В блоке могут быть объявлены те же объекты
языка, которые объявляются в теле архитектуры.
Отдельное необязательное булевское выражение сдерживания
неявно задает специальный необъявляемый сигнал guard,
который разрешает или запрещает (сдерживает) выполнение
операторов присваивания сигналу с условием guard. Этот же
сигнал может участвовать как операнд в выражениях в пределах
блока.
Как и в других языках программирования, блоки в VHDL
выполняют две основные функции: создание локальной памяти
75
для сигналов и введение обособленной области их действия
(области видимости). Также блоки могут иметь иерархическое
построение, т.е. могут применяться в блоках на более высоком
уровне. С помощью оператора конфигурации можно вместо
одних блоков подставлять блоки с другим исполнением.
Эквивалентным блоком можно заменить любую пару объект-
архитектура, используемую как компонент.
В разделах, посвященных операторам процесса и присваивания
сигналу указывалось, что нельзя одному сигналу присваивать
значение в разных процессах, если над типом сигнала не
определена функция разрешения. Для реализации корректного
76
присваивания сигналу любого типа в разных процессах,
язык VHDL предоставляет операторы присваивания сигналу со
сдерживанием.
Для этого, во-первых, процесс с оператором присваивания
сигналу или соответствующий параллельный оператор
помещают в блок с выражением сдерживания. Во-вторых,
оператор присваивания сигналу оформляют как оператор со
сдерживанием, для чего перед выражением оператора ставится
ключевое слово guardedguardedguardedguarded. Например, блоки В1 и В2:
signal signal signal signal A,B,C: outoutoutout integer bus bus bus bus :=0;
disconnectdisconnectdisconnectdisconnect С:integer afterafterafterafter 2 ns;
77
…
4B1: blockblockblockblock (sel = 1) is is is is beginbeginbeginbegin
С <= guarded guarded guarded guarded А;
endendendend blockblockblockblock B1;
B2: bbbblocklocklocklock (sel = 2) is beginis beginis beginis begin
С <= guarded guarded guarded guarded D;
endendendend blockblockblockblock B2;
выдают в общую шину, представленную сигналом С, целое
значение А при условии равенства 1 управляющего сигнала sel
(т.е. когда сигнал guard<=(sel = 1) равен true) и значение
сигнала D при другом условии в выражении сдерживания. Если
guard = false, то источник сигнала отключается от шины,
78
т.е. выполняется его сдерживание. Отключение источника
может происходить с задержкой, устанавливаемой в объявлении
disconnectdisconnectdisconnectdisconnect, которое следует за объявлением сигнала. В
приведенном примере отключение происходит с задержкой 2 нс.
В случае, когда не выбран ни один источник, сигнал принимает
свое предыдущее значение, если источник сигнала типа
registerregisterregisterregister или предварительно заданное значение, если
источник сигнала типа busbusbusbus. Ключевыми словами registerregisterregisterregister и
busbusbusbus сигналы обозначаются при их объявлении. Благодаря
механизму сдерживания, один сигнал может иметь несколько
источников – выходов блоков. При этом правильное поведение
79
этого сигнала состоит в выборке не более одного источника
сигнала одновременно, т.е. сигнал guard защищает (guards)
общую шину от неправильного функционирования. Таким
образом, еще одной основной функцией блоков в VHDL
является организация нескольких источников для одного
сигнала.
Обычно трансляция операторов блоков поддерживается
компиляторами-синтезаторами. Но использование механизма
подключения к общей шине, обеспечиваемого блоками, а также
программирование поведения модели, связанное с ключевыми
словами registerregisterregisterregister, busbusbusbus, disconnectdisconnectdisconnectdisconnect, как правило,
80
запрещаются. Также не поддерживаются связывания портов
и настроечных констант в блоках. Следует отметить, что при
внедрении проекта устройства иногда его необходимо перевести
на язык Verilog, в котором отсутствует оператор, эквивалентный
оператору blockblockblockblock. Поэтому использование оператора blockblockblockblock
при синтезе не рекомендуется.