A function is a subprogram that accepts zero or more input arguments and returns a single output value. Because a function returns a value, it has a type associated with it. The following is an example of a function that accepts two integer arguments and returns the greater of the two as an integer value:

 

function maxval (arg1, arg2: integer) return integer is

     variable result: integer;

begin

     if arg1 > arg2 then

         result := arg1;

     else

         result := arg2;

     end if;

      return result;

end maxval;

 

The arguments to a function are all inputs to the function. They cannot be modified or otherwise assigned values within the function. By default, the arguments are of a constant kind. This means that the arguments are interpreted within the function as if they had been supplied as constants declared in the function itself. An alternative type of argument, indicated by the use of the signal keyword, allows the use of signal attributes (such as 'event) within the function. The following function (which is provided in the IEEE 1164 standard library) demonstrates the use of a signal argument in a function:

 

function rising_edge (signal s: std_logic) return boolean is

begin

     return (s'event and (To_X01(s) = '1') and

         (To_X01(s'last_value) = '0'));

end;

 

In this example, the keyword signal is critical to the correct operation of the function. In the absence of the signal keyword, the 'event attribute would not be preserved.

 

Functions are most commonly used in situations where you require a calculation or conversion based on the subprogram inputs. Examples of this include arithmetic or logic functions (such as the one just presented), type conversion functions, and value checks such as you might use when writing a test bench.

 

Because they return a value, functions must be used as part of a larger expression. The following VHDL code fragment demonstrates a type conversion function being used in an expression to convert an array data type to an integer:

 

signal Offset: integer range (0 to 1023);

signal BUS1: std_logic_vector(11 downto 0);

 

. . .

 

Offset <= to_integer(BUS1) + 136;

 

Operators as Functions

One interesting feature of VHDL is its support for operator overloading. Operator overloading allows you to specify custom functions representing symbolic operations for your own data types. To define a new operation (or modify an existing one), you simply write a function and enclose its name (which can be a non-numeric name such as an operator symbol) in double-quote characters.

 

The following operator function is taken directly from the IEEE 1164 standard logic package, and demonstrates how operator overloading works:

 

function "and" (l : std_logic; r : std_logic ) return UX01 is

begin

    return(and_table(l, r));

end "and";

 

In this example, the function and is declared as a function returning the type UX01 (a four-valued logic type used internally in the standard logic package). The function is identified during compilation by its name (and) and by the types and number of its arguments. For example, in the expression:

 

architecture simple of and_operation is

    signal Y, A, B: std_logic;

begin

    Y <= A and B;

end simple;

 

the and operation is actually a function defined using the previously listed statements. In fact, all of the standard operations that you use in VHDL (including such operators as and, or, not, +, -, *, & and <) are actually functions declared in libraries such as std and ieee.

 

Note: In source code listings presented in this document we have used the typographic convention of listing all VHDL keywords in bold face. As you have just seen, however, many of the keywords that we list in bold face are actually functions defined in a standard library.

 

See also

image\diamond.gif  Subprogram Overloading