Friday, July 24, 2015

Libraries and Packages

LIBRARIES AND PACKAGES

A package provides a convenient mechanism to store and share declarations that are common across many design units. A package is represented by
1. a package declaration, and optionally,
2. a package body.

A package declaration contains a set of declarations that may possibly be shared by many design units. It defines the interface to the package, i.e., it defines items that can be made visible to other design units, for example, a function declaration. A package body, in contrast, contains the hidden details of a package, for example, a function body.

The syntax of a package declaration is

package package-name is
package-item-declarations "> These may be:
- subprogram declarations ~ type declarations
- subtype declarations
- constant declarations
- signal declarations
- file declarations
- alias declarations
- component declarations
- attribute declarations
- attribute specifications
- disconnection specifications
- use clauses
end [ package-name ] ;

Eg.,
package SYNTH_PACK is
constant LOW2HIGH: TIME := 20ns:
type ALU_OP is (ADD, SUB, MUL, DIV, EQL);
attribute PIPELINE: BOOLEAN;
type MVL is ('U', '0', '1', 'Z');
type MVL_VECTOR is array (NATURAL range <>) of MVL;
subtype MY_ALU_OP is ALU_OP range ADD to DIV;
component NAND2
port (A, B: in MVL; C: out MVL);
end component;
end SYNTH_PACK;
Items declared in a package declaration can be accessed by other design units by using the library and use context clauses.

The set of common declarations may also include function and procedure declarations and deferred constant declarations.

In this case, the behavior of the subprograms and the values of the deferred constants are specified in a separate design unit called the package body. Since the previous package example did not contain any subprogram declarations and deferred constant declarations, a package body was not necessary.

Consider the following package declaration.

use WORK.SYNTH_PACK.all:
package PROGRAM_PACK is
constant PROP_DELAY: TIME; -A deferred constant.
function "and" (L, R: MVL) return MVL;
procedure LOAD (signal ARRAY_NAME: inout MVL_VECTOR;
START_BIT, STOP_BIT, INT_VALUE: in INTEGER);
end PROGRAM_PACK;

In this case, a package body is required.

A package body primarily contains the behavior of the subprograms and the values of the deferred constants declared in a package declaration.

It may contain other declarations as well, as shown by the following syntax of a package body.

package body package-name is
package-body-item-daclarations "> These are:
- subprogram bodies -- complete constant declarations
- subprogram declarations
- type and subtype declarations
- file and alias declarations
- use clauses
end [ package-name ];

The package name must be the same as the name of its corresponding package declaration. A package body is not necessary if its associated package declaration does not have any subprogram or deferred constant declarations. The associated package body for the package declaration, PROGRAM_PACK, described in the previous section is

package body PROGRAM_PACK is
constant PROP_DELAY: TIME := 15ns;
function "and" (L, R: MVL) return MVL is
begin
return TABLE_AND(L, R);
-- TABLE_AND is a 2-D constant defined elsewhere.
end "and";
procedure LOAD (signal ARRAY_NAME: inout MVL_VECTOR;
START_BIT, STOP_BIT, INT_VALUE: in INTEGER) is
-- Local declarations here.
begin
-- Procedure behavior here.
end LOAD;
end PROGRAM_PACK;

An item declared inside a package body has its scope restricted to be within the package body and it cannot be made visible in other design units. This is in contrast to items declared in a package declaration that can be accessed by other design units. Therefore, a package body is used to store private declarations that should not be visible, while a package declaration is used to store public declarations which other design units can access. This is very similar to declarations within an architecture body which are not visible outside of its scope while items declared in an entity declaration can be made visible to other design units.

An important difference between a package declaration and an entity declaration is that an entity can have multiple architecture bodies with different names, while a package declaration can have exactly one package body, the names for both being the same.

A subprogram written in any other language can be made accessible to design units by specifying a subprogram declaration in a package declaration without a subprogram body in the corresponding package body. The association of this subprogram with its declaration in the package is not defined by the language and is, therefore, tool implementation-specific.

DESIGN LIBRARIES

A compiled VHDL description is stored in a design library. A design library is an area of storage in the file system of the host environment. The format of this storage is not defined by the language.

Typically, a design library is implemented on a host system as a file directory and the compiled descriptions are stored as files in this directory. The management of the design libraries is also not defined by the language and is again tool implementation-specific.

An arbitrary number of design libraries may be specified. Each design library has a logical name with which it is referenced inside a VHDL description. The association of the logical names with their physical storage names is maintained by the host environment.

There is one design library with the logical name, STD, predefined in the language; this library contains the compiled descriptions for the two predefined packages, STANDARD and TEXTIO. Exactly one design library must be designated as the working library with the logical name, WORK.

When a VHDL description is compiled, the compiled description is always stored in the working library. Therefore, before compilation begins, the logical name WORK must point to one of the design libraries.

Fig.1 shows a typical compilation scenario.
Fig.1: A Typical Compilation Process

The VHDL source is present in an ASCII file called the design file. This is processed by the VHDL analyzer, which after verifying the syntactic and semantic correctness of the source, compiles it into an intermediate form.

The intermediate form is stored in the design library that has been designated as the working library.

Design File

The design file is an ASCII file containing the VHDL source. It can contain one or more design units, where a design unit is one of the following:
• entity declaration,
• architecture body,
• configuration declaration,
• package declaration,
• package body.

This means that each design unit can also be compiled separately.

A design library consists of a number of compiled design units. Design units are further classified as

1. Primary units: These units allow items to be exported out of the design unit. They are
a. entity declaration: The items declared in an entity declaration are implicitly visible within the associated architecture bodies.
b. package declaration: Items declared within a package declaration can be exported to other design units using context clauses.
c. configuration declaration.

2. Secondary units: These units do not allow items declared within them to be exported out of the design unit, that is, these items cannot be referenced in other design units. These are
a. architecture body: A signal declared in an architecture body, for example, cannot be referenced in other design units.
b. package body.

There can be exactly one primary unit with a given name in a single design library. Secondary units associated with different primary units can have identical names in the same design library; also a secondary unit may have the same name as its associated primary unit. For example, assume there exists an entity called AND_GATE in a design library. It may have an architecture body with the same name, and another entity, MY_GATE, in the same design library may have an architecture body that also has the name, AND_GATE.

Secondary units must coexist with their associated primary units in the same design library, for example, an entity declaration and all of its architecture bodies must reside in the same library. Similarly, a package declaration and its associated package body must reside in a single library.

Even though a configuration declaration is a primary unit, it must reside in the same library as the entity declaration to which it is associated.

ORDER OF ANALYSIS

Since it is possible to export items declared in primary units to other design units, a constraint is imposed in the sequence in which design units must be analyzed.

A design unit that references an item declared in another primary unit can be analyzed only after that primary unit has been analyzed.

Eg., if a configuration declaration references an entity, COUNTER, the entity declaration for COUNTER must be analyzed before the configuration declaration.

A primary unit must be analyzed before any of its associated secondary units. For example, an entity declaration must be analyzed before its architecture bodies are analyzed.

IMPLICIT VISIBILITY

An architecture body implicitly inherits all declarations in the entity since it is tied to that entity by virtue of the statement

architecture architecture-name of entity-name is . . .

Similarly, a package body implicitly inherits all items declared in the package declaration by virtue of its first statement

package body package-name is. . .

where the package name is the same as the one in the package declaration.

EXPLICIT VISIBILITY
Explicit visibility of items declared in other design units can be achieved using context clauses.

There are two types of context clauses:
1. library clause,
2. use clause.

Context clauses are associated with design units and may be written just before the design unit to which visibility is to be made available.

Fig.2 shows an example. Items specified in the context clause become visible only to the design unit that follows the context clause. This means that if a design file contains three design units as shown in Fig.3, then context clauses must be specified for each design unit.

Eg., the context clauses specified before design unit A makes them visible to design unit A only; context clauses specified before design unit B makes them visible to design unit B only.


Fig.2 Context Clause associated with design unit

Fig.3 Separate Context Clauses with each design unit

Library Clause

The library clause makes visible the logical names of design libraries that can be referenced within a design unit.

The format of a library clause is
library list-of-logical-library-names;

Eg.,
library TTL, CMOS;

makes the logical names, TTL and CMOS, visible in the design unit that follows. Note that the library clause does not make design units or items present in the library visible, it makes only the library name visible (it is like a declaration for a library name).

Eg., it is illegal to use the expression "TTL.SYNTH_PACK.MVL" within a design unit without first declaring the library name using the "library TTL;" clause.

The following library clause

library STD, WORK;

is implicitly declared for every design unit.

USE CLAUSE

There are two main forms of the use clause.

use library-name. primafy-unit-name ; --Form 1.
use library-name. primafy-unit-name. Item ; --Form 2.

The first form of the use clause allows the specified primary unit name from the specified design library to be referenced in a design description.

Eg.,
library CMOS;
use CMOS.NOR2;
configuration...
. . . use entity NOR2( . . . );
end;

Note that entity NOR2 must be available in compiled form in the design library, CMOS, before attempting to compile the design unit where it is used.

The second form of the use clause makes the item declared in the primary unit visible and the item can, therefore, be referenced within the following design unit.

Eg.,

library ATTLIB;
use ATTLIB.SYNTH_PACK.MVL;
-- MVL is a type declared in SYNTH_PACK package.
-- The package, SYNTH_PACK, is stored in the ATTLIB design library.
entity NAND2 is
port (A, B: in MVL; ...)...
If all items within a primary unit are to be made visible, the keyword all can be used.

Eg.,
use ATTLIB.SYNTH_PACK.all;

makes all items declared in package SYNTH_PACK in design library ATTLIB visible.

Items external to a design unit can be accessed by other means as well. One way is to use a selected name.

Eg., using a selected name

library ATTLIB;
use ATTLIB.SYNTH_PACK;
entity NOR2 is
port (A, B: in SYNTH_PACK.MVL; ...)...

Since only the primary unit name was made visible by the use clause, the complete name of the item, that is, SYNTH_PACK.MVL must be specified.

Eg.,

The type VALUE_9 is defined in package SIMPACK that has been compiled into the CMOS design library.

library CMOS;
package P1 is
procedure LOAD (A, B: CMOS.SIMPACK.VALUE_9; ...)...
. . . end P1;

In this case, the primary unit name was specified only at the time of usage.

If it is necessary to export items from design units that are in the same library, there is no need to specify a library clause since every design unit has the following library clause implicitly declared.

library WORK;

The predefined design library STD contains the package STANDARD.

The package STANDARD contains the declarations for the predefined types such as CHARACTER, BOOLEAN, BIT_VECTOR, and INTEGER.

The following two clauses are also implicitly declared for every design unit:

library STD;
use STD.STANDARD.all;

Thus all items declared within the package STANDARD are available for use in every VHDL description.

The package STANDARD is a predefined package that contains the definitions for the predefined types and functions of the language. A source code listing of this package follows.

package STANDARD is
-- Predefined enumeration types:
type BOOLEAN is (FALSE, TRUE);
type BIT is ('0', '1');
type CHARACTER is (
NUL, SOH, STX, ETX, EOT, ENQ, ACK,BEL, BS, HT, LF, VT, FF, CR,
SO, SI, DLE, DCI, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC,
FSP, GSP, RSP, USP, ' ' , ' ! ', ' ” ', ' # ', ' $ ', ' % ', ' & ', ' ’ ', ' (' , ' ) ', ' * ', ' + ', ' , ', ' - ', ' . ', ' / ', ' 0 ', ' 1 ', ' 2 ', ' 3 ', ' 4 ', ' 5 ', ' 6 ', ' 7 ', ' 8 ', ' 9', ' : ', ' ; ',' < ', ' = ', ' > ', ' ? ', ' @ ', ' A ', ' B ', ' C ', ' D ', ' E ', ' F ', ' G ', ' H ', ' I ', ' J ', ' K ', ' L ', ' M ', ' N ', ' O ', ' P ', ' Q ', ' R ', ' S ', ' T ', ' U ', ' V ', ' W ', ' X ', ' Y ', ' Z ', ' [ ', ' \ ', ' ] ', ' ^ ', ' _ ', ' ` ', ' a ', ' b ', ' c ', ' d ', ' e ', ' f ', ' g ', ' h ', ' i ', ' j ', ' k ', ' l ', ' m ', ' n ', ' o ', ' p ', ' q ', ' r ', ' s ', ' t ', ' u ', ' v ', ' w ', ' x ', ' y ', ' z ', ' { ', ' | ', ' } ', ' ~ ', DEL );
type SEVERITY_LEVEL is (NOTE, WARNING, ERROR, FAILURE);
-- Predefined numeric types:
type INTEGER is range implementation_defined;
type REAL is range implementation_defined;
- Predefined type TIME:
type TIME is range implementation_defined
units
fs; -- femtosecond
ps = 1000 fs; -- picosecond
ns = 1000 ps; -- nanosecond
us = 1000 ns; -- microsecond
ms = 1000 us; -- microsecond
sec = 1000 ms; -- seconds
min = 60 sees; -- minutes
hr = 60 min; -- hours
end units;
-- Function that returns the current simulation time:
function NOW return TIME;
-- Predefined numeric subtypes:
subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;
subtype POSITIVE is INTEGER range 1 to INTEGER'HIGH;
- Predefined array types:
type STRING is array (POSITIVE range <>) of CHARACTER;
type BIT_VECTOR is array (NATURAL range <>) of BIT;
end STANDARD;

Package TEXTIO contains declarations of types and subprograms that support formatted ASCII I/O operations. A source code listing of the package follows.

package TEXTIO is -- Type definitions for text I/O:
type LINE is access STRING; -- A line is a pointer to a STRING value.
type TEXT is file of STRING; -- A file of variable-length --ASCII records.
type SIDE is (RIGHT, LEFT); -- For justifying output data -- within fields.
subtype WIDTH is NATURAL; -- For specifying widths of output fields.
-- Standard text files:
file INPUT: TEXT is in "STD_INPUT";
file OUTPUT: TEXT is out "STD_OUTPUT":
-- Input routines for standard types:
procedure READLINE (F: in TEXT; L: out LINE);
procedure READ (L: inout LINE; VALUE: out BIT; GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out BIT);
procedure READ (L: inout LINE; VALUE: out BIT_VECTOR;GOOD; out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out BIT_VECTOR);
procedure READ (L; inout LINE; VALUE: out BOOLEAN;GOOD: out BOOLEAN);
procedure READ (L; inout LINE; VALUE: out BOOLEAN):
procedure READ (L: inout LINE; VALUE: out CHARACTER;GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out CHARACTER);
procedure READ (L: inout LINE; VALUE: out INTEGER;GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out INTEGER);
procedure READ (L: inout LINE; VALUE: out REAL;GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out REAL);
procedure READ (L: inout LINE; VALUE: out STRING;GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out STRING);
procedure READ (L: inout LINE; VALUE: out TIME;GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out TIME);
-- Output routines for standard types;
procedure WRITELINE (F: out TEXT; L: in LINE);
procedure WRITE (L: inout LINE; VALUE: in BIT; JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0);
procedure WRITE (L: inout LINE; VALUE: in BIT_VECTOR;
JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0);
procedure WRITE (L: inout LINE; VALUE: in BOOLEAN:
JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0);
procedure WRITE (L: inout LINE; VALUE: in CHARACTER;
JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0);
procedure WRITE (L: inout LINE; VALUE: in INTEGER;
JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0);
procedure WRITE (L: inout LINE; VALUE: in REAL; JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0; DIGITS: in NATURAL := 0);
procedure WRITE (L: inout LINE; VALUE: in STRING;
JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0);
procedure WRITE (L: inout LINE; VALUE: in TIME; JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0; UNIT; in TIME := ns); -- File position predicates:
function ENDLINE (L: in LINE) return BOOLEAN;
-- function ENDFILE (F: in TEXT) return BOOLEAN;

end TEXTIO;

No comments:

Post a Comment