Sunteți pe pagina 1din 51

VER 1.

INDEX

1 SYSTEM REPRESENTATION IN VHDL: DESIGN UNIT ........................................................................ 3


1.1 SYSTEM REPRESENTATION ........................................................................................................................... 3
1.2 VHDL STANDARD PACKAGES ..................................................................................................................... 3
1.3 COMMENTS .................................................................................................................................................. 4
2 VHDL OBJECT: SIGNALS............................................................................................................................. 5
2.1 SIGNALS IN ELECTRONIC DESIGNS ............................................................................................................... 5
2.1.1 Generic ................................................................................................................................................ 5
2.1.2 Costants ................................................................................................Error! Bookmark not defined.
2.1.3 Constants vs. Generics ........................................................................................................................ 5
2.1.4 Ports .................................................................................................................................................... 5
2.2 VISIBILITY OF SIGNALS ................................................................................................................................ 6
2.3 DATA TYPES ................................................................................................................................................ 7
2.3.1 Scalar Types ........................................................................................................................................ 7
2.3.2 User Defined Enumeration Types........................................................................................................ 8
2.3.3 Physical Types..................................................................................................................................... 8
2.3.4 Predefined Arrays................................................................................................................................ 8
2.3.5 User-Defined Arrays ........................................................................................................................... 9
2.3.6 Records................................................................................................................................................ 9
2.4 EXPRESSIONS AND OPERATORS .................................................................................................................. 10
2.4.1 Logical Operators ............................................................................................................................. 10
2.4.2 Numerical Operators......................................................................................................................... 10
2.4.3 Relational Operators ......................................................................................................................... 10
2.4.4 Shift Operators .................................................................................................................................. 11
2.4.5 Concatenation Operator.................................................................................................................... 12
2.4.6 Assigning Expressions to Signals ...................................................................................................... 12
2.4.7 Assignments with Delay..................................................................................................................... 13

Alberto Cerdeira - VHDL: Quick Reference 1


3 PROCESS IN VHDL....................................................................................................................................... 14
3.1 PROCESS DECLARATIVE PART..................................................................................................................... 14
3.2 MULTIPLE PROCESS IN AN ARCHITECTURE ................................................................................................ 15
3.3 ACTIVATION OF CONCURRENT ASSIGNMENTS ........................................................................................... 16
3.4 CONTROLLING THE SEQUENCE OF STATEMENTS (FINITE STATE MACHINE)............................................... 17
3.5 CONDITIONAL STATEMENTS ...................................................................................................................... 19
3.6 MULTIPLE CHOICES ................................................................................................................................... 19
3.7 CONDITIONAL LOOP ................................................................................................................................... 20
3.8 LOOP WITH A COUNTER.............................................................................................................................. 20
3.9 BREAKING UP LOOPS ................................................................................................................................. 20
3.10 CONDITIONAL SIGNAL ASSIGNMENT.......................................................................................................... 21
4 ATTRIBUTES OF SIGNALS ........................................................................................................................ 22
4.1 THE CONCEPT OF A DRIVER ....................................................................................................................... 22
4.2 OTHER SIGNAL ATTRIBUTES ...................................................................................................................... 23
4.3 CAN A SIGNAL HAVE TWO DRIVERS?......................................................................................................... 24
4.4 MULTIPLE-DRIVER SIGNAL MUST BE RESOLVED ....................................................................................... 24
4.5 TWO-VALUE LOGIC IS NOT ENOUGH FOR RESOLUTION.............................................................................. 24
4.6 MULTI-VALUE LOGIC ................................................................................................................................ 24
4.7 RESOLVED MULTI-VALUE LOGIC ............................................................................................................... 26
5 SPECIFYING THE SYSTEM’S STRUCTURE .......................................................................................... 27
5.1 INTRODUCTION TO STRUCTURAL DESCRIPTION ......................................................................................... 27
5.2 ELEMENTS OF STRUCTURAL DESCRIPTION ................................................................................................. 27
5.3 COMPONENTS AND COMPONENT INSTANCES ............................................................................................. 27
5.4 PORT MAPPING .......................................................................................................................................... 28
5.5 DIRECT INSTANTIATION ............................................................................................................................. 29
5.6 POSITIONAL PORT ASSOCIATION ................................................................................................................ 30
5.7 NAMED PORT ASSOCIATION ....................................................................................................................... 31
5.8 COMPLEX PORTS AND SIGNALS.................................................................................................................. 32
5.9 PORT WITHOUT CONNECTIONS ................................................................................................................... 33
5.10 INTRODUCTION TO COMPONENTS ............................................................................................................... 33
5.11 COMPONENT DECLARATION....................................................................................................................... 34
5.12 COMPONENT INSTANTIATIONS ................................................................................................................... 34
5.13 GENERAL FORM OF USING COMPONENT DECLARATION AND INSTANTIATION. ............................................ 36
5.14 CONFIGURATIONS ...................................................................................................................................... 37
6 SUBPROGRAMS............................................................................................................................................ 38
6.1 PROCEDURES.............................................................................................................................................. 38
6.2 FUNCTIONS................................................................................................................................................. 39
7 TESTING THE DESIGN FUNCTIONALITY............................................................................................. 40
7.1 TEST BENCH............................................................................................................................................... 40
7.2 ELEMENTS OF A VHDL TEST BENCH ......................................................................................................... 40
7.3 USING TEST BENCH.................................................................................................................................... 41
7.4 UNIT UNDER TEST ..................................................................................................................................... 41
7.5 STIMULI OF SIGNALS .................................................................................................................................. 42
7.6 ASSERTION STATEMENT............................................................................................................................. 43
7.7 REPORTING WITH ASSERTIONS ................................................................................................................... 43
APPENDIX A. EXAMPLES OF VHDL DESCRIPTION FOR D-FF WITH SYNCHRONOUS AND
ASYNCHRONOUS RESET................................................................................................................................... 44

APPENDIX B. EXAMPLE OF A SERIAL TO PARALLEL CONVERTER- SHIFTER ............................. 47

EXAMPLE OF A PARALLEL TO SERIAL CONVERTER. ........................................................................... 49

Alberto Cerdeira - VHDL: Quick Reference 2


1 System representation in VHDL: Design Unit

1.1 System Representation

The main design unit of the system is the so called: entity. The entity provides system’s interface
specification and is generally comprised of two elements:

•= Parameters of the system as seen from the outside, such as bus width, delays, clock frequency,
etc. (Are declared as generic).

•= Connections which are transferring information to an from the system (system’s inputs and
outputs). (Are declared as port).

Every stand alone system, entity, most have a description, a functionality, and this is the
architecture. The architecture are always related to an entity. Since different types of architecture can
perform the same function, a system (an entity) can be specified with different architectures.

Each system’s architecture can be described either in terms of its functionality (behavior) or
structural, which require different kinds of information about the system. The synthesis tools work with
both them.
The behavioral description can be mixed with the structural one. The synthesis tool first of all needs
to transform the behavioral part in a fully structural one. The structural design is referred to concrete
physical components, and are easier to synthesize but more difficult to specify.
The Behavioral description specifies what the system is expected to do. Is a description of output’s
response to input’s changes.
The Structural description specifies what components should be used and how they should be
connected.
Another important concept is the Package. It is an external source of description when something is
undefined in the standard language. A library is a simple example of a package use. There are two
clauses, which serve to declare a library: library and use.

1.2 VHDL Standard Packages

The STANDARD package has the declaration of all-standard types, operators and objects. It is
used by default in any VHDL compiler and it is not needed to use the library and use clause for this
package.

library Std;
use Std.Standard.all

The TEXTIO package has the declaration of types and object relating to reading and writing texts as
defined by VHDL standard. The operations are not synthesizeable and can be used for simulation and
modeling only.

library Std;
use Std.TextIO.all;

The STD_LOGIC_1164 defined by IEEE Standard 1164 are extension to the standard VHDL
language. Multiple value logic, resolution functions and extended operators are the most important
declarations here.

library IEEE;
use IEEE.Std_Logic_1164.all;

The IEEE 1029 WAVES specify waveforms and vector Exchange Specification. Define data format for
testing and timing verification.

Alberto Cerdeira - VHDL: Quick Reference 3


Inside the IEEE Std 1076-93 is the core for the VHDL standard, containing definition of the language.
there are 5 sub-packages the only actually released is the 1076.4.

IEEE Std 1076.1 – Analog and mixed analog-digital system.


IEEE Std 1076.2 – VHDL Math Utilities.
IEEE Std 1076.3 – VHDL synthesis ( the subset usable only for synthesis)
IEEE Std 1076.4 – VITAL (VHDL Initiative Towards ASIC Libraries) – aimed standardization of
application specific integrated circuit (ADSIC) models.
IEEE Std 1076.5 – Devoted to extensions and unification of IEEE library components in VHDL.

Apart from this main packages many vendors use to add their own packages that usually bears the
vendor’s name.

-------------------------------------------------------------------------------------
-- Example of a system --
-------------------------------------------------------------------------------------
library IEEE;
use IEEE.Std_Logic_1164.all;

entity entity_name is

generic (
BusWidth : integer :=8;
MaxDelay : time :=20 ns;
LoopIteration : integer:=3
);

constant t_setup : time := 1 ns;

port (
CS, RST : in std_logic;
DATA1 : inout std_logic_vector (15 downto 0);
DATA2 : inout std_logic _vector (BusWith-1 downto 0);
ADDR : out std_logic _vector (19 downto 0)
);

end entity entity_name;

architecture architechture_name1 of entity_name is

signals ( X, Y : std_logic;
InternalBus : std_logic_vector
);

constant N : integer :=1998;

begin
….

end architecture architecture name1;

1.3 Comments

Comments can be included in the VHDL code for documenting the description. Comments in VHDL
start with two hyphens (--) and terminate at the end of the line. They can be located almost everywhere,
but may not start in the middle of an identifier or reserved word.

-- any comments

Alberto Cerdeira - VHDL: Quick Reference 4


2 VHDL Object: Signals
2.1 Signals in Electronic Designs

2.1.1 Generic

Are specifying only in entities inside the generic clause, always before port declarations. Generics
provide constant values for different parameters, as seen from the outside of the system. For example,
they can control size of a model, in particular the width of buses a size of such parameterized modules
as n-bit adders and n-bit comparators. They can be used for timing parameters such as delays, setup
times, hold times, switching times and any other timing parameters used in electronics. They can also be
used as loop counters, etc.

generic (
generic_name : generic_type := optional_value;
……
generic_name : generic_type := optional_value
);

2.1.2 Constants

The main use of constant is to apply “legible names” with explicitly defined types instead of literal
values, which are called “hard-coded”. This way the code becomes more readable an easier to maintain
because changing a constant in one place will affect all of its instances in the entire architecture. The
constant is generally used the same way as generic does. Because a constant is not visible from the
outside it cannot declare size of vectors declared as ports in entities. This restriction, however, can be
overcome if the constant is declared in a package used by an entity.
The constants are declaring only one per each line. If two or more constants are of the same type
and have the same value, they can be specifying in one declaration.

constant constant_name : constant_type := value;


……
constant constant_name : constant_type := value;

2.1.3 Constants vs. Generics

Basically the main difference between generics and constants is that generics can be used
dynamically while constants are purely static. This means that you can change the value of a generic
without any changes to the code. However, constants cannot be changed without changing the code.
This is important especially in case when the specification will be used as a component for a high-level
specification. Its time such a component is used, it may assigned new values if they are specified by
generics.
Any change in a generic value would affect all architectures and ports of its entity.
Any change in a constant value would affect the architecture where it is declared and if declare in a
package, in any design unit using the package; this include entities and architectures assigned to them.
Generic are used only in entity.
Constant are used in all declarations: package, entity, architecture, process, block, component.

2.1.4 Ports

There are 5 modes for declaring types of ports:

in -- in data only (reading)


out -- output data only (writing)
inout -- bi-directional port (read-write)
buffer -- similar to inout but restricted to writing to it only.
linkage -- bi-directional port with many restrictions (very seldom use)

Alberto Cerdeira - VHDL: Quick Reference 5


The ports definitions using the standard library can be of types: bit (for single signals, wires) or
bit_vector (for buses). In case of vector the width of the bus and the order of numbered lines or bits
must be explicitly listed. For example, it makes a major difference whether the left bit number is the most
significant bit (MSB) and right number the least significant bit (LSB).
E.g. bit_vector(7 downto 0) where bit 7 is the MSB and bit 0 is the LSB or vice versa bit_vector (0 to 7).

If we use the IEEE standard is enough to declare the std_ulogic (std_ulogic_vector) in case of
use of unresolved functions or std_logic (std_logic_vector) when using resolved functions. This
means that possible conflicts in a bus can be resolved.
The signals can be classified as either internal or external.

•= External signals are the signals that connect the system to the outside word; they form the system
interface. (Declared only in entities).
•= Internal signals are not visible from the outside. Are parts of its internal architecture, providing
signals between internal circuits. (Declared only in architectures).

The ports are also signals but the keyword signal in port is not needed because each port by
definition is a signal. Internal signals do not require mode (in, out, inout, etc) declarations.

2.2 Visibility of Signals

The visibility of each signal is determined by the place in which it is declared: Only higher level
definitions are seen by lower level.

•= A signal declared in a package is visible in all design units which use this package

package MyPack is -- declaration of the signal A inside the package MyPack


signal A

use MyPack -- the next body (entity) will use the package MyPack
entity En1 is
…..
use MyPack -- the next body (architecture) will use the package MyPack
architecture Arch1 of En1 is
…..

•= A signal declared as a port in an entity is visible in all architectures assigned to this entity

entity En2 is -- declaration of the port C inside the entity En2


port (C)

architecture Arch2 of En2 is -- The architecture inside one entity will use all signals
….. signals that were before declared in the entity.
architecture Arch3 of En2 is
…..

•= A signal declared in the declarative part of an architecture is visible only inside this architecture

architecture Arch2 of En2 is -- declaration of the signal B inside the architecture Arch2
signal B -- signal B is not seen by the other architecture Arch3
…..
architecture Arch3 of En2 is -- declaration of the signal C inside the architecture Arch3
signal C -- signal C is not seen by the other architecture Arch2
…...

•= A signal declared in a block located within an architecture is visible only inside this block

P1 : process( ) -- declaration of the signal D inside the process P1


signal D -- signal D is not seen by other same or higher levels
….. like other processes or any of architectures.

Alberto Cerdeira - VHDL: Quick Reference 6


2.3 Data Types

Every piece of information inside a digital system is stored in the form of bit and bit_vector.
However, often it is inconvenient to use this form. For example is much better to represent a 32 bit bus
in an Hexadecimal way than in Binary. Similarly, many complex but regular data structures can be
represented by arrays and physical parameters.

2.3.1 Scalar Types

Scalar type is a generic name that refers to all types whose objects have no elements or internal
structure. VHDL defines several scalar types. However, you may specify your proprietary types, either
range-based or enumerated. Usually, such a user-defined scalar type is declared as a subtype of a type
defined earlier, either as a standard type or other user-defined type.

•= Boolean

type BOOLEAN is (false, true);

In VHDL Boolean values TRUE/FALSE are not equivalent to 1/0 logical values. Therefor, it may not
be assume that True is the same as ‘1’ and vice versa. They are completely different types.

•= Character

type CHARACTER is (null, soh,’+’, …, ‘a’,’b’, …);

The set of values specified in the character types covers all characters defined by the eight-bit
character set ISO 8859-1 (known as Latin-1).

•= Integer

type INTEGER is range –2147483647 to 2147483647;

The range of integer values depends on the implementation but must include the range specified
above. In synthesis, integer type is usually limited to some subset of a complete type (e.g. 0 to 15 or 0
to 99) in order to reduce the number of storage resources.

•= Real

type REAL is range –1.0E308 to 1.0E308;

Real type, also called the floating-point type, is specified with a range, which is implementation
dependent. However, the specified range is the maximum that must be covered by all implementations.
Also all implementations must guarantee a minimum of six decimal digits of precision.

•= Bit

type BIT is (‘0’, ‘1’);

Bit type is an enumeration type that defines two standard logical values: ‘0’, ‘1’. This is the only type
that can be used for logical operations and unlike in gate-level designs.

Alberto Cerdeira - VHDL: Quick Reference 7


2.3.2 User Defined Enumeration Types

An example of User Defined Enumeration Types is when we use a Finite State Machine (FSM)
representing a sequential design. Each state of the FSM is encoded with state variables (flip-flops),
which store information on the actual state.

IDLE

EXECUTE FETCH type FSMStates is (IDLE, FETCH, DECODE, EXECUTE);

DECODE

2.3.3 Physical Types

Physical Types are unique in VHDL because they specify not only the object values but also units in
which the values are expressed. This allows such physical quantities as time, distance, current,
temperature, etc., to be specified with precision. VHDL standard defines only one physical type – time,
but other types can be defined at will. One example how to do this is the following.
There are two kinds of units in physical type declarations: the primary unit (at the header) and
secondary unit that are defined in terms of the primary unit.
Despite their descriptive power, the physical types are not synthesizeable.

type time is range –2147483647 to 2147483647


units
fs;
ps = 1000 fs;
ns = 1000 ps;
us = 1000 ns;
ms = 1000 us;
sec = 1000 ms;
min = 60 sec;
hr = 60 min;
end units;

2.3.4 Predefined Arrays

Arrays are complex types, with a regular structure consisting of elements of the same type. The
unlimited range is specified as: range <>
There are two predefined VHDL arrays: bit_vector (with elements of the type bit) and string
(having elements of the type character).
They differ the way they define the lower limit: the first element of a bit_vector is indexed as 0 and
string starts with 1.
Notes that a single element of those arrays is specified in single quotes, but two or more elements,
called a slice, require double quotes.

signal DataBus : bit_vector(7 downto 0); signal DataBus : bit_vector(0 to 7);

DataBus(7) = ‘0’ DataBus(0) = ‘0’


DataBus(6) = ‘0’ DataBus(1) = ‘0’
DataBus(5) = ‘0’ DataBus(2) = ‘0’
DataBus = “00010001” DataBus(4) = ‘1’ DataBus = “00010001” DataBus(3) = ‘1’
DataBus(3) = ‘0’ DataBus(4) = ‘0’
DataBus(2) = ‘0’ DataBus(5) = ‘0’
DataBus(1) = ‘0’ DataBus(6) = ‘0’
DataBus(0) = ‘1’ DataBus(7) = ‘1’

Alberto Cerdeira - VHDL: Quick Reference 8


2.3.5 User-Defined Arrays

Since the predefined arrays are one-dimensional, they are sometimes called vectors. Every element
in the array is ordered in one dimension. A user, however, may declare an array with an arbitrary
number of dimensions.
A typical application of an array is a memory device, which can be considered to be a two-
dimensional array of bits, grouped into words (vector of vectors).

signal name : array(dim_range1, dim_range2) of element_type

Example of a memory of (1024 x 4) bits:

signal Mem1kx4 : array(0 to 1023) of bit_vector(3 downto 0);

3 2 1 0
0
1
2
3

1021
1022
1023

2.3.6 Records

Records, like arrays, belong to the complex types. They differ, however, in two features: elements of
a record can be different types and they are referenced by names instead of indexes. A reference to a
record element has the following form: record_name: element_name
These names are always written without parentheses.
The primary role of records is to group together different parameters of single object. Each such
object is referenced by a single name, which makes the code more compact and readable.
Not every record can be synthesized, but most synthesizers are able to cope with records of bit,
bit_vector, boolean and integer types.

Type Instr_t is a record


Mnemonic : String;
Code : Bit_vector(3 downto 0);
ExeCycles : Integer;
end record;

signal Instr1, Instr2, Instr3 : Instr_T;

Examples: Instr1.Mnemonic : add reg1, reg2


Instr1.Code : “0010”
Instr1.ExeCycles : 2

Instr2.Mnemonic : or reg1, reg2


Instr2.Code : “0001”
Instr2.ExeCycles : 1

Instr3.Mnemonic : mul reg1, reg2


Instr3.Code : “1110”
Instr3.ExeCycles : 8

Alberto Cerdeira - VHDL: Quick Reference 9


2.4 Expressions and Operators

Apart from very trivial systems, input signals must always be transformed in some way to generate
the desired output signals. This process can be visualized as: outputs <- transformations (inputs).

2.4.1 Logical Operators

Since digital system signals are typically logical signals, the most often used class of VHDL
operators are logical operators as: and, or, nand, nor, xor and xor. The not operation is a one-operand
operation. The logical operations are defined for the types: Bit, Boolean and Bit_vector, so the operands
and result must be from one of these types.
In case of vectors a logical operation is performed on individual bits, i.e. the leftmost bit of the result
vector is computed on the leftmost bit of the operands and so on. This means that the operands and the
resulting vector must be of the same length.

2.4.2 Numerical Operators

This refers to operators performing operations on numerical operands. It covers addition,


subtraction, multiplication, division, modulus, remainder, exponentiation and absolute value.
These operations can be performed both on integer and real types, but require both operands to be
of the same type. The only exception from this rule is exponentiation, where the second operand is
always an integer.
The time type is another exception. In addition and subtraction both most be of the time type, but
the time value can be multiplied by integers and real numbers or divided by an integer. In each case the
result is of the time type.

Addition: 3ns + 1us -- 1003ns


Subtraction: BusWith - 1 -- if BusWith is an integer
Multiplication: Mult * 5ns -- Mult can be either integer or real
Division: 10ns / 2ns -- theresult is 5 (integer, not time)
Modulus: 6 mod 4 -- the result is 2
Remainder: 6 rem 4 -- the result is 2
Exponentiation: A ** 3 -- A^3
Absolute value: abs(5(-2)) -- 10

2.4.3 Relational Operators

The are use to compare two objects. They cover all kinds of comparisons:

equal to ( = )
not equal ( /= )
less than ( < )
less than or equal to ( <= )
greater than ( > )
greater than or equal to ( >= )

The compared objects must be of the same type and can be Boolean, bit, character, integer, real,
time string or bit_vector. However, the result is always Boolean.

Alberto Cerdeira - VHDL: Quick Reference 10


2.4.4 Shift Operators

The shift operators shift elements of one-dimensional arrays. This class of operations is restricted to
arrays, whose elements are of the types Bit or Boolean.
There are 6 shift operands: sll, srl, sla, sra, rol, ror.

Let’s see the operation of shifting with the example:

signal MyBus : bit_vector(7 downto 0) := ”01101001”;

sll -- shift left logical ( the new value inserted after shifting is the default logical value: ‘0’, if
signal is a bit. In case the signal was a boolean type then the default used was ‘false’)

start: ‘01101001’
step1: ‘11010010’ Register 0
step2: ‘10100100’

srl -- shift right logical ( the new value inserted after shifting is the default logical value: ‘0’, if
bit, or ‘false’, if Boolean)

start: ‘01101001’ Register


step1: ‘00110100’ 0
step2: ‘00011010’

sla -- shift left arithmetic ( the new value inserted after shifting is equal to the most right one.
In this case is the ‘1’)

start: ‘01101001’ Register


step1: ‘11010011’ msb
step2: ‘10100111’

sra -- shift right arithmetic ( the new value inserted after shifting is equal to the most left one.
In this case is the ‘0’)

start: ‘01101001’ Register


step1: ‘00110100’ lsb
step2: ‘00011010’

rol -- rotate left logical ( the new value inserted after shifting is the one goes out )

start: ‘01101001’
step1: ‘11010010’ Register
step2: ‘10100101’

ror -- rotate right logical ( the new value inserted after shifting is the one goes out )

start: ‘01101001’
step1: ‘10110100’
step2: ‘01011010’ Register

Alberto Cerdeira - VHDL: Quick Reference 11


2.4.5 Concatenation Operator

Concatenation is a convenient way of creating new values of arrays of any types. This operation is
predefined for one-dimensional arrays.

Example:

Entity Example is

Port( AggVec : out bit_vector(0 to 7)


);

end Example;

architecture Concatenation of Example is

Data1 : bit_vector(0 to 7) := “10110010”;


Data2 : bit_vector(0 to 7) := “00101010”;
BitOne : bit := ‘1’;

begin

AggVec <= (Data2(3 to 5) & Data1(0 to 3) & BitOne); --- AggVec = 01010111

end Concatenation;

2.4.6 Assigning Expressions to Signals

The assignment mechanism is simple: the target signal appears on the left, followed by the
assignment symbol (<=) and then the expression. Notes that this symbol (=>) exists also in VHDL but
has totally different use and meaning.

Examples:

x <= y <= z; -- It is not a “pipelined assignment” ( z to y and then to x), but the boolean result of
the comparison (y less or equal to z) is assigned to signal x.

a <= b or c; -- This is a typical assignment for a logical operation. (legal for boolean, bit and
bit_vector types).

k <= ‘1 ; -- This is a classical assignment. Place the value in apostrophes if it is a single bit
or a character value. Do not use apostrophes if boolean, integer, real or
enumeration types.

m <= “0101”; -- Assignment of a bit_vector or string value (depending on the type of m signal).
See that the value is in double quotes. The number of elements on the right and left
must match.

n <= m & k; -- Bit vectors can be merged with single bits to form a new vector. The number of
elements in the declared target signal must match the total number of bits merged.

Alberto Cerdeira - VHDL: Quick Reference 12


2.4.7 Assignments with Delay

In the real world nothing happens instantly, all systems have their own delay. In VHDL this fact is
modeled by the after clause added to any signal assignment statement. (The after clause cannot be
synthesized, is only use during simulation proposes).

There are two delays declaration used in VHDL: Inertial and Transport.

2.4.7.1 Inertial Delay

Inertial Delay is typical of most real-life systems and because of that, it is the default delay model in
VHDL. The after automatically assumes the inertial delay. A classical inertial process can be a led. If
applying power on to a led and then power off it, faster than the time (delay time) it needs to light, we will
not see any lighting. The same happens with the flip-flops, no signal will be output if the input pulse is
shorter than the time needed to read it. This kind of delay is also known as setup time.

Output <= Input after 3s;

2.4.7.2 Transport Delay

Transmission lines have not inertial delay but transport delay.

Output <= transport Input after 3s;

2.4.7.3 Inertia vs. Transport Delay

The inertial and transport delay models are sufficient for describing any physical system in VHDL.
Their main similarities and differences are as follows:

•= Inertial delay is the default delay in VHDL and does not require any additional declaration.
Transport delay requires the transport keyword to be used.

•= Inertial delays do not propagate impulses shorter than the specific delays.
Transport delay propagates all changes of the input signal no matter how fast or how often
they may appears.

•= Inertial and transport delays are specified using the after clause, followed by the time value.

•= Both inertial and transport delay can be applied to signals of any type.

Alberto Cerdeira - VHDL: Quick Reference 13


3 Process in VHDL
3.1 Process declarative part

Process is a formal way of making such a list of sequential operations. It has a very structured
format, even if it represents behavior of only a minor part of a design.
Process is declared by the process keyword. You may assign a name to a process if you want. The
list of statements in a process starts from the keyword begin and terminate with end process.
name: process (sensitivity list)
declarations;
begin
sequential statments;
end process name;

Any process may have a sensitivity list. The process is resume any time one or more of the
parameters in the sensitivity list changes. If not parameters declared the process is always executing. In
declarations we define variables and constants.

MUX2TO1: process (A, B, SEL)


constant high : bit := ‘1’;
begin
Y <= A;
If (SEL = ‘1’) then Y <= B;
end if;
end process MUX2TO1;

There are various conditions that are used to stop and/or resume a process. In VHDL we use 3
types of wait statements:

•= wait for type_expression -- waiting for some time to elapse

wait for 10ns; wait for ClkPeriod / 2;

•= wait until condition -- waiting until some Boolean conditions is met

wait until CLK=’1’;


wait until CE and ( not RST );
wait until IntData > 16;

•= wait on sensitivity_list -- waiting for a change of the signal value

wait on CLK;
wait on Enable, Data;

•= If several of these conditions are mixed, they form the fourth construct called complex.

wait on Data until CLK = ’1’;


wait until Clk =’1’ for 10ns;

The wait statement can be located anywhere inside the sequential statements. When the process
found a wait the execution stops and resumes (continues from the next statements after the wait) only
after the conditions are fulfilled. If the wait is the last statement of the process, it resumes starting from
the beginning.

Waiting on sensitivity list, i.e. waiting for a change of the signal value is probably the most often
used condition for resuming processes. The sensitivity_list has the same function as the wait on at the
end of a process.

Alberto Cerdeira - VHDL: Quick Reference 14


3.2 Multiple Process in an Architecture

Real systems have many subcircuits working at the same time. The architecture body has a
concurrent structure, which is sometimes hard to imagine because all statements (process and their
contents) are listed sequentially. Nevertheless, all processes in any architecture are executed
concurrently with each other. Whenever a signal on the sensitivity list of a process changes its value, the
process is activated. This happens regardless of whether the signal has been changed by the system’s
environments, by other processes or even by the same process (non-advisable).

A Microcomputer is a classical example of process concurrency within a complex system.

CPU Memory I/O System Floppy Hard Disk

Microcomputer

Architecture Example of Microcomputer is


begin
CPU: process
begin
…..
end process CPU;
CPU: process
begin
…..
end process CPU;
Mem: process
begin
…..
end process Mem;
I_O: process
begin
…..
end process I_O;
FDD: process
begin
…..
end process FDD;
HDD: process
begin
…..
end process HDD;
end architecture Example;

Signals cannot be declare inside processes. Any assignment to a signal takes effect only when
the process suspends. Until that happens, all signals keep their previous values. Only the last
assignment to a signal listed inside a process is effective.
Since signals can store only the last value assignment, they cannot be used for storing intermediate
or temporary data within a process. For that in VHDL an object called variable is used to store temporary
data. Variable are similar to signals. However because of their specific applications they can be used
only for description of algorithms inside processes and cannot have delay applied. Variables are
declared only inside processes.
An assignment to a variable is made with the ‘:=’ symbol. This assignment takes instant effect and
each variable can be assigned new values as many time as needed.

Alberto Cerdeira - VHDL: Quick Reference 15


Signals have 3 properties: type, value and time while variables have only 2: type and value. They
can be assigned to each other as long as both are of the same type.

Lets suppose that signal were A=B=C=D=E=1.


Process (C,D) What will happen if signal D changes to 2 ?
variable Av, Bv, Ev : integer := 0; Process starts executing after a change in signals C or D.
begin Begin -- Av = Bv = Ev = 0
Av := 2; Av := 2; -- Av = 2
Bv := Av + C; Bv := Av + C; -- Bv = 3
Av := D + 1; Av := D + 1; -- Av = 3
Ev := Av * 2; Ev := Av * 2; -- Ev = 6
A <= Av; A <= Av; -- A = 3
B <= Bv; B <= Bv; -- B = 3
E <= Ev; E <= Ev; -- E = 6
end process; End process -- A = 3, B = 3, C = 1, D = 2, E = 6

Some Processes are so simple that can be assigning inside the architecture in so called concurrent
signal assignment. These can be done because all assignments inside architecture are concurrent. A
concurrent signal assignment statement can appear inside architecture in parallel with some processes
and can be executed concurrently with other assignments, similarly to processes. If two or more
assignments appear in a process, they will be executed in the listed sequence. However, if they were
represented by concurrent signal assignment, they would be executed concurrently.

architecture Arch1 of Example is


signal Int1, Int2 : bit;
begin
Gate1: process (A,C)
begin architecture Arch1 of Example is
Int1 <= A or C; signal Int1, Int2 : bit;
end process Gate1; begin
Gate2 : process (B,D) Int1 <= A or C;
Begin Int2 <= B or D;
Int2 <= B or D; Out <= Int1 and Int2;
end process Gate2; end architecture Arch1;
Gate3 : process (Int1, Int2)
begin
Out <= Int1 and Int2;
end process Gate3;
end architecture Arch1;

3.3 Activation of Concurrent Assignments

S
architecture Gates of Mux2to1 is
signal AOK, BOK, NS : bit, A AO K
begin
AOK <= A and S after 1 ns;
BOK <= B and NS after 1 ns; NS
NS <= not S after 1ns; Z
Z <= AOK or BOK after 1 ns;
end architecture Gates

B BO K

Concurrent signal assignment statements are sensitive to a change of any signal that appears to
the right from the assignment symbol. The order of the statements are not important, because all have
the same priority, all are concurrent. On the contrary from a process the assignment can be delayed with
the after clause, either with an inertial or transport delay model.

Alberto Cerdeira - VHDL: Quick Reference 16


3.4 Controlling the Sequence of Statements (Finite State Machine)

The changing environment conditions are represented in VHDL by four classes of conditional
statements:
•= Conditional execution of statements ( if…then… statements )
•= Conditional execution with alternatives ( if…then…else… and if…then…elseif… statements )
•= Multiple choice of statements ( case… statement )
•= Loops, allowing repeating the execution of some statements ( while…do… statement and
for…do… statements ).

ExProc:process
(Sensitivity_List)

then if Cond1 else

while Cond3
...
loop

...
case Cond2 is others

For I in 1 to 4 end loop


Val1 Val2 loop

... ... ... ...

end loop

end case

end if

...

end process

ExProc : process(Sensitivity_List )
begin
if Cond1
then

case Cond2 is
when Val1 => …
when Val2 => …
when others => for I in 1 to 4 loop

end loop;
end case;
else
while Cond3 loop

end loop;

end if;

end process ExProc;

Alberto Cerdeira - VHDL: Quick Reference 17


Package TYPES is
TYPE STATE_TYPE is (STATE_1, STATE_2,.., STATE_N, STATE_RESET);
Constant …
SUBTYPE …
end TYPES;

use WORK.TYPES.ALL; -- use the TYPE package

Entity Control_Unit is
Port (

);
end ControlUnit;

Architecture FSM of Control_Unit is


SIGNAL CURRENT_STATE, NEXT_STATE : STATE_TYPE; -- signal for stored values
SIGNAL …
Begin

NEXT_ST: PROCESS (CURRENT_STATE, RESET, …) – list of all process sensitive signals


BEGIN

NEXT_STATE <= CURRENT_STATE;

Signal…<= …?

IF (RESET = '1') then


NEXT_STATE <= STATE_RESET;
ELSE

CASE CURRENT_STATE IS

WHEN STATE_1 =>


….
WHEN STATE_2 =>
….
WHEN STATE_N =>
….
WHEN STATE_RESET =>
….
WHEN OTHERS =>
….

END CASE;

END IF;

END PROCESS NEXT_ST;

SYNCH: PROCESS
BEGIN
wait until CLOCK'event and CLOCK ='1';
CURRENT_STATE <= NEXT_STATE;

END PROCESS SYNCH;

END FSM;

Alberto Cerdeira - VHDL: Quick Reference 18


3.5 Conditional Statements

Some operations are performed only when listed conditions are met. Such operations are called
conditional. Syntaxes: if condition_met then execute_operations. If true go through then if false go
thru else. Let’s see in an example of a simple D-FF.

D_FF 1: process (D, CLK)


begin
D Q
If rising_edge(CLK)
then D_FF
Q <= D; CLK
end if;
end process D_FF1;

Now we give more flexibility adding a synchronous Reset and Preset to our Example of D-FF.
Syntaxes: if condition_met then execute_operations elseif condition_met then … elseif …

D_FF2 : process (D, CLK, Rst, Set)


begin
If Rst = 1
Rst Set
then
Q <= ‘0’;
elseif Set = 1
then
Q <= ‘1’; D Q
elseIf rising_edge(CLK) D_FF
then CLK
Q <= D;
end if;
end process D FF2;

3.6 Multiple Choices

The if…then…elseif… construct is a multiple-choice statement that allows selecting only one
branch out of several, depending upon the encountered conditions. A more readable construction when
many decision have to be taken is the multiple-choice case statement.
architecture CaseBased of ProgrammmableGates is
ProgrGate : process (Mode, PrGIn1, PrGIn2) Mode1 Mode2 Mode3
begin
case Mode is
when “000” => PrGOut <= PrGIn1 and PrGIn2;
when “001” => PrGOut <= PrGIn1 or PrGIn2;
PrGIn1 Programmable PrGOut
when “010” => PrGOut <= PrGIn1 nand PrGIn2;
when “011” => PrGOut <= PrGIn1 nor PrGIn2; Gate
when “100” => PrGOut <= not PrGIn1; PrGIn2
when “101” => PrGOut <= not PrGIn2;
when others => PrGOut <= ‘0’;
end case;
end process ProgrGate;
end architecture CaseBased;

Important! In (case signal_name is) structure the signals used (Signals in the previous example are
Mode and PrGOut) must be static. This means that any parameter defined for them like bus width must
be declared directly or using Constant. Definition of kind Generic is not allowed. These constraints are
the same for the (with signal_name select) structure. To avoid this, use (if condition then).

Alberto Cerdeira - VHDL: Quick Reference 19


3.7 Conditional Loop

This loop is iterated as long as the condition at the beginning is true. The control is passed to the
next statements after the loop finished. Syntaxes: while condition_true loop

Example: Count Clk pulses while signal Level is high.

Process
variable Count : integer := 0;
begin
wait until Clk = ‘1’;
while Level = ‘1’ loop
Count := Count + 1;
wait until Clk = ‘0’;
end loop;
end process;

3.8 Loop with a Counter

The while loop repeats its contents an unlimited number of times as long as the condition specified
in the loop header is true. What happen if we want to repeat the operations only a selected number of
times. In this case we use a for loop.
A for loop does not contain an explicit boolean condition. Instead, a discrete counter is specified
with a range and as long as the counter falls within that range, the loop is iterated.
The counter range does not need to be specified in the classical for as from…to… It can also be
listed as a subtype or enumeration type. In such a case only the (subtypes is specified as the range of
the counter.

Example: Reversing the bit of a byte ( Flip a Byte )

constant MSB : natural := 7;


subtype BusRange is natural range MSB downto 0;
signal SourceBus : bit_vector(BusRange);

ReverseBus: process (SourceBus)


variable ResultBus : bit_vector(BusRange);
begin
for Cntr in BusRange loop
ResultBus(MSB – Cntr) :=
SourceBus(Cntr);
end loop;

3.9 Breaking Up Loops

The while and for loop iterate and execute all their statements as long as the iteration condition is
met. Sometimes, however, it is decidable to skip some of the loop statements in the current iteration and
go directly to the next iteration of the same loop, or even to exit the loop and terminate the execution of
the loop.
The jump to next iteration and jump out of loop (exit) operations can be assigned a condition of
their execution. This condition are specified in a when clause which is following the statement.

Example: Counting bits with a value of ‘1’ in a bit vectors and exit if they are more than 4.

for Cntr in 16 downto 0 loop


Signal DataBus : bit_vector(3 downto 0); next when DataBus(Cntr) = ’0’;
signal Ones : integer; NumOfOnes := NumOfOnes + 1;
exit when NumOfOnes >= 4
CountOnes: process (DataBus) end loop;
variable NumOfOnes : integer := 0; Ones <= NumOfOnes;
begin
end process CountOnes;
Alberto Cerdeira - VHDL: Quick Reference 20
3.10 Conditional Signal Assignment

Perform a signal assignment when a condition is true. Since the if…then… conditional assignment
is a sequential statement that is restricted to processes only, you may have to use the conditional signal
assignment which can also be used inside architectures. It is a functional equivalent of the conditional
statement but is written in a different way to distinguish it from the conditional signal assignment.

The important difference between conditional signal assignment and conditional assignment is that
the first is restricted to signal assignments only and the last can be used for any kind of sequential
statements.

Example of a Mux 2 to 1 using conditional signal assignment


S
architecture Conditional of Mux2to1 is
begin
Z <= A when S= ‘1’ else A
B; Mux2to1 Z
end architecture Conditional; B

Example of the same Programmable Gate, this time using conditional signal assignment instead of using
the multiple-choice statement.

architecture SelBased of ProgrammmableGates is

begin
Mode1 Mode2 Mode3
with Mode select
PrGOut <=

PrGIn1 and PrGIn2 when “000”,


PrGIn1 or PrGIn2 when “001”, PrGIn1 Programmable PrGOut
PrGIn1 nand PrGIn2 when “010”,
PrGIn1 nor PrGIn2 when “011”, Gate
PrGIn2
not PrGIn1 when “100”,
not PrGIn2 when “101”,
‘0’ when others;

end architecture SelBased;

To conditionally assign to a signal one of several values, use the selected signal assignment
construct. It is a concurrent construct that cannot be used inside processes, where the case statement
should be used instead. The opposite is true as well: a case statement cannot be used outside
processes, were the selected signal assignment construct should be used.
Unlike the case statement, the selected signal assignment is restricted to signal assignments only and
cannot contain another statements.

Alberto Cerdeira - VHDL: Quick Reference 21


4 Attributes of Signals
4.1 The Concept of a Driver

As we saw already, when signals are assigned their new values inside processes, this assignment
is taking place only after the process is suspended. Moreover, if there is more then one assignment to a
signal, only the last one will take effect, because we are in presence of sequential statements.

How VHDL store information about signal events inside processes?

Using the driver performs these functions. The VHDL compiler creates a driver for every signal that
is assigned a value inside a process. The rule is very simple: no matter how values are assigned to the
signal in a process, there is only one driver per signal per process. All operations are performed on the
driver, which is copied to the signal only when process suspends.

ExProc: process (SigA, SigB)


begin
In this case the signal SigC will leave the process with the
SigC <= SigA;
SigC <= SigB + 1; last value assigned.
end process ExProc;

How VHDL store information about signal events outside processes, were the statements are
concurrent we will see later on “Signals with many drivers”.

Thanks to its driver a signal can have its past, current and future values. Drivers containing the
current signal value were shown on the previous box. However, drivers can also specify the projected
output waveform for a signal. Each driver can be assigned such a waveform consisting of a sequence of
one or more transaction. A transaction consists of a signal value and time. Time specifies the instant
when the driver will be assigned the new value specified by the transaction.
A waveform can be specified explicitly as a sequence of values and the associated delays related to
the same point in time. Waveforms can be considered as projected future of a signal. Since simulators
store transactions for each signal, they create in effect the history of signals.

SignalEx <= ‘0’ after 2 s, Time [s] 0 1 2 3 4 5 6 7 8 9


‘1’ after 5 s, SignalEx ‘0’ ‘0’ ‘0’ ‘0’ ‘0’ ‘1’ ‘0’ ‘0’ ‘1’ ‘1’
‘0’ after 6 s,
‘1’ after 8 s; SignalEx

Time [s] 0 1 2 3 4 5 6 7 8 9 10

Describing the future signals is important for creating so called test benches, where a VHDL
specification is tested in a VHDL environment and stimuli are represented by waveforms.

Why do we need a signal history?

For example, having only the current vale would not allows us to check whether a signal has
changed recently, or to verify whether it was a rising or a falling edge. The signal history is represented
by signal attributes. The attributes are pieces of information attached to a signal and automatically
updated based on the signal’s history. The information includes the previous value of the signal
(‘last_value), the amount of time that has elapsed since the last change of the signal value
(‘last_event), etc. To get the current attribute you need to specify the signal’s name followed by an
apostrophe and the attribute’s name. Every time an assignation happens, means a ‘Transaction occurs.
Time [s] 0 1 2 3 4 5 6 7 8
SignalEx 0 0 0 0 0 1 0 0 1
SignalEx’Transaction False False True False False True True False True
SignalEx’Event False False False False False True True False True
SignalEx’Last_event Max time Max time Max time Max time Max time 0 0 1 0
SignalEx’Last_value 0 0 0 0 0 0 1 0 0

Alberto Cerdeira - VHDL: Quick Reference 22


4.2 Other Signal Attributes

Attributes related to the history of signals are not the only attributes available. In fact, attributes are
quite often used in VHDL and the language defines 36 different attributes for different classes of objects:
scalar types, discrete types, array types, array signals and named entities. See Appendix ___.
Apart from the predefined attributes you may also define your attributes, extending the VHDL set
almost indefinitely.
Attributes have many applications – from edge detection (based on the ‘event attribute) to size-
independent specifications. Some of the most typical examples of the attribute applications are
presented in the following examples.

Example: Edge detection.

In order to verify whether a signal (usually CLK) has a rising or falling edge, it is necessary to
know that it just changed it value and the actual value is ‘1’ or ‘0’, respectively. The first condition can
be verified by the ‘event attribute and the entire condition looks as follows: rising edge first, then falling
edge.

If CLK’event and CLK=’1’ and CLK’last_value=’0’ then … -- rising edge sensitive

If CLK’event and CLK=’0’ and CLK’last_value=’1’ then … -- falling edge sensitive

Example: Universal loop.

To avoid hard-coded loop boundaries a range attribute can be used. No matter what is specified
for the DataArray one –dimensional array (including bit vectors), the loop will iterate exactly the same
number of times, as there are elements in the array. Such universal ranges facilitate easy code
maintenance. Note that the loop can iterate in the listed and in reverse order.

for i in DataArray’range loop


for i in DataArray’reverse_range loop

Example: Index of most significant bit.

Sometimes you may need the index of the most significant bit in a bit_vector. Instead of writing it
as a “hard-coded” number, which is difficult to maintain in case of changes, it can be easily extracted
using the ‘left’ attribute. Similarly, the least significant (rightmost) bit index can be determined with the
‘right’ attribute.

ArrayType’ left

ArrayType’ rigth

Example: Setup time.

Setup time is violated when the last signal event before active edge of the clock took place in less
than the “setup” time. In the example below the Setup violated boolean variable will become true
when the setup time on SomeSignal is violated. This is how errors are automatically reported in
VHDL.

If CLK’event and CLK = ’1’ and CLK’last_value=”0” then

SetupVioleted := SomeSignal’last_event < SetupTime;

Alberto Cerdeira - VHDL: Quick Reference 23


4.3 Can a signal Have Two Drivers?

When a signal has only one driver, its value is easy to determine. However, what happens when a
signal has multiple drivers? What signal values will such drivers generate?
Signal with multiple sources can be found in numerous applications. For example, the computer
data bus may receive data from the processor, memory, disk and I/O devices. Each of those device
drivers the bus and each bus signal line may have multiple drivers. Since VHDL is a language for
describing digital systems, such multiple drivers are handled in VHDL with easy.

It is difficult to determine in advance if a “multiple-source” signal will always be driven by a single


source only. In some systems this will always be true, while in others it may be even desired to mixed
signals from different sources, emulating for example the “wired AND” or “wired OR” operations.
Generally, multiple-source signals require establishing a method for determining the resulting value
when several sources are concurrently feeding the same signal line.

4.4 Multiple-Driver Signal Must be Resolved

A VHDL simulator cannot “know” in advance whether a signal with multiple drivers will never be
activated from two or more sources at the same time. Because of that the simulator must be prepared
for mixing the signals values. Such “mixing” of signals is called in VHDL resolving. The rules for mixing
signal values are specified as a table, which is called the “resolution function”. The table lists all
possible signal values in columns and rows and each cell contains information on what value will be
generated if the two values are mixed.

Example: a resolution function for a RGB color resolving.

R G B
R R R/G R/B
G G/R G G/B
B B/R B/G B
4.5 Two-Value Logic is not enough for Resolution

As you have probably noticed on the previous example, the resolution function requires more than
the basic set of values – three basic colors needed an additional three to be solved. Similar situation
appears when considering how to represent multiple-source signal in VHDL. When we take a look at the
bit signal type, an obvious question arises: what will happen if we mix ‘0’ and ‘1’ (what is the resolved
value of ‘0’ and ‘1’?). The problem with the bit type is that is not possible to specify resolved signals with
only two values and there is not answer the above question.
This fact has very far-reaching consequences: if you are using only bit and bit_vector types, you are
NOT able to specify a microprocessor in VHDL.
Unresolved types (like the two mentioned) cannot be used for multiple-driver signals, which in turn
are necessary to specify data buses (which obviously exist in every microprocessor). To solve this
problem you must use some other logic data type, one with more than two values and a resolution
function defined for all signal values combinations.

4.6 Multi-Value Logic

The value of ’0’ and ‘1’ alone are not sufficient for resolving multiple-source signals. Even some
single-source signals often require more than two values for representing real-life digital objects:

•= Sometimes it is not important what value a signal has. This condition it is represented by the “don’t
care” value.
•= Tri-state buffers disconnect drivers from signal lines with a “high impedance” state, which is neither
‘0’ nor ‘1’.
•= Occasionally, a system can have an “unassigned” or “unknown” value, which is different from “don’t
care”.

Alberto Cerdeira - VHDL: Quick Reference 24


Those 3 and several other most often used values are specified by the std_ulogic type, defined in
the Std_Logic_1164 package. This package also contains a definition of a vector type, which is based
on the std_ulogic type and std_ulogic_vector elements. Both types also have a set of basic logical
operations defined for them.

NOTE: The letter ú’ inside the ulogic name indicates “unresolved types”. Such values cannot be
used with signals that have multiple drivers.

Example: Declarations.

The std_ulogic type is declare in the std_logic_1164 package and contains nine enumerated
values (MVL9). The std_ulogic_vector is a non-limited vector of std_ulogic elements.

TYPE std_ulogic is
( ‘U’ , -- Uninitialized
‘X’ , -- Forcing 0 or 1
‘0’ , -- Forcing 0
‘1’ , -- Forcing 1
‘Z’ , -- High impedance
‘W’ , -- Weak 0 or 1
‘L’ , -- Weak 0 ( for ECL open emitter)
‘H’ , -- Weak 1 (for open Drain or Collector)
‘-‘ , -- don’t care
);

TYPE std_ulogic_vector IS ARRAY


( NATURAL RANGE <> ) of std_ulogic;

Example: In order to Use…

The type std_ulogic and std_ulogic_vector are not defined in the VHDL standard and such
have to be used from an external package. This requires using library and the ‘use’ statements as
presented below. Usually they are specified before the entity header.

Library IEEE;
use IEEE.Std_Logic_1164.all;

Example: Logical operators

All logical operators available for bit and bitvector types are available for std_ulogic and
std_ulogic_vector, respectively. This relates to and, nand, or, nor, xor and not operators. The
specification bellow shows what values can be expected from applying the AND operator to
std_ulogic values.

CONSTANT and_table : stdlogic_table := (


-- -------------------------------------------------------------------------
-- | U X 0 1 Z W L H - | |
-- -------------------------------------------------------------------------
( ‘U’, ‘U’, ‘0’, ‘U’, ‘U’, ‘U’, ‘0’, ‘U’, ‘U’), -- | U |
( ‘U’, ‘X’, ‘0’, ‘X’, ‘X’, ‘X’, ‘0’, ‘X’, ‘X’), -- | X |
( ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’), -- | 0 |
( ‘U’, ‘X’, ‘0’, ‘1’, ‘X’, ‘X’, ‘0’, ‘1’, ‘X’), -- | 1 |
( ‘U’, ‘X’, ‘0’, ‘X’, ‘X’, ‘X’, ‘0’, ‘X’, ‘X’), -- | Z |
( ‘U’, ‘X’, ‘0’, ‘X’, ‘X’, ‘X’, ‘0’, ‘X’, ‘X’), -- | W |
( ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’), -- | L |
( ‘U’, ‘X’, ‘0’, ‘1’, ‘X’, ‘X’, ‘0’, ‘1’, ‘X’), -- | H |
( ‘U’, ‘X’, ‘0’, ‘X’, ‘X’, ‘X’, ‘0’, ‘X’, ‘X’), -- | - |
);

Alberto Cerdeira - VHDL: Quick Reference 25


Example: rising / falling edge

For greater convenience two additional functions are defined for signals of std_ulogic:
falling_edge and rising_edge. They check whether a falling edge or a rising edge, respectively, was
detected on the selected signal. The result is given as a boolean value. The D-type flip-flop in the
below representations is specified using both the rising_edge function and a description without it.

If rising_edge(CLK) if ( CLK’event and CLK= ’1’ and CLK’last_value= ’0’ )


then Q <= ‘D’; then Q <= ‘D’;
end if; end if;

4.7 Resolved Multi-Value logic

The Std_ulogic type supports all the values that may be needed to specify a typical digital system.
It is, however, unresolved, which makes it still useless in case of multiple-driven signals. Because of that
one more type is defined in Std_Logic_1164 package: std_logic. It connects the expressive power of
nine values of std_ulogic with resolution, giving a VHDL designer a really universal logical type.
Std_logic is nowadays a defacto industrial standard.
The only difference between std_logic and std_ulogic is that the former is a resolved version of the
latter. Thanks to that, all the operations and functions (including rising_edge and falling_edge) defined
for std_ulogic can be used with std_logic without any additional declarations.
There is a resolved version of std_ulogic_vector as well. Its name is quite logical: std_logic_vector
(resolved functions remove the ‘u’ from the name)

Example: Resolution Table for std_logic type

U X O 1 Z W L H -
U ‘U’ ‘U’ ‘U’ ‘U’ ‘U’ ‘U’ ‘U’ ‘U’ ‘U’
X ‘U’ ‘X’ ‘X’ ‘X’ ‘X’ ‘X’ ‘X’ ‘X’ ‘X’
0 ‘U’ ‘X’ ‘0’ ‘X’ ‘0’ ‘0’ ‘0’ ‘0’ ‘X’
1 ‘U’ ‘X’ ‘X’ ‘1’ ‘1’ ‘1’ ‘1’ ‘1’ ‘X’
Z ‘U’ ‘X’ ‘0’ ‘1’ ‘Z’ ‘W’ ‘L’ ‘H’ ‘X’
W ‘U’ ‘X’ ‘0’ ‘1’ ‘W’ ‘W’ ‘W’ ‘W’ ‘X’
L ‘U’ ‘X’ ‘0’ ‘1’ ‘L’ ‘W’ ‘L’ ‘W’ ‘X’
H ‘U’ ‘X’ ‘0’ ‘1’ ‘H’ ‘W’ ‘W’ ‘H’ ‘X’
- ‘U’ ‘X’ ‘X’ ‘X’ ‘X’ ‘X’ ‘X’ ‘X’ ‘X’

Alberto Cerdeira - VHDL: Quick Reference 26


5 Specifying the System’s Structure
5.1 Introduction to Structural Description

Behavioral VHDL description specifies systems in terms of their operations. The structural
description specifies what is the system made of, what do the subsystems or components consist of and
how they are interconnected.
Structural description allows having multiple levels of hierarchy and a component can be specified
either with a behavioral or structural description. In the latter case it is composed of sub-components,
etc. Finally, on the lowest level each primitive component is specified in behavioral way.

Block 1 Block 2 Block 3

Behavioral Structural Behavioral

Block 2.1 Block 2.2

Behavioral Behavioral

5.2 Elements of Structural Description

A structural specification consists of interconnected components. These components are connected


with each other and their external environment through signals. A structural specification requires two
groups of elements:
•= A component can be an individual system, specified as a separate entity and architecture.
•= A component can be defined inside architecture with the component declaration.

In both cases the component declaration is treated as a general specification – something like a
catalog item. To use such items they must be instantiated in the structural specification.
Component instantiation is thus the basic statement in a structural architecture. Similar to other
architecture statements, component instances are concurrent with each other.
A component instance is not complete without a port map – a reference of the actual port name in
the higher-level structural description and formal port, which is specified in the component entity port
clause. Signals used in port maps can be either specified as port or internal to the system. The latter
must be declared in declarative section of the architecture.

5.3 Components and Component Instances

Effective use of components is the focal point of the structural VHDL descriptions. The entire next
section will be devoted to this topic.
Generally, a component is any module specified either in behavioral or structural way. In its simplest
form, a component is an entity with the associated architecture. Before a component can be used, it
must be instantiated. Instantiation is selecting a compiled specification in the library and linking it with
the architecture where it will be used.

Each component instance consist of the following parts:

instance_name: entity Where ‘work’ is the name of the library where all
work.entity_name(architecture_name) user-defined items are saved.

Alberto Cerdeira - VHDL: Quick Reference 27


DLatch_En Latch
DLatch
Din D Q Qout

Gate
And2 Clk
Clk In1
IntClk
Out1
En In2

Entity Dlatch_En is -- Entity type componet And2


Port (Din, Clk, En : in bit;
Qout : out bit ); entity And2 is
end entity Dlatch_En; port (In1, In2 : in bit ;
Out1 : out bit);
architecture Struct of Dlatch_En is end entity And2;
signal IntClk : bit;
begin architecture Beh of And2 is
begin
gate: entity work.And2(Beh) Out1 <= In1 and In2 after 2 ns;
end architecture Beh;
port map (In1 => Clk,
In2 => En, -- Entity type componet Dlatch
Out1 => IntClk);
entity Dlatch is
latch: entity work.Dlatch(Beh) port (D, CLK : in bit ;
Q : out bit);
port map (D => Din, end entity Dlatch;
Clk => IntClk,
Q => Qout); architecture Beh of Dlatch is
begin
end architecture Struct; process (Clk, D)
if Clk = ’1’ then
Q <= D after 3 ns;
end if;
end process;
end architecture Beh;

5.4 Port Mapping

Component instantiation cannot be completed without appropriate port mapping – assignment of


actual signals in the system to the formal port of the component declaration.
The mapping that is used in the enclosed example is called named association because each port
is assigned a signal using the explicit port name. A simpler form is positional association where signals
in port mapping are listed in the same order as the ports in the component’s entity declaration.

Alberto Cerdeira - VHDL: Quick Reference 28


5.5 Direct Instantiation

Direct entity instantiation is the simplest way to specify a structural system. The only things that are
needed is a compiled specification of the component that will be instantiated and its instantiation
statements.

The direct instantiation statement consist of:

•= A mandatory label for the component that is necessary because one component can be instantiated
more than once in each architecture,
•= The keyword entity followed by the name of the library and the entity containing the specification of
the component,
•= Optionally, architecture name enclosed in brackets and the port map clause.

Since all user-defined specifications are compiled into the work library, the library in the component
instantiation statement will be called work as well.
The name of the architecture is needed only when there are several architectures in a single entity.
If the specification of a system that is being used as a component, consists of only one architecture, the
architecture name can be omitted.

entity SomeSystem is
MyGate port (…);
A
end entity SomeSystem;
C
B architecture Struct of SomeSystem is
begin
Mygate: entity …
….
end architecture Struct;

And2 Nand2

entity And2 is entity And2 is


port (In1, In2 : in bit ; port (In1, In2 : in bit ;
Out1 : out bit ); Out1 : out bit );
end entity And2; end entity And2;

architecture Beh of And2 is architecture Beh of And2 is


begin begin
Out1 <= In1 and In2 after 2ns; Out1 <= In1 nand In2 after 2ns;
end architecture Beh; end architecture Beh;

Or2 Nor2

entity And2 is entity And2 is


port (In1, In2 : in bit ; port (In1, In2 : in bit ;
Out1 : out bit ); Out1 : out bit );
end entity And2; end entity And2;

architecture Beh of And2 is architecture Beh of And2 is


begin begin
Out1 <= In1 and In2 after 2ns; Out1 <= In1 and In2 after 2ns;
end architecture Beh; end architecture Beh;

Alberto Cerdeira - VHDL: Quick Reference 29


5.6 Positional Port Association

Each port map specifies connections between ports of an entity (component) and signals in the
architecture where the component is instantiated.
These are two ways of port mapping: positional port association and named port association.
In the positional association, signals are listed in the same order as ports have been declared in the
component’s entity declaration. This way, the connections between signals and ports are specified by
their position. For example, the first signal on the list is connected to the first port, the second signal to
the second port, etc. Of course, you must use signals of the same type as their respective ports.

MyGate entity SomeSystem is


A port (…);
In1 end entity SomeSystem;
C
B Out1 architecture Struct of SomeSystem is
In2 begin
MyGate: entity work.And2
port map (A, B, C);

end architecture Struct;

MyGate entity SomeSystem is


C port (…);
In1 end entity SomeSystem;
B
A Out1 architecture Struct of SomeSystem is
In2 begin
MyGate: entity work.And2
port map (C, A, B);

end architecture Struct;

MyGate entity SomeSystem is


B port (…);
In1 end entity SomeSystem;
A
C architecture Struct of SomeSystem is
Out1
In2 begin
MyGate: entity work.And2
port map (B, C, A);

end architecture Struct;
And2

entity And2 is
port (In1, In2 : in bit ;
Out1 : out bit );
end entity And2;

architecture Beh of And2 is


begin
Out1 <= In1 and In2 after 2ns;
end architecture Beh;

Alberto Cerdeira - VHDL: Quick Reference 30


5.7 Named Port Association

The positional association of signals and ports seems like natural way. However, sometimes it may
cause problems in determining which signals are connected to which ports. This is particularly true when
there are many signals on the list.
A handy solution to this problem is the named association. In this type of association, signals are
assigned the names of the associated ports. This way the order of the ports is irrelevant and the direct
relationships between formal ports and actual signals can be observed.
The association between ports and signals is represented by the => symbol. Note that this symbol
has nothing to do with the direction the information flow through the port.

MyGate entity SomeSystem is


port (…);
A end entity SomeSystem;
In1
C architecture Struct of SomeSystem is
Out1
B In2 begin
MyGate: entity work.And2
port map (In1 => A,
In2 => B,
Out1 => C);

end architecture Struct;
MyGate
entity SomeSystem is
C port (…);
In1
end entity SomeSystem;
B
A Out1
In2 architecture Struct of SomeSystem is
begin
MyGate: entity work.And2
port map (In1 => C,
In2 => A,
Out1 => B);

end architecture Struct;
MyGate

B entity SomeSystem is
In1 port (…);
A end entity SomeSystem;
C Out1
In2 architecture Struct of SomeSystem is
begin
MyGate: entity work.And2
port map (In1 => B,
In2 => C,
And2 Out1 => A);

end architecture Struct;
entity And2 is
port (In1, In2 : in bit ;
Out1 : out bit );
end entity And2;

architecture Beh of And2 is


begin
Out1 <= In1 and In2 after 2ns;
end architecture Beh;

Alberto Cerdeira - VHDL: Quick Reference 31


5.8 Complex Ports and Signals

So far we have discussed only single-bit signals. However, complex signals and ports can also be
used in component instantiation. VHDL allows great flexibility in assigning actual signals to the formal
ports of the complex types (arrays or records). Such signals/ports can be assigned element by element
or in slices. Any combination of signals and ports is allowed as long as types of the associated ports and
signals are compatible.
Note that all elements of a composite port must be associated with an actual signal.
Also, if elements of a composite port are individually associated signals, then all associations of this
port cannot be separated by other associations.

3 CF
2 ZF
Flags 1 OF
0 MF

7 OpCode(3)
6 OpCode(2)
5 OpCode(1)
4 OpCode(0)

Memory
3 OperandA(3)
2 OperandA(2)
1 OperandA(1)
0 OperandA(0)

3 OperandB(3)
2 OperandB(2)
Accumulator 1 OperandB(1)
0 OperandB(0)

Operational Register

entity OpReg is
Port(CF, ZF, OF, MF : in BIT;
OpCode, OperandA, OperandB: in BIT_Vector(3 downto 0));
…..
signal Flags : Bit_Vector(3 downto 0);
signal Memory : Bit_Vector (7 downto 0);
signal Accumulator : Bit_Vector(3 downto 0);
….
OperationalRegister : entity work.OpReg
Port map ( CF => Flags(3),
ZF => Flags(2),
OF => Flags(1),
MF => Flags(0),
OpCode => Memory(7 downto 4),
OperandA => Memory(3 downto 0),
OperandB => Accumulator,

Alberto Cerdeira - VHDL: Quick Reference 32


5.9 Port without connections

How about situation when some of the ports are not connected? This can be handle by specifying
such ports as open in the port map.
In addition, an unused port can be omitted in the port map clause. This is perfectly legal in VHDL
but not recommended because there is no guarantee that the missing port is omitted on purpose. It may
happen, and during debugging is difficult to find the mistake. We advice to use the open status to all-non
used ports.

Comp1

SigA Input1 Comp1: entity work.SomeSystem


Port map ( Input1 => SigA,
Input1 => SigA,
SigA Input2 Output1 SigE Input1 => SigA,
Input1 => SigA,
SigA Input1 => SigA,
Input3 Output2 SigF Input1 => SigA,
Input1 => SigA);
SigA Input4

5.10 Introduction to Components

If s named entity can be used as a component then why should consider other constructs for the
same purpose? Aren’t entity instantiations enough?
In case of simple structural descriptions where all the components are known in advance, direct
instantiation of entities is sufficient indeed.
However, when it comes to large designs their components are created concurrently and at some
stage it is necessary to relate to the components which structural or behavioral implementation is not yet
defined.
In such a situation for a structural specification it would be enough to have a declaration of the
component’s interface (as required by the system). Declaration of the component’s interface is called
component declaration and is located in the declarative part of the architecture body (or package
interface).

Component Component

Entity Entity

Architecture Architecture
Configuration
Component Declaration

Component Instantiation Component Instantiation

Alberto Cerdeira - VHDL: Quick Reference 33


5.11 Component Declaration

The syntax of the component declaration and entity is similar. This is not a coincidence because
component and entity play similar role in defining the external interfaces of modules.

There is, however, an important difference between the two distinct VHDL constructs:

•= Entity declaration defines the interface of the “real” module, i.e. a system or circuit that physically
exists; the system is a separate design unit and can be individually simulated, analyzed or
synthesized.
•= Component declaration on the other hand defines the interface of “nonexistent” or “virtual” module;
it is specified within architecture and is rather an expectation of what the component interface should
be rather than a description of an existing circuit.

The general description of a component is:

component component_name is -- The keyword is is optional.


generic (generic_list); -- Generics are specified similarly to entities.
port (port_list); -- Ports are specified similarly to entities.
end component component_name; -- In this case the end component MUST be written
f ll

Example of a D flip-flop (DFF) declared as a Component inside the architecture.

Architecture Struct of Reg4 is

Component DFF is
Generic ( t_prop : time; -- propagation time
t_setup : time); -- setup time

port (D : in bit; -- information input


Clk: : in bit; -- clock input
Rst : in bit; -- asynchronous reset
Q : out bit); -- information output
end component DFF;

begin

5.12 Component Instantiations

A component instantiation is very similar to an entity instantiation. It has the following main
elements:

•= A colon follows Instantiation label, this label is mandatory in order to identify the instance.
•= Optional component keyword, which indicates that it is a component instantiation.
•= Component name as it is specified in the component declaration.
•= Generic map clause, which provides actual values for the component’s generics. Generics can be
specified without a value and in such cases the actual value can be provided in the generic map
clause. If the component is specified without generics, this clause can be omitted.
•= Port map clause, which is specified in the same way as in case of direct instantiations.

Note: There is no semicolon after the component’s name and the generic map clause. All the above
elements from a single statement and the semicolon appear after the statement.

Alberto Cerdeira - VHDL: Quick Reference 34


Example of a 4 bit Register:

Reg4 RegQ(0) RegQ(1) RegQ(2) RegQ(3)

Q B Q B Q B Q B
i i i i
Rst t Rst t Rst t Rst t
D Clk 0 D Clk 1 D Clk 2 D Clk 3

Clk RegD(0) RegD(1) RegD(2) RegD(3) Rst

Entity Reg4 is
Port ( RegD : in bit_vector(3 downto0);
Clk, Rst : in bit;
RegQ : out bit_vector(3 downto 0));
end entity Reg4;

architecture Struct of Reg4 is

component DFF is
generic (t_prop : time; t_setup : time);
port ( D, Clk, Rst : in bit;
Q : out bit);
end component DFF;

begin

Bit0: component DFF


generic map(t_prop => 2 ns, t_setup => 1 ns)
port map ( D => RegD(0), Clk => Clk, Rst => Rst, Q => RegQ(0);

Bit1: component DFF


generic map(t_prop => 2 ns, t_setup => 1 ns)
port map ( D => RegD(0), Clk => Clk, Rst => Rst, Q => RegQ(0);

Bit2: component DFF


generic map(t_prop => 2 ns, t_setup => 1 ns)
port map ( D => RegD(0), Clk => Clk, Rst => Rst, Q => RegQ(0);

Bit3: component DFF


generic map(t_prop => 2 ns, t_setup => 1 ns)
port map ( D => RegD(0), Clk => Clk, Rst => Rst, Q => RegQ(0);

end architecture Struct;

Alberto Cerdeira - VHDL: Quick Reference 35


5.13 General form of using component declaration and instantiation.

The Component as we seen before is an easy way of organizing the project. It uses is very tied to
package uses because of the needs to be reused by other part of code or even by other program. The
combination of a package including component or/and function is the library.

Components are declared in package and in architecture. The description part are described in
entity + architecture.
Functions are declared in package. The description part is defined in package body.

Library IEEE; Library IEEE;


Use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
use work.package_1.all
package package_1 is
component_1 package package_top is
port (…); component_top
end component; port (…);
component_2 end component;
port (…); end package_top;
end component;
end package_1; Library IEEE;
use IEEE.std_logic_1164.all;
Library IEEE; use work.package_1.all
use IEEE.std_logic_1164.all;
use work.package_1.all entity component_top is
port (…);
entity component_1 is end component_top;
port (…);
end component_1; architecture beh of component_top is
component component_top
architecture beh of component_1 is port(…);
begin end component;
… begin
end beh; u1:component_1 port map(…);
u2:component_2 port map(…);
Library IEEE;
use IEEE.std_logic_1164.all; end beh;
use work.package_1.all

entity component_2 is
port (…);
end component_2;

architecture beh of component_2 is


begin

end beh;

Alberto Cerdeira - VHDL: Quick Reference 36


5.14 Configurations

A declaration of a component and its instantiation is not enough to have a complete specification of
a structural architecture because implementation description of the components would still be missing.
The information that binds a component to real entities and architectures is specified in the
configuration that is a separate design unit that can be simulated and analyzed apart from other units.
When you take a closer look at the component binding you may notice that is very similar to direct
entity instantiation. However, the configuration approach is more flexible and easier to maintain if a
different implementation of the same component must be used. If there are any changes, they need only
to be introduced in the configuration file that is relatively short. The structural architecture will remain
unchanged. Using direct instantiations would require all changes to be introduced into the code.
Configurations can become quite complex if multiple levels of hierarchy are used. The example
below shows a simple configuration case.

Configuration Reg4_conf of Reg4 is -- The configuration specified the entity (Reg4).


for Struc -- Referes to an specific architecture Struct of Reg4.
for Bit0 : DFF -- Bit0, component instantiation label of DFF.
use entity Dflipflop(fast); -- Uses the fast architecture of the entity Dflipflop.
end for; -- End of Bit0.
for others : DFF -- For remaining instances of the same component.
use entity Dflipflop(normal); -- Uses the normal architecture of the entity Dflipflop.
end for; -- End of others.
end for; -- End of architecture Struct.
end Configuration Reg4_conf; -- End of Configuration.

Configuration Reg4_conf of Reg4 is


- A configuration is specified for a specific entity (Reg4) in the same way architecture does.

for Struc
- Refers to a specific architecture within the entity. for architecture_name
- All the information in between, if some, refers to the (component configuration)
component configuration inside that architecture. end for;

for Bit0 : DFF


- Component instantiation label is the same as the identifier that appears at the beginning of the
component instantiation statement. If more than one instance of a component will be bound to the same
entity/architecture pair then their labels can be listed and separated by colons; if all instances of the
same component would have to be listed, the list can be substituted by the keyword all. DFF is the name
of the component while Bit0 refers to the label is the specific instantiated.

use entity Dfilpflop(fast)


- The use entity clause binds component instantiation to an entity that specifies the component’s
implementation. In parentheses (fast) the architecture name will be used in that entity if more than one.

end for
- Each binding indication is enclosed in the for…end for clauses.

for others : DFF


- The keyword others can be used for remaining instances of the same component (in this case DFF).

use entity Dflipflop(normal)


- In this case the architecture used is the normal referred to the entity Dflipflop.

end for
- End of the binding indication for…end for.

end configuration Reg4_conf


- Terminate the configuration Reg4_conf specification.

Alberto Cerdeira - VHDL: Quick Reference 37


6 Subprograms
6.1 Procedures

Procedure is a form of subprogram. It contains local declarations and a sequence of statements.


Procedures can be called in any place of the architecture. The procedure definition consists of two parts:

•= procedure declaration, which contains the procedure name and the parameter list required when
the procedure is called;
•= procedure body, which consists of the local declaration and statements required to execute the
procedure.

Declaration of a procedure are local to this declaration an can declare subprogram declarations,
subprogram bodies, types, subtypes, constants, variables, files, aliases, attribute declarations attribute
specifications, use clauses, group template and group declarations.

Procedure Example (X,Y: inout Integer) is


type Word_16 is range 0 to 65536;
subtype Byte is Word 16 range 0 to 255;
variable Vb1,Vb2,Vb3: real;
constant Pi: Real :=3.14;
Procedure Compute (variable V1, V2: real) is
begin
-- subprogram_statement_part
end procedure Compute;
begin
-- subprogram_statement_part
end procedure Example;

There are three modes available: in, out and inout. When in mode is declared and object class is
not defined, then by default it is assumed that the object is a constant. In case of inout and out modes,
the default class is variable. A procedure can be declared also without any parameters.

The procedure body defines the procedure’s algorithm composed of sequential statements. A
procedure can contain any sequential statements (including wait statements). A wait statement,
however, cannot be used in procedures which are called from a process with a sensitivity list or from
within a function.

The overload procedures are procedures with the same name but different number or different types
of formal parameters. The actual parameters decide which overload procedure will be called.


Procedure Calculate(In1, In2: in Real; signal Out1: inout Integer);
Procedure Calculate(In1, In2: in Integer; signal Out1: inout Real);

-- Calling of overload procedures:

Calculate(23.76, 1.632, Sign1);


Calculate(23, 826, Sign2);

Important notes:

•= The procedure declaration is optional - Procedures body can exist without it declarative part.
•= Subprograms (procedures and functions) can be nested.
•= Subprograms can be called recursively.
•= Synthesis tools usually support procedures as long as they do not contain the wait statement.

Alberto Cerdeira - VHDL: Quick Reference 38


6.2 Functions

A function call is a subprogram of the form of an expression that returns a value. It is a subprogram
that either defines an algorithm for computing values or describes a behavior. The important feature
of functions is that they are used as expressions that return values of specified type. This is the
main difference from another type of subprograms: procedures, which are used as statements.

library IEEE;
use IEEE.std_logic_1164.all;

PACKAGE my_functions IS

-- <Convert std_logic to natural>


function std_logic_to_natural(s: in std_logic) return natural;

-- <function or_tree>
-- or of a std_logic_vector implemented in a tree structure
function or_tree (data : std_logic_vector) return std_logic;

end my_functions;

PACKAGE BODY my_functions IS

function std_logic_to_natural(s : in std_logic) return natural is


variable result : natural;
begin
result :=0;
case s is
when '1' | 'H' => result := 1;
when others => result := 0;
end case;
return result;
end std_logic_to_natural;

function or_tree (data : std_logic_vector) return std_logic is


variable UPPER_TREE, LOWER_TREE: std_logic;
variable MID, LEN: natural;
variable result: std_logic;
variable i_data: std_logic_vector(data'LENGTH-1 downto 0);
begin
i_data := data;
LEN := i_data'LENGTH;
if LEN = 1 then
result := i_data(i_data'LEFT);
elsif LEN = 2 then
result := i_data(i_data'LEFT) or i_data(i_data'RIGHT);
else
MID := (LEN + 1)/2 + i_data'RIGHT;
UPPER_TREE := or_tree(i_data(i_data'LEFT downto MID));
LOWER_TREE := or_tree(i_data(MID-1 downto i_data'RIGHT));
result := UPPER_TREE or LOWER_TREE;
end if;
return result;
end or_tree;

END cpu_functions;

Alberto Cerdeira - VHDL: Quick Reference 39


7 Testing the Design Functionality
7.1 Test Bench

A design is incomplete without verification. There are several ways to verify a VHDL design. The
most popular solution is using test benches. A test bench is an environment, where a design (called
design or unit under test) is checked by applying signals (stimuli) and monitoring its responses by
observing signal probes and monitors.
A test bench is composes of the instantiation of the Unit Under Test (UUT) and processes
supporting the stimuli applied to the UUT. In this way a hybrid specification is created that mixes both
structural and behavioral types of statements.
Stimuli for the UUT are specified inside the test bench architecture or can be read from an external
file. The reactions of the UUT, on the other hand, can be observed either trough the simulator outputs
(waveforms plot on the screen), or written to a file using VHDL text I/O operations.

7.2 Elements of a VHDL Test Bench

The VHDL test bench is just another specification with its own entity and architecture. It has,
however, a special structure with some elements that are characteristic to this type of specifications.

•= Test bench entity has no port.


•= UUT component instantiation – the relationship between the test bench and UUT is specified
through component instantiation and structural-type specification,
•= Stimuli – it is a set of signals that are declared internally in the test bench architecture and assigned
to UUT’s port in its instantiation. The stimuli are defined as waveforms in one or more behavioral
processes.

TESTBENCH ENTITY entity TB is


end entity TB;
architecture TBArch of TB is architecture TBArch of TB is

TESTBENCH ENTITY signal A, B, … : bit;


signal … ;
begin begin
UUT INSTANTIATION UUT: entity work.MyProcessor(Beh)
port map (…);

STIMULI DEFINITIONS sitimuli: process


begin
A <= …;
B <= …;

wait for …;

wait for …;

wait;
end process stimuli;

end architecture TBArch; end architecture TBArch;

A VHDL test bench does have one important feature, they do not have ports or generics. The
reason for that is very simple – test bench is not a real device or system that will have to communicate
with its environment. All the values for the input ports of a UUT are specified inside the test bench
architecture as stimuli. The outputs are observed through the simulator watch or waveform display and
are saved to a file. Why are we treating test bench as entity when it is practically only architecture?
Because in VHDL, the architecture definition cannot be specified without specifying its entity.

Alberto Cerdeira - VHDL: Quick Reference 40


7.3 Using Test Bench

When a Unit Under Test and a Test Bench for it are complete, the verification can be started. Note
that it is the test bench, which is simulated, not the UUT. The UUT is only one of the component
instantiated in a test bench. There is no limitation on VHDL simulator used capability.

Design
Design Specification

Verification
Design Specification

Design Specification

Design Specification

7.4 Unit Under Test

A system that will be verified with a test bench does not need any modifications or additional
declarations. For that reason a test bench can be applied to any VHDL specification, even received from
an external source.
The unit under test has to be instantiated in the test bench architecture. This can be done in the
same way as in any structural specification – either through a direct instantiation or component
instantiation with component declaration and a configuration. The ports of the UUT instantiation will be
assigned stimuli signals.
As both processes (as a whole) and component instantiations are concurrent statements, it does not
matter whether the UUT will be instantiated first and the stimuli will be defined next or vice versa.

entity Mux2to1 is entity Reg8 is


port ( A, B, Sel : in bit; port (D :in bit _vector(7 downto 0);
Y : out bit); En, Clk : in bit;
end entity Mux2to1; Q : out bit);
end entity Reg8;
architecture Beh of Mux2to1 is architecture Beh of Reg8 is
… …
end architecture Beh; end architecture Beh;

________________Unit Under Test ________________Unit Under Test

entity TestBench is entity TestBench is


end entity TestBench; end entity TestBench;
architecture TBArch of TestBench is architecture TBArch of TestBench is
… …
begin begin
UUT: entity work.Mux2to1 UUT: entity work.Reg8
port map ( A => … ; port map ( D => … ;
B => … ; En => … ;
Sel => … ; Clk => … ;
Y => …); Q => …);
… …
end architecture TBArch; end architecture TBArch;

____________________Test Bench ____________________Test Bench

Alberto Cerdeira - VHDL: Quick Reference 41


7.5 Stimuli of Signals

The heart of each test bench is a set of stimuli - a sequence of values for each UUT input signal
applied over time. As we said before, since the test bench does not communicate with the environment
through signals, all stimuli must be declared internally in the test bench architecture. They are declared
like any other signal inside the declarative part of the architecture.
The stimuli can be specified both as concurrent signal assignments (with input signal changes
specified as waveforms) or in a process that contains signal assignments separated by the wait for
statements, introducing delays between subsequent signal assignment. In the latter case, an empty wait
(without any condition) is added as the last statement in the process. Such a statement causes the
simulation to suspend indefinitely (otherwise it will run from the beginning of the process again).
Finally, the relationship between stimuli and the unit under test is reached through the assignments
in the port map clause of the UUT instantiation.

Example: Lets see a Mux2to1 code description with both of Test Bench that can be used: Sequential
or Concurrent.
-- Unit Under Test Declaration

entity Mux2to1_T is
generic ( MuxDel : time := 5 ns);
port ( A, B, : in std_logic_vector(1 downto 0);
Sel : in std_logic;
Y : out std_logic_vector(1 downto 0));
end entity Mux2to1_T;

architecture Beh of Mux2to1_T is


begin
with Sel select
Y <= A after MuxDel when ‘0’,
B after MexDel when ‘1’,
“XX” when others;
end architecture Beh;

-- Tets Bench Sequential -- Test Bench Concurrent

entity TetsBench is entity TetsBench is


end entity TestBench; end entity TestBench;
architecture TestBenchArch of TestBench is architecture TestBenchArch of TestBench is
signal A,B,Y : std_logic(1 downto 0); signal A,B,Y : std_logic(1 downto 0);
signal Sel : std_logic; signal Sel : std_logic;
begin begin
UUT: entity work.Mux2to1_T UUT: entity work.Mux2to1_T
port map (A,B,Sel,Y); port map (A,B,Sel,Y);
Sel <= ‘X’, ‘0’ after 40 ns, stimuli: process
‘1’ after 80 ns, begin
‘0’ after 120 ns, Sel <= ‘X’; A <= “00”; B <=”11”; wait for 40 ns;
‘1’ after 160ns; Sel <= ‘0’; wait for 20 ns;
A <= “00”, A <= ‘”00”; wait for 20 ns;
“01” after 60 ns, Sel <= ‘1’; wait for 20 ns;
“11” after 140 ns; B <= “10”; wait for 20 ns;
B <= “11”, Sel <= ‘0’; wait for 20 ns;
“10” after 100ns, A <= “11”; wait for 20 ns;
“00” after 180 ns; Sel <= ‘1’; wait for 20 ns;
end architecture TestBenchArch; B <= “00”; wait for 20 ns;
wait;
end process stimuli;
end architecture TestBenchArch;

Alberto Cerdeira - VHDL: Quick Reference 42


7.6 Assertion Statement

The last element of successful device verification is getting the simulation results or reporting
results. This can be done in several ways, from using built-in simulator features such as displaying list of
signal values changing over time or waveform displays, to writing a complete simulation log to a file, or
using the VHDL report clause
The last option is easy to apply and is usually used to display a message when something goes
wrong. If this option is used and no reports are displayed during the simulation, then it can be assumed
that the UUT worked as expected.
A report clause consists of three elements: assert statement (checking a Boolean condition),
report statement (defining a message that will be displayed when the condition is false) and a severity
statement (informing the simulator how severe the erroneous situation is – from just a general note to a
system failure).
Assert ( LeftNum > RighNum)
report “RightNum greater then LeftNum”
severity warning;

In this example if the RighNum is bigger than the LeftNum then the monitor screen the message:
“RightNum greater then LeftNum”

7.7 Reporting with Assertions

The assertion statement is by nature sequential and as such is used inside processes. Its
application is not limited to test benches, but it is here where it is most frequently used.
A general rule of thumb in applying assertions for reporting incorrect responses of the UUT to the
stimuli is as follows:

•= Use an assert-report pair each time a new value of UUT output is expected;
•= Specify the error expected value as the condition in assertion;
•= Try to be specific in the report text string, a simple Error will tell you nothing during simulation;
write what is wrong and when it happened (i.e. in what situation on the inputs).

Remember that the new values are assigned only when process is suspended – do not expect a
change on the outputs right after assigning new values to the inputs!

-- Test Bench for the Mux2to1_T entity


entity TetsBench is
end entity TestBench;
architecture TestBenchArch of TestBench is
signal A,B,Y : std_logic(1 downto 0);
signal Sel : std_logic;
begin
UUT: entity work.Mux2to1_T
port map (A,B,Sel,Y);
stimuli: process
begin
Sel <= ‘X’; A <= “00”; B <=”11”; wait for 40 ns; assert (Y=”XX”) report “Test Failed on Sel=X”;
Sel <= ‘0’; wait for 20 ns; assert (Y=”00”) report “Test Failed on Sel=0”;
A <= ‘”00”; wait for 20 ns; assert (Y=”01”) report “Test Failed on Sel=0 - A not changed”;
Sel <= ‘1’; wait for 20 ns; assert (Y=”11”) report “Test Failed on Sel=1”;
B <= “10”; wait for 20 ns; assert (Y=”10”) report “Test Failed on Sel=1 - B not changed”;
Sel <= ‘0’; wait for 20 ns;
A <= “11”; wait for 20 ns; -- Time=120ns + MuxDel
Sel <= ‘1’; wait for 20 ns; -- Time=140ns + MuxDel
B <= “00”; wait for 20 ns;
wait;
end process stimuli;
end architecture TestBenchArch;

Alberto Cerdeira - VHDL: Quick Reference 43


Appendix A. Examples of VHDL Description for D-FF with synchronous and
asynchronous reset.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

package data_types_Example is
end data_types_Example;

library IEEE;
library work;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.data_types_Example.all;

package components_Example is
component extclk_1
port (
hds_ceo : out std_logic_vector(0 downto 0)
);
end component;

component dff_synch
port (
d : in std_logic_vector(0 downto 0);
pre : in std_logic_vector(0 downto 0);
clr : in std_logic_vector(0 downto 0);
q : out std_logic_vector(0 downto 0);
q_bar : out std_logic_vector(0 downto 0);
hds_cei : in std_logic_vector(0 downto 0);
lock : in std_logic_vector(0 downto 0)
);
end component;

component dff_asynch
port (
d : in std_logic_vector(0 downto 0);
pre : in std_logic_vector(0 downto 0);
clr : in std_logic_vector(0 downto 0);
q : out std_logic_vector(0 downto 0);
q_bar : out std_logic_vector(0 downto 0);
hds_cei : in std_logic_vector(0 downto 0);
lock : in std_logic_vector(0 downto 0)
);
end component;
end components_Example;

library IEEE;
library work;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.components_Example.all;
use work.data_types_Example.all;

entity extclk_1 is
port (
hds_ceo : out std_logic_vector(0 downto 0)
);
end extclk_1;

Alberto Cerdeira - VHDL: Quick Reference 44


library IEEE;
library work;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.components_Example.all;
use work.data_types_Example.all;

entity dff_synch is
port (
d : in std_logic_vector(0 downto 0);
pre : in std_logic_vector(0 downto 0);
clr : in std_logic_vector(0 downto 0);
q : out std_logic_vector(0 downto 0);
q_bar : out std_logic_vector(0 downto 0);
hds_cei : in std_logic_vector(0 downto 0);
lock : in std_logic_vector(0 downto 0)
);
end dff_synch;

library IEEE;
library work;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.components_Example.all;
use work.data_types_Example.all;

entity dff_asynch is
port (
d : in std_logic_vector(0 downto 0);
pre : in std_logic_vector(0 downto 0);
clr : in std_logic_vector(0 downto 0);
q : out std_logic_vector(0 downto 0);
q_bar : out std_logic_vector(0 downto 0);
hds_cei : in std_logic_vector(0 downto 0);
lock : in std_logic_vector(0 downto 0)
);
end dff_asynch;

library IEEE;
library work;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.components_Example.all;
use work.data_types_Example.all;

architecture hds_body_1 of dff_synch is


signal dff_state : std_logic_vector(0 downto 0); -- <1,1,u>
signal clock : std_logic;
begin
P1 : process ( dff_state )
variable var_q : std_logic_vector(0 downto 0); -- <1,1,u>
variable var_q_bar : std_logic_vector(0 downto 0); -- <1,1,u>
begin
var_q := dff_state;
var_q_bar := not dff_state;
q <= var_q;
q_bar <= var_q_bar;
end process P1;
clock <= hds_cei(0);

Alberto Cerdeira - VHDL: Quick Reference 45


P2 : process ( clock )
begin
if ( clock'event and clock = '1' ) then
if ( clr(0) = '1' ) then
dff_state <= "0";
else
dff_state <= d;
end if;
end if;
end process dff_synch;

end hds_body_1;

library IEEE;
library work;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.components_aptix.all;
use work.data_types_aptix.all;

architecture hds_body_1 of dff_asynch is


signal dff_state : std_logic_vector(0 downto 0); -- <1,1,u>
signal clock : std_logic;
begin
P1 : process ( dff_state )
variable var_q : std_logic_vector(0 downto 0); -- <1,1,u>
variable var_q_bar : std_logic_vector(0 downto 0); -- <1,1,u>
begin
var_q := dff_state;
var_q_bar := not dff_state;
q <= var_q;
q_bar <= var_q_bar;
end process P1;

clock <= hds_cei(0);

P2 : process ( clock )
begin
if ( clock'event and clock = '1' ) then
if ( pre(0) = '1' ) then
dff_state <= "1";
else
dff_state <= d;
end if;
end if;
end process P2;

end hds_body_2;

----------------------------------------- END of File ------------------------------------

Alberto Cerdeira - VHDL: Quick Reference 46


Appendix B. Example of a Serial to Parallel Converter- Shifter
--
-- Serial to Parallel Converter - Shifter
--
Package TYPES is
TYPE STATE_TYPE is (WAIT_FOR_START, READ_BITS, PARITY_ERROR_DETECTED,
ALLOW_READ);
Constant PARALLEL_BIT_COUNT : INTEGER := 8;
SUBTYPE PARALLEL_RANGE is INTEGER range 0 to (PARALLEL_BIT_COUNT-1);
SUBTYPE PARALLEL_TYPE is BIT_VECTOR(PARALLEL_RANGE);
end TYPES;

use WORK.TYPES.ALL; -- use the TYPE package

Entity SER_PAR is
Port (
SERIAL_IN : IN BIT;
CLOCK : IN BIT;
RESET : IN BIT;
PARALLEL_OUT : OUT PARALLEL_TYPE;
PARITY_ERROR : OUT BIT;
READ_ENABLE : OUT BIT
);
end SER_PAR;

Architecture BEHAVIOR of SER_PAR is


SIGNAL CURRENT_STATE, NEXT_STATE : STATE_TYPE; -- signal for stored values
SIGNAL CURRENT_PARITY, NEXT_PARITY : BIT;
SIGNAL CURRENT_HIGH_BIT, NEXT_HIGH_BIT : BIT;
SIGNAL CURRENT_PARALLEL_OUT, NEXT_PARALLEL_OUT : PARALLEL_TYPE;
begin

NEXT_ST: PROCESS (SERIAL_IN, CURRENT_STATE, RESET, CURRENT_HIGH_BIT,


CURRENT_PARITY, CURRENT_PARALLEL_OUT)
BEGIN
PARITY_ERROR <= '0';
READ_ENABLE <= '0';
NEXT_STATE <= CURRENT_STATE;
NEXT_HIGH_BIT <= '0';
NEXT_PARITY <= '0';
NEXT_PARALLEL_OUT <= PARALLEL_TYPE'(others=>'0');

IF (RESET = '1') then


NEXT_STATE <= WAIT_FOR_START;
ELSE
CASE CURRENT_STATE IS
WHEN WAIT_FOR_START =>
IF (SERIAL_IN ='1') THEN
NEXT_STATE <= READ_BITS;
NEXT_PARALLEL_OUT <= PARALLEL_TYPE'(OTHERS=>'0');
END IF;
WHEN READ_BITS =>
IF (CURRENT_HIGH_BIT = '1') THEN
IF (CURRENT_PARITY = SERIAL_IN) THEN
NEXT_STATE <= ALLOW_READ;
READ_ENABLE <= '1';
ELSE
NEXT_STATE <= PARITY_ERROR_DETECTED;
END IF;
ELSE

Alberto Cerdeira - VHDL: Quick Reference 47


NEXT_HIGH_BIT <= CURRENT_PARALLEL_OUT(0);
NEXT_PARALLEL_OUT <= CURRENT_PARALLEL_OUT(1 to
PARALLEL_BIT_COUNT-1) & SERIAL_IN;
NEXT_PARITY <= CURRENT_PARITY xor SERIAL_IN;
END IF;
WHEN PARITY_ERROR_DETECTED => PARITY_ERROR <= '1';
WHEN ALLOW_READ => NEXT_STATE <= WAIT_FOR_START;
END CASE;
END IF;
END PROCESS NEXT_ST;

SYNCH: PROCESS
BEGIN
wait until CLOCK'event and CLOCK ='1';
CURRENT_STATE <= NEXT_STATE;
CURRENT_HIGH_BIT <= NEXT_HIGH_BIT;
CURRENT_PARALLEL_OUT <= NEXT_PARALLEL_OUT;
END PROCESS SYNCH;

PARALLEL_OUT <= CURRENT_PARALLEL_OUT;

END BEHAVIOR;

----------------------------------------- END of File ------------------------------------

Alberto Cerdeira - VHDL: Quick Reference 48


Appendix C. Example of a Parallel to Serial Converter.
-- ************************************************************************
-- Synopsys style Description:
--
-- Parallel to Serial converter
-- ************************************************************************
--
-- Functional desrciption:
-- This macro accepts an N-bits value and load it into a shift register
-- when the L(load) and CE ( clock enable) are asserted.
-- With the L signal not asserted and the CE signal asserted, SDI data is
-- shifted into the MSB register while the registered data is shifted out
-- serially, LSB to MSB, on each rising edge of the C (clock) signal.
-------------------------------------------------------------
-- Truth Table
-------------------------------------------------------------
-- Load CE C SDO PO[n:0]
-------------------------------------------------------------
-- X 0 ^ No-Change No-Change
-------------------------------------------------------------
-- 0 1 ^ PO[0] SDI,PO[n:1]
-------------------------------------------------------------
-- 1 1 ^ PI[0] PI[n:0]
-------------------------------------------------------------

------------------------------------------------------------------------------
-- Description of the package: funzioni
------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- ------------------------------------------------------------------------ --
-- SIMULATION FUNCTION PROTOTYPES: --
-- ------------------------------------------------------------------------ --
PACKAGE funzioni IS

-- convert a variable from MVL9 to MVL3


FUNCTION rat( value : std_logic ) RETURN std_logic;

-- convert a vector from MVL9 to MVL3


FUNCTION std_logic_vector_2_var(vect: std_logic_vector) RETURN std_logic_vector;

-- set a vector to all 0


FUNCTION setall0(width : integer) RETURN std_logic_vector;

END funzioni;

-- ------------------------------------------------------------------------ --
-- FUNCTIONS: --
-- ------------------------------------------------------------------------ --
PACKAGE BODY funzioni IS

FUNCTION rat( value : std_logic ) RETURN std_logic IS

BEGIN

CASE value IS
WHEN '0' | '1' => RETURN value;
WHEN 'H' => RETURN '1';
WHEN 'L' => RETURN '0';

Alberto Cerdeira - VHDL: Quick Reference 49


WHEN OTHERS => RETURN 'X';
END CASE;

END rat;
-- ------------------------------------------------------------------------ --
FUNCTION std_logic_vector_2_var (vect: std_logic_vector) RETURN std_logic_vector IS

VARIABLE mvl: std_logic_vector(vect'LEFT DOWNTO vect'RIGHT);

BEGIN
FOR i IN vect'RANGE LOOP
mvl(i) := rat(vect(i));
END LOOP;
RETURN mvl;

END std_logic_vector_2_var;
-- ------------------------------------------------------------------------ --
FUNCTION setall0(width : integer) RETURN std_logic_vector IS

variable vect: std_logic_vector(width-1 downto 0);

BEGIN

FOR i in 0 to width-1 LOOP


vect(i) := '0';
END LOOP;

return vect;

END setall0;

END funzioni;

------------------------------------
-- VHDL core description
------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.all;

use work.funzioni.all;

entity parallel2serial is
GENERIC (datawidth : INTEGER := 8);
port(pi : in std_logic_vector(datawidth-1 downto 0); -- Parallel Data Input
sdi : in std_logic; -- Serial Data Input
l : in std_logic; -- Load
c : in std_logic; -- Clock
ce : in std_logic; -- Clock enable
sdo : out std_logic; -- Serial Data Output
po : out std_logic_vector(datawidth-1 downto 0)); -- Parallel Data Output
end parallel2serial;

architecture behv of parallel2serial is

begin

process
variable setup : boolean := TRUE;
variable vsdi : std_logic;

Alberto Cerdeira - VHDL: Quick Reference 50


variable vl : std_logic;
variable vpi : std_logic_vector( datawidth - 1 downto 0 );
variable vsdo : std_logic;
variable vpo : std_logic_vector( datawidth - 1 downto 0 );
variable s : std_logic_vector( datawidth - 1 downto 0 );
begin
if (setup = TRUE) then
s := setall0(datawidth);
setup := FALSE;
end if;

vpi := std_logic_vector_2_var(pi);
vsdi := rat(sdi);
vl := rat(l);

-- the { if (clk'event and clk='1'and cte='1') then } is not correct in Synopsys Style use wait until.

wait until c'event and c='1' and ce='1';

case vl is
when '0' => -- Shifting
for i in 0 to datawidth-2 loop
s(i) := s(i+1);
end loop;

s(datawidth-1) := vsdi;

when '1' => -- Parallel load


s := vpi;

when others =>


end case;

po <= s;
sdo <= s(0);

end process;

end behv;

----------------------------------------- END of File ------------------------------------

Alberto Cerdeira - VHDL: Quick Reference 51

S-ar putea să vă placă și