Você está na página 1de 5

Types and Arrays

Dr DC Hendry

February 17, 2006

1 Enumerated Types

The first type that we looked at with VHDL, type BIT, allowed two values, 0 and 1. Thus
a signal or variable of type BIT can only take one of these two values. Type BIT is an
enumerated type - that is, it is a type for which all of the possible values a signal or variable
of that type may be listed.

VHDL permits the designer to create enumerated types as needed. In fact, type BIT is one
of a standard set of type definitions available to every VHDL design. Type BIT is in fact
declared by:

type BIT is (0, 1);

The same mechanism is available to any designer, but caution is needed. Remember that
VHDL was originally conceived as a tool for simulation and documentation of a design, not
for synthesis. For simulation and documentation the tools do not need to know anything
of the semantics or intent of the designer. Thus designers could introduce new types to
describe logic systems as they felt fit.

Synthesis tools however need to associate logic values with symbols used, and all synthesis
tools consider 1 (of types BIT and STD LOGIC) as being the logic true value. As we have
moved to making universal use of synthesis tools it was necessary to restrict the set of types
used. The types defined by the package std logic 1164 are standardised by IEEE for use
in both simulation and synthesis in IEEE standard 1164.

Type std logic is (almost) defined as:

type std logic is (


U, Uninitialised
X, Forcing unknown
0, Forcing 0
1, Forcing 1
Z, high impedance
W, weak unknown
L, weak 0
H, weak 1
, dont care
);
EG/ES 3560

Unless you have good reason not to, use type std logic, or for arrays type std logic vector
in all designs. Mechanisms based on attributes are available to permit limited alternatives,
but I recommend that you avoid these.

There is however one situation where the enumerated type mechanism can be put to very
good use, finite state machines. A finite state machine, an FSM, be it a Moore or a Mealy
machine, will be described as having a number of states. These states are typically given
descriptive names in the early stage of a design, and then as a manual design process
proceeds, these state names are converted to binary codes (the state assignment process).

In a synthesis based design flow, state minimisation and state assignment will be the respon-
sibility of the synthesis tool. The VHDL description will therefore be in terms of the original
textual state names. We shall return to this topic again when we consider the coding of
finite state machines.

2 Array Types

The majority of digital designs will involve address buses or data buses of 16, 32 or more
bits. For high level design work it may be satisfactory to describe parts of such systems
using type integer, but as we seek a description which is bit accurate such buses will be
described by an array of bits, such as types bit vector or std logic vector.

VHDL permits the declaration of new array types as needed, and it is this mechanism that
is used to declare type std logic vector. The syntax for declaring a new array type (there
is an example of this in the testbenches supplied in the laboratory exercise) is:

type <new type name> is array (<index range>) of <element type>;

where new type name is the name the designer creates for the new type, index range
describes the range of the index (the number in round brackets which selects one element of
the array), and element type indicates what each element of the array consists of. Here is
an example for a type called myArray which consists of an array of 20 elements where each
element is an integer. This is followed by the declaration of a variable (so this code may be
within the declarations at the head of a process) called counters of this type:
type countersT is array (19 downto 0) of integer;
variable counters : countersT;

We can describe the index range as either n downto m or as m to n. It is not necessary to


include an index 0 within the range. The index range does not have to be of type integer,
any enumerated type may be used.

There are many occasions however where we dont want to include the range of the index
within the type declaration, rather we simply want to indicate that the index is an integer or
a natural number (that is, +ve or zero). The following syntax, referred to as an unconstrained
array, may then be used:

type <new type name> is array (natural range <>) of <element type>;

Here is an example from std logic 1164:

type std logic vector is array (natural range <>) of std logic;

Revision : 1.2 Page 2 Dr DC Hendry


EG/ES 3560

When we declare signals or variables of an unconstrained type we then indicate the index
range within round brackets following the signal name.

Arrays have some very useful attributes available which can make code very much more
readable and re-usable. Remember that attributes follow the signal or variable name they
refer to, and are seperated from that name by a mark. Here is an example where we want
to construct a for loop over every element of an array:
variable xs : std logic vector(15 downto 0);
.
begin
.
.
for n in xsrange loop
.
.
end loop;
.
end process . . . ;

So the attribute range return the index range. Writing the code this way means that any
changes to the signal declaration will be automatically communicated to the for loop. This
make subsequent modifications to the code very much easier. This may seem trivial, but in
real code the same for loop could occur many times in the code, finding all such instances
and reliably changing them may not be easy.

3 Strings

Strings

VHDL character strings are defined as the type:

type string is array (positive range <>) of character;

Note the use of positive as the index range. Type positive is defined in VHDL to consist
of the positive numbers only, not including zero. So we cannot use zero as one end of the
index range:
signal correct : string(10 downto 1); OK
signal FAILS : string(9 downto 0); fails to compile.

A useful operator with strings is the concatenation operator &, which simple concatenates
two strings to make a longer string. This is useful with the report and assert sequential
statements for constructing output messages. See the testbenches for an example.

4 Useful Array Operators

When dealing with arrays we often want to access a small number of the elements. Two
useful constructs will be considered here, slices and aggregates.

Revision : 1.2 Page 3 Dr DC Hendry


4.1 Slices EG/ES 3560

4.1 Slices

A slice is simply a section of the original array defined by a subset of the range of the index.
For example:
signal r15, r16 : std logic vector(0 to 31);
.
begin
.
r15(0 to 3) <= 1101;
r16(28 to 31) <= r15(4 to 7);

The slice direction must be the same as that of the original declaration. So the next
statement is illegal:

r15(3 downto 0) <= 1101;

4.2 Aggregates

An aggregate allows us to construct an expression for the individual elements of the array
in a shorthand manner. An aggregate will appear on the right hand side of an assignment
(concurrent or sequential). Here is an example:

signal flags : std logic vector(3 downto 0);


signal zFlag : std logic;
signal address : std logic vector(63 downto 0);
.
begin
.
flags <= (0, zFlag, 1, 0);
address <= (1, 1, others => 0);

So an aggregate consists of a list of values in round brackets.

There should be the same number of elements in the aggregate as are in the signal/variable
on the left hand side unless an others clause is used.

If you use others then all elements not already assigned will be given the value in the others
clause. This is widely used by designers to provide a mechanism for typically initialising an
array without having to worry about the number of elements in the array, as follows:

address <= (others => 0);

Rather than just giving a list of values to be placed into the array, it is also possible to
indicate the point in the array where the element is to be placed (this is called a named

Revision : 1.2 Page 4 Dr DC Hendry


4.2 Aggregates EG/ES 3560

association):

flags <= (2 => zFlag, 1 => 1, others => 0);

Positional and named association can be mixed:

flags <= (0, 2 => zFlag, 1 => 1, others => 0);

Revision : 1.2 Page 5 Dr DC Hendry

Você também pode gostar