Creating Modular Designs

(from VHDL Made Easy!)


Modular (or structured) programming is a technique that you can use to enhance your own design productivity, as well as that of your design team. A modular design approach allows commonly-used segments of VHDL code to be re-used. It also enhances design readability.

VHDL includes many features that can help you create modular designs. In this chapter we will look at features that allow you to quickly and easily create reusable segments of your design, based on methods similar to those used in software programming languages.

Functions and Procedures

Functions and procedures in VHDL, which are collectively known as subprograms, are directly analogous to functions and procedures in a high-level software programming language such as C or Pascal. A procedure is a subprogram that has an argument list consisting of inputs and outputs, and no return value. A function is a subprogram that has only inputs in its argument list, and has a return value.

Subprograms are useful for isolating commonly-used segments of VHDL source code. They can either be defined locally (within an architecture, for example), or they can be placed in a package and used globally throughout the design description or project.

Statements within a subprogram are sequential (like a process), regardless of where the subprogram is invoked. Subprograms can be invoked from within the concurrent area of an architecture or from within a sequential process or higher-level subprogram. They can also be invoked from within other subprograms.

Subprograms are very much like processes in VHDL. In fact, any statement that you can enter in a VHDL process can also be entered in a function or procedure, with the exception of a wait statement (since a subprogram executes once each time it is invoked and cannot be suspended while it is executing). It is therefore useful to think of subprograms as processes that (1) have been located outside the body of an architecture, and (2) operate only on their input and (in the case of procedures) their output parameters.

VHDL '93 Note:

In VHDL '93, functions can be declared as impure, meaning that they can operate on and modify objects other than those passed as parameters. Impure functions can therefore have side-effects, and they can return different values for the same input parameters.

Nesting of functions and procedures is allowed to any level of complexity, and recursion is also supported in the language. (Of course, if you expect to generate actual hardware from your VHDL descriptions using synthesis tools, then you will need to avoid writing recursive functions and procedures, as such descriptions are not synthesizable).

Declaring a Global Subprogram

Functions and procedures can be declared either globally, so they are usable throughout a design description, or they can be declared locally within the declarative region of an architecture, block, process, or even within another subprogram. If you are writing a subprogram that will be used throughout your design, you will write the subprogram declaration in an external package, as shown in the following example:

package my_package is

    function my_global_function(...)

        return bit;

end my_package;



package body my_package is

    function my_global_function(...)

        return bit is

    begin

        . . .

    end my_global_function;

end my_package;

. . .

use work.my_package.my_global_function;

entity my_design is

begin

    . . .

end my_design;

In this example, the function my_global_function() has been declared within the package my_package. The actual body of the function—the sequence of statements that define its operation—is placed into a package body. (The reasons why a subprogram requires a package body in addition to a package are somewhat obscure, but they have to do with the fact that the statements in a subprogram must be executed when the design description is simulated, while other declarations appearing in a package can be completely resolved at the time the VHDL description is first analyzed by the VHDL compiler.) To use the global function in subsequent architectures (such as the architecture associated with entity my_design in this example), a use statement (and library statement, if the package has been compiled into a named library) must precede the declaration for that architecture or its parent entity.

Declaring a Local Subprogram

Another way of using subprograms is to declare them locally, such as within an architecture or block declaration. In the following example, my_local_function() has been declared entirely within the architecture my_architecture.

architecture my_architecture of my_design is

begin

    my_process: process(...)

        function my_local_function(...)

            return bit is

        begin

            . . .

        end my_local_function;

    begin

        . . .

    end process my_process;

end my_architecture;

This example demonstrates the concept of local scoping. We saw in Chapter 3, Exploring Objects and Data Types, that VHDL objects (such as signals, variables and constants) can be declared at many points in a design, and that the visibility, or scoping, of those objects depends on where they have been declared. Subprograms (functions and procedures) also have scoping. In this example, the function my_local_function can only be referenced within the architecture in which it has been declared and defined.

Consistent scoping of objects and subprograms is an important part of modular VHDL coding and of structured programming in general. If you will only be using an object or subprogram in one section of your overall design, then you should keep the declaration of that object or subprogram local to that section of the design. This will make it possible to re-use that section of the design elsewhere with a minimum of fuss (since you won't have to remember to declare the object or subprogram globally in the new design).


Then, we go into more detail about functions, operators as functions, subprogram overloading (wow! that's an impressive term), procedures, and parameter mapping.

If you want the best learning guide to VHDL, this is it! To order your copy of VHDL Made Easy!, just click below.


[How to order VHDL Made Easy!]