Partitioning Your Design

(from VHDL Made Easy!)


VHDL provides many high-level features to help you manage a complex design description. In fact, design management is one of VHDL's key strengths when compared to alternative design entry languages and methods.

The modularity features (procedures and functions) that we have seen in previous chapters are one aspect of design management, allowing commonly-used declarations and sequential statements to be collected in one place. Design partitioning is another important aspect of design management. Design partitioning goes beyond simpler design modularity methods to provide comprehensive design management across multiple projects and allow alternative structural implementations to be tried out with minimal effort.

Design partitioning is particularly useful for those designs being developed in a team environment, as it promotes cooperative design efforts and well-defined system interfaces.

The design partitioning features of VHDL include:

Blocks

Blocks are the simplest form of design partitioning. They provide an easy way to segment a large VHDL architecture into multiple self-contained parts. Blocks allow the logical grouping of statements within an architecture, and provide a place to declare locally-used signals, constants, and other objects as needed.

VHDL blocks are analogous to sheets in a multi-sheet schematic. They do not represent re-usable components (unless you re-use them by copying them with your text editor or by using configurations), but do enhance readability by allowing declarations of objects to be kept close to where those objects are actually used.

The general form of the block statement is shown below:

architecture my_arch of my_entity is

begin



    BLOCK1: block

        signal a,b: std_logic;

    begin

        -- some local statements here

    end block BLOCK1;



    BLOCK2: block

        signal a,b std_logic;

    begin

        -- some other local statements here

        -- Note that `a' and `b' are unique to this block!

    end block BLOCK2;



end my_arch;

This simple example includes two blocks, named BLOCK1 and BLOCK2, that each include declarations for local signals. In the first block, BLOCK1, the signals a and b are declared prior to the begin statement of the block. These signals are therefore local to block BLOCK1 and are not visible outside of it. The second block, BLOCK2, also has declarations for local signals named a and b, but these are not the same signals as those declared in block BLOCK1.

This concept of local declarations is important to understand and is probably familiar to you if you have used high-level programming languages. One of the most important techniques of structured programming (whether you are describing software or hardware) is to minimize the overall complexity of your design description by localizing the declarations as much as is practical. Keeping signals local will make the design description easier to read, allow it to be modified more easily in the future, and also enhance design re-use, since it will be easier to copy one portion of the design to another project or source file.

Nested Blocks

Blocks can be nested, as shown in the following example:

architecture my_arch of my_entity is

begin



    BLOCK1: block

        signal a,b: std_logic;

    begin



        BLOCK2: block

            signal c,d std_logic;

        begin

            -- This block is now local to block BLOCK1 and has

            -- access to `a' and `b'

        end block BLOCK2;



    end block BLOCK1;



end my_arch;

In this example, block BLOCK2 has been placed within block BLOCK1. This means that all declarations made within BLOCK1 (signals a and b, in this example) are visible both within block BLOCK1 and block BLOCK2. The reverse is not true, however. The declarations for c and d within block BLOCK2 are local only to BLOCK2 and are not visible outside that block.

What happens when the same signals are declared in two blocks that are nested? Consider the following:

architecture my_arch of my_entity is

begin



    BLOCK1: block

        signal a,b: std_logic;

    begin



        BLOCK2: block

            signal a,b std_logic;

        begin

            -- This a and b overrides previous

        end block BLOCK2;



    end block BLOCK1;



end my_arch;

In this example, the signals a and b are declared both in the outer block (BLOCK1) and in the inner block (BLOCK2). The result is that the signals a and b in the outer block are hidden (but not replaced or overwritten) by the declarations of a and b in the inner block.

Note:

If you need to access a signal that has been effectively hidden by a declaration of the same name, you can qualify the signal name with a block name prefix, as in BLOCK1.a or BLOCK1.b.


Of course, this is just the beginning. VHDL Made Easy! goes on to cover guarded blocks, packages, package bodies, and design libraries, to name only a few. This is the VHDL learning guide you've been waiting for! Plus, it includes a bonus CD-ROM with a host of programs and demos that can really get you rolling in VHDL design and simulation.

So what are you waiting for?


[How to order VHDL Made Easy!]