Процедуры и функции

Cодержание Следующая

Изучение VHDL

Процедуры и функции.

Процедуры и функции относятся к числу подпрограмм. Здесь рассмотрены правила и особенности составления и объявления процедур и функций, а также их вызова.

Спецификация процедуры.

Спецификация процедуры описывает действия при вызове процедуры и имеет следующий синтаксис:

\спецификация процедуры\::=procedure \имя процедуры\[(\список параметров\)] is
       {\объявление в подпрограмме\}
       begin
       {\последовательный оператор\}
       end [procedure][\имя процедуры\];

\список параметров\::=(\элемент списка\ {; \элемент списка\})
       \элемент списка\::=[constant | variable | signal ]

       \идентификатор\{,\идентификатор\}: [in | out | inout] \тип параметра\
       [ := \статическое выражение\]

Здесь \имя процедуры\ — идентификатор процедуры. В списке параметров указывается информация о формальных параметрах процедуры. Вместо формальных параметров подставляются фактические параметры во время вызова процедуры. В каждом из элементов списка параметров может объявляться какой это параметр (константа, переменная или сигнал) направление передачи параметра (in, out или inout) его тип или подтип и его значение по умолчанию, равное статическому выражению.

Список параметров может отсутствовать, т.е. он тогда задан неявно. При этом имена фактических параметров совпадают с именами формальных параметров, объявленных в процедуре. Обычно трудно понять программу с процедурами без списков параметров. Поэтому в соответствии с условиями повторного использования проектов, не рекомендуется программирование процедур без списка параметров.

Объявленными в процессе могут быть: объявление и тело другой процедуры или функции, объявление типа и подтипа, объявление константы, переменной, файла, псевдонима, объявление и спецификация атрибута, объявление группы, описание use.

Рассмотрим пример программирования и использования процедуры в процессе для сортировки трех целых чисел.

process(a1,a2,a3)
  varіable b1,b2,b3:іnteger;  
   procedure sort2(varіable x1,x2:іnout іnteger) іs
  varіable t:іnteger;
   begіn 
         іf x1>x2 then
           return; 
         else
            t:=x1; x1:=x2; x2:=t;
         end іf;
   end procedure;
       begіn	
	   b1:=a1; b2:=a2; b3:=a3;
	   sort2(b2,b3);
	   sort2(b1,b2);
	   sort2(b2,b3);
	   c1<=b1; c2<=b2; c3<=b3;           
 end process; 

Здесь процедура sort2 выполняет сортировку двух переменных х1, х2, которые являются входными - выходными формальными параметрами процедуры. Вызов процедуры выполняется с позиционным связыванием.

Оператор return досрочно прерывает исполнение процедуры. Последовательный оператор return -оператор возврата из подпрограммы - немедленно прерывает выполнение процедуры или вызова функции и возвращает управление в программу, вызвавшую процедуру.

Спецификация функции.

Спецификация функции имеет следующий синтаксис:

\спецификация функции\::=[pure | impure] function \имя функции\ |\знак функции\

       [(\список параметров\)] return \тип параметра\ is
       {\объявление в подпрограме\}
begin
       {\последовательный оператор\}
       return \выражение\;
end [function][\имя функции\];

В ней знак функции - символ в кавычках, например, "+", список параметров - такой же, как в процедуре за исключением того, что режимы параметров out и inout не допускаются. После ключевого слова return в объявлении функции указывается тип возвращаемого параметра. Объявления в функции могут быть такими же, как в процедуре. Выполнение функции должно оканчиваться оператором return, вычисляющим выражение возвращаемого параметра.

Объявление процедур и функций.

Объявление подпрограмм вставляется в части объявлений в процессов, блоков, объявлениях объектов и пакетов, если эти подпрограммы используются в этих программных единицах. Оно представляет собой часть спецификации процедуры и функции до слова is :

\объявление процедуры\::= procedure \имя процедуры\[(\список параметров\)];
\объявление функции\::=[pure | impure] function \имя функции\ |\знак функции\

       [(\список параметров\)] return \тип параметра\;

Вызов процедуры.

Вызов процедуры представляет собой последовательный или параллельный оператор, в зависимости от того, стоит ли он внутри или снаружи процесса. Упрощенный синтаксис последовательного вызова процедуры:

\вызов процедуры\::=\имя процедуры\[([\имя параметра =>\] \выражение\

       {,[\имя параметра\ => ] \выражение\})];

Здесь \имя процедуры\ - имя ранее определенной процедуры. Связывание формальных и фактических параметров выполняется аналогично как в вызове функции. Выражение - параметр функции - должно давать результат типа, соответствующего имени параметра \имя параметра\. Параметры можно задавать с поименованным или позиционным связыванием. При позиционном связывании параметры-выражения подставляются в порядке, определенном порядком следования имен параметров в определении функции. При поименованном связывании каждое имя, параметра связывается с соответствующим параметром с помощью символов "=>", причем порядок следования параметров может быть произвольным.

В пакете IEEE.Math_Real определена процедура генерации случайных чисел:

procedure UNIFORM(variable SEED1,SEED2:inout POSITIVE; variable X:out real);

Она может быть вызвана со связыванием параметров:

varіable s1,s2:natural:=12345; 
varіable Random:real;
...
UNІFORM(X=> Random, SEED1=>s1,SEED2=>s2);

или без связывания параметров:

UNІFORM(s1,s2, Random);

Следующий пример представляет использование процедуры со связыванием не всех формальных параметров.

procedure and4(varіable x1,x2,x3,x4:іn bіt:='1';
 sіgnal y:out bіt) іs
	   begіn 
	 y<=x1 and x2 and x3 and x4;
end procedure;

При вызове этой процедуры:

and4(a1,a2,a3, open, b);

четвертый входной параметр отсутствует, на что указывает ключевое слово open и вместо него подставляется начальное значение '1'.

Вызов процедуры без параметров - это просто написанное ее имя.

При вызове процедуры входные параметры переменных копируются внутрь процедуры. После исполнения процедуры выходные параметры записываются на место соответствующих переменных.

Входные параметры сигналов представляются как ссылки на сигналы. Параметру сигнала нельзя присваивать начальное значение, так как источник этого сигнала недоступен. Поэтому нельзя также использовать такие атрибуты сигнала, как 'delayed, 'stable, 'quiet или 'transaction. Выходной параметр сигнала передается в процедуру вместе с источником сигнала, в котором происходит присваивание сигналу. Это эквивалентно тому, что цепочка последовательных операторов тела процедуры копируется в процесс на место вызова процедуры с соответствующей подстановкой параметров. В отличие от вызова процедуры в обычных алгоритмических языках, в которых используется одно тело процедуры, в VHDL каждый вычислительный процесс, вызывающий процедуру, использует свой собственный экземпляр тела процедуры.

Параллельный вызов процедуры имеет такой же синтаксис, как у последовательного вызова процедуры. Он исполняется точно так же, как процесс, который имеет в своей исполнительной части такой же вызов процедуры с такими же параметрами и оператор wait ожидания прихода сигналов - входных параметров. Поэтому каждый параллельный вызов процедуры соответствует некоторому виртуальному процессорному элементу, исполняющему алгоритм этой процедуры.

Если программа предназначена для синтеза, то процедура, вызываемая параллельно, не должна иметь операторов wait. Такая процедура отображается в комбинационную схему или комбинацию шин, т.е. некоторый специализированный процессорный элемент.

Вызов функции.

При вызове функции выполняется функция с заданными значениями параметров. Упрощенный синтаксис вызова функции:

\вызов функции\::=\имя функции\ ([\имя параметра\ =>] \выражение\

       {,[\имя параметра\ => ] \выражение\});

где \имя функции\ - имя функции, определяемой ранее, \имя параметра\ - не обязательный формальный параметр этой функции. Выражение-параметр функции - должно давать результат типа, соответствующий имени параметра.

Параметры можно задавать с поименованным или позиционированным связыванием. При позиционированном связывании параметры-выражения подставляются в порядке, определенном порядком следования имен параметров в определении функции. При поименованном связывании каждое имя, параметра связывается с соответствующим параметром с помощью символов "=>", причем порядок следования параметров может быть произвольным.

В отличие от процедуры, вызов функции возвращает только один параметр, зато он может участвовать как операнд в выражениях. В языке VHDL очень мало встроенных функций. Большинство функций реализовано в виде подпрограмм. Для преобразования типов чаще всего используются функции. Например, функция

functіon BІ_TO_ІNT(x:bіt_vector) return natural іs
   varіable t, j:іnteger:=0;
 begіn
    for І іn x'reverse_range loop 
         іf ( x(І)='1') then
              t:=t + 2**j;
        end іf;
              j:=j+1;
         end loop;
         return t;
end functіon BІ_TO_ІNT;

преобразует вектор битов в целое. При этом атрибут x'reverse_range возвращает диапазон, обратный диапазону представления входного параметра. Например, если входной параметр - bit_vector(7 downto 0), то в оператор цикла подставится диапазон 0 to 7. Таким образом, получается функция, универсальная для множества различных параметров - операндов.

Ключевые слова pure и impure обозначают идеальную и неидеальную функции. В отличие от идеальной функции, неидеальная функция может возвращать различные результаты для одинаковых наборов входных параметров. Например, если входной параметр - глобальная переменная, то она может измениться в момент вызова функции и результат будет отличаться от ожидаемого. Поэтому глобальные переменные не могут быть операндами в идеальных функциях. Примером неидеальной функции является функция Now из пакета STANDARD, которая при вызове возвращает переменную предопределенного типа delay_length, равную текущему моменту времени моделирования. Естественно, что при различных вызовах этой функции она возвращает различные значения.

Возврат из процедуры или функции.

Оператор возврата из подпрограммы - последовательный оператор return - немедленно прерывает выполнение процедуры или вызова функции и возвращает управление в программу, вызвавшую процедуру.

Перезагрузка процедур и функций.

В языке VHDL допускается определять несколько процедур и функций с одинаковыми названиями. При вызове функции или процедуры из числа функций или процедур с одинаковым названием выбирается такая, которая подходит по типам и числу входных и выходных параметров. Такая функция перезагружает (overloads) остальные функции. Перезагрузка процедур и функций удобна при вычислениях с различными типами. Например, над типами integer, real, подтипами signed, unsigned определены одни и те же арифметические функции, но имеющие различное сочетание типов аргументов и результатов.

Примером перезагрузки служит следующая функция, которая не входит ни в один стандартный пакет:

functіon "and"(x1,x2:bіt) return boolean іs 
begіn  
            return (x1 and x2) ='1';
end;

Если эта функция объявлена, то теперь транслятор не выдаст сообщения об ошибке при выполнении оператора if, вызывающего эту функцию:

varіable a,b,c: bіt;
...
іf (a and b and c) then
...
end іf;

так как выражение в скобках будет иметь правильный тип boolean.

Анатолий Сергиенко
E-mail: aser@comsys.kpi.ua