Vous êtes sur la page 1sur 18



Syllabus: Design flow, program structure, History of VHDL, VHDL requirements, Levels of Abstraction,
Elements of VHDL, Concurrent and Sequential Statements, Packages, Libraries and Bindings, Objects and
Classes, Subprograms, Comparison of VHDL and Verilog HDL.

HDL-Based Design Flow

It is very useful to understand the overall HDL design environment before going into the language. There
are several steps in an HDL-based design process, often called the design flow. These steps are applicable to any
HDL-based design process and are outlined in Figure 5-1.

Hierarchy/block diagram:
Front end part begins with figuring out the basic approach and building blocks at the block-diagram level. Large
logic designs, like software programs, are hierarchical, and VHDL gives a good framework for defining modules
and their interfaces and filling in the details later.
This is the actual writing of HDL code for modules, their interfaces, and their internal details. Although we can
use any text editor for coding but the editor included in the HDL‘s tool suite can make the job a little easier. HDL
editor features may include highlighting of keywords, automatic indenting, templates for frequently used program
structures, built-in syntax checking, and one-click access to the compiler.
Once we write some code, we have to compile it. The HDL compiler analyzes our code for syntax errors and also
checks it for compatibility with other modules on which it relies. It also creates the internal information that is
needed for the simulator to process our design later. As in other programming endeavors, we probably shouldn‘t
wait until the very end of coding to compile all of our code. Doing a piece at a time can prevent proliferating
syntax errors, inconsistent names, and so on.
The HDL simulator is useful to define and apply inputs to our design, and to observe its outputs, without
ever having to build the physical circuit. In small circuits, we would probably generate inputs and observe outputs
manually. But for larger projects, HDL tool suites give the ability to create ―test benches‖ that automatically apply
inputs and compare them with expected outputs.
The main action of simulation is verification. It is to verify that the circuit works as desired. Finding
design bugs at this stage has a high value; if bugs are not found until later, all of the so-called ―back-end‖ steps
must typically be repeated.
There are two dimensions for verification: i) Functional & ii) Timing verification
In functional verification, we study the circuit‘s logical operation independent of timing considerations; gate
delays and other timing parameters are considered to be zero.


In timing verification, we study the circuit‘s operation including estimated delays, and we verify that the setup,
hold, and other timing requirements for sequential devices like flip-flops are met.
The nature of and tools for this stage vary depending on the target technology for the design, but there are three
basic steps.
It converts the HDL description into a set of primitives or components that can be assembled in the target
technology. With ASICs (Application specific ICs), it may generate a list of gates and a netlist that specifies how
they should be interconnected. The designer may help the synthesis tool by specifying certain technology-specific
constraints, such as the maximum number of logic levels or the strength of logic buffers to use.
Fitting/place & route:
Here fitter maps the synthesized primitives or components onto available device resources. For a PLD or CPLD,
this may mean assigning equations to available AND –OR elements. For an FPGA or ASIC, it may mean
selecting macrocells or laying down individual gates in a pattern and finding ways to connect them within the
physical constraints of the FPGA or ASIC die; this is called the place-and-route process. The designer can usually
specify the placement of modules within a chip or the pin assignments of external input and output pins.
Timing verification:
At this stage that the actual circuit delays due to wire lengths, electrical loading, and other factors can be
calculated with reasonable precision. It is usual during this step to apply the same test cases that were used in
functional verification, but in this step they run against the circuit as it will actually be built.
We may occasionally take two steps forward and one step back. In Figure 5-1, during coding we may
encounter problems that force to go back and rethink our hierarchy and we will almost certainly have compilation
and simulation errors that are forced to rewrite parts of the code. It might be painful but not uncommon.
The most painful problems are the ones that we encounter in the back end of the design flow is if the
synthesized design doesn‘t fit into an available FPGA or doesn‘t meet timing requirements, we may have to go
back as far as rethinking our whole design approach.

Program Structure
VHDL was designed with principles of structured programming in mind, borrowing ideas from the Pascal
and Ada software programming languages. A key idea is to define the interface of a hardware module while
hiding its internal details. Thus, a VHDL entity is simply a declaration of a module‘s inputs and outputs, while
VHDL architecture is a detailed description of the module‘s internal behavior or structure.
Many designers think that a VHDL ‗entity declaration‘ as a ―wrapper‖ for the architecture, hiding the
details of what‘s inside while providing the hooks for other modules to use it. As shown in fig (b), a Higher-level
architecture may use a lower-level entity multiple times, and multiple top-level architectures may use the same
lower-level one. In the figure, architectures B, E, and F stand alone; they do not use any other entities.



In a VHDL program, the entity declaration and architecture definition are separated, as shown in Figure
5-3. For example, Table 5-13 is a very simple VHDL program for a 2-input gate. In large projects, entities and
architectures are sometimes defined in separate files, which the compiler matches up according to their declared

Like other high-level programming languages, VHDL generally ignores spaces and line breaks, and these
may be provided as desired for readability. Comments begin with two hyphens (--) and end at the end of a line.
VHDL defines many special character strings, called reserved words or keywords. Our example includes—entity,
port, is, in, out, end, architecture, begin, when, else, and not. User-defined identifiers begin with a letter and
contain letters, digits and underscores. Identifiers in the example are Inhibit, X, Y, BIT, Z, and Inhibit_arch.

A basic entity declaration has the syntax shown in Table 5-14. Besides naming the entity, the purpose of
the entity declaration is to define its external interface signals or ports in its port declaration part. In addition to
the keywords- entity, is, port, & end. An entity declaration has the following elements:
entity-name A user-selected identifier to name the entity.
Signal-names A comma-separated list of one or more user-selected identifiers to name external-interface
Mode One of four reserved words, specifying the signal direction:
in The signal is an input to the entity.
Out The signal is an output of the entity. Note that the value of such a signal cannot be ―read‖ inside
the entity‘s architecture, only by other entities that use it.
Buffer The signal is an output of the entity, and its value can also be read inside the entity‘s architecture.
Inout The signal can be used as an input or an output of the entity. This mode is typically used for
three-state input/output pins on PLDs.
Signal-type A built-in or user-defined signal type.
Note that there is no semicolon after the final signal-type\ swapping the closing parenthesis with the semicolon
after it is a common syntax error for beginning VHDL programmers.
The internal operation of entity is specified in its architecture definition, whose general syntax is shown
in Table 5-15. The entity-name in this definition must be the same as the one given previously in the entity
declaration. The architecture-name is a user-selected identifier, usually related to the entity name; it can be the
same as the entity name if desired.
Architecture‘s external interface signals (ports) are inherited from the port-declaration part of its
corresponding entity declaration. Architecture may also include signals and other declarations that are local to that
architecture, similar to other high-level languages. The declarations in Table 5-15 can appear in any order.

History of VHDL
Reason: The requirements for the language were first generated in 1981 under the VHSIC program. In
this program, a number of U.S. companies were involved in designing VHSIC chips for the Department of
Defense (DoD). At that time, most of the companies were using different hardware description languages to
describe and develop their integrated circuits. As a result, different vendors could not effectively exchange
designs with one another. Also, different vendors provided DoD with descriptions of their chips in different
hardware description languages. Reprocurement and reuse was also a big issue. Thus, a need for a standardized
hardware description language for design, documentation, and verification of digital systems was generated.
Development: A team of three companies, IBM, Texas Instruments, and Intermetrics, were first awarded
the contract by the DoD to develop a version of the language in 1983. Version 7.2 of VHDL was developed and
released to the public in 1985. After the release of version 7.2, there was an increasing need to make the language
an industry-wide standard.
Standardization: Consequently, the language was transferred to the IEEE for standardization in 1986.
After a substantial enhancement to the language, made by a team of industry, university, and DoD representatives,
the language was standardized by the IEEE in December 1987; this version of the language is now known as the
IEEE Std 1076-1987. The official language description appears in the IEEE Standard VHDL Language Reference
Manual made available by the IEEE. The language described in this book is based on this standard. The language
has since also been recognized as an American National Standards Institute (ANSI) standard.
The Department of Defense, since September 1988, requires all its digital Application-Specific Integrated
Circuit (ASIC) suppliers to deliver VHDL descriptions of the ASICs and their subcomponents, at both the
behavioral and structural levels. Test benches that are used to validate the ASIC chip at all levels in its hierarchy
must also be delivered in VHDL. This set of government requirements is described in military standard 454.
VHDL Requirements
1. General Features: documentation, high level design, simulation, synthesis, test, automatic hardware.
2. Design Hierarchy: Multilevel description, partitioning.
3. Library Support: Standard packages, cell based design.
4. Sequential Statements: Behavioral software-like constructs.
5. Generic Design: Binding to specific libraries.
6. Type Declaration: strongly typed language.
7. Subprograms.
8. Timing: delay and concurrency.
9. Structural specification: wiring components.
Levels of Abstraction
VHDL can be used to describe electronic hardware at many different levels of abstraction. When
considering the application of VHDL to FPGA/ASIC design, it is helpful to identify and understand the three
levels of abstraction shown below – algorithm, register transfer level (RTL), and gate level. Algorithms are
unsynthesizable, RTL is the input to synthesis, and gate level is the output from synthesis. The difference between
these levels of abstraction can be understood in terms of timing.
Levels of abstraction in the context of their time domain

A pure algorithm consists of a set of instructions that are executed in sequence to perform some task. A pure
algorithm has neither a clock nor detailed delays. Some aspects of timing can be inferred from the partial ordering
of operations within the algorithm. Some synthesis tools (behavioural synthesis) are available that can take
algorithmic VHDL code as input. However, even in the case of such tools, the VHDL input may have to be
constrained in some artificial way, perhaps through the presence of an ‗algorithm‘ clock – operations in the
VHDL code can then be synchronized to this clock.
An RTL description has an explicit clock. All operations are scheduled to occur in specific clock cycles, but there
are no detailed delays below the cycle level. Commercially available synthesis tools do allow some freedom in
this respect. A single global clock is not required but may be preferred. In addition, retiming is a feature that
allows operations to be re-scheduled across clock cycles, though not to the degree permitted in behavioural
synthesis tools.
A gate level description consists of a network of gates and registers instanced from a technology library, which
contains technology-specific delay information for each gate. Transistors are grouped together into gates.
Voltages are discrete values such as 0 and 1.
Basic VHDL Elements
1. Identifiers
2. DataObjects
3. DataTypes
i. Subtypes
ii. Scalar Types
iii. Composite Types
iv. Access Types
v. Incomplete Types
vi. File Types
4. Operators
i. Logical Operators
ii. Relational Operators
iii. Adding Operators
iv. Multiplying Operators
v. Miscellaneous Operators


1. Identifiers
An identifier in VHDL is composed of a sequence of one or more characters. A legal character is an
upper-case letter (A... Z), or a lower-case letter (a. .. z), or a digit (0 . . . 9) or the underscore ( _ ) character. The
first character in an identifier must be a letter and the last character may not be an underscore. Lower-case and
upper-case letters are considered to be identical when used in an identifier; as an example. Count, COUNT, and
CouNT, all refer to the same identifier. Also,-two underscore characters cannot appear consecutively.
Ex: DRIVE_BUS, SelectSignal, SET_CK_HIGH, CONST32_59, r2d2
Comments in a description must be preceded by two consecutive hyphens (--); the comment extends to
the end of the line. Comments can appear anywhere within a description.
1) -- This is a comment, it ends at the end of this line.
2) Entity UART is end; --This comment starts after the entity declaration.
2. Data Objects
A data object is an identifier that holds a value of a specified type. It is created by means of an object
declaration. An example is
variable COUNT: INTEGER;
This results in the creation of a data object called COUNT which can hold integer values. The object COUNT is
also declared to be of variable class.
Every data object belongs to one of the following three classes:
1. Constant: An object of constant class can hold a single value of a given type. This value is assigned to the object
before simulation starts and the value cannot be changed during the course of the simulation.
2. Variable: An object of variable class can also hold a single value of a given type. However in this case, different
values can be assigned to the object at different times using a variable assignment statement.
3. Signal: An object belonging to the signal class has a past history of values, a current value, and a set of future
values. Future values can be assigned to a signal object using a signal assignment statement.
Signal objects can be regarded as wires in a circuit while variable and constant objects are analogous to
their counterparts.
An object declaration is used to declare an object, its type, and its class, and optionally assign it a value. Some
examples of object declarations of various types and classes follow.
Constant Declarations:
Example of constant declaration is
constant RISE_TIME: TIME := 10ns;
The declaration declares the object RISE_TIME that can hold a value of type TIME (a predefined type in the
language) and the value assigned to the object at the start of simulation is 10 ns.
Variable Declarations:
Examples of variable declarations are
variable CTRL_STATUS: BIT_VECTOR(10 downto 0);
The first declaration specifies a variable object CTRL_STATUS as an array of 11 elements, with each array
element of type BIT. The initial value for all the array elements of CTRL_STATUS is ‗0‘. In the third declaration,
the initial values assigned to FOUND and DONE at start of simulation is FALSE (FALSE is the leftmost value of
the predefined type, BOOLEAN).
Signal Declarations:
Here are some examples of signal declarations.
Signal CLOCK: BIT;
signal GATE_DELAY: TIME := 10 ns;
The interpretation for these signal declarations is very similar to that of the variable declarations. The first signal
declaration declares the signal object CLOCK of type BIT and gives it an initial value of ‗0‘ (‗0‘ being the
leftmost value of type BIT). The second signal declaration declares a signal object GATE_DELAY of type TIME
that has an initial value of 10 ns.
3. Data Types


Every data object in VHDL can hold a value that belongs to a set of values. This set of values is specified by
using a type declaration. For example, INTEGER is a predefined type with the set of values being integers in a
specific range provided by the VHDL.
The possible types exist in the language are categorized into the following major categories:
a) Subtype:
A subtype is a type with a constraint. The constraint specifies the subset of values for the type. The type is
called the base type of the subtype. An object is said to belong to a subtype if it is of the base type and if it
satisfies the constraint.
Examples of subtypes are:

In the first example, MYINTEGER is a subtype of the INTEGER base type and has a range constraint with
values ranging from 48 through 156. DIGIT is a user-defined enumeration type. The last subtype declaration
declares a new subtype called MIDDLE whose base type is DIGIT and has the values‘3‘, ‗4‘, ‗5‘, ‗6‘ and‘7‘.
b) Scalar Types:
The values belonging to this type are ordered, that is, relational operators can be used on these values. For
example, BIT is a scalar type and the expression ‗0‘< ‗1‘ is valid and has Hie value TRUE. There are four
different kinds of scalar types. These types are
1. enumeration,
2. integer,
3. floating point
4. physical,
Integer types, floating point types, and physical types are classified as numeric types since the values associated
with these types are numeric. Further, enumeration and integer types are called discrete types since these types
have discrete values associated with them.
i. Enumeration Types:
An enumeration type declaration defines a type that has a set of user-defined values consisting of
identifiers and character literals. Examples are
type MVL is (‗U‘,‘0‘,‘1‘,‘Z);
MVL is an enumeration type that has the set of ordered values, ‗U‘,‘0‘,‘1‘, and ‗Z‘. When using relational
operators, a value is always less than a value that appears to its right in the order. For instance, in the MICRO_OP
type declaration, STORE < DIV is true, and SUB > MUL is false. Values of an enumeration type also have a
position number associated with them. The position number of the left most element is 0. The position number of
any particular element is one more than the position number of the element to its left.
ii. Integer Types:
An integer type defines a type whose set of values fall within a specified integer range. The minimum
range that must be provided is –(231 – 1) through +(231 – 1). Examples of integer type declarations are
type INDEX is range 0 to15;
type WORD_LENGTH is range 31 downto 0;
constant MUX_ADDRESS: INDEX:= 5;
INDEX is an integer type that includes the integer values from 0 through 15.
iii. Floating Point Types
A floating point type has a set of values in a given range of real numbers. Examples of floating point
type declarations are
type TTL_VOLTAGE is range -5.5 to -1.4;
type REAL_DATA is range 0.0 to 31.9;
iv. Physical Types
A physical type contains values that represent measurement of some physical quantity, like time,
length, voltage, and current. Values of this type are expressed as integer multiples of a base unit. An example
of a physical type declaration is



type CURRENT is range 0 to 1E9

nA; -- (base unit) nano-ampere
uA =1000 nA; -- micro-ampere
mA =1000 µA; --milli-ampere
Amp =1000 mA; -- ampere
end units;
subtype FILTER_CURRENT is CURRENT range 10 µA to 5 mA;

CURRENT is defined to be a physical type that contains values from 0 nA to 10^9 nA. The base unit is a nano-
ampere while all others are derived units. The position number of a value is the number of base units represented
by that value. For example, 2 µA has a position of 2000 while 100 nA has a position of 100.
c) Composite Type:
A composite type represents a collection of values. There are two composite types: an array type and a record
type. An array type represents a collection of values all belonging to a single type; on the other hand, a record
type represents a collection of values that may belong to same or different types.
i. Array Types
An object of an array type consists of elements that have the same type. Examples of array type
declarations are:

ii. Record Types:

An object of a record type is composed of elements of same or different types. It is analogous to the record
data type in Pascal and the struct declaration in C. An example of a record type declaration is

d) Access Types:
Values belonging to an access type are pointers to a dynamically allocated object of some other type. They are
similar to pointers in Pascal and C languages. Examples of access type declarations are:
--- MODULE is a record type declared in the previous sub-section.
type PTR is access MODULE;
type FIFO is array (0 to 63) of BIT;
type FIFO_PTR is access FIFO;
PTR is an access type whose values are addresses that point to objects of type MODULE. Every access type
may also have the value null, which means that it does not point to any object but the address.
e) Incomplete Types:
It is possible to have an access type that points to an object that has elements which are also access types. This
can lead to mutually dependent or recursive access types. Since a type must be declared before it is used, an
incomplete type declaration can be used to solve this problem. An incomplete type declaration has the form:
type type-name;
Once an incomplete type has been declared, the type-name can now be used in any mutually dependent or
recursive access type. However, a corresponding full type declaration must follow later. An example of a
mutually dependent access type is:



Here, COMP and NET have elements which access objects of type NET and COMP, respectively.
f) File Types:
Objects of file types represent files in the host environment. They provide a mechanism by which a VHDL
design communicates with the host environment. The syntax of a file type declaration is

type file-type-name is file of type-name,

The type-name is the type of values contained in the file. Here are two examples.

type VECTORS is file of BIT_VECTOR;

type NAMES is file of STRING;

A file of type VECTORS has a sequence of values of type BIT_VECTOR; a file of type NAMES has a sequence
of strings as values in it. A file is declared using a file declaration. The syntax of a file declaration is:

file file-name: file-type-name is mode string-expression;

The string-expression is interpreted by the host environment as the physical name of the file. The mode of a file,
in or out, specifies whether it is an input or an output file, respectively. Input files can only be read while output
files can only be written to.
Here are two examples of declaring files.
file VEC_FILE: VECTORS is in‖/usr/home/jb/uart/div.vec‖;
file OUTPUT: NAMES is out ―stdout‖;
VEC_FILE is declared to be a file that contains a sequence of bit vectors and it is an input file. It is associated
with the file ―/usr/home/jb/uart/div.vec‖ in the host environment, similarly the output.
4. Operators
The predefined operators in the language are classified into the following five categories:
1. Logical operators
2. Relational operators
3. Adding operators
4. Multiplying operators
5. Miscellaneous operators
a. Logical Operators:
The six logical operators are
And or nand nor xor not
These operators are defined for the predefined types BIT and BOOLEAN. They are also defined for one-
dimensional arrays of BIT and BOOLEAN. During evaluation, bit values ‗0‘ and ‗1‘ are treated as FALSE and
TRUE values of the BOOLEAN type, respectively. The result of a logical operation has the same type as its
operands. The not operator is a unaiy logical operator and
has the same precedence as that of miscellaneous operators.
b. Relational Operators:
These are
= /= < <= > >=
The result types for all relational operations are always BOOLEAN. The = (equality) and the /= (inequality)
operators are permitted on any type except file types. The remaining four relational operators are permitted on any
scalar type (e.g., integer or enumerated types) or discrete array type (i.e., arrays in which element values belong to
a discrete type). When operands are discrete array types, comparison is performed one element at a time from left
to right. For example,
BIT_VECTOR‘(‗0‘, ‗1‘, ‗1‘) < BIT_VECTOR‘(‗1‘, ‗0‘, ‗1‘)
is true, since the first element in the first array aggregate is less than the first element in the second aggregate.
Similarly, if
type MVL is (‗U‘, ‗0‘, ‗1‘, ‗Z‘ );
MVL‘( ‗U‘ ) < MVL‘( ‗Z‘ ) is true since ‗U‘ occurs to the left of ‗Z‘.
c. Adding Operators:
These are
+ - &
The operands for the + (addition) and – (subtraction) operators must be of the same numeric type with the result
being of the same numeric type. The addition and subtraction operators may also be used as unary operators, in
which case, the operand and the result type must be the same. The operands for the & (concatenation) operator
can be either a I-dimensional array type or an element type. The result is always an array type. For example,
„0‟ & „1‟
results in an array of characters ―01‖.
„C‟ & „A‟ & „T‟
results in the value ―CAT‖.
“BA” & “LL”
creates an array of characters ―BALL‖.
d. Multiplying Operators:
These are
* / mod rem
The * (multiplication) and / (division) operators are predefined for both operands being of the same integer or
floating point type. The result is also of the same type.
The rem (remainder) and mod (modulus) operators operate on operands of integer types and the result is also of
the same type. The result of a rem operation has the sign of its first operand and is defined as
A rem B = A – (A / B) * B
The result of a mod operator has the sign of the second operand and is defined as
A mod B = A – B * N -For some integer N.
f. Miscellaneous Operators:
The miscellaneous operators are
Abs **
The abs (absolute) operator is defined for any numeric type.
The ** (exponentiation) operator is defined for the left operand to be of integer or floating point type and
the right operand (i.e., the exponent) to be of integer type only.


Concurrent and Sequential Statements
1. Concurrent: The statements which execute in parallel are called ―Concurrent Statements‖.
Architecture architecture-name of entity-name is
[ architecture-item-declarations ]
concurrent-statements; these are —>
end [ architecture-name ] ;
The concurrent statements describe the internal composition of the entity. All concurrent statements
execute in parallel, and therefore, their textual order of appearance within the architecture body has no impact on
the implied behavior. The internal composition of an entity can be expressed in terms of structure, dataflow and
sequential behavior. These are described using concurrent statements. For example, component instantiations are
used to express structure, concurrent signal assignment statements are used to express dataflow and process
statements are used to express sequential behavior. Each concurrent statement is a different element operating in
parallel in a similar sense that individual gates of a design are operating in parallel.

Architecture AOI_CONCURRENT of AOI is

Z <= not ( (A and B) or (C and D) );

The architecture body, AOI_CONCURRENT, describes the AOI entity using the dataflow style of modeling.
2. Sequential: The statements which execute in sequential fashion are called ―Sequential statements‖.
[ process-label: ] process [ ( sensitivity-list ) ]
sequential-statements; these are ->
End process [ process-label];
Concurrent Vs Sequential:
Concurrent statements are within the architecture whereas the sequential circuits are within the process.
Modelling Style Concurrent Sequential
Location Inside architecture Inside process
Example statement Process, component instance, If, for, switch-case, signal
concurrent signal assignment assignment



Fig: Concurrent Vs Sequential Statements.

Libraries and Packages

A VHDL library is a place where the VHDL compiler stores information about a particular design
project, including intermediate files used in the analysis, simulation, and synthesis of the design. The location
of the library within a host computer‘s file system is implementation dependent. For a given VHDL design, the
compiler automatically creates and uses a library named ―work‖.
A complete VHDL design usually has multiple files, each containing different design units including
entities and architectures. When the VHDL compiler analyzes each file in the design, it places the results
in the ―work‖ library, and it also searches this library for needed definitions, such as other entities.
Because of this feature, a large design can be broken up into multiple files, yet the compiler will find external
references as needed.
Not all of the information needed in a design may be in the ―work‖ library. For example, a designer may
rely on common definitions or functional modules across a family of different projects. Each project has its own
―work‖ library (typically a subdirectory within that project‘s overall directory), but it must also refer to a common
library containing the shared definitions. Even small projects may use a standard library such as the one
containing IEEE standard definitions. The designer can specify the name of such a library using a library clause at
the beginning of the design file. For example, we can specify the IEEE library:
library ieee;
The clause ―library work;‖ is included implicitly at the beginning of every VHDL design file.
Specifying a library name in a design gives it access to any previously analyzed entities and
architectures stored in the library, but it does not give access to type definitions and the like.
A VHDL package is a file containing definitions of objects that can be used in other programs. The kind
of objects that can be put into a package include signal, type, constant, function, procedure, and component
declarations. Signals that are defined in a package are ―global‖ signals, available to any VHDL entity that uses the
package. Types and constants defined in a package are known in any file that uses the package. Likewise,
functions and procedures defined in a package can be called in files that use the package, and components
(described in the next subsection) can be instantiated in architectures that use the package.
A design can ―use‖ a package by including a use clause at the beginning of the design file. For example, to use
all of the definitions in the IEEE standard 1164 package, we would write
use ieee.std_logic_1164.all;
Here, ―ieee‖ is the name of a library which has been previously given in a library clause. Within this
library, the file named ―std _ logic_1164‖ contains the desired definitions. The suffix ―all‖ tells the compiler
to use all of the definitions in this file. Instead of ―all‖, you can write the name of a particular object to use just
its definition, for example,
use ieee .std_logic_1164.std_ulogic


This clause would make available just the definition of the std _ ulogic type in the table below, without all of the
related types and functions. However, multiple ―use‖ clauses can be written to use additional definitions.

Table1: Definition of VHDL std logic type

Defining packages is not limited to standards bodies. Anyone can write a package, using the syntax
shown in Table below.

Table2: Syntax of a VHDL package definition

All of the objects declared between ―package‖ and the first ―end‖ statement are visible in any design file
that uses the package; objects following the ―package body‖ keyword are local.
Objects and Classes
(For these topics please refer the topic ―Elements of VHDL‖).
Attaching the subprogram into the main program is called Binding. The top-level entity is
organized in terms of lower level entities by specifying the bindings between the entities. The language provides
two ways of performing this binding:
1. by using a configuration specification,
2. by using a configuration declaration.
1. Configuration Specification
A configuration specification is used to bind component instantiations to specific entities that are stored in design
libraries. The specification appears in the declarations part of the architecture or block in which the components
are instantiated. Binding of a component to an entity can be done on a per instance basis, or for all instantiations


of a component, or for a selected set of instantiations of a component. Instantiations of different components can
also be bound to the same entity.
Figure below shows a logic diagram for a 1-bit full-adder. Its structural model is described next.
entity FULL_ADDER is
port (A, B, CIN: in BIT; SUM, COUT: out BIT);
architecture FA_STR of FULL_ADDER is
component XOR2
port (A, B: in BIT; C: out BIT);
end component;

component AND2
port (Z: out BIT; AO, A1: in BIT);
end component;

component OR2
port (A, B: in BIT; C: out BIT);
end component;
-- The following four statements are configuration specifications:
for X1, X2: XOR2
use entity WORK.XOR2(XOR2BEH); -- Binding the entity with more than one
instantiation of a component.
For A3: AND2
use entity HS_LIBAND2HS(AND2STR)
port map (HS_B=>A1, HS_Z=>Z, HS_A=>A0); --Binding the entity with a
single instantiation of a component.
For all: OR2
use entity CMOS_LIB.OR2CMOS(OR2STR); - Binding the
-- entity with all instantiations of OR2 component.
For others: AND2
port map (A0, A1, Z);-Binding the entity with all unbound
-- instantiations of AND2 component.
Signal S1, S2, S3, S4, S5: BIT;
X1: XOR2 port map (A, B, S1);
X2: XOR2 port map (S1, CIN, SUM);
A1: AND2 port map (S2, A, B);
A2: AND2 port map (S3, B, CIN);
A3: AND2 port map (S4, A, CIN);
O1: OR2 port map (S2, S3, S5):
O2: OR2 port map (S4, S5, COUT);
end FA_STR;

Figure: A 1 –bit full-adder circuit


The four for statements appearing in the declarative part of the architecture body are the configuration
specifications. The first specification statement indicates that instances XI and X2 of component XOR2 are bound
to the entity represented by the entity-architecture pair, XOR2 and XOR2BEH, respectively, that resides in library
WORK. Similarly the remaining statements.
2. Configuration Declaration
Configuration specifications have to appear in an architecture body. Therefore, to change a binding, it is necessary
to change the architecture body and re-analyze it. This may sometimes be cumbersome and time consuming. To
avoid this, a configuration declaration may be used to specify a binding.
A configuration declaration is a separate design unit, therefore, it allows for late binding of components,
that is, the binding can be performed after the architecture body has been written.
The typical format of a configuration declaration is
configuration configuration-name of entity-name is
end [ configuration-name ];
It declares a configuration with the name, configuration-name, for the entity, entity-name. A block-configuration
defines the binding of components in a block, where a block may be an architecture body, a block statement, or a
generate statement. A block configuration is a recursive structure of the form
for block-name
end for;
The block-name is the name of an architecture body, a block statement label, or a generate statement label. The
top-level block is always an architecture body. A component-configuration binds components that appear in a
block to entities and is of the form
for list-of-comp-labels: comp-name [ use binding-indication; ]
[ block-configuration ]
end for;
The block configuration that appears within a component configuration defines the bindings of components at the
next level of hierarchy in the entity-architecture pair specified by the binding indication.
Here is an example of a configuration declaration that specifies the component configurations for all component
instances in architecture FA_STR of entity FULL_ADDER described in the previous section.
Library CMOS_UB;
configuration FA_CON of FULL_ADDER is
for FA_STR
use WORK.all;
for A1,A2,A3:AND2
use entity CMOS_LIB.BIGAND2 (AND2STR);
end for;
for others: OR2 --use defaults, i.e. use OR2 from
-- library WORK.
End for ;
for all: XOR2
use configuration WORK.X6R2CON;
end for;
end for;
end FA_CON;
The configuration with name, FA_CON, binds architecture FA_STR with the FULL_ADDER entity. For
components within this architecture body, instances Al, A2, and A3, are bound to the entity, BIGAND2, that
exists in the design library, CMOS_LIB. For all instances of component OR2, the default bindings are used. The
last component configuration shows a different type of binding indication. In this case, all component instances
are bound to a configuration instead of an entity-architecture pair. All instances of component XOR2 are bound to
a configuration with name XOR2CON, that exists in the working library.


A subprogram defines a sequential algorithm that performs a certain computation and executes in zero
simulation time. There are two kinds of subprograms:
1. Functions: These are usually used for computing a single value.
2. Procedures: These are used to partition large behavioral descriptions. Procedures can return zero or more
A subprogram is defined using a subprogram body. The typical format for a subprogram body is

The subprogram-specification specifies the name of a subprogram and defines its interface, that is, it defines the
formal parameter names, their class (i.e., signal, variable, or constant), their type, and their mode (whether they
are in, out, or inout). Parameters of mode in are read-only parameters; these cannot be updated within a
subprogram body. Parameters of mode out are write-only parameters; their values cannot be used but can only be
updated within a subprogram body. Parameters of mode inout can be read as well as updated.
1. Functions
Functions are used to describe frequently used sequential algorithms that return a single value. This value is
returned to the calling program using a return statement. Some of their common uses are as resolution functions,
and as type conversion functions. The following is an example of a function body.

Variable RETURN_VALUE comes into existence with an initial value of 0.0 every time the function is
called. It ceases to exist after the function returns back to the calling program.
The general syntax of a subprogram specification for a function body is
function function-name (parameter-list) return return-type
The parameter-list describes the list of formal parameters for the function. The only mode allowed for the
parameters is mode in. Also, only constants and signal objects can be passed in as parameters. The default object
class is constant For example, in function LARGEST, TOTAL_NO is a constant and its value cannot be modified
within the function body. Another example of a function body is shown next. This function returns true if a rising
edge has been detected on the input signal.

Function VRISE (signal CLOCK_NAME: BIT) return BOOLEAN is

return (CLOCK_NAME =‘1‘) and CLOCK_NAME‘EVENT;
end VRISE;

A function call is an expression and can, therefore, be used in expressions. For example,



A function call has the form

function-name( list-of-actual-values )

The actual values maybe associated by position (the first actual value corresponds to the first formal parameter,
the second actual value corresponds to the second parameter, and so on) or they may be associated using named
association (the association of actual values and formal parameters are explicitly specified). The function call in
the last example used positional association. An equivalent function call using named association is


2. Procedures
Procedures allow decomposition of large behaviors into modular sections. In contrast to a function, a
procedure can return zero or more values using parameters of mode out and inout. The syntax for the subprogram
specification for a procedure body is
procedure procedure-name( parameter-list )
The parameter-list specifies the list of formal parameters for the procedure. Parameters may be constants,
variables, or signals and their modes maybe in, out, or inout. If the object class of a parameter is not explicitly
specified, then the object class is by default a constant if the parameter is of mode in, else it is a variable if the
parameter is of mode out or inout.
A simple example of a procedure body is shown next. It describes the behavior of an arithmetic logic unit.

VHDL Vs Verilog
1. Verilog is based on C, while VHDL is based on Pascal and Ada-

Verilog and VHDL are Hardware Description languages that are used to write programs for electronic
chips. These languages are used in electronic devices that do not share a computer‘s basic architecture. VHDL is
the older, and is based on Ada and Pascal, thus inheriting characteristics from both languages. Verilog is
relatively recent, and follows the coding methods of the C programming language.

2. Unlike Verilog, VHDL is strongly typed-

VHDL is a strongly typed language, and scripts that are not strongly typed, are unable to compile. A
strongly typed language like VHDL does not allow the intermixing, or operation of variables, with different
classes. Verilog uses weak typing, which is the opposite of a strongly typed language.

3. Ulike VHDL, Verilog is case sensitive-

Verilog is case sensitive, and would not recognize a variable if the case used is not consistent with what it
was previously. On the other hand, VHDL is not case sensitive, and users can freely change the case, as long as
the characters in the name, and the order, stay the same.
4. Verilog is easier to learn compared to VHDL-

In general, Verilog is easier to learn than VHDL. This is due, in part, to the popularity of the C
programming language, making most programmers familiar with the conventions that are used in Verilog. VHDL
is a little bit more difficult to learn and program.

5. Verilog has very simple data types, while VHDL allows users to create more complex data types-

VHDL has the advantage of having a lot more constructs that aid in high-level modeling and it reflects the
actual operation of the device being programmed. Complex data types and packages are very desirable when
programming big and complex systems, that might have a lot of functional parts. Verilog has no concept of
packages, and all programming must be done with the simple data types that are provided by the programmer.

6. Verilog lacks the library management, like that of VHDL-

Verilog lacks the library management of software programming languages. This means that Verilog will
not allow programmers to put needed modules in separate files that are called during compilation. Large projects
on Verilog might end up in a large, and difficult to trace, file.

** All the best **

1. Digital Design Principles & Practices – John F. Wakerly, PHI/ Pearson Education Asia,
3rd Edition, 2005.
2. VHDL Primer – J. Bhasker, Pearson Education/ PHI, 3rd Edition.
3. From Internet.

-K. P. Prasannakumar
Asst. Professor
ECE Department
Contact No: 9014797201