Local variables can be declared within subprograms and their values are defined only until the return from a subprogram occurs. In contrast, variables of a process correspond to the local memory locations.
A subprogram must be declared prior to its call. Therefore, if it is called within a process, it must be declared in its respective architecture, entity or package.
During the subprogram call, passing of parameters is done by either the proper position in the parameter list or by the name, such that declaration_name => actual_parameter.
Syntax:
function func_name (parameter_list)
return type_name is
[variable_declaration]
[constant_declaration]
[type_declaration]
[use_clause]
begin
[sequential_statements]
return expression;
[sequential_statements]
end [func_name];
In the following example, function VEC2INT converts a bit-vector into an integer value.
Example:
architecture ...
...
function VEC2INT (S: bit_vector range 1 to 8)
return integer is
variable RES: integer := 0; local variable
begin
for I in 1 to 8 loop
RES := RES * 2;
if S(I) = '1' then RES := RES + 1;
end if;
end loop;
return RES;
end VEC2INT;
...
begin
...
process ...
...
XVAL := VEC2INT (XBUS); function call
...
end process;
...
end ...
in | : | readable only within the procedure |
out | : | writable only; the use of these parameter is allowed only on the left side of an assignment. |
inout | : | read/write paramenter, which can be universally used within a procedure. |
Procedure parameters can be both variables and signals (after their explicit declaration). In VHDL code procedures are handled similarly to the assignments.
Syntax:
procedure proc_name (parameter_list) is
[variable_declaration]
[constant_declaration]
[type_declaration]
[use_clause]
begin
sequential_statements
end [proc_name];
parameter_list:
[variable]name_list [in|out|inout] type_name
[:= expression];|
signal name_list [in|out|inout] type_name;
The example below shows a procedure which performs the same
bit-vector conversion into an integer value as the function of the
previous example. In addition, the procedure also sets a Flag.
Example:
architecture ...
...
procedure VEC2INT Declaration
( S: in bit_vector;
ZFLAG: out boolean;
Q: inout integer ) is mode assignments
begin
Q := 0;
ZFLAG := true;
for I in 1 to 8 loop
Q := Q * 2; Q allowed on the right side
if S(I) = '1' then
Q := Q + 1;
Mode is: inout
ZFLAG := false;
end if;
end loop;
end VEC2INT;
begin - architecture statement part
...
process ...
...
VEC2INT (XBUS, XFLG, XVAL); procedure call
...
end process;
...
end ...
Example:
function DECR (X: integer) return integer is
begin
...
end DECR;
function DECR (X: real) return real is
begin
...
end DECR;
...
variable A, B: integer;
...
B := DECR(A); call the first (integer) function
Example:
function CONV_ADDR (A0, A1: bit) return integer is
begin 2 arguments
...
end;
function CONV_ADDR (A0, A1, A2: bit) return integer is
begin 3 arguments
...
end;
In general, overloading permits extension of already existing operators found in the default package STANDARD. This is particularly useful for writing vendor/ user-specific packages. Some of the most commonly used extended packages are n-value logic packages MVL7, MVL9 and STD_LOGIC_1164. They define logic values 'X' (unknown), 'Z' (high-impedance), etc., as well as drivers of different strengths, in addition to the conventional '0' und '1'. Logical (and, or, not, xor...), arithmetic (+, -, *...) and comparison operators (=, / =, >, <...) for the new types are also provided. For the often used STD_LOGIC_1164 package an extension exists which defines operators for unsigned and signed (2's complement) binary representations. The user can then take advantage of overloading and conveniently use these types with their respective operators. For functions with only two arguments it is possible to use the infix-Notation.
In the following example, a new addition function for a 4-bit bit_vector is defined.7
Example:
function "
+"
(A, B: bit_vector (3 downto 0))
return bit_vector is
variable SUM: bit_vector (3 downto 0);
variable CARRY: bit;
begin
CARRY := '0';
for I in 0 to 3 loop
SUM(I) := A(I) xor B(I) xor CARRY;
CARRY := ((A(I) and B(I)) or (A(I) and CARRY)
or (B(I) and CARRY));
end loop;
return SUM;
end;