2.5. Subprograms and Packages

Like other programming languages, VHDL provides subprogram facilities in the form of procedures and functions. VHDL also provided a package facility for collecting declarations and objects into modular units. Packages also provide a measure of data abstraction and information hiding.

2.5.1. Procedures and Functions

Procedure and function subprograms are declared using the syntax:

subprogram_declaration ::= subprogram_specification ;

A subprogram declaration in this form simply names the subprogram and specifies the parameters required. The body of statements defining the behaviour of the subprogram is deferred. For function subprograms, the declaration also specifies the type of the result returned when the function is called. This form of subprogram declaration is typically used in package specifications (see Section 2.5.3), where the subprogram body is given in the package body, or to define mutually recursive procedures.

The syntax for specifying the formal parameters of a subprogram is:

For now we will only consider constant and variable parameters, although signals can also be used (see Chapter 3). Some examples will clarify this syntax. Firstly, a simple example of a procedure with no parameters:

This simply defines reset as a procedure with no parameters, whose statement body will be given subsequently in the VHDL program. A procedure call to reset would be:

Secondly, here is a declaration of a procedure with some parameters:

In this example, the procedure increment_reg has two parameters, the first called reg and the second called incr. Reg is a variable parameter, which means that in the subprogram body, it is treated as a variable object and may be assigned to. This means that when the procedure is called, the actual parameter associated with reg must itself be a variable. The mode of reg is inout, which means that reg can be both read and assigned to. Other possible modes for subprogram parameters are in, which means that the parameter may only be read, and out, which means that the parameter may only be assigned to. If the mode is inout or out, then the word variable can be omitted and is assumed.

The second parameter, incr, is a constant parameter, which means that it is treated as a constant object in the subprogram statement body, and may not be assigned to. The actual parameter associated with incr when the procedure is called must be an expression. Given the mode of the parameter, in, the word constant could be omitted and assumed. The expression after the assignment operator is a default expression, which is used if no actual parameter is associated with incr in a call to the procedure.

A call to a subprogram includes a list of actual parameters to be associated with the formal parameters. This association list can be position, named, or a combination of both. (Compare this with the format of aggregates for values of composite types.) A call with positional association lists the actual parameters in the same order as the formals. For example:

A call with named association explicitly gives the formal parameter name to be associated with each actual parameter, so the parameters can be in any order. For example:

Note that the second call in each example does not give a value for the formal parameter incr, so the default value is used.

Thirdly, here is an example of function subprogram declaration:

The function has one parameter. For functions, the parameter mode must be in, and this is assumed if not explicitly specified. If the parameter class is not specified it is assumed to be constant. The value returned by the body of this function must be an integer.

When the body of a subprogram is specified, the syntax used is:

The declarative items listed after the subprogram specification declare things which are to be used locally within the subprogram body. The names of these items are not visible outside of the subprogram, but are visible inside locally declared subprograms. Furthermore, these items shadow any things with the same names declared outside the subprogram.

When the subprogram is called, the statements in the body are executed until either the end of the statement list is encountered, or a return statement is executed. The syntax of a return statement is:

If a return statement occurs in a procedure body, it must not include an expression. There must be at least one return statement in a function body, it must have an expression, and the function must complete by executing a return statement. The value of the expression is the valued returned to the function call.

Another point to note about function subprograms is that they may not have any side-effects. This means that no visible variable declared outside the function body may be assigned to or altered by the function. This includes passing a non-local variable to a procedure as a variable parameter with mode out or inout. The important result of this rule is that functions can be called without them having any effect on the environment of the call.

An example of a function body:

2.5.2. Overloading

VHDL allows two subprograms to have the same name, provided the number or base types of parameters differs. The subprogram name is then said to be overloaded. When a subprogram call is made using an overloaded name, the number of actual parameters, their order, their base types and the corresponding formal parameter names (if named association is used) are used to determine which subprogram is meant. If the call is a function call, the result type is also used. For example, suppose we declared the two subprograms:

Then which of the two functions is called depends on whether a value of type integer or word_8 is used as the actual parameter. So

would call the first function, and

would call the second function.

The designator used to define a subprogram can be either an identifier or a string representing any of the operator symbols listed in Section 2.3. The latter case allows extra operand types to be defined for those operators. For example, the addition operator might be overloaded to add word_32 operands by declaring a function:

Within the body of this function, the addition operator is used to add integers, since its operands are both integers. However, in the expression:

the newly declared function is called, since the operands to the addition operator are both of type word_32. Note that it is also possible to call operators using the prefix notation used for ordinary subprogram calls, for example:

2.5.3. Package and Package Body Declarations

A package is a collection of types, constants, subprograms and possibly other things, usually intended to implement some particular service or to isolate a group of related items. In particular, the details of constant values and subprogram bodies can be hidden from users of a package, with only their interfaces made visible.

A package may be split into two parts: a package declaration, which defines its interface, and a package body, which defines the deferred details. The body part may be omitted if there are no deferred details. The syntax of a package declaration is:

The declarations define things which are to be visible to users of the package, and which are also visible inside the package body. (There are also other kinds of declarations which can be included, but they are not discussed here.)

An example of a package declaration:

In this example, the value of the constant vector_table_loc and the bodies of the two functions are deferred, so a package body needs to be given.

The syntax for a package body is:

Note that subprogram bodies may be included in a package body, whereas only subprogram interface declarations may be included in the package interface declaration.

The body for the package data_types shown above might be written as:

In this package body, the value for the constant is specified, and the function bodies are given. The subtype declarations are not repeated, as those in the package declarations are visible in the package body.

2.5.4. Package Use and Name Visibility

Once a package has been declared, items declared within it can be used by prefixing their names with the package name. For example, given the package declaration in SectionĘ2.4.3 above, the items declared might be used as follows:

Often it is convenient to be able to refer to names from a package without having to qualify each use with the package name. This may be done using a use clause in a declaration region. The syntax is:

The effect of the use clause is that all of the listed names can subsequently be used without having to prefix them. If all of the declared names in a package are to be used in this way, you can use the special suffix all, for example: