0% found this document useful (0 votes)
26 views

Study of Advanced VHDL Features

This document is a project report presented in partial fulfillment of the requirements for a 'LICENCE' degree in Electrical and Electronic Engineering. The report provides an introduction to VHDL, covering fundamentals such as design units, data types, design styles, and statements. It then discusses advanced VHDL features like packages, subprograms, and testbenches. Finally, the report applies these concepts by designing and simulating a single port RAM using ModelSim SE. The overall document serves as both a tutorial on VHDL and a demonstration of skills gained through a direct application of the language.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views

Study of Advanced VHDL Features

This document is a project report presented in partial fulfillment of the requirements for a 'LICENCE' degree in Electrical and Electronic Engineering. The report provides an introduction to VHDL, covering fundamentals such as design units, data types, design styles, and statements. It then discusses advanced VHDL features like packages, subprograms, and testbenches. Finally, the report applies these concepts by designing and simulating a single port RAM using ModelSim SE. The overall document serves as both a tutorial on VHDL and a demonstration of skills gained through a direct application of the language.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 46

People’s Democratic Republic of Algeria

Ministry of Higher Education and Scientific Research


University M’Hamed BOUGARA - Boumerdes

Institute of Electrical and Electronic Engineering


Department of Electronics

Project Report Presented in Partial Fulfillment of the


Requirements of the Degree of:
‘LICENCE’

In Electrical and Electronic Engineering

Title:

Study of Advanced VHDL Features

Presented By:

Supervisor:
Dr A. BENZEKRI

Registration Number:......./2021
Acknowledgements
Praise be to Allah for guiding us on our educational path and helping us to complete this
project.

Our sincere gratitude and appreciation go to:


Our friends and family, who have helped us create an inspiring environment during these difficult
times.
Dr A. BENZEKRI, who taught us the fundamentals of digital electronics, piqued our interest in the
subject and encouraged us to keep learning. We would like to offer our highest appreciation and
gratitude to him as our supervisor during this project for his direction, assistance, and orientation.
We would want to also thank our friend AZZAZ Aissa for the tremendous assistance and support
with this report.
We would also like to express our gratitude to the teaching faculty for their assistance in making
this initiative a success.

i
Abstract
VHDL is a comprehensive language for digital system design and documentation, with degrees
of abstraction ranging from system to gate. This report begins with a brief history of the language
and its intended use. The fundamentals of VHDL are next covered, followed by some of its more
advanced features, such as packages and subprograms, as well as the testbench. Finally, as a
direct application of what we have learnt, a single port RAM will be designed and simulated using
ModelSim SE.

ii
Contents

Acknowledgements i

Abstract ii
Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii

Introduction 1

1 VHDL Fundamentals 2
1.1 Design Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1 Entity Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.3 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.4 Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Data Types and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.1 Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.2 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3 Design Styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.1 DataFlow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.2 Behavioral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.3 Structural . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4 VHDL Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.4.1 Concurrent statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.4.2 Sequential statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2 Advanced Features of VHDL 29


2.1 Packages and Subprograms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.1.1 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.1.2 Subprograms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.2 Testbenches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3 Application 36
3.1 Tools and Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

iii
3.2 Design Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.3 Simulation and Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

iv
Introduction
VHDL is one of the most widely used hardware description languages. The acronym "VHDL"
stands for "VHSIC Hardware Description Language"; "VHSIC" in turn stands for "Very-High Speed
Integrated Circuits." The VHSIC is an industry standard language used to describe hardware from
the abstract to the concrete level.
VHDL arose out the VHSIC program that was an initiative within the United States Department of
Defense in the late 1970’s and early 1980’s. These facts imply that VHDL has some connection with
the US DoD. Although historically true, today VHDL is owned, standardized by, and administered
through the Institute of Electrical and Electronics Engineers (IEEE), an international professional
organization.
The development of VHDL was initiated in 1981. Hardware description languages (HDLs)
were a topic of much research at that time. These languages showed promise for expressing
hardware systems at varying levels of abstraction. However, none were commonly accepted, all
suffered from limited abstraction capabilities and their accommodation of varying design styles.
Furthermore, all tended to be technology-specific. The requirement was for a language with a
wide range of descriptive capability that would work the same on any simulator and independent
of technology or design methodology.Thus, the VHSIC Program Office began a project to develop
a VHSIC-standard hardware description language that could be used to communicate systems
specifications and designs among the DoD contractors. Hence the VHSIC Hardware Description
Language (VHDL) was developed. It was subsequently developed further under the auspices of
the IEEE and adopted in the form of the IEEE Standard 1076, Standard VHDL Language Reference
Manual, in 1987. This first standard version of the language is often referred to as VHDL-87. Like
all IEEE standards, the VHDL standard is subject to review from time to time.
Comments and suggestions from users of the 1987 standard were analyzed by the IEEE working
group responsible for VHDL, and in 1992 a revised version of the standard was proposed. This
was eventually adopted in 1993, giving us VHDL-93, used in this project report. A second round of
revision of the standard was started in 1998. That process was completed in 2001, giving us VHDL-
2002. After that, further development took place in the IEEE working group and in a technical
committee of an organization, Accellera, whose charter is to promote standards for electronics
design. These efforts led to the current version of the language, VHDL-2008.
VHDL is designed to fill a number of needs in the design process. First, it allows description of the
structure of a system, that is, how it is decomposed into subsystems and how those subsystems
are interconnected. Second, it allows the specification of the function of a system using familiar
programming language forms.Third, as a result, it allows the design of a system to be simulated
before being manufactured, so that designers can quickly compare alternatives and test for
correctness without the delay and expense of hardware prototyping. Fourth, it allows the detailed
structure of a design to be synthesized from a more abstract specification, allowing designers to
concentrate on more strategic design decisions and reducing time to market.

1
Chapter 1

VHDL Fundamentals
1.1 Design Units
Design units are the fundamental building blocks in a VHDL program. When a program is pro-
cessed, it is broken into individual design units and each unit is analyzed and stored independently
[1] [2]. There are five kinds of design units:
• Entity declaration

• Architecture body

• Configuration

• Library

• Package declaration

• package body
For the package declaration and package body they are covered in Chapter 2, Section 1. In this
chapter we will focus mainly on the first four units.

1.1.1 Entity Declaration

--=========================================================
ENTITY syntax
--=========================================================
Entity <entity name> is :
generic (generic list); ----- Entity Header
port (port list); -----

subprogram_declaration
type_declaration -----
subtype_declaration ----- Entity declarative part
constant_declaration -----
.
.
.
begin
concurrent_assertion_statement -----
passive_process_statement ----- Entity statement part
passive_concurrent_procedure_call -----
end [ entity ] [ entity_name ]

Listing 1.1: Simple Syntax of Entity

3
Entity Declaration
An entity declaration describes the interface of a design entity through which it communicates
with other design entities in the same environment. It is structured in three main parts: entity
header, entity declarative part, entity statement part. However, an entity can be empty as in the
case of the top-level entity in a simulatable VHDL and its architecture is usually the testbench
(reference it to Chapter 2, Section 3). In addition, an entity can have multiple architectures that
link to the same entity, for a VHDL program to run it has to have at least an entity-architecture
pair.[3]

Entity Header
The entity header consists mainly of a port declaration and a generic declaration.

Port Declaration
Involves the port_name,mode and data_type terms. Ports are essentially signals that provide a
dynamic communication between a block and its environments.
The mode term indicates the direction of the signal, which can be in, out, inout or a Buffer. The in
and out keywords indicate that the signal flows “into” and “out of” the circuit respectively. Inout
indicates that this port is a bidirectional port and buffer is employed when a signal is sent out but
it must also be used internally.
The type can be bit, integer, std_logic...etc. The various data types will be discussed in the Data
types Chapter 1, Section 2 [3] .

[PORT (
Port_name: mode signal_type;
...);]

Listing 1.2: Syntax of a Port Declaration

Generic Declaration
Allows the specification of generic parameters that is generic constants.
Generics are a general mechanism used to pass information to an instance of an entity. The
information passed to the entity can be of most types allowed in VHDL. They are used for design
re-usability.

GENERIC (constant_name: constant_type := constant_value;


constant_name: constant_type := constant_value;
... );

Listing 1.3: Syntax of Generic Declaration

4
Entity Declarative Part
The entity declarative part of a given entity declaration which is optional, declares items that are
shared to all design entities whose interfaces are defined by the given entity declaration, and these
include type declaration,subtype declaration,constant declaration,subprogram declaration,signal
declaration [3]...

Entity Statement Part


Optional statements section, also rarely used, can contain passive calls and/or passive processes.

1.1.2 Architecture
The architecture describes the underlying functionality of the entity and contains the state-
ments that model the behavior of the entity. An architecture is always related to an entity. But an
entity can have several architectures associated with it. The architecture is structured in two main
part: declarative part and a statement part.

Architecture identifier of entity_name is


architecture_declarative_part
begin
architecture_statement_part
end [ architecture ] [ architecture_simple_name ] ;

Listing 1.4: Syntax of an Architecture


Architecture Declarative Part
Includes local identifiers that are used inside the specific architecture that are not ports or generics.
These can be signals,constants,components declarations,type declarations...etc.

Architecture Statement Part


Contains executable lines of code within the design like Process statements, concurrent procedu-
ral calls, concurrent signal assingements, components instantiation statements...etc.

5
1.1.3 Configuration
Configuration provides an architecture-entity bindings. Since entities can have multiple
architectures associated with them, the configuration gives a unique name to a single architecture-
entity paring.
Configuration can be defined as the process of binding a component with a design entity and
architecture. When a component is declared and instantiated,the configuration will bound it with
a design entity and architecture.
There are two ways to specify the configuration. It can be described in an independent design
unit, which is known as configuration declaration, or included in the declaration section of the
architecture body, which is known as configuration specification[4].

1.1.3.1 Configuration Declaration

In the configuration declaration method, we create a new explicit design unit to specify the
bindings of components. Configuration unit is an independent design unit, just like an entity
declaration and an architecture body [3].

configuration <identifier> of <entity_name is


For <architecture_name>
for <instance_name>:<component_name> use <entity>(<architecture>)
End for;
for <instance_name>:<component_name> use <entity>(<architecture>)
End for;
End for;
End configuration <identifier>;

Listing 1.5: Configuration Syntax

Default Configuration

The simplest form of explicit configuration is the default configuration. This configuration can be
used for models that do not contain any blocks or components to configure.

The default configuration specifies the configuration name, the entity being configured,and
the architecture to be used for the entity. It is a direct entity-architecture binding. It starts with
the word configuration followed by a chosen name for this configuration setup; then, the name of
the entity to which the architecture will be bound.

6
In the second line, the keyword FOR determines the name of the architecture to be bound. The
configuration code must be located outside any entities or architectures [5].

configuration config_name of entity_name is


for arch_name
end for;
end [configuration] [config_name];

Listing 1.6: Syntax of a Direct Configuration Binding

1.1.3.2 Configuration Specification

The configuration declaration is general and flexible. However, for a simple design, creating
a new design unit for this purpose is somewhat cumbersome. An alternative is to specify the
relevant configuration in the declaration section of the architecture body. This is known as a
configuration specification [3] .

for instance_name:component name


use entity lib_name.b_entity name(bound_arch);
for instance_name:component name
use entity lib_name.b_entity name(bound_arch);

Listing 1.7: Syntax of a Configuration Specification

1.1.4 Library
A VHDL library is the virtual repository that stores the analyzed design units. For a complex
design, there may exist a large number of design units. It is desirable to organize these units and
store them in separate places in which we may have a collection of commonly used design units
that are shared by many different designs. It is more effective to save these units in a common
library rather than duplicating them in every design directory [4] [2].
To access the content of a library, we must first make it known by using a library statement. The
syntax is :

library lib-name , lib-name , . . . , lib-name ;

Listing 1.8: Syntax of a Library Statement

7
If a design unit is accessed frequently, we can make it visible by adding a use clause. The unit
can then be accessed directly without referring to the library. The syntax is :

use lib-name . unit-name ;

Listing 1.9: The Use Clause


Note: The all keyword can be used in place of unit name to make all units of the library visible.

1.2 Data Types and Objects

1.2.1 Objects
An object in VHDL is a named item that holds the value of a specific data type. It is created by
means of an object declaration. Every object has associated with a unique name,class and a data
type. The class of an object determines the nature of data it holds. There are four kinds of object
classes: signal, variable, constant and file [3] [6].

1.2.1.1 Constants

A constant is an object whose value cannot change. The syntax of constant declaration is:

constant constant-name:data type:= value-expression ;

Listing 1.10: Syntax of a Constant Declaration

1.2.1.2 Variables

An object of variable class can hold a single value of a given type. Variables are used for local
storage in process statements and subprograms. It is important to know that all assignments
to variables occur immediately. However, the are also shared variables [2]. Shared variable are
variables that can be accessed by more than one process. A variable declaration syntax is:

[shared]variable variable_name:variable-type[range] [:= default_value];

Listing 1.11: Syntax of a Variable Declaration

8
1.2.1.3 Signals

The signal is the most common object. Signals serve to pass values in and out of the circuit, as
well as between its internal units. In other words, a signal represents circuit interconnects (wires).
All ports of an entity are signals by default. Signal declarations can be made in the declarative part
of entity, architecture and package. Signal declarations are not allowed in sequential code (i.e.,
Process and Subprograms) but signals can be used there.
A simplified syntax for signal declaration is :

signal signal_name:signal_type [:= initial_value];

Listing 1.12: Syntax of a Signal Declaration


Architecture Local Signals
Architecture local signals are signals that are declared in the architecture declarative part. This
type of signals can only be referenced inside the specific architecture. Thus, the name local.

Signals Global to Entities


Global signals are signals that are declared inside the entity declaration section. This signal can
be referenced in this entity and in any architecture for that entity [3].

1.2.1.4 Files

The fourth and last VHDL object is file. However, to declare an object of that kind,a file type
must first be created [2].

File Type Declaration


File type declaration specifies the name of the file type and the base type of the file.

type type_name is type_in_file

Listing 1.13: Syntax of a File Type Declaration


File Object Declaration
A file object makes use of a file type and declares an object of type file. The file object declaration
specifies the name of the file object, the mode of the file, and the physical disk path.
The file mode can be in or out. If the mode is in, then the file can be read with the READ procedure.
If the mode is out, then the file can be written with the WRITE procedure.
After declaration, files must be opened prior to use and then closed after use. We have procedures
for opening and closing files.

file file_identifier: type_name [OPEN open_mode] is expression ];

Listing 1.14: Syntax of a File Object Declaration

9
1.2.2 Data Types
Each data object has a type associated with it. The type defines the set of values that the object
can have and the set of operations that are allowed on it. Every type has associated with it a name
and a range of values.
Data types are of two kinds: Predefined Data Types,User Defined Data Types[6] .

1.2.2.1 Predefined Data Types

The most commonly used predefined types are the following ones:

• Bit Type
Is based on binary logic values of ‘1’ and ‘0’. All arithmetic,logical and relational operators
are allowed on bit type.

• Bit Vector
It is an extension of two level bit logic to present an array of values instead of a single value.
The range of n-bit vector can be specified starting from ‘0’ to n − 1 or starting from n − 1 to
‘0’. However, arithmetic and relational operators are not allowed on bit vector type.

• Integer
It is an inbuilt type with a range from −2, 147, 483, 647 to 2, 147, 483, 647 (32 bit integer). All
arithmetic and relational operators are allowed with integers.

• Character Type
It is a single ASCII characters are represented in VHDL predefined-type CHAR. It represents
single characters included in single quotes (‘’) or a string of characters included in double
quotes (“”).

• Boolean
This type is used to represent condition values, which can control execution of a behavioral
model. It takes only ‘TRUE’ or ‘FALSE’ values.

• Std_ulogic
It is a nine-valued logic system defined in the std _logic_1163 package of the library IEEE.
The nine possible values are: ’U’, ’X’, ’O’, ’ l ’ , ’Z’, ’W’, ’L’, ’H’, ’ - ’ .

• Std_logic
It is a subtype of std_ulogic. It is aN eight value logic system that does not include the ‘U’
logic level. It allows signals driven by more then one source. All Arithmetic.logical and
relational operations are allowed on this type.

10
• Std_logic _vector It represents a vector of elements of type std_logic. Its assignment and
definition rules are the same ones as the std_logic ones.
Note
The type std_ulogic is unresolved (the “u” standard for “unresolved”). This means that if
a signal is being driven by two circuits with type std_ulogic, the VHDL simulator will not
be able to resolve the conflict and it will result in a compiler error. The std_logic type is
resolved. This means that if a signal is being driven by two circuits with type std_logic, the
VHDL simulator will be able to resolve the conflict and will allow the simulation to continue.

1.2.2.2 User-defined Data Types

VHDL allows users to define their own data types according to their needs, and those are called
user-defined data types. User-defined data types can be defined in a separate file and shared as a
library.
Scalar Types
Scalar types describe objects that can hold, at most, one value at a time. Scalar types encompass
these four classes of types: [6]

• Integer Types: have values that are whole numbers.It includes all the whole numbers
representable from −2, 147, 483, 647 to 2, 147, 483, 647. We can define a new integer type us-
ing a range-constraint type definition. The simplified syntax for an integer type definition is :

type type_name is range whole value (to\downto) whole value;

Listing 1.15: Syntax of the Integer Type Declaration


The keyword to defines an ascending range, in which values are ordered from the smallest
on the left to the largest on the right. On the other hand, using the keyword downto defines
a descending range.

11
• Physical Types: are numeric scalars that represent some real world quantities such as
distance, current, time. Each value of a physical type has a position number that is an
integer value. Any value of a physical type is a straight multiple of the primary unit of
measurement for that type.

range_constraint
units
primary_unit_declaration ;
{ secondary_unit_declaration };
end units [ physical_type_name ] ;

Listing 1.16: Syntax of a Physical Type Declaration

• Floating Point Types: are used to represent real numbers. Mathematically speaking, there
is an infinite number of real numbers within any interval, so it is not possible to represent
real numbers exactly on a computer. Hence, floating-point types are only an approximation
to real numbers. However, there is a predefined floating-point type called real, which in-
cludes the greatest range allowed by the implementation’s floating-point representation.
The simplified syntax rule for a floating-point type definition is relatively similar to that of
an integer:[4]

type type_name is range value (to\downto) value ;

Listing 1.17: Syntax of Floating Point Type Declaration

• Enumerated Types: define a type that has a set of user defined whose valued are defined
by listing them explicitly it consists of identifiers and character literals

type type_name is (type_values_list);

Listing 1.18: Syntax of Enumerated Type Declaration

Composite Types
Composite types are used to define collections of values. These include both arrays of values
which are collections of values of the same type and records of values that represent collections of
values of potentially different type. Constrained type arrays are covered in this report[3].

Arrays: contain multiple elements of the same type. Elements within an array can be scalar
or vectors. In order to use an array, a new type must be declared that defines the configuration of
the array. Once the new type is created, signals may be declared of that type. The range of the
array must be defined in the array type declaration and these are known as constrained arrays.
The range is specified with integers and either the keywords downto or to.

12
Constrained type array is an array whose range is defined at the time of declaration of the array
object.

type type_name is array(range) of elements_type ;

Listing 1.19: Syntax of Constrained Array Type Declaration


the dimensionality of the array is identified by the number of indices and the type, position, and
range of each index. A one-dimensional array has a distinct element for each possible index value.
A multidimensional array has a distinct element for each possible sequence of index values. In
our application a multidimensional array is used to form a 128x8 RAM.

1.3 Design Styles


VHDL supports three kinds of modeling styles: dataflow, structural, and behavioral. Dataflow
design style is used to model combinational circuits; whereas, behavioral modeling and structural
modeling are used for more complex circuit.

1.3.1 DataFlow
Dataflow modeling can be used to describe combinational circuits. The flow of data through
the entity is expressed using concurrent (parallel) statements. In addition to those statements,
assignments using only operators (AND, NOT, +, *, etc.) can also be used to construct the code.
Furthermore, a special kind of assignment, called BLOCK, can also be employed in this kind of
code.

1.3.2 Behavioral
Behavioral modeling is used to describe complex circuits. In this modeling style, the behavior
of an entity as set of statements is executed sequentially in the specified order. Only statements
placed inside a Process, Function, or Procedure are sequential.
Processes, Functions, and Procedures are the only sections of code that are executed sequentially.
However, as a whole, any of these blocks is still concurrent with any other statements placed
outside of it.
One important aspect of the behavior code is that it is not limited to sequential logic. Indeed, it
can be used to build both sequential and combinational circuits.

1.3.3 Structural
Structural modeling involves connecting instantiated components to define the functionality
of a circuit. A component instantiation statement is one of the concurrent statements. The struc-
tural style of modeling describes only an interconnection of components, without implying any

13
behavior of the components themselves nor of the entity that they collectively represent. This
design style allows the construction of simplified combinational circuits.
In this design style, the architecture body is composed of two parts; the declarative part which is
the part just before the reserved word begin, and the statement part after it.

A structural description can best be compared to a schematic block diagram that can be de-
scribed by the components and the interconnections. VHDL provides a formal way to do this
by:

• Declare a list of components being used.

• Declare signals which define the nets that interconnect components.

• Label multiple instances of the same component so that each instance is uniquely defined.

The components and signals are declared within the architecture body.

architecture architecture_name of NAME_OF_ENTITY is


-- Declarations
component declarations
signal declarations
begin
-- Statements
component instantiation and connections
end architecture_name;

Listing 1.20: Syntax of the Structural Design Style

14
1.4 VHDL Statements
A combinational logic circuit is one in which the outputs depend exclusively on the current
inputs, therefore exhibiting no memory. In contrast, a sequential logic circuit is one in which the
outputs do depend on previous system state(s), so storage elements are needed (usually D-type
flip-flops (DFFs)), along with a clock signal to control the system evolution.
To design those circuits, VHDL defines two code types; concurrent (parallel) and sequential codes.
The concurrent code is intended only for the design of combinational circuits, while sequential
code can be used indistinctly to design both sequential and combinational circuits.

1.4.1 Concurrent statements


Concurrent statements are used to define interconnected blocks and processes that jointly
describe the overall behavior or structure of a design.

1.4.1.1 Block Statement

The Block statement is a grouping together of concurrent statements within an architecture,


whose main purpose is to provide a mean for code partitioning which make the overall code more
readable and manageable.

block_label : block [ is ]
block_declarative_part
begin
block_statement_part
end block [ block_label ] ;

Listing 1.21: Syntax of the Block Statement

The declarative part can contain generic, generic map, port, port map, plus all kinds of dec-
larations allowed in the architecture’s declarative part.
The block statements can be nested inside one another; hence, it allows construction of complex
block arrangements.

15
1.4.1.2 Process Statement

A Process statement defines an independent sequential process representing the behavior of


some portion of the design.

[ label : ] process [ ( sensitivity_list ) ] [ is ]


process_declarative_part
begin
sequential_statement_part
end process [ process_label ] ;

Listing 1.22: Syntax of the Process Statement


A process usually has a sensitivity list containing all of the inputs to the block of logic. Though
including all of the inputs in the process statement is not mandatory. In the case where a Wait
statement is used inside a process, no sensitivity list should occur within that process.
A process_declarative_part declares subprograms, types, constants, and variables local to the
process [3]. It can contain any of the following items:

• Subprogram declaration

• Subprogram body

• Type declaration

• Subtype declaration

• Constant declaration

• Variable declaration

• File declaration

Signal declaration is not allowed, though it can be used inside the process. In the statements part
of the process, only sequential statements are allowed besides operators and signal assignments.

Passive Processes
If neither the process itself nor any procedure of which the process is a parent contains a signal
assignment statement, the process is said to be passive. Passive processes may appear in entity
declarations.

16
1.4.1.3 Procedure Call Statement

A concurrent procedure call statement represents a process whose body contains a sequential
procedure call statement. It is used in an architecture or a block, rather than in a process.

[ label : ] procedure_name [(parameter_association_list)] ;

Listing 1.23: Syntax of the Procedure Call Statement


This syntax looks identical to a sequential procedure call that will be discussed later. The difference
is that it appears as a concurrent statement, rather than as a sequential statement.
A concurrent procedure call is exactly equivalent to a process that contains a single sequential
procedure call to the same procedure with the same actual parameters. This equivalent process
contains a wait statement, whose sensitivity clause includes the signals mentioned in the actual
parameter list.
The execution of a concurrent procedure call statement is equivalent to executing the equivalent
process statement.
Concurrent procedure call statements make it possible to declare procedures representing com-
monly used processes and to create such processes easily by simply calling the procedure as a
concurrent statement [3].

1.4.1.4 Assertion Statement

A statement that checks that a specified condition is TRUE and reports an error if it is not.

[ label : ] assertion ;

Listing 1.24: Syntax of the Assertion S tatement

A concurrent assertion statement represents a passive process statement containing the specified
assertion statement. The assertion is a sequential assertion statement that will be discussed
further in the Sequential Statements section.

1.4.1.5 Signal Assignment Statements

A concurrent signal assignment statement represents an equivalent process statement that


assigns values to signals. It is similar to the sequential assignment statement that will be discussed
later but declared outside a process.

Target_signal <= expression;

Listing 1.25: Syntax of the Direct Signal Assignment Statement

As soon as an event occurs on one of the signals, the expression will be evaluated. The type of
the target_signal has to be the same as the type of the value of the expression.

17
There exist two types of the concurrent signal assignment statements; the conditional signal
assignment statement and the selected signal assignment statement [3] [4].

1.4.1.6 Conditional Signal Assignment Statement

Also called the When-Else statement. The simplest conditional statement. The conditional
assignment in a process is equivalent to the if statement. It is useful to express logic function in
the form of a truth table.

target <= waveform1 when condition1 else


waveform2 when condition2 else
...
waveformN-1 when conditionN-1 else
waveformN when conditionN;

Listing 1.26: Syntax of the Conditional Signal Assignment Statement

Note that multiple conditions (Boolean expressions) are accepted in the WHEN statement, which
are grouped using AND, OR, and NOT.
The WHEN statement does not require that all input values be specified. However, it is better to
cover at all times all input options. For such, the Others clause can be used.
When this statement is executed, each condition is tested in the order it appears in the statement.
The first condition that evaluates TRUE has its expression assigned to target. If no condition
is TRUE, the final expression or the expression associated with the Others clause, if preset, is
assigned to the target. If more than one condition is TRUE, the value of the first condition that is
TRUE will be assigned [3].

1.4.1.7 Selected Signal Assignment Statement

Also called the With-Select statement. It is similar to the conditional one described above and
it is as well useful to express a function as a truth table.

with expression select


target <= waveform1 when choice_list1,
waveform2 when choice_list2,
...
waveformN-1 when choice_listN-1,
waveformN when choice_listN;

Listing 1.27: Syntax of the Selected Signal Assignment Statement

18
The execution of this statement is that the target, that is a signal, receives the value of an
expression whose choice includes the value of the expression. The selected expression is the first
with a matching choice. The choice can be a static expression or a range expression and no two
choices can overlap. Moreover, all possible values of the expression must be covered by the set of
choices, unless an others choice is present.
The case statement within a process is equivalent to the selected signal assignment statement.

1.4.1.8 Component Instantiation Statement

It is to instantiate subcomponents described purely in terms of their behavior and perform


smaller operations of the complete model. In order to write a structural implementation, we must
use the component instantiation statement.

Component Declaration

Before components can be instantiated, they need to be declared in the architecture declara-
tion section or in the package declaration. If the component is declared in a package, it should
not be declared again in the architecture body as long the library and the use clause are used. [6]

component component_name [is]


[port (port_signal_names: mode type;
port_signal_names: mode type;
...
port_signal_names: mode type);]
end component [component_name];

Listing 1.28: Syntax of the Component Declaration Statement

Component Instantiation

The component instantiation statement references a component that can be either previously
defined at the current level of the hierarchy or defined in a technology library.

instance_name : component_name
port map (port_map_aspect);

Listing 1.29: Syntax of the Component Instantiation Statement


The instance name or label can be any legal identifier and is the name of this particular instance.
The component name is the name of the component declared earlier using the component
declaration statement. The port map contains the ports to be associated. There exist two ways
for the port map association; the Named association, and an alternative method which is the
Positional association [6].

19
• Named Association
This method assigns each signal to the corresponding port.

port map (port1=>signal1,


port2=> signal2,
...
portN=>signalN);

Listing 1.30: Syntax of the Named Association

• Positional Association
In this association, the first port in the component declaration corresponds to the first signal,
the second port to the second signal, etc. The signal position must be in the same order as
the declared component’s ports.

port map (signal1, signal2,...signalN);

Listing 1.31: Syntax of the Positional Association

Named associations can be given in any order, but if both positional and named associations
appear in the same association list, then all positional associations shall occur first at their normal
position. Hence, once a named association is used, the rest of the association list shall use only
named associations.
Assigning ports for every signal may be hard and take time when there are several ports. In this
case, the positional association is recommended, but in this later, the error prone is great.

1.4.2 Sequential statements


Represent the way data may be operated within processes and subprograms. They are executed
in sequence.

1.4.2.1 Wait statement

A Wait statement is a sequential statement that causes the suspension of a process statement
or a procedure [3].

[ label : ] wait [ on signal_name { , signal_name }]


[ until boolean_expression] [ for time_expression] ;

Listing 1.32: Syntax of the Wait Statement

20
The sensitivity clause (on signal_name , signal_name ), condition clause (until boolean_expression),
and the timeout clause (for time_expression) specify when the process is subsequently to resume
execution. We can include any combination of these clauses, or we may omit all three.

Sensitivity Clause
Allows us to specify a list of signals to which the process responds. If we just include a sensitivity
clause in a Wait statement, the process will resume whenever any one of the listed signals changes
value.
A process with a sensitivity list in its heading is equivalent to a process with a Wait statement at
the end, containing a sensitivity clause naming the signals in the sensitivity list.

Condition Clause
In a Wait statement, allows us to specify a condition that must be TRUE for the process to resume.
The condition expression is tested while the process is suspended to determine whether to resume
the process. A consequence of this is that even if the condition is TRUE when the Wait statement
is executed, the process will still suspend until the appropriate signals change and cause the con-
dition to be TRUE again. If the Wait statement does not include a sensitivity clause, the condition
is tested whenever an event occurs on any of the signals mentioned in the condition.
If a Wait statement includes a sensitivity clause as well as a condition clause, the condition is only
tested when an event occurs on any of the signals in the sensitivity clause.

Timeout Clause
In a Wait statement, the time clause allows us to specify a maximum interval of simulation time
for which the process should be suspended. If we also include a sensitivity or condition clause,
these may cause the process to be resumed earlier depending on which comes first; an event
occurs on any of the signals of the sensitivity list or on the condition, or the specified simulation
time has elapsed.
If we just include a timeout clause by itself in a Wait statement, the process will suspend for the
time given.
If the three clauses are omitted, the statement "wait;" results which suspends the execution for the
reminder of the simulation. Although this may at first seem strange, it is quite useful in practice.

21
1.4.2.2 Assertion Statement

Used to check whether a condition is TRUE and generates an error message if it is not [3].

[ label : ] assert condition [ report expression ]


[ severity expression ];

Listing 1.33: Syntax of the Assertion Statement

The report clause specifies a message string to be included in error messages generated by the
assertion; hence, it must include an expression of predefined type STRING.
The severity clause specifies a severity level associated with the assertion; thus, it requires an
expression of predefined type SEVERITY_LEVEL.

The default string “Assertion violation.” appears as a generated message in the absence of a
report clause for a given assertion. Similarly, in the absence of a severity clause, the default value
of the severity level is ERROR.

Evaluating this statement involves the evaluation of the asserted condition which have to be
a Boolean expression. If the condition is FALSE, the report and severity clause expressions of the
corresponding assertion are evaluated (or the corresponding default values, if one or both clauses
are not specified). The specified message string and severity level are then used to construct an
error message.

1.4.2.3 Report Statement

This statement is used to display a message.

[ label : ] report expression [ severity expression ] ;

Listing 1.34: Syntax of the Report Statement

The report statement expression must be of the predefined type STRING which will be included
in the message generated by the report statement.

If the severity clause is present, it must specify an expression of predefined type SEVERITY_LEVEL.
The severity clause specifies a severity level associated with the report. In the absence of a severity
clause for a given report, the default value of the severity level is the predefined severity name
NOTE (other predefined severity names are: WARNING, ERROR, FAILURE).

The evaluation of both the report and the assertion statements are alike.

22
1.4.2.4 Signal Assignment Statement

A signal assignment statement modifies the target signal.

[ label: ] target_signal <= expression


[ after time_expression ] [ when condition ];

Listing 1.35: Syntax of the Signal Assignment Statement

The time expression defines the time period for which the execution of the statement is de-
layed.

The keyword unaffected which can be placed in the condition of the when statement indicates a
choice where the signal is not given a new assignment. This is roughly equivalent to the use of the
null statement within case that will be discussed further.

1.4.2.5 Variable Assignment Statement

It is the way of replacing the current value of a variable with a new value specified by an
expression. The named variable and the right-hand side expression must be of the same type.

[ label: ] target_variable := expression;

Listing 1.36: Syntax of the Variable Assignment Statement


The expression within the statement must be the same as the type of the target variable. This form
of variable assignment assigns the right-hand side value to a single (scalar or composite) variable.

1.4.2.6 Procedure Call Statement

Another VHDL sequential statement by which the actions of a procedure are invoked.

[ label : ] procedure_name [ ( actual_parameter_part ) ];

Listing 1.37: Syntax of the Procedure Call Statement

The procedure name specifies the procedure body to be invoked. The actual parameter part, if
present, specifies the association of actual parameters with formal parameters of the procedure.
They can be listed in both positional association and named association (both methods can be
mixed in one procedure call).
The procedure call statement is executed whenever control reaches it.

23
1.4.2.7 IF Statements

The If statement selects one or more statement sequences for execution, based on the evalua-
tion of a Boolean condition corresponding to that sequence [5].

[ label: ] if condition then


sequence_of_statements
{ elsif condition then
sequence_of_statements }
[ else
sequence_of_statements ]
end if [ if_label ] ;

Listing 1.38: Syntax of the If Statement


Each condition is a Boolean expression, which is evaluated to TRUE or FALSE. More than one elsif
clauses may be present, but a single else clause may exist.

The execution of this statement is as follows:


The condition after the If reserved word is firstly evaluated. If it evaluates TRUE, the correspond-
ing statement or statements are executed. If it evaluates FALSE and the elsif clause is present,
the condition after this clause is evaluated; if it evaluates TRUE, the corresponding statement or
statements are executed, otherwise; if there are other elsif clauses, the evaluation of their con-
ditions continues, and if none of the conditions evaluated is TRUE, the sequence of statements
corresponding to the else clause is executed (if present).

This statement generates series circuits. The more complex the circuit is the longer execution it
will take (increase in the generated delay).

24
1.4.2.8 Case Statement

Like the If statement, the case statement selects for execution only one of several alternative
statement sequences based on the value of an expression.
Unlike the If statement, the expression does not need to be Boolean, but it may be represented
by a signal, variable, or expression of any discrete type (an enumeration or an integer type) or a
character array type (including bit_vector and std_logic_vector).
This statement is more readable and allow an ease identification a value and the associated state-
ment sequence.

[ label: ] case expression is


when_clause;
{when_clause};
end case [ case_label ] ;

Listing 1.39: Syntax of the Case Statement


The Case statement contains several when clauses, each of them specifies one or more options.
The options represent either an individual value or a set of values to which the expression of the
Case statement is compared. If the expression is equal to the individual value or one of the values
from the set, the statement sequence specified after the "=>" symbol is executed.
A statement sequence may also be represented by the null statement. The others clause (when
others => sequence_of_statements) may be used to specify the execution of a statement sequence
when the expression value does not equal any of the values in by the when clauses.
The set of values of the options are either individual values that are separated by the “|” symbol
(means “or”), or a range of the values, or a combination of these.
In a case statement all the possible values of the selection expression must be enumerated, based
on the expression’s type or subtype. If all the possible values are not enumerated, the others clause
must be used which have to be the last of all options.
This statement implements parallel circuits; short delay time is generated.

NOTE
Since if statement infers priority, it should be used when more than one input condition could
occur. Using case, on the other hand, is appropriate when the inputs are mutually exclusive.

1.4.2.9 Loop Statements

Loop statements allow the repeated execution of a statement sequence, zero or more times.
In the VHDL language there are three types of loop statements:

• Simple loop

• While loop

25
• For loop

Simple Loop Statement

The simple loop statement specifies an indefinite repetition of some statements.

[ label: ] loop
sequence_of_statements
end loop [label];

Listing 1.40: Syntax of the Simple Loop Statement


It keeps repeating the statements within the statement body an unlimited number of times. An
exit statement should be used to end the execution.

While Loop Statement

It is a conditional loop statement, where the statements of the loop body are repeated until a
condition specified becomes FALSE.

[label:] while condition loop


statement_sequence
end loop [label];

Listing 1.41: Syntax of the While Loop Statement


The condition is tested before each execution of the loop. If the condition is TRUE, the statements
within the loop body are executed, after which the control is transferred to the beginning of the
loop. If the condition is FALSE, the loop execution terminates.
The loop statements may be nested on several levels. Thus, the loop body of a while loop statement
may contain another loop statement.

For Loop Statement

For the for loop, the statements of the loop body are repeated a number of times specified by a
counter.

[label:] for counter in range loop


Sequence_of _statement
end loop [label];

Listing 1.42: Syntax of the For Loop Statement

26
For this statement, an iteration counter and a range are specified. The statements within the loop
body are executed while the counter is in the specified range. The range may be an ascending
one, specified by the to keyword, or a descending one, specified by the downto keyword. This
range may also be specified as an enumeration type or subtype, when the range boundaries are
not explicitly specified in the statement. In such case, the range boundaries are determined by
the compiler from the type or subtype declaration.

1.4.2.10 Next Statement

The Next statement is used when the statements remaining in the current iteration of a loop
must be skipped and the execution must be continued with the next iteration.

[ label : ] next [ loop_label ] [ when condition ] ;

Listing 1.43: Syntax of the Next Statement


When a next statement is encountered in a For-loop body, the execution of the current iteration is
skipped and the control is passed to the beginning of the loop statement either unconditionally if
the when clause is not present, or conditionally if this clause is present. The iteration count is
updated and, if the bound of the range is not reached, the execution will continue with the first
statement of the loop body. Otherwise, the execution of the loop statement will terminate.

1.4.2.11 Exit Statement

Used when the processing must be terminated before the iteration count exceeds its range.

[ label : ] exit [ loop_label ] [ when condition ] ;

Listing 1.44: Syntax of the Exit Statement


An Exit statement with a loop label is only allowed within the labeled loop and applies to that
loop, while an exit statement without a loop label is only allowed within a loop and applies only
to the innermost enclosing loop (whether labeled or not).
The exit from the loop is executed when the value of the evaluated condition is TRUE or if there is
no specified condition.

27
1.4.2.12 Return statement

A Return statement is only allowed within the body of a subprogram. It is used to complete
the execution of the innermost enclosing subprogram body.

[ label : ] return [ expression ] ;

Listing 1.45: Syntax of the Return Statement


A Return statement appearing in a procedure body must not have an expression, whereas; when
appearing in a function body, it must have an expression.
When the return statement is executed within a procedure, the latest is immediately terminated
and control is transferred back to the caller. The return statement in a Function must return a
value of the type specified in the function header after the return clause.
For the execution of this statement, the expression, if present, is first evaluated and a checked that
the value belongs to the result subtype. If the check succeeds, the execution is completed; thus,
the execution of the subprogram. Otherwise, an error occurs at the place of the Return statement
if the check fails.

1.4.2.13 Null Statement

A null statement performs no action.

[ label : ] null ;

Listing 1.46: Syntax of the Null Statement


The execution of the Null statement has no effect other than to pass on to the next statement.
The null statement can be used to specify explicitly that no action is to be performed when certain
conditions are TRUE. This is particularly useful in conjunction with the Case statement (where
for some choices, it may be that no action is required).

28
Chapter 2

Advanced Features of VHDL


2.1 Packages and Subprograms

2.1.1 Packages
As a system becomes complex, more information is included in the declaration section. The
declaration section of an architecture body may consist of the declarations of constants, data types,
components, functions and so on. When a system is divided into several smaller subsystems,
some declarations must be duplicated in many different design units.
The VHDL package construct is a method of organizing declarations. We can gather the commonly
used declarations in a design, group them together and store them in a package. A design unit
just needs to include a use clause to access these declarations.
A VHDL package is divided into package declaration and package body. The declaration items
are placed in a package declaration. If an item is a subprogram, only the declaration of the sub-
program is included. The body of the subprogram is placed in the associated package body. The
package body is optional and is needed only when subprograms exist.
Important aspect of packages is that they separate the external view of the items they declare
from the implementation of those items. The external view is specified in a package declaration,
whereas the implementation is defined in a separate package body [3][7].
Package declaration and package body are design units of VHDL. They are analyzed independently
and stored in a library.
To make a declaration item visible, a use clause is needed. Its syntax is

use lib_name.package_name.item_name;

Listing 2.1: Application of the Use Clause


Most of the time, we use the all keyword in place of item_name to make all items of the named
package visible.

Many extensions to VHDL are done by defining additional packages, such as the IEEE std_logic_1164
and numeric_std packages.

use ieee.std_logic_1164. all ;

Listing 2.2: Syntax of IEEE std-logic-1164


It makes all of the declaration items of the predefined std-logic_1164 package visible, and thus,
we can use the std_logic and std_logic_vector data types in VHDL code.

30
2.1.1.1 Package Declaration

We can also define our own package. The syntax of a package declaration is very simple: [2]

package package_name is
declaration items ;
declaration items;
end package_name ;

Listing 2.3: Syntax of Package Declaration

2.1.1.2 Package Body

If the declaration items include subprograms, an associated package body is needed. Its syntax
is[2]

package body package-name is


subprogram ;
subprogram;
end package-name ;

Listing 2.4: Syntax of a Package Body

2.1.2 Subprograms
It is more convenient when we write complex behavioral models to divide the code into
sections, each dealing with a relatively self-contained part of the behavior. VHDL provides sub-
programs to facilitate this option. There are two kinds of subprograms; procedures and functions.
A procedure is a generalization of a statement, whereas; a function is a generalization of an ex-
pression.
There are two versions of procedures and functions; concurrent procedure and function which
exist outside of a process statement or another subprogram; and sequential procedure and func-
tion which exist only in a process statement or another subprogram statement.
Unlike the entity and the architecture, procedures and functions are not design units and thus
cannot be processed independently, they are basic building blocks of software hierarchy but
cannot describe the hardware hierarchy.

31
2.1.2.1 Functions

It is a section of sequential VHDL code whose main purpose is to allow the creation and storage
in libraries of solutions for commonly encountered problems. The important feature of functions
is that they are used as expressions that return values of specified type.
The Function is similar to the Process discussed earlier in the sense of including sequential state-
ments. Moreover, the items that can be declared in its declarative part are the same as those for
the Process.
Functions can be either pure (default) or impure. Pure functions always return the same value for
the same set of actual parameters. Impure functions may return different values for the same set
of parameters [4].

[pure| impure] function function_name [(input_formal_parameter_list)]


return return_value_type is
[declarative_part]
begin
Sequential_statement_part
end [function] [function_name];

Listing 2.5: Syntax of Function


The function declaration can be preceded by an optional reserved word pure or impure, denoting
the character of the function. If left unspecified, the default value (pure) is assumed.
The parameters of the function are by definition inputs and therefore they do not need to have the
mode (direction) explicitly specified. Only constants, signals and files can be function parameters.
The object class is specified by a reserved word (constant, signal or file) preceding the parameter’s
name. If no reserved word is used, it is assumed by default that the parameter is a constant.
The input list can contain any number of parameters (including zero). Regardless of the number
of input parameters, a function always returns one parameter value, whose type must be specified
after the keyword return in the function header.
A function can be called mostly anywhere (in a combinational or a sequential code, inside sub-
programs, Generate...etc.).
In general, when a subprogram is constructed in a package, a package body is required, where only
the subprogram declaration goes in the package, and the subprogram body goes in the package
body .
Similarly to port map in component instantiation, the mapping between a function call and the
corresponding function declaration can be positional or nominal.

32
2.1.2.2 Procedures

A procedure is a subprogram that defines algorithm for computing values or exhibiting behav-
ior. The purpose, structure, and usage of procedure are similar to those of function. The main
difference is that a procedure can return more than one value [4].

Procedure procedure_name [(input_output_formal_parameter_list)]


[declarative_part]
begin
Sequential_statement_part
end [procedure] [procedure _name];

Listing 2.6: Syntax of Procedure

It has a sequence of statements and local declarations. The procedure call statement can be
used to call a procedure from anywhere in the architecture.

There are two sections to the procedure definition:

• The procedure declaration, which includes the procedure name as well as the parameter
list that must be supplied when the procedure is invoked.

• The procedure body which contains the local declarations and statements needed to run
the procedure.

2.2 Testbenches
One major use of a VHDL program is simulation, which is used to study the operation of a
circuit or to verify the correctness of a design.
Performing simulation is similar to doing an experiment with a physical circuit, in which we
connect the circuit’s input to a stimulus and observe the output. Simulating a VHDL description
is like doing a virtual experiment, in which the physical circuit is replaced by the corresponding
VHDL description [4].

33
library ieee;
use ieee.std_logic_1164.all;

entity test_UUT is -- empty entity


end test_UUT

architecture testbenk_arch of test_UUT is


Component UUT:
port
(
...... -- component declaration
);
end component;

signal ......
signal ...... :=’0’; -- defining signals for each port

begin
U1: UUT
port map (........); -- component instantiation

STIMULI:
process
begin
......
...... -- test sequencer to provide stimuli
......
wait;
end process;
end architecture;

Listing 2.7: Syntax of a TestBench


The testbench is a specification in VHDL that plays the role of a complete simulation environment
for the analyzed system (Design Under Test, DUT). A testbench contains both the DUT as well as
stimuli for the simulation.

Four types of testbenches can be distinguish according to the way the generated output data is
analysed and DUT’s internal delays consideration in the simulation.

• Type I Testbench (manual functional simulation): the DUT’s internal delays are not con-
sidered and the output is manually verified.

34
• Type II Testbench (manual timing simulation): the DUT’s internal delays are taken into
account, but the output is still manually verified.

• Type III Testbench (automated functional simulation): the DUT’s internal delays are not
considered, but the output is automatically verified by the simulator.

• Type IV Testbench (automated timing simulation): the DUT’s internal delays are taken into
account and the output is automatically verified by the simulator.

In our application we used the Type I approach where the entity of the testbench file has no inputs
or outputs. The testbench declares the design to be tested as a component and then instantiates
it, then input conditions are generated and driven into the input ports of the system being tested.
VHDL contains numerous methods to generate stimulus patterns. Since a test bench will not be
synthesized, very abstract behavioral modeling can be used to generate the inputs.
The output of the system can be viewed as a waveform in a simulation tool.

The testbench consists of an empty entity since it is self-contained; no port is specified in the
entity declaration. The functionality of a testbench is to verify the design not to implement it[7]
[4] .

35
Chapter 3

Application
3.1 Tools and Software
ModelSim is a multi-language simulation environment for hardware description languages
including VHDL, Verilog, and System C. It can be used on its own or in conjunction with other
programs such as Intel Quartus Prime, PSIM, and others. The ModelSim SE Version was used for
our simulation.

3.2 Design Specifications


We are going to design a 128 × 8 single port RAM that supports synchronous read and write.
An external view of device is depicted in Figure3.1.

Figure 3.1: External View of the Single Port RAM

The inputs and output are:

• RAM_CLOCK: the clock signal for sequentially writing data to the single port RAM.

• RAM_DATA_IN: 8-bit input data to be written to RAM at the provided input address RAM_ADDR
when it is enabled.

• RAM_WR: Write enable signal for writing to RAM, only if RAM_WR = 1, RAM_DATA_IN is
written to the RAM at the rising edge of the clock signal.

• RAM_ADDR: 6-bit Address where 8-bit input data are written to and data are read out.

• RAM_DATA_OUT: 8-bit output data read out from the provided input address RAM_ADDR.

37
We set some random values for the contents of some addresses of the RAM. Starting from the first
address 00H, and incrementing by one, the following values were set: 01H, 03H, 17H, 87H, 99H,
11H, 12H, 11H, 98H,15H...

We started our VHDL code for the design by declaring the inputs and output in the entity. In
the declarative part of the architecture, we declared a multidimensional array that represents
the content of the RAM. A process statement is followed where we implemented the write and
read mechanisms using priority to the control signals RAM_WR and RAM_CLOCK. The signal
RAM_WR being High indicates the writing process and being LOW indicates the reading process.
These are checked every rising edge of the clock.
In the reading process, the output RAM_DATA_OUT gets the content of the address provided with
RAM_ADDR. In the writing process, the input data through RAM_DATA_IN Is transmitted to the
output.

3.3 Simulation and Analysis


To test the functionality of our design, a testbench file was created. It consists of an empty
entity followed by the declaration of the design as a component and then instantiating it in the
declarative part of the architecture. After that, a clock signal is driven having a 10ns period with
50% duty cycle.
An input stimulus is generated for both the read and write operations using a process statement
having two incremental loops of 8 iterations, each iteration lasting for 50 ns. In the two loops, the
RAM_ADDR is incremented by one after being initialised to 00H. RAM_DATA_IN is initialised
to 26H and decremented by 2H for every iteration in the second loop corresponding to writing
process. In addition, A wait statement of 100 ns is before each loop.
A waveform of the inputs and output are generated through graphical interface of ModelSim
depicted in Figure3.2.

Figure 3.2: The Simulation Waveforms.

38
In the first 500ns of the simulation, the write enable is LOW which refers to the reading process.
The content of address 00H is read from the RAM and it appears in the RAM_DATA_OUT as value
01H. This lasts for 100ns.
The address now is incremented by 1 and the content of address 01H appears in an output, this
happens in the interval 100 to 150ns.
Similarly, the address 01H is incremented by 1. The content of the new address is read and the
value 17H corresponding to address 02H is seen as output. This process of reading the content of
addresses continues till reaching the last iteration that corresponds to address 08H at time 500ns
where the RAM_ADDR is again initialized to 00H and RAM_WR to value 1.
When the write signal is set, the write process may be enabled in the next 500ns, this is related to
the clock’s event.
We can notice that at 500ns, RAM_WR is set but we have a falling edge of the clock as shown in
Figure3.3.

Figure 3.3: Case Where The Write Signal is Set and a Falling Edge of The System Clock Occurs.

In this case, the writing operation to the corresponding address is not allowed, we can only read
from it. Thus, at the output we find the value 01H not 26H which is provided by RAM_DATA_IN.
This reading operation lasts for 5ns which is equivalent to the occurrence of the next rising edge.
At the next positive edge of the clock corresponding to 505 ns, the initialized value of the RAM_DATA_IN
is written to the location pointed by the address 00H. The output is then of value 26H.
At 600ns, the address is incremented by 1 and the initialized input value is decremented by 02H
and again we face the case of a falling edge which means that the content of that address is read
from our RAM.
At 605ns, the value 24H (the initial input value 26H decremented by 02H) is written to the address
location 01H of the RAM.
These processes of reading from and writing to the RAM continue until the last tested address
08H where the simulation is suspended for the rest of the simulation.
The simulation waveforms show the correct writing and reading operations of the single-port
RAM.

39
Conclusion
In this report, one of the most complex hardware description languages was introduced. The
VHDL language, which stands for Very-High-Speed Integrated Circuits Hardware Description
Language, is a programming language for designing high-speed integrated circuits. Fundamental
features including the design units, data types and objects, various design styles in addition to
several statements are the basis for understanding more advanced features of the language. The
most used advanced features, packages and subprograms along with the testbench, are covered
in this work. The application of these features helped us get a thorough understanding of this
language by designing and simulating a single port RAM. The scope of this work can further be
extended to more complex applications by being incorporated in a CPU.

40
References

[1] D. J. Smith and A. Zamfirescu, HDL Chip Design: A Practical Guide for Designing, Synthesizing
and Simulating ASICs and FPGAs Using VHDL or Verilog. Doone Publications, 1998, ISBN:
0965193438.
[2] P. P. Chu, RTL Hardware Design Using VHDL: Coding for Efficiency, Portability, and Scalability.
Wiley-IEEE Press, 2006, ISBN: 0471720925.
[3] “Ieee standard vhdl language reference manual,” ANSI/IEEE Std 1076-1993, pp. 1–288, 1994.
DOI: 10.1109/IEEESTD.1994.121433.
[4] V. A. Pedroni, Circuit Design and Simulation with VHDL, Second Edition, 2nd. The MIT Press,
2010, ISBN: 0262014335.
[5] D. L. Perry, VHDL: Programming by Example, 4th ed. USA: McGraw-Hill, Inc., 2002, ISBN:
0071400702.
[6] P. J. Ashenden, The Designer’s Guide to VHDL, Volume 3, Third Edition (Systems on Silicon)
(Systems on Silicon), 3rd ed. San Francisco, CA, USA: Morgan Kaufmann Publishers Inc., 2008,
ISBN: 0120887851.
[7] B. J. LaMeres, Introduction to Logic Circuits Logic Design with VHDL, 1st. Springer Publishing
Company, Incorporated, 2016, ISBN: 3319341944.

41

You might also like