Learning Center
Plans & pricing Sign in
Sign Out
Get this document free



									0. General Information/Introduction
0.1 The Group - Why and What

The newsgroup comp.lang.vhdl was created in January 1991. It's an international
forum to discuss ALL topics related to the language VHDL which is currently
defined by the IEEE Standard 1076/2002. Included are language problems, tools
that only support subsets etc. but NOT other languages such as Verilog HDL. This
is not strict - if there is the need to discuss information exchange from EDIF to
VHDL for example, this is a topic of the group. The group is unmoderated. Please
think carefully before posting - it costs a lot of money! (Take a look into your
LRM for example or try to search Google Groups - if you still cannot find the
answer, post your question, but make sure, that other readers will get the point).

0.2 What Is VHDL

VHDL-1076 (VHSIC (Very High Speed Integrated Circuits) Hardware Description
Language) is an IEEE Standard since 1987. It is "a formal notation intended for use
in all phases of the creation of electronic systems. ... it supports the development,
verification, synthesis, and testing of hardware designs, the communication of
hardware design data ..." [Preface to the IEEE Standard VHDL Language
Reference Manual] and especially simulation of hardware descriptions.
Additionally, VHDL-models are a DoD requirement for vendors.

Today many simulation systems and other tools (synthesis, verification and others)
based on VHDL are available. The VHDL users community is growing fast.
Several international conferences organized by the VHDL Users Groups(s) have
been held with relevant interest. Other international conferences address the topic
as well.

Chapter 1 - An Introduction and Background
VHDL is an acronym which stands for VHSIC Hardware Description Language.
VHSIC is yet another achronym which stands for Very High Speed Integrated
Circuits. If you can remember that, then you're off to a good start. The language
has been known to be somewhat complicated, as its title (as titles go). The
acronym does have a purpose, though; it is supposed to capture the entire theme
of the language, that is to describe hardware much the same way we use

VHDL can wear many hats. It is being used for documentation, verification, and
synthesis of large digital designs. This is actually one of the key features of VHDL,
since the same VHDL code can theoretically achieve all three of these goals, thus
saving a lot of effort. In addition to being used for each of these purposes, VHDL
can be used to take three different approaches to describing hardware. These three
different approaches are the structural, data flow, and behavioral methods of
hardware description. Most of the time a mixture of the three methods are
employed. The following sections introduce you to the language by examining its
use for each of these three methodologies. There are also certain guidelines that
form an approach to using VHDL for synthesis, which is not addressed by this

VHDL is a standard (VHDL-1076) developed by IEEE (Institute of Electrical and
Electronics Engineers). The language has been through a few revisions, and you
will come across this in the VHDL community. Currently, the most widely used
version is the 1987 (std 1076-1987) version, sometimes referred to as VHDL'87,
but also just VHDL. However, there is a newer revision of the language referred to
as VHDL'93. VHDL'93 (adopted in 1994 of course) is fairly new and is still in the
process of replacing VHDL'87.

Chapter 2 - Structural Descriptions
This chapter discusses the first of the three approaches to design with VHDL, the
structural description.

Section 1 - Building Blocks
To make designs more understandable and maintainable, a design is typically
decomposed into several blocks. These blocks are then connected together to
form a complete design. Using the schematic capture approach to design, this
might be done with a block diagram editor. Every portion of a VHDL design is
considered a block. A VHDL design may be completely described in a single block,
or it may be decomposed in several blocks. Each block in VHDL is analogous to an
off-the-shelf part and is called an entity. The entity describes the interface to that
block and a separate part associated with the entity describes how that block
operates. The interface description is like a pin description in a data book,
specifying the inputs and outputs to the block. The description of the operation of
the part is like a schematic for the block. For the remainder of the tutorial we will
refer to a block as a design, even though a complete design may be a collection of
many blocks interconnected.

The following is an example of an entity declaration in VHDL.
entity latch is
  port (s,r: in bit;
        q,nq: out bit);
end latch;
The first line indicates a definition of a new entity, whose name is latch. The last
line marks the end of the definition. The lines in between, called the port clause,
describe the interface to the design. The port clause contains a list of interface
declarations. Each interface declaration defines one or more signals that are
inputs or outputs to the design.

Each interface declaration contains a list of names, a mode, and a type. In the first
interface declaration of the example, two input signals are defined, s and r. The list
to the left of the colon contains the names of the signals, and to the right of the
colon is the mode and type of the signals. The mode specifies whether this is an
input (in), output (out), or both (inout). The type specifies what kind of values the
signal can have. The signals s and rare of mode in (inputs) and type bit. Next the
signals q and nq are defined to be of the mode out (outputs) and of the
type bit (binary). Notice the particular use of the semicolon in the port clause. Each
interface declaration is followed by a semicolon, except the last one, and the entire
port clause has a semicolon at the end.

All of the signals in the example are defined to be of the type bit. The type bit is a
predefined type that can have two values represented by '0' and '1'. This type is
used to represent two level logic signals.

The second part of the description of the latch design is a description of how the
design operates. This is defined by the architecture declaration. The following is an
example of an architecture declaration for the latch entity.
architecture dataflow of latch is
  signal q0 : bit := '0';
  signal nq0 : bit := '1';
  q0<=r nor nq0;
  nq0<=s nor q0;

end dataflow;

The first line of the declaration indicates that this is the definition of a new
architecture called dataflow and it belongs to the entity named latch. So this
architecture describes the operation of the latch entity. The lines in between the
begin and end describe the latch's operation. This example uses the data flow
approach which is discussed later, so we won't discuss the meaning of these lines
here. The next section explains how to specify the latch's operation using the
structural approach.

Section 2 - Connecting Blocks
Once we have defined the basic building blocks of our design using entities and
their associated architectures, we can combine them together to form other designs.
This section describes how to combine these blocks together in a structural

Let's specify the operation of the latch entity used in the previous section by
connecting some previously defined entities. The entity declaration for the latch
entity latch is
  port (s,r: in bit;
        q,nq: out bit);
end latch;
We will declare an architecture different from the one in the last section that
demonstrates the structural approach. To do so, we assume that an entity
named nor_gate has been defined that will be used in the design. The schematic for
the latch might be

We can specify the same connections that occur in the schematic using VHDL with
the following architecture declaration:
architecture structure of latch is
  component nor_gate
    port (a,b: in bit;
          c: out bit);
  end component;
  n1: nor_gate
    port map (r,nq,q);
  n2: nor_gate
    port map (s,q,nq);
end structure;
The lines between the first and the keyword begin are a component declaration. It
describes the interface of the entity nor_gate that we would like to use as a
component in (or part of) this design. Between the begin andend keywords, the
first two lines and second two lines define two component instances.

There is an important distinction between an entity, a component, and a component
instance in VHDL. The entity describes a design interface, the component
describes the interface of an entity that will be used as an instance (or a sub-block),
and the component instance is a distinct copy of the component that has been
connected to other parts and signals. To compare these with the process of bread
board design with off-the-self parts. The entity and architecture is like the data
book describing the interface and schematics of how the part works. The
component is like the short pin listing that comes with the part to describe how it
should be connected. The component instance is the actual part itself, of which you
may have many that each operate independently.

In this example the component nor_gate has two inputs (a and b) and an output (c).
There are two instances of the nor_gate component in this architecture
corresponding to the two nor symbols in the schematic. The first instance
represents the top nor gate in the schematic. The first line of the component
instantiation statement gives this instance a name, n1, and specifies that it is an
instance of the component nor_gate. The second line describes how the component
is connected to the reset of the design using the port map clause. The port map
clause specifies what signals of the design to connect to the interface of the
component in the same order as they are listed in the component declaration. The
interface is specified in order as a,b, and then c, so this instance
connects r to a, nq to b, and q to c. This corresponds to the way the top gate in the
schematic is connected. The second instance, named n2, connects s to a, q to b,
and nq to c of a different instance of the same nor_gate component in the same
manner as shown in the schematic.

The structural description of a design is simply a textual description of a
schematic. A list of components and there connections in any language is
sometimes called a netlist. The structural description of a design in VHDL is one
of many means of specifying netlists.

Chapter 3 - Data Flow Descriptions
The data flow description is the second of the three paradigms for describing
hardware with VHDL. The following sections discuss this approach to VHDL

Section 1 - A First Example
In the data flow approach, circuits are described by indicating how the inputs and
outputs of built-in primitive components (ex. an and gate) are connected
together. In other words we describe how signals (data) flow through the circuit.
Let's look at the first example.
Suppose we were to describe the following SR latch using VHDL as in the
following schematic.

We might build an entity like the one that follows.
entity latch is
  port (s,r : in bit;
        q,nq : out bit);
end latch;

architecture dataflow of latch is
  q<=r nor nq;
  nq<=s nor q;
end dataflow;
note: If you are familiar with programming languages, notice that the <= symbol
was chosen carefully to avoid confusion with the variable assignment operator
(usually = or :=) of typical programming languages. The signal assignment
operator in VHDL specifies a relationship between signals, not a transfer of data
as in programming langauges.

As we saw in the last section, the entity describes the interface to the design. There
are four signals s,r,q, and nq that are accessible externally to the design. Again we
model the signals in our design with the VHDL data type bit, which can represent
two level logic values.

The architecture part describes the internal operation of the design. In the data flow
approach we indicated how data flows from the inputs to the outputs. In VHDL
this is accomplished with the signal assignment statement. The example
architecture consists of two signal assignment statements.

A signal assignment statement describes how data flows from the signals on the
right side of the <= operator to the signal on the left side. The first signal
assignment in the example tells us that the data coming from signals rand nq flow
through a nor gate to determine the value of the signal q. The nor represents a
built-in component called an operator, because it operates on some data to produce
new data. The second signal assignment, similar to the first, indicates that the
signal nq is produced from data (s and q) flowing through (or processed by)
the nor operator.

The right side of the <= operator is called an expression. The value of the
expression is determined by evaluating the expression. Evaluating the expression is
performed by substituting the values of the signals in the expression and
computing the result of each operator in the expression.

Section 2 - How it Works
In the last section we saw an example of a data flow description and what it
describes. In this section we will learn how a simulator uses that description to
model the design.

The VHDL standard not only describes how designs are specified, but also how
they should be interpreted. This is the purpose of having standards, so that we can
all agree on the meaning of a design. It is important to understand how a VHDL
simulator interprets a design because that dictates what the "correct" interpretation
is according to the standard (Hopefully, simulators are not all 100% correct).

The scheme used to model a VHDL design is called discrete event time simulation.
When the value of a signal changes, we say an event has occurred on that signal. If
data flows from signal A to signal B, and an event has occurred on signal A (i.e.
A's value changes), then we need to determine the possibly new value of B. This is
the foundation of the discrete event time simulation. The values of signals are only
updated when certain events occur and events occur at discrete instances of time.

Since one event causes another, simulation proceeds in rounds. The simulator
maintains a list of events that need to be processed. In each round, all events in a
list are processed, any new events that are produced are placed in a separate list
(and are said to be scheduled) for processing in a later round. Each signal
assignment is evaluated once, when simulation begins to determine the initial value
of each signal.

Lets examine how the event time simulation proceeds for the previous example of
an SR latch. The following is a schematic version of the SR latch.
The internal operation of the latch was essentially captured using the following two
q<=r nor nq;
nq<=s nor q;
Since data flows from r and nq to q, we say that q depends on r and nq. In general,
given any signal assignment statement, the signal on the left side of the <= operator
depends on all the signals appearing on the right side. If a signal depends on
another signal that an event has occurred on, then the expression in the signal
assignment is re-evaluated. If the result of the evaluation is different than the
current value of the signal, an event will be scheduled (added to the list of events to
be processed) to update the signal with the new value. Thus, if an event occurs
on r or nq, then the nor operator is evaluated, and if the result is different than the
current value of q, then an event will be scheduled to update q.

Suppose at a particular moment during a simulation of the SR latch example, the
values of the signals are s='0',r='0', q='1', and nq='0'. Now suppose the value of the
signal r changes (due to some event external to the design) to the value '1'.
Since q depends on r, we must re-evaluate the expression r nor nq, which now
evaluates to '0'. Since the value of q must be changed to '0', a new event will be
scheduled on the signal q. During the next round the event scheduled for q is
processed and q's value is updated to be '0'. Also, since nq depends on q, the
expression s nor q must be re-evaluated. The result of the expression is '1', so an
event is scheduled to update the value of nq. During the next round, when the event
on nq is processed, the expression for q will be evaluated again because it depends
on nq. However, the result of the expression will be '0' and no new event will be
scheduled because q is already '0'. Since, no new events were scheduled, there are
no more events that will occur internally to the latch.

Now, suppose an external event causes r to return to the value '0'. Since q depends
on r, r nor nq is evaluated again. The result of this expression is '0' and q is already
'0', so no events are scheduled. As you can see, this correctly models the SR latch
as we would expect. When the signal r became active ('1') the output of the latch
was reset, and when r became inactive ('0') the output remained unchanged.
The simulation rounds described in these last two paragraphs can be summarized
as follows.
start    :   r='0',s='0',q='1',nq='0'
round   1:   r='1',s='0',q='1',nq='0',   The value '0'   is scheduled on q.
round   2:   r='1',s='0',q='0',nq='0',   The value '1'   is scheduled on nq.
round   3:   r='1',s='0',q='0',nq='1',   No new events   are scheduled.
round   4:   r='0',s='0',q='0',nq='1',   No new events   are scheduled.

Section 3 - The Delay Model
The example from the last section shows how a functional simulation proceeds. It
is called a functional simulation because it models only how the design functions
without timing considerations. This is in contrast to atiming simulation, which
models the internal delays that are present in real circuits. This section explains
how VHDL can be used to model time delays to obtain a timing simulation.

We will discuss two models of delay that are used in VHDL. The first is called
the inertial delay model. The inertial delay model is specified by adding an after
clause to the signal assignment statement. For example, suppose that a change on
the input of a nor gate would cause the output to change after a delay of 1ns. To
model this delay in the SR latch example, we could replace the two signal
assignments with the following two statements.
q<=r nor nq after 1ns;
nq<=s nor q after 1ns;
Now during simulation, say signal r changes and will cause the signal q to change,
rather than schedule the event on q to occur during the next round, it is scheduled
to occur 1ns form the current time. Thus the simulator must maintain a current time
value. When no more events exist to be processed at the current time value, time is
updated to the time of the next earliest event and all events scheduled for that time
will be processed. A timing diagram for this modified SR latch produced by a
simulator might be:
Notice the change did not occur in q until 1ns after the change in r. Likewise the
change in nq did not occur until 1ns after the change in q. Thus, the "after 1ns"
models an internal delay of the nor gate.

However, this is not the end of the story for the inertial delay model. Typically,
when a component has some internal delay and an input changes for a time less
than this delay, then no change in the output will occur. This is also the case for the
inertial delay model. The following timing diagram would be produced using the
inertial delay model, if the '1' pulse on the signal r was shortened (to anything less
than 1ns) from the previous example.

The value of q never changed because the change in r did not last long enough.
Said another way, the change in r did not gain enough inertia.

Although most often the inertial delay is desired, sometimes all changes on the
input should have an effect on the output. For example, a bus experiences a time
delay, but will not "absorb" short pulses as with the inertial delay model. As a
result, VHDL provides the transport delay model. The transport delay model just
delays the change in the output by the time specified in the after clause. You can
elect to use the transport delay model instead of the inertial delay model by adding
the keyword transport to the signal assignment statement.

The SR latch example could be modified to use the transport delay model by
replacing the signal assignments with the following two statements.
q<=transport r nor nq after 1ns;
nq<=transport s nor q after 1ns;
If the transport delay model were used, the result of the same simulation shown in
the last diagram would result in the following timing diagram.
Section 4 - Other Types
In the previous sections all of the signals in the examples have been of the type bit.
VHDL provides several other types, some of which are described here. Often times
we use several bit signals together to represent a binary number in a design. VHDL
provides a mechanism for defining new types which represent a collection of
several data items of the same type. These kinds of types are called arrays. There
is a predefined array type calledbit_vector which represents a collection of bits.
The following example demonstrates how the bit_vector type can be used to define
a 1-to-4-line demultiplexer.
entity demux is
  port (e: in bit_vector (3 downto 0);           -- enables for each output
        s: in bit_vector (1 downto 0);           -- select signals
        d: out bit_vector (3 downto 0));         -- four output signals
end demux;

architecture rtl of demux is
  signal t : bit_vector(3 downto 0);             -- an internal signal
  t(3)<=s(1) and s(0);
  t(2)<=s(1) and not s(0);
  t(1)<=not s(1) and s(0);
  t(0)<=not s(1) and not s(0);
  d<=e and t;
end rtl;
Comments can be added at the end of a VHDL statement or on a line by itself
preceeded by the -- symbol. First notice how the bit_vector is used in the definition
of a signal. The definition of s indicates that s is a bit_vector and the (1 downto 0)
part specifies that the signal s contains two bits numbered 1 down to 0.
Similarly, d and e are arrays of 4 bits numbered from 3 down to 0. Second, notice
that signals, such as t, can be declared within an architecture that are not visible
from outside this entity. These internal signals are created with signal
declarations as the one in the example. They contain the key word signal followed
by a list of names of the signals to create, followed by the type of the signals.
Third, the architecture refers to the individual bits in t and s by number. The two
bits in s are number 1 and 0, so they are referred to as s(1) and s(0). Finally, notice
that the last signal assignment demonstrates that operations can be performed on a
whole array of data at once. This statement is equivalent to the four following
d(3)<=e(3)   and   t(3);
d(2)<=e(2)   and   t(2);
d(1)<=e(1)   and   t(1);
d(0)<=e(0)   and   t(0);
Each data item in an array is called an element. The number of elements in a signal
of an array type is indicated by the range that follows the type name. The elements
are numbered according to the range, and each element is referred to as an
individual by number. Operations can be performed on an array as a whole
(applying to every element in the array), or they can be performed using individual
elements of the array, independent of the others.

When operations are performed on whole vectors, the vectors must have the same
number of elements. If they do not, the simulator will report an error and stop the
simulation. In an operation between vectors, elements are matched as they are
number from left to right. Thus, if a variable v1 has elements 0 to 1 and
variable v2 has elements 1 downto 0. Then
would assign v2(1) to v1(0) and v2(0) to v1(1).

Another predefined type is time. This type is used to represent values of time. We
have already used constant values of this type in the after clause. Time is an
example of a physical type. All values of a physical type have two parts, a number
and a unit name. The type time includes the following predefined unit names sec
(seconds), ms (milliseconds), us (microseconds), ns (nanoseconds), ps
(picoseconds), and fs (femtoseconds). There are several other types predefined in
VHDL including types for integers and real numbers. These are mentioned later in
the sections related to behavioral descriptions. There are also many capabilities for
defining your own types, which is beyond this tutorial but are described in standard
VHDL texts.

Section 5 - Other Operators
The previous sectioned mentioned a few different types that are available in
VHDL. There are also several built-in operators that can be used with those types.
This section mentions some of these.

The logical operators NOT, AND, OR, NAND, NOR, and XOR can be used with
any bit type or bit_vector. When used as operators on bits they have their usual
meaning. When used with bit_vectors, the bit_vectors must have the same number
of elements, and the operation is performed bitwise. For example, "00101001" xor
"11100101" results in "11001100".
note: just as '0' and '1' represent constant bit values, constant bit_vectors can be
written in VHDL as a list of bit values in double quotes. For example, if d is a
bit_vector(1 to 4) the following statement gives d the permanent values d(1)='1',
d(2)='1', d(3)='0', and d(4)='0'.

Hexadecimal can also be used as a shortcut as in the following example.

Since C is the hexadecimal number 12, which in binary is 1100, this statement is
equivalent to the one preceeding it. The X in the front indicates that the number is
in hexadecimal instead of the normal binary.

The typical algebraic operators are available for integers, such as +,-,*
(multilication), and / (division). Although these operations are not built-in for
bit_vectors, they are often provided in libraries that come with your VHDL
software. They are used with bit_vectors by interpreting them as a binary
representation of integers, which may be added, subtracted, multiplied, or divided.

Also predefined are the normal relational operators. They are =, /=, <, <=, > and
>= and have their usual meanings (/= denotes the not equal operator). The result of
all these operators is a boolean value (TRUE or FALSE). The arguments to the =
and /= operators may be of any type. The arguments of the <, <=, > and >=
operators may be any scalar type (integer, real, and physical types) or the
bit_vector type. If the arguments are bit_vectors, then the arguments must be the
same length and the result is TRUE only if the relation is true for each
corresponding element of the array arguments.

The & operator is a built-in VHDL operator that performs the concatenation of
bit_vectors. For example, with the following declarations:

signal a: bit_vector (1 to 4);

signal b: bit_vector (1 to 8);

The following statement would connect a to the right half of b and make the left
half of b constant '0'.
b<="0000" & a;
The & appends the a to the end of the "0000" to form a result that contains 8 bits.
Chapter 4 - Behavioral Descriptions
There are three different paradigms for describing digital components with VHDL,
structural, data flow, and behavioral descriptions. This chapter dicusses the
behavioral approach.

Section 1 - The Process Statement
The behavioral approach to modeling hardware components is different from the
other two methods in that it does not necessarily in any way reflect how the
design is implemented. It is basically the black box approach to modeling. It
accurately models what happens on the inputs and outputs of the black box, but
what is inside the box (how it works) is irrelevant. The behavioral description is
usually used in two ways in VHDL. First, it can be used to model complex
components that would be tedious to model using the other methods. This might
be the case for example, if you wish to simulate the operation of your custom
design connected to a commercial part like a microprocessor. In this case, the
microprocessor is complex and its internal operation is irrelevant (only the
external behavior is important) so it would probably be modeled using the
behavioral style. Second, the behavioral capabilities of VHDL can be more
powerful and is more convenient for some designs. In this case the behavioral
description will likely imply some structure of the implementation.

Behavioral descriptions are supported with the process statement. The process
statement can appear in the body of an architecture declaration just as the signal
assignment statement does. The contents of the process statement can include
sequential statements like those found in software programming languages. These
statements are used to compute the outputs of the process from its inputs.
Sequential statements are often more powerful, but sometimes have no direct
correspondence to a hardware implementation. The process statement can also
contain signal assignments in order to specify the outputs of the process.

Our first example of the process statement is trivial and would not normally be
done in a process statement. However, it allows us to examine the process
statement without learning any sequential statements first.
compute_xor: process (b,c)
  a<=b xor c;
end process;
The first part
is used to name the process. This part is optional. Next is the
keyword process that starts the definition of a process. Following that is a list of
signals in parenthesis, called the sensitivity list. Since the process statement's
contents may not have indicated any structural characteristics, there is no way to
know when the process should be re-evaluated to update the outputs. The signal
sensitivity list is used to specify which signals should cause the process to be re-
evaluated. Whenever any event occurs on one of the signals in the sensitivity list,
the process is re-evaluated. A process is evaluated by performing each statement
that it contains. These statements (the body of the process) appear between
the begin and end keywords.

This example process contains one statement, the signal assignment. Unlike signal
assignments that appear outside the process statement, this signal assignment is
only evaluated when events occur on the signals in the process' sensitivity list,
regardless of which signals appear on the right side of the <= operators. This
means it is critical to make sure the proper signals are in the sensitivity list. The
statements in the body of the process are performed (or executed) in order from
first to last. When the last statement has been executed the process is finished and
is said to be suspended. When an event occurs on a signal in the sensitivity list, the
process is said to be resumed and the statements will be executed from top to
bottom again. Each process is executed once during the beginning of a simulation
to determine the initial values of its outputs.

Section 2 - Using Variables
There are two major kinds of objects used to hold data. The first kind, used mostly
in structural and data flow descriptions, is the signal. The second, which can only
be used in processes is called a variable. A variable behaves like you would expect
in a software programming language, which is much different than the behavior of
a signal.

Although variables represent data like the signal, they do not have or cause events
and are modified differently. Variables are modified with the variable assignment.
For example,
assigns the value of b to a. The value is simply copied to a immediately. Since
variables may only be used in processes, the assignment statement may only
appear in a process. The assignment is performed when the process is executed, as
explained in the last section.

The following example shows how a variable is used in a process.
count: process (x)
  variable cnt : integer := -1;
end process;
Variable declarations appear before the begin keyword of a process statement as in
the example. The variable declaration is the same as the signal declaration except
the key word variable is used instead of signal. The declaration in this example
includes an optional part, which specifies the initial value of the variable, when a
simulation begins. The initialization part is included by adding the := and some
constant expression after the type part of the declaration. This initialization part
may also be included in signal declarations. The variable cnt is declared to be of
the type integer. The integer type represents negative and positive integer values.

The process in the example contains one statement, the assignment statement. This
assignment computes the value of cnt plus one and immediately stores that new
value in the variable cnt. Thus, cnt will be incremented by one each time this
process is executed. Remember, from the last section, that a process is executed
once at the beginning of simulation and then each time an event occurs on any
signal in its sensitivity list. Since the value is initialized to -1, and the process is
executed once before beginning simulation, the value of cnt will be 0 when
simulation begins. Once simulation begins, cnt will be incremented by one each
time the signal x changes, since xis in the sensitivity list. If x is a bit signal, then
this process will count the number of rising and falling edges that occur on the
signal x.

Section 3 - Sequential Statements
There are several statements that may only be used in the body of a process. These
statements are called sequential statements because they are executed sequentially.
That is, one after the other as they appear in the design from the top of the process
body to the bottom. In this section we will examine some of these statements.

The first example illustrates the if statement and a common use of the
VHDL attribute.
count: process (x)
  variable cnt : integer :=0 ;
  if (x='1' and x'last_value='0') then
  end if;
end process;
This if statement has two main parts, the condition and the statement body.
A condition is any boolean expression (an expression that evaluates to TRUE and
FALSE, such as expressions using relational operators). The condition in the
example uses the attribute last_value, which is used to determine the last value that
a signal had. Attributes can be used to obtain a lot of auxiliary information about
signals. The value of an attribute for a particular signal is obtained by specifying
the name of the signal, followed by a ' (called a tick) and the name of the attribute
desired. Thus the condition in the example is true only if the current value of x is '1'
and its previous value was '0'. Since this statement will only be executed when an
event has occurred on x (i.e. x has just changed), this condition will be true when a
rising edge occurs on x. This is because we know x just changed, we know it was a
'0' and now it is a '1'. The statement body of the if statement is just a list of
sequential statements that appear between the key words then and end if.

The execution of the if statement begins by evaluating the condition. If the
condition evaluates to the value TRUE then the statements in the statement body
will be executed. Otherwise, execution will continue after the end ifand the
statement body of the if statement is skipped. Thus, the assignment statement in
this example is executed every time there is a rising edge on the signal x, counting
the number of rising edges.

An example of another common form of the if statement is
if (inc='1') then
end if;
This form has two statement bodies. If the condition is TRUE, the first list of
statements is executed (between the then and the else) and the second list of
statements (between the else and the end if) is not. Otherwise, the second statement
list is executed and the first is not. Thus, this example will increment cnt if inc is '1'
and decrement it otherwise.

The last statement we will look at is the loop statement. We will explain just one
form of the loop statement, often called a for statement. The for statement is used
to execute a list of statements several times. The following example uses a loop
statement to compute the even parity of a bit vector.
signal x : bit_vector (7 downto 0);
process (x)
  variable p : bit;
  for i in 7 downto 0 loop
    p:=p xor x(i);
  end loop;
end process;
The signal x is an 8 bit signal representing a byte. The variable p is used to
compute the parity of this byte. The first part of the for loop i in 7 downto 0 is
called the parameter specification. It specifies how many times the loop body will
be executed and creates a temporary variable. It begins with the name of the
temporary variable that will be created, in this case it is i. This is followed by the
key word in and then a range of values as we have seen before. The body of the
loop is executed once for every value in the range specified. The value of the
temporary variable is assigned one of the values in the range each time the loop
body is executed. In this example, the assignment will be executed first with i=7
then again with i=6, and again with i=5, and so on down to 0. This loop statement
behaves the same as the following statements.
p:=p xor   x(7);
p:=p xor   x(6);
p:=p xor   x(5);
p:=p xor   x(4);
p:=p xor   x(3);
p:=p xor   x(2);
p:=p xor   x(1);
p:=p xor   x(0);
Notice how the temporary variable i was used in the statement body of the loop to
operate on different elements of the vector x each time the body of the loop is
executed. This is a very common use of the loop statement. Although this loop
contains only one statement, there may be many statements in the loop body.

Section 3 - Signals and Processes
This section is short, but contains important information about the use of signals in
the process statement. The issue of concern is to avoid confusion about the
difference between how a signal assignment and variable assignment behave in the
process statement. Remember a signal assignment, if anything, merely schedules
an event to occur on a signal and does not have an immediate effect. When a
process is resumed, it executes from top to bottom and no events are processed
until after the process is complete. This means, if an event is scheduled on a signal
during the execution of a process, that event can be processed after the process has
completed at the earliest. Let's examine an example of this behavior. In the
following process two events are scheduled on signals x and z.
signal x,y,z : bit;
process (y)
  z<=not x;
end process;
If the signal y changes then an event will be scheduled on x to make it the same
as y. Also, an event is scheduled on z to make it the opposite of x. The question is,
will the value of z be the opposite of y? Of course, the answer is no, because when
the second statement is executed, the event on x has not been processed yet, and
the event scheduled on z will be the opposite of the value of x before the process
This is pointed out because this is not necessarily the intuitive behavior and
because variables operate differently. For example, in
process (y)
variable x,z : bit;
  z:=not x;
end process;
The value of the variable z would be the opposite of the value of y because the
value of the variable x is changed immediately.

Section 4 - Program Output
In most programming languages there is a mechanism for printing text on the
monitor and getting input from the user through the keyboard. Even though your
simulator will let you monitor the value of signals and variables in your design, it
is also nice to be able to output certain information during simulation. It is not
provided as a language feature in VHDL, but rather as a standard library that
comes with every VHDL language system. In VHDL, common code can be put in
a separate file to be used by many designs. This common code is called a library.
In order to use the library that provides input and output capabilities you must add
the statement
use textio.all;
immediately before every architecture that uses input and output. The name of the
library is textio and this statement indicates that you wish to use everything or all
of the textio library. Once you have done that, you may use any of the features
discussed in this section. Note that although it is not part of the language, the
library is standard and will be the same regardless of the VHDL tools you are

Text is input and output using textio via a variable of the type line. Since variables
are used for textio, input and output is done in processes. The procedure for
outputting information is to first place it in text form into the variable of type line
and then to request that the line be output. This is shown in the following example.
use textio.all;
architecture behavior of check is
  process (x)
    variable s : line;
    variable cnt : integer:=0;
    if (x='1' and x'last_value='0') then
      if (cnt>MAX_COUNT) then
        write(s,"Counter overflow - ");
      end if;
    end if;
  end process;
end behavior;
The write function is used to append text information at the end of a line variable
which is empty when the simulator is initialized. The function takes two
arguments, the first is the name of the line to append to, and the second is the
information to be appended. In the example, s is set to "Counter overflow - ", and
then the current value of cnt is converted to text and added to the end of that.
The writeline function outputs the current value of a line to the monitor, and
empties the line for re-use. The first argument of the writeline function just
indicates that the text should be output to the screen. If MAX_COUNT were a
constant equal to 15 and more than 15 rising edges occur on the signal x, then the
Counter overflow - 16
would be printed on the screen.

The write statement can also be used to append constant values and the value of
variables and signals of the types bit, bit_vector, time, integer, and real. Keyboard
input is more complex than output, and is not discussed in this tutorial.

To top