Subprograms in VHDL

This article describes the two kinds of subprograms in VHDL: procedures and functions. A function call can be used within an expression. A procedure call may be a sequential or a concurrent statement. It is possible for two or more subprograms to have the same name. This is called overloading.


  • A subprogram defines a sequential algorithm that performs a certain computation and executes in zero simulation time. Subprograms consist of procedures and functions.
  • A procedure can return zero or more arguments; a function always returns just one.
  • In a function, all parameters are input parameters; a procedure can have input parameters, output parameters, and inout parameters.
  • There are two versions of procedures and functions: a concurrent procedure and concurrent function, and a sequential procedure and sequential function.
  • The concurrent procedure and function exist outside of a process statement or another subprogram; the sequential function and procedure exist only in a process statement or another subprogram statement.
  • All statements inside of a subprogram are sequential. The same statements that exist in a process statement can be used in a subprogram, including WAIT
  • A procedure exists as a separate statement in an architecture or process; a function is usually used in an assignment statement or expression.


The typical format for a subprogram body is

subprogram-name is



subprogram-statements                                   — Same as sequential-statements.

end [ subprogram-name ];

  • The subprogram-name specifies the name of a subprogram and defines its interface, that is, it defines the formal parameter names, their class (i.e., signal, variable, or constant), their type, and their mode (whether they are in, out, or inout).
    • Parameters of mode in are read-only parameters; these cannot be updated within a subprogram body. Parameters of mode out are write-only parameters; their values cannot be used but can only be updated within a subprogram body. Parameters of mode inout can be read as well as updated.
    • Actual values are passed to and from a subprogram via a subprogram call. Only a signal object may be used to pass a value to a parameter of the signal class.
    • Only a variable object may be used to pass a value to a parameter of the variable class.
    • A constant or an expression may be used to pass a value to a parameter of constant class. When parameters are of a variable or constant class, values are passed to the subprogram by value. Arrays may or may not be passed by reference. For signal objects, the reference to the signal, its driver, or both are passed into the subprogram.


  • The subprogram-item-declarations part contains a set of declarations (e.g., type and object declarations) that are accessible for use locally within the subprogram. These declarations come into effect every time the subprogram is called. Variables are also created and initialized every time the subprogram is called.
  • The subprogram-statements part contains sequential statements that define the computation to be performed by the subprogram.
  • A return statement, which is also a sequential statement, is a special statement that is allowed only within subprograms.


The format of a return statement is

return { expression];

  • The return statement causes the subprogram to terminate and control is returned back to the calling object. All functions must have a return statement and the value of the expression in the return statement is returned to the calling program.
  • For procedures, objects of mode out and inout return their values to the calling program.
  • The subprogram-name appearing at the end of a subprogram body, if present, must be the same as the function or procedure name specified in the subprogram specification part.


Functions are used to describe frequently used sequential algorithms that return a single value. This value is returned to the calling program using a return statement. Some of their common uses are as resolution functions, and as type conversion functions.


The following example is a function that takes in an array of the std_logic type and returns an integer value. The integer value represents the numeric value of all of the bits treated as a binary number:


USE IEEE.std_logic_1164.ALL;


PACKAGE num_types IS

TYPE log8 IS ARRAY(0 TO 7) OF std_logic;       –line 1

END num_types;



USE WORK.num_types.ALL;


ENTITY convert IS

PORT(I1 : IN log8;                             –line 2

O1 : OUT INTEGER);                             –line 3

END convert;


ARCHITECTURE behave OF convert IS

FUNCTION vector_to_int(S : log8)               –line 4


VARIABLE result : INTEGER := 0;                –line 6


FOR i IN 0 TO 7 LOOP                           –line 7

result := result * 2;                          –line 8

IF S(i) = ‘1’ THEN                             –line 9

result := result + 1;                          –line 10



RETURN result;                                 –line 11

END vector_to_int;


O1 <= vector_to_int(I1);                       –line 12

END behave;

  • Line 1 of the example declares the array type used throughout the example. Lines 2 and 3 show the input and output ports of the convert entity and their types.
  • Lines 4 through 11 describe a function that is declared in the declaration region of the architecture behave. By declaring the function in the declaration region of the architecture, the function is visible to any region of the architecture.
  • Lines 4 and 5 declare the name of the function, the arguments to the function, and the type that the function returns. The name of the function is followed by its arguments enclosed in parentheses. The function always returns a value; therefore, the calling process, concurrent statement, and so on must have a place for the function to return the value to.
  • In line 6, a variable local to the function is declared. Functions have declaration regions very similar to process statements.
  • Lines 7 through 10 declare a loop statement that loops once for each value in the array type. The basic algorithm of the function is to do a shift and add for each bit position in the array. The result is first shifted (by multiplying by 2), and then, if the bit position is a logical 1, a 1 value is added to the result.
  • The value of the function is passed back via the RETURN An example RETURN statement is shown in line 11. Finally, line 12 shows how a function is called.
  • In this example, the output of the function is assigned to an output port. Parameters to a function are always input only. No assignment can be done to any of the parameters of the function.



Procedures allow decomposition of large behaviors into modular sections. In contrast to a function, a procedure can return zero or more values using parameters of mode out and inout.

The syntax for the subprogram specification for a procedure body is

procedure procedure-name ( parameter-list )

  • The parameter-list specifies the list of formal parameters for the procedure. Parameters may be constants, variables, or signals and their modes may be in, out, or inout.
  • If the object class of a parameter is not explicitly specified, then the object class is by default a constant if the parameter is of mode in, else it is a variable if the parameter is of mode out or inout.


 It describes the behavior of an arithmetic logic unit.

type OP_CODE is (ADD, SUB, MUL, DIV, LT, LE, EQ);

. . .

procedure ARITH_UNIT (A, B: in INTEGER; OP: in OP_CODE;



case OP is

when ADD=>Z:=A+B;

when SUB=>Z:=A-B;

when MUL=>Z:=A*B;

when DIV => Z := A/B;

when LT => ZCOMP := A < B;

when LE => ZCOMP := A <= B;

when EQ => ZCOMP := A = B;

end case;


  • A procedure can normally be used simultaneously as a concurrent and a sequential statement. However, if any of the procedure parameters are of the variable class, the procedure would be restricted to be used as a sequential procedural call, since variables can only be defined inside of a process.
  • A procedure body can have a wait statement while a function cannot. Functions are used to compute values that are available instantaneously. Therefore, a function cannot be made to wait. A process that calls a procedure with a wait statement cannot have a sensitivity list.


A subprogram body may appear in the declarative part of the block in which a call is made. This is not convenient if the subprogram is to be shared by many entities. In such cases, the subprogram body can be described at one place, possibly in a package body and then in the package declaration, the corresponding subprogram declaration is specified.

If this package declaration is included in other design units using context clauses, the subprograms can then be used in these design units.

A subprogram declaration describes the subprogram name and the list of parameters without describing the internal behavior of the subprogram, that is, it describes the interface for the subprogram.


The syntax of a subprogram declaration is



procedure ARITH_UNIT (A, B: in INTEGER; OP: in OP_CODE;


Recent posts

1 thought on “Subprograms in VHDL”

Comments are closed.