File

advertisement
1|Page
VHDL PROGRAMMING
By Prashant Pacific
Module I
Fundamental VHDL Units , LIBRARY Declarations, ENTITY, ARCHITECTURE,
Introductory Examples, Specification of combinational systems using VHDL,
Introduction to VHDL, Basic language element of VHDL, Behavioral Modeling, Data
flow modeling, Structural modeling, Subprograms and overloading, VHDL description
of gates.
What the F*** is VHDL?
VHDL is an acronym for VHSlC Hardware Description Language (VHSIC is an acronym for
Very High Speed Integrated Circuits). It is a hardware description language that can be used
to model a digital system at many levels of abstraction ranging from the algorithmic level to
the gate level.
The VHDL language can be regarded as an integrated amalgamation of the following
languages:
sequential language + concurrent language + net-list language +
timing specifications +
waveform generation language => VHDL
Fundamental VHDL Units
A standalone piece of VHDL code is composed of at least
three fundamental sections:
 LIBRARY declarations: Contains a list of all libraries to be used in the design. For
example: ieee, std, work, etc.
 ENTITY: Specifies the I/O pins of the circuit.
 ARCHITECTURE: Contains the VHDL code proper, which describes how the
2|Page
LIBRARY Declarations
To declare a LIBRARY (that is, to make it visible to the design) two lines of code
are needed, one containing the name of the library, and the other a use clause, as
shown in the syntax below.
LIBRARY library_name;
USE library_name.package_name.package_parts;
At least three packages, from three di¤erent libraries, are usually needed in a
design:
 ieee.std_logic_1164 (from the ieee library),
 standard (from the std library), and
 work (work library).
Their declarations are as follows:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY std;
USE std.standard.all;
-- A semi-colon (;) indicates
-- the end of a statement or
-- declaration, while a double
-- dash (--) indicates a comment.
LIBRARY work;
USE work.all;
The libraries std and work shown above are made visible by default, so there is no
need to declare them; only the ieee library must be explicitly written. However, the
latter is only necessary when the STD_LOGIC (or STD_ULOGIC) data type is
employed in the design (data types will be studied in detail in the next chapter).
The purpose of the three packages/libraries mentioned above is the following: the
std_logic_1164 package of the ieee library specifies a multi-level logic system; std is a
resource library (data types, text i/o, etc.) for the VHDL design environment; and the
work library is where we save our design (the .vhd file, plus all files created by the
compiler, simulator, etc.).
ENTITY
An ENTITY is a list with specifications of all input and output pins (PORTS) of the
circuit. Its syntax is shown below.
ENTITY entity_name IS
PORT (
port_name : signal_mode signal_type;
port_name : signal_mode signal_type;
...);
END entity_name;
Example: Let us consider the NAND gate of figure 2.4. Its ENTITY can be specified
as:
3|Page
The mode of the signal can be IN, OUT,
INOUT, or BUFFER. As illustrated in
figure 2.3, IN and OUT are truly
unidirectional pins, while INOUT is
bidirectional.
BUFFER, on the other hand, is employed
when the output signal must be used
(read) internally.
The type of the signal can be BIT,
STD_LOGIC, INTEGER, etc. Data types
will
be discussed LATER.
Finally, the name of the entity can be
basically any name, except VHDL
reserved
words (VHDL reserved words are listed
in appendix E).
The meaning of the ENTITY above is the following: the circuit has three I/O pins,
being two inputs (a and b, mode IN) and one output (x, mode OUT). All three signals
are of type BIT. The name chosen for the entity was nand gate.
4|Page
HALF ADDER
entity HALF_ADDER is
port (A, B: in BIT; SUM, CARRY: out BIT);
end HALF_ADDER;
FULL ADDER
entity FULL_ADDER is
port (A, B, CIN: in BIT; SUM, COUT: out BIT);
end FULL_ADDER;
2x4 DECODER
entity DECODER2x4 is
port (A, B, ENABLE: in BIT;
Z: out BIT_VECTOR(0 to 3));
end DECODER2x4;
MUX 2x1
entity MUX2x1 is
Port ( A : in std_logic;
B : in std_logic;
S : in std_logic;
Y : out std_logic);
end MUX2x1;
DFF
entity DFF is
port ( D, CLK, RST: in STD_LOGIC;
Q: out STD_LOGIC);
end DFF;
5|Page
ARCHITECTURE
The ARCHITECTURE is a description of how the circuit should behave (function).
Its syntax is the following:
ARCHITECTURE architecture_name OF entity_name IS
[declarations]
BEGIN
(code)
END architecture_name;
As shown above, an architecture has two parts: a declarative part (optional), where
signals and constants (among others) are declared, and the code part (from BEGIN
down). Like in the case of an entity, the name of an architecture can be basically any
name (except VHDL reserved words), including the same name as the entity’s.
The internal details of an entity are specified by an architecture body using any of the
following modeling styles:
1. As a set of interconnected components (to represent structure),
2. As a set of concurrent assignment statements (to represent dataflow),
3. As a set of sequential assignment statements (to represent be-hav.ior),
4. Any combination of the above three.
Structural modeling
In the structural style of modeling, an entity is described as a set of interconnected
components.
architecture identifier of entity_name is
architecture_declarative_part
begin
architecture_statement_part
end [ architecture_simple_name ] ;
architecture_declarative_part ::= { block_declarative_item }
architecture_statement_part ::= { concurrent_statement }
block_declarative_item ::=
subprogram_declaration
subprogram_body
type_declaration
subtype_declaration
constant_declaration
signal_declaration
alias_declaration
component_declaration
6 | P a ADDER
ge
HALF
architecture HA_STRUCTURE of HALF_ADDER
is
component XOR2
port (X, Y: in BIT; Z: out BIT);
end component;
component AND2
port (L, M: in BIT; N: out BIT);
end component;
begin
X1: XOR2 port map (A, B, SUM);
A1: AND2 port map (A, B, CARRY);
end HA_STRUCTURE;
FULL ADDER
architecture FA_STRUCT of FULL_ADDER is
component XOR1
port (A,B: in BIT; S1: out BIT);
end component;
component XOR2
port (S1,CIN: in BIT; SUM: out BIT);
end component;
component AND1
port (CIN,S1: in BIT; N1: out BIT);
end component;
component AND2
port (A,B: in BIT; N2: out BIT);
end component;
component OR
port (N1,N2: in BIT; COUT: out BIT);
end component;
begin
X1: XOR1 port map (A, B, S1);
A1: XOR2 port map (S1,CIN,SUM);
A1: AND1 port map (CIN,S1,N1);
A2: AND2 port map (A,B,N2);
01: OR1 port map (N1,N2,COUT)
end FA_STRUCT;
2x4 DECODER
architecture DEC_STR of DECODER2x4 is
component INV
port (A: in BIT; Z: out BIT);
end component;
component NAND3
port (A, B, C: in BIT; Z: out BIT);
end component;
signal ABAR, BBAR: BIT;
begin
I0: INV port map (A, ABAR);
I1: INV port map (B, BBAR);
N0: NAND3 port map (ABAR, BBAR,
ENABLE, Z(0));
N1: NAND3 port map (ABAR, B, ENABLE,
Z(1));
7|Page
N2: NAND3 port map (A, BBAR, ENABLE,
Z(2));
N3: NAND3 port map (A, B, ENABLE, Z(3));
end DEC_STR;
MUX 2x1
architecture MUX_STRUCT of mux2to1 is
component AND1
port (A,SEL: in BIT; S1: out BIT);
end component;
component INV
port (SEL: in BIT; K: out BIT);
end component;
signal SELBAR: BIT;
component AND2
port (B,SELBAR: in BIT; S2: out BIT);
end component;
component 0R
port (S1,S2: in BIT; Z: out BIT);
end component;
begin
I0: INV port map (SEL, SELBAR);
A1: AND1 port map (A,SEL);
A2: AND2 port map (SELBAR,B);
OR: OR port map (S1,S2);
end MUX_STRUCT
DFF
8|Page
Data Flow Modeling
In this modeling style, the flow of data through the entity is expressed primarily using
concurrent signal assignment statements. The structure of the entity is not explicitly specified
in this modeling style, but it can be implicitly deduced.
HALF ADDER
architecture HA_dataflow of HA
begin
SUM <= A xor B after 8 ns;
CARRY <= A and B after 4 ns;
end HA_dataflow;
FULL ADDER
architecture FA_dataflow OF full_adder IS
signal x1, x2, x3, x4, y1 : BIT;
begin
x1 <= a AND b;
x2 <= a AND carry_in;
x3 <= b AND carry_in;
x4 <= x1 OR x2;
Cout <= x3 OR x4;
y1 <= a XOR b;
S<= y1 XOR carry_in;
end FA_dataflow;
2x4 DECODER
architecture dec_dataflgw of DECODER2x4 is
signal ABAR, BBAR: BIT;
begin
Z(3) <= not (A and B and ENABLE);
Z(0) <= not (ABAR and BBAR and
ENABLE);
BBAR <= not B;
Z(2) <= not (A and BBAR and ENABLE);
ABAR <= not A;
Z(1 ) <= not (ABAR and B and ENABLE);
end DEC_DATAFLOW;
9|Page
MUX 2x1
architecture MUX_dataflow OF MUX_2to1 IS
signal x1, x2,SELBAR : BIT;
begin
x1 <= A AND SEL ;
x2 <= SELBAR AND B;
OUT <= x1 OR x2;
end MUX_dataflow;
DFF
Behavioral Style of Modeling
In contrast to the styles of modeling described earlier, the behavioral style of modeling
specifies the behavior of an entity as a set of statements that are executed sequentially in the
specified order. This set of sequential statements, that are specified inside a process
statement, do not explicitly specify the structure of the entity but merely specifies its
functionality. A process statement is a concurrent statement that can appear within an
architecture body.
HALF ADDER
10 | P a g e
FULL ADDER
2x4 DECODER
Architecture dec_seq of DECODER2x4 is
begin process (A, B, ENABLE)
variable ABAR, BBAR: BIT;
begin
ABAR := not A;
BBAR := not B;
if (ENABLE = '1')
then Z(3) <= not (A and B):
Z(0) <= not (ABAR and BBAR);
Z(2) <= not (A and BBAR);
Z(1 ) <= not (ABAR and B);
else
Z<= "1111";
end if; end process; end;
MUX 2x1
11 | P a g e
DFF
architecture LS_DFF_BEH of LS_DFF is
begin
process (D, CLK)
begin
if (CLK = '1') then
Q <= D;
end if;
end process;
end LS_DFF_BEH;
Basic elements of the VHDL language
1.
2.
3.
4.
Data objects
Literals
Operators
Object declarations (how to associate types with objects)
DATA OBJECTS
A data object holds a value of a specified type. It is created by means of an object declaration.
An example is
variable COUNT: INTEGER;
This results in the creation of a data object called COUNT which can hold integer values. The
object COUNT is also declared to be of variable class.
Every data object belongs to one of the following three classes:
1. Constant: An object of constant cla^s can hold a single value of a given type. This value is
assigned to the object before simulation starts and the value cannot be changed during the
course of the simulation.
2. Variable: An object of variable class can also hold a single value of a given type. However
in this case, different values can be assigned to the object at different times using a variable
assignment statement.
3. Signal: An object belonging to the signal class has a past history of values, a current value,
and a set of future values. Future values can be assigned to a signal object using a signal
assignment statement.
Signal objects can be regarded as wires in a circuit while variable and constant objects
are analogous to their counterparts in a high-level programming language like C or Pascal.
Signal objects are typically used to model wires and flip-flops while variable and constant
objects are typically used to model the behavior of the circuit.
An object declaration is used to declare an object, its type, and its class, and optionally assign
it a value. Some examples of object declarations of various types and classes follow.
Constant Declarations
Examples of constant declarations are
constant RISE_TIME: TIME := 10ns;
constant BUS_WIDTH: INTEGER := 8:
12 | P a g e
The first declaration declares the object RISE_TIME that can hold a value of type TIME (a
predefined type in the language) and the value assigned to the object at the start of simulation
is 10 ns. The second constant declaration declares a constant BUS_WIDTH of type
INTEGER with a value of 8.
An example of another form of constant declaration is
constant NO_OF_INPUTS: INTEGER;
The value of the constant has not been specified in this case. Such a constant is called a
deferred constant and it can appear only inside a package declaration. The complete constant
declaration with the associated value must appear in the corresponding package body.
Variable Declarations Examples of variable declarations are
variable CTRL_STATUS: BIT_VECTOR(10 downto 0);
variable SUM: INTEGER range O to 100 := 10;
variable FOUND, DONE: BOOLEAN;
The first declaration specifies a variable object CTRL_STATUS as an array of II
elements, with each array element of type BIT. In the second declaration, an explicit initial
value has been assigned to the variable SUM. When simulation starts, SUM will have an
initial value of 10. If no initial value is specified for a variable object, a default value is used
as an initial value. This default value is T'LEFT, where T is the object type and LEFT is a
predefined attribute of a type that gives the leftmost value in the set of values belonging to
type T. In the third declaration, the initial values assigned to FOUND and DONE at start of
simulation is FALSE (FALSE is the leftmost value of the predefined type, BOOLEAN). The
initial value for all the array elements of CTRL_STATUS is '0'.
Signal Declarations
Here are some examples of signal declarations.
signal CLOCK: BIT;
signal DATA_BUS: BIT_VECTOR(0 to 7);
signal GATE_DELAY: TIME := 10 ns;
The interpretation for these signal declarations is very similar to that of the variable
declarations. The first signal declaration declares the signal object CLOCK of type BIT and
gives it an initial value of '0' ('0' being the leftmost value of type BIT). The third signal
declaration declares a signal object GATE_DELAY of type TIME that has an initial value of
10 ns.
Other Ways to Declare Objects
Not all objects in a VHDL description are created using object declarations. These other
objects are declared as
1. ports of an entity. All ports are signal objects.
2. generics of an entity .These are constant objects.
3. formal parameters of functions and procedures. Function parameters are constant objects or
signal objects while procedure parameters can belong to any object class,
4. a file declared by a file declaration.
There are two other types of objects that are implicitly declared. These are the indices of a
for. . . loop statement and the generate statement. An example of such an implicit declaration
for the loop index in a for. . . loop statement is shown.
for COUNT in 1 to 10 loop
SUM := SUM + COUNT;
end loop;
13 | P a g e
In this for . . . loop statement, object COUNT has an implicit declaration of type INTEGER
with range I to 10, and therefore, need not be explicitly declared. The object COUNT is
created when the loop is first entered and ceases to exist after the loop is exited.
IDENTIFIERS
An identifier in VHDL is composed of a sequence of one or more characters. A legal
character is an upper-case letter (A... Z), or a lower-case letter (a. .. z), or a digit (0 . . . 9) or
the underscore ( _ ) character. The first character in an identifier must be a letter and the last
character may not be an underscore. Lower-case and upper-case letters are considered to be
identical when used in an identifier; as an example. Count, COUNT, and CouNT, all refer to
the same identifier. Also,-two underscore characters cannot appear consecutively. Some more
examples of identifiers are
DRIVE_BUS SelectSignal RAM_Address
SET_CK_HIGH CONST32_59 r2d2
Comments in a description must be preceded by two consecutive hyphens (-); the comment
extends to the end of the line. Comments can appear anywhere within a description.
Examples are
— This is a comment; it ends at the end of this line.
— To continue a comment onto a second line, a separate
— comment line must be started.
entity UART is end; --This comment starts after the entity declaration.
The language defines a set of reserved words; these are listed in Appendix A.I. These words,
also called keywofds, have a specific meaning in the language, and therefore, cannot be used
as identifiers.
DATA TYPES(We have complete MODULE 2 on this…So We’ll study this later in Detail)
14 | P a g e
OPERATORS
In the order of Increasing Precedence
1.Logical
2.Relational 3.Adding
4.Multiplying 5.Misc.
The six logical
operators are
and
or
nand
nor
xor
not
These
operators are
defined for the
predefined
types BIT and
BOOLEAN.
They are also
defined
for
onedimensional
arrays of BIT
and
BOOLEAN.
During
evaluation, bit
values '0' and
1' are treated as
FALSE
and
TRUE values
of
the
BOOLEAN
type,
respectively.
The result of a
logical
operation has
the same type
as its operands.
The
not
operator is a
unaiy logical
operator and
has the same
precedence as
that of
miscellaneous
operators.
These are
=
!=
<
<=
>
>=
The result types
for all relational
operations is
always
BOOLEAN. The
= (equality) and
the /=
(inequality)
operators are
permitted on any
type except file
types. The
remaining four
relational
operators are
permitted on any
scalar type (e.g.,
integer or
enumerated
types) or
discrete array
type (i.e., arrays
in which
element values
belong to a
discrete type).
When operands
are discrete
array types,
comparison is
performed one
element at a
time from left to
right.
These are
*
/
mod
rem
The
*
(multiplication)
and / (division)
operators
are
predefined for both
operands being of
the same integer or
floating point type.
The result is also
of the same type.
The multiplication
operator is also
defined for the
case when one of
the operands is of
a physical type and
the second operand
is of integer or real
type. The result is
of physical type.
For the division
operator, division
of an object of a
physical type by
either an integer or
a real type object
is allowed and the
result type is of the
physical type.
Same goes for
mod and rem.
These are
+
&
The operands
for
the
+
(addition) and (subtraction)
operators must
be of the same
numeric type
with the result
being of the
same numeric
type.
The
addition
and
subtraction
operators may
also be used as
unary
operators,
in
which case, the
operand and the
result type must
be the same.
The operands
for
the
&
(concatenation)
operator can be
either
a
Idirnensional
array type or an
element type.
The result is
always an array
type.
For
example,
'0' & '1'
results in an
array of
characters
"01".
The
miscellaneous
operators are
abs
**
The
abs
(absolute)
operator
is
defined for any
numeric type.
The **
(exponentiation)
operator
is
defined for the
left operand to
be of integer or
floating
point
type and the
right
operand
(i.e.,
the
exponent) to be
of integer type
only.
The not logical
operator has the
same
precedence as
the above two
operators
15 | P a g e
LITERALS
1.Comments
Comments in VHDL start with two adjacent hyphens (‘--’) and extend to
the end of the line. They have no part in the meaning of a VHDL
description.
2.Identifiers
Identifiers in VHDL are used as reserved words and as programmer
defined names. They must conform to the rule:
identifier ::= letter { [ underline ] letter_or_digit }
Note that case of letters is not considered significant, so the identifiers cat
and Cat are the same. Underline characters in identifiers are significant,
so This_Name and ThisName are different identifiers.
3.Numbers
Literal numbers may be expressed either in decimal or in a base
between two and sixteen. If the literal includes a point, it represents a real
number, otherwise it represents an integer. Decimal literals are defined
by:
decimal_literal ::= integer [ . integer ] [ exponent ]
integer ::= digit { [ underline ] digit }
exponent ::= E [ + ] integer | E - integer
Some examples are:
0 1 123_456_789 987E6 -- integer literals
0.0 0.5 2.718_28 12.4E-9 -- real literals
Based literal numbers are defined by:
based_literal ::= base # based_integer [ . based_integer ] # [ exponent ]
base ::= integer
based_integer ::= extended_digit { [ underline ] extended_digit }
2-2 The VHDL Cookbook
extended_digit ::= digit | letter
The base and the exponent are expressed in decimal. The exponent
indicates the power of the base by which the literal is multiplied. The
letters A to F (upper or lower case) are used as extended digits to represent
10 to 15. Some examples:
2#1100_0100# 16#C4# 4#301#E1 -- the integer 196
2#1.1111_1111_111#E+11 16#F.FF#E2 -- the real number 4095.0
4.Characters
Literal characters are formed by enclosing an ASCII character in
single-quote marks. For example:
'A' '*' ''' ' '
5.Strings
Literal strings of characters are formed by enclosing the characters in
double-quote marks. To include a double-quote mark itself in a string, a
pair of double-quote marks must be put together. A string can be used as a
value for an object which is an array of characters.
16 | P a g e
6.Bit Strings
VHDL provides a convenient way of specifying literal values for arrays of
type bit ('0's and '1's, see Section 2.2.5). The syntax is:
bit_string_literal ::= base_specifier " bit_value "
base_specifier ::= B | O | X
bit_value ::= extended_digit { [ underline ] extended_digit }
Base specifier B stands for binary, O for octal and X for hexadecimal. Some
examples:
B"1010110" -- length is 7
O"126" -- length is 9, equivalent to B"001_010_110"
SUBPROGRAMS
There are two kinds of subprograms: procedures and functions.
Both procedures and functions written in VHDL must have
a body and may have declarations.
Procedures perform sequential computations and return values
in global objects or by storing values into formal parameters.
Functions perform sequential computations and return a value
as the value of the function. Functions do not change their
formal parameters.
Subprograms may exist as just a procedure body or a function body.
Subprograms may also have a procedure declarations or a
function declaration.
When subprograms are provided in a package, the subprogram declaration
is placed in the package declaration and the subprogram body is
placed in the package body.
OVERLOADING
VHDL allows two subprograms to have the same name, provided the
number or base types of parameters differs. The subprogram name is then
said to be overloaded. When a subprogram call is made using an
overloaded name, the number of actual parameters, their order, their base
types and the corresponding formal parameter names (if named
association is used) are used to determine which subprogram is meant. If
the call is a function call, the result type is also used. For example, suppose
we declared the two subprograms:
function check_limit(value : integer) return boolean;
function check_limit(value : word_32) return boolean;
Then which of the two functions is called depends on whether a value of
type integer or word_8 is used as the actual parameter.
17 | P a g e
So
test := check_limit(4095)
would call the first function, and
test := check_limit(X"0000_0FFF")
would call the second function.
The designator used to define a subprogram can be either an identifier
or a string representing any of the operator symbols listed in Section2.3.
The latter case allows extra operand types to be defined for those operators.
For example, the addition operator might be overloaded to add word_32
operands by declaring a function:
function "+" (a, b : word_32) return word_32 is
begin
return int_to_word_32( word_32_to_int(a) + word_32_to_int(b) );
end "+";
Within the body of this function, the addition operator is used to add
integers, since its operands are both integers. However, in the expression:
X"1000_0010" + X"0000_FFD0"
the newly declared function is called, since the operands to the addition
operator are both of type word_32. Note that it is also possible to call
operators using the prefix notation used for ordinary subprogram calls, for
example:
"+" (X"1000_0010", X"0000_FFD0")
18 | P a g e
VHDL PROGRAMMING
By Prashant Pacific
Module II
Data Types; Pre-Defined Data Types, User-Defined Data Types, Subtypes, Arrays, Port
Array, Records, Signed and Unsigned Data Types, Data Conversion
Pre-Defined Data Types
VHDL contains a series of pre-defined data types, specified through the IEEE 1076
and IEEE 1164 standards. More specifically, such data type definitions can be found
in the following packages / libraries:
PACKAGE
standard of library std
std_logic_1164 of library ieee
std_logic_arith of library ieee
std_logic_signed and std_logic_unsigned of
library ieee
DATA TYPES
Defines BIT, BOOLEAN, INTEGER, and
REAL
data types.
Defines STD_LOGIC and STD_ULOGIC
data types.
Defines SIGNED and UNSIGNED
data types, plus several data conversion
functions, like conv_integer(p),
conv_unsigned(p, b), conv_signed(p, b), and
conv_std_logic_vector(p, b).
Contain functions
that allow operations with
STD_LOGIC_VECTOR data to be
performed as if the
data were of type SIGNED or UNSIGNED,
respectively.
User-Defined Data Types
VHDL also allows the user to define his/her own data types. Two categories of userdefined
data types are shown below: integer and enumerated.
User-defined integer types:
TYPE my_integer IS RANGE -32 TO 32;
-- A user-defined subset of integers.
TYPE student_grade IS RANGE 0 TO 100;
-- A user-defined subset of integers or naturals.
User-defined enumerated types:
TYPE state IS (idle, forward, backward, stop);
-- An enumerated data type, typical of finite state machines.
TYPE color IS (red, green, blue, white);
-- Another enumerated data type.
TYPE my_logic IS ('0', '1', 'Z');
-- A user-defined subset of std_logic.
19 | P a g e
The encoding of enumerated types is done sequentially and automatically (unless
specified otherwise by a user-defined attribute.
A SUBTYPE is a TYPE with a constraint. The main reason for using a subtype
rather than specifying a new type is that, though operations between data of di¤erent
types are not allowed, they are allowed between a subtype and its corresponding base
type.
Examples:
SUBTYPE natural IS INTEGER RANGE 0 TO INTEGER'HIGH;
-- As expected, NATURAL is a subtype (subset) of INTEGER.
SUBTYPE my_logic IS STD_LOGIC RANGE '0' TO 'Z';
-- Recall that STD_LOGIC=('X','0','1','Z','W','L','H','-').
-- Therefore, my_logic=('0','1','Z').
SUBTYPE my_color IS color RANGE red TO blue;
-- Since color=(red, green, blue, white), then
-- my_color=(red, green, blue).
SUBTYPE small_integer IS INTEGER RANGE -32 TO 32;
-- A subtype of INTEGER.
Arrays
Arrays are collections of objects of the same type. They can be one-dimensional
(1D), two-dimensional (2D), or one-dimensional-by-one-dimensional (1Dx1D). They
can also be of higher dimensions, but then they are generally not synthesizable.
To specify a new array type:
TYPE type_name IS ARRAY (specification) OF data_type;
To make use of the new array type:
SIGNAL signal_name: type_name [:= initial_value];
In the syntax above, a SIGNAL was declared. However, it could also be a CONSTANT
or a VARIABLE. Notice that the initial value is optional (for simulation
only).
20 | P a g e
Port Array
As we have seen, there are no pre-defined data types of more than one dimension.
However, in the specification of the input or output pins (PORTS) of a circuit (which
is made in the ENTITY), we might need to specify the ports as arrays of vectors.
Since TYPE declarations are not allowed in an ENTITY, the solution is to declare
user-defined data types in a PACKAGE, which will then be visible to the whole design
(thus including the ENTITY).
Records
Records are similar to arrays, with the only di¤erence that they contain objects of
di¤erent types.
Example:
TYPE birthday IS RECORD
day: INTEGER RANGE 1 TO 31;
month: month_name;
END RECORD;
Signed and Unsigned Data Types
As mentioned earlier, these types are defined in the std_logic_arith package of the
ieee library. Their syntax is illustrated in the examples below.
Examples:
SIGNAL x: SIGNED (7 DOWNTO 0);
SIGNAL y: UNSIGNED (0 TO 3);
Notice that their syntax is similar to that of STD_LOGIC_VECTOR, not like that
of an INTEGER, as one might have expected.
To use SIGNED or UNSIGNED data types, the std_logic_arith package, of
the ieee library, must be declared.
Despite their syntax, SIGNED and UNSIGNED
data types are intended mainly for arithmetic operations, that is, contrary to
STD_LOGIC_VECTOR, they accept arithmetic operations. On the other hand,
logical operations are not allowed. With respect to relational (comparison) operations,
there are no restrictions.
Example: Legal and illegal operations with
signed/unsigned data types.
Example: Legal and illegal operations
with std_logic_vector.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all; -- extra package
necessary
...
SIGNAL a: IN SIGNED (7 DOWNTO 0);
SIGNAL b: IN SIGNED (7 DOWNTO 0);
SIGNAL x: OUT SIGNED (7 DOWNTO 0);
...
v <= a + b; -- legal (arithmetic operation OK)
w <= a AND b; -- illegal (logical operation not OK)
LIBRARY ieee;
USE ieee.std_logic_1164.all; -- no extra package
required
...
SIGNAL a: IN STD_LOGIC_VECTOR (7
DOWNTO 0);
SIGNAL b: IN STD_LOGIC_VECTOR (7
DOWNTO 0);
SIGNAL x: OUT STD_LOGIC_VECTOR (7
DOWNTO 0);
...
v <= a + b; -- illegal (arithmetic operation not
OK)
w <= a AND b; -- legal (logical operation OK)
21 | P a g e
Despite the constraint mentioned above, there is a simple way of allowing data of
type STD_LOGIC_VECTOR to participate directly in arithmetic operations. For
that, the ieee library provides two packages, std_logic_signed and std_logic_unsigned,
which allow operations with STD_LOGIC_VECTOR data to be performed as if the
data were of type SIGNED or UNSIGNED, respectively.
Example: Arithmetic operations with std_logic_vector.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all; -- extra package included
SIGNAL a: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
SIGNAL b: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
SIGNAL x: OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
...
v <= a + b; -- legal (arithmetic operation OK), unsigned
w <= a AND b; -- legal (logical operation OK)
DATA CONVERSIONS
VHDL does not allow direct operations (arithmetic, logical, etc.) between data of
different types. Therefore, it is often necessary to convert data from one type to another.
This can be done in basically two ways: or we write a piece of VHDL code for
that, or we invoke a FUNCTION from a pre-defined PACKAGE which is capable
of doing it for us.
If the data are closely related (that is, both operands have the same base type,
despite being declared as belonging to two different type classes), then the
std_logic_1164 of the ieee library provides straightforward conversion functions.
Example: Legal and illegal operations with subsets.
TYPE long IS INTEGER RANGE -100 TO 100;
TYPE short IS INTEGER RANGE -10 TO 10;
SIGNAL x : short;
SIGNAL y : long;
...
y <= 2*x + 5; -- error, type mismatch
y <= long(2*x + 5); -- OK, result converted into type long
Several data conversion functions can be found in the std_logic_arith package of
the ieee library. They are:
 conv_integer(p) : Converts a parameter p of type INTEGER, UNSIGNED,
SIGNED, or STD_ULOGIC to an INTEGER value. Notice that STD_LOGIC_
VECTOR is not included.
 conv_unsigned(p, b): Converts a parameter p of type INTEGER, UNSIGNED,
SIGNED, or STD_ULOGIC to an UNSIGNED value with size b bits.
 conv_signed(p, b): Converts a parameter p of type INTEGER, UNSIGNED,
SIGNED, or STD_ULOGIC to a SIGNED value with size b bits.
 conv_std_logic_vector(p, b): Converts a parameter p of type INTEGER,
UNSIGNED, SIGNED, or STD_LOGIC to a STD_LOGIC_VECTOR value with size
b bits.
22 | P a g e
Example: Data conversion.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
...
SIGNAL a: IN UNSIGNED (7 DOWNTO 0);
SIGNAL b: IN UNSIGNED (7 DOWNTO 0);
SIGNAL y: OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
...
y <= CONV_STD_LOGIC_VECTOR ((a+b), 8);
-- Legal operation: a+b is converted from UNSIGNED to an
-- 8-bit STD_LOGIC_VECTOR value, then assigned to y.
23 | P a g e
VHDL PROGRAMMING
By Prashant Pacific
Module III
Sequential codes:
PROCESS: Signals and Variables, IF, WAIT, CASE, LOOP, CASE versus IF, CASE
versus WHEN, Bad Clocking, Using Sequential Code to Design Combinational Circuits
Description and design of sequential circuits using VHDL
SEQUENTIAL CODES
VHDL code is inherently concurrent. PROCESSES,
FUNCTIONS, and PROCEDURES are the only sections of code that are executed
sequentially. However, as a whole, any of these blocks is still concurrent with any
other statements placed outside it.
One important aspect of sequential code is that it is not limited to sequential logic.
Indeed, with it we can build sequential circuits as well as combinational circuits. Sequential
code is also called behavioral code.
PROCESS
A PROCESS is a sequential section of VHDL code. It is characterized by the presence
of IF, WAIT, CASE, or LOOP, and by a sensitivity list (except when WAIT is
used). A PROCESS must be installed in the main code, and is executed every time a
signal in the sensitivity list changes (or the condition related to WAIT is fulfilled). Its
syntax is shown below.
[label:] PROCESS (sensitivity list)
[VARIABLE name type [range] [:= initial_value;]]
BEGIN
(sequential code)
END PROCESS [label];
VARIABLES are optional. If used, they must be declared in the declarative part
of the PROCESS (before the word BEGIN, as indicated in the syntax above). The
initial value is not synthesizable, being only taken into consideration in simulations.
The use of a label is also optional. Its purpose is to improve code readability. The
label can be any word, except VHDL reserved words.
SIGNALS AND VARIABLES
VHDL has two ways of passing non-static values around: by means of a SIGNAL
or by means of a VARIABLE.
A SIGNAL can be declared in a PACKAGE, ENTITY or ARCHITECTURE (in its
declarative part), while
A VARIABLE can only be declared inside a piece of sequential code (in a PROCESS, for
example).
Therefore, while the value of the former can be global, the latter is always local.
The value of a VARIABLE can never be passed out of the PROCESS directly; if
necessary, then it must be assigned to a SIGNAL. On the other hand, the update of a
VARIABLE is immediate, that is, we can promptly count on its new value in the
next line of code. That is not the case with a SIGNAL (when used in a PROCESS),
24 | P a g e
for its new value is generally only guaranteed to be available after the conclusion of
the present run of the PROCESS.
SIGNAL Assignment Statement - signal-object <= expression [ after delay-value ];
VARIABLE Assignment Statement - variable-object := expression;
Delta Delay
A delta delay is a very small delay (infinitesimally small). It does not correspond to any real
delay and actual simulation time does not advance. This delay models hardware where a
minimal amount of time is needed for a change to occur, for example, in performing zero
delay simulation. Delta delay allows for ordering of events that occur at the same simulation
time during a simulation. Each unit of simulation time can be considered to be composed of
an infinite number of delta delays. Therefore, an event always occurs at a real simulation time
plus an integral multiple of delta delays. For example, events can occur at 15 ns, 15 ns+IA,
15 ns+2A, 15 ns+3A, 22 ns, 22 ns+A, 27 ns, 27 ns+A, and so on.
WAIT
The wait statement provides an alternate way to suspend the execution of a process. There
are three basic forms of the wait statement.
wait on sensitivity-list;
wait until boolean-expression ;
wait for time-expression ;
They may also be combined in a single wait statement. For example,
25 | P a g e
wait on sensitivity-list until boolean-expression for time-expression;
Some examples of wait statements are
wait on A, B, C; -- statement 1
wait until (A = B); -- statement 2
wait for 10ns; -- statement 3
wait on CLOCK for 20ns; -- statement 4
wait until (SUM > 100) for 50 ms; -- statement 5
IF
An if statement selects a sequence of statements for execution based on the value of a
condition. The condition can be any expression that evaluates to a boolean value. The general
form of an if statement is
if boolean-expressionthen
sequential-statements
[ elsif boolean-expression then sequential-statements ]
[ else sequential-statements ]
end if;
The if statement is executed by checking each condition sequentially until the first true
condition is found; then, the set of sequential statements associated with this condition is
executed. The if statement can have zero or more else if clauses and an optional else clause.
An if statement is also a sequential statement, and therefore, the previous syntax allows for
arbitrary nesting of if statements.
CASE
CASE is another statement intended exclusively for sequential code (along with IF,LOOP,
and WAIT). Its syntax is shown below.
CASE identifier IS
WHEN value => assignments;
WHEN value => assignments;
...
END CASE;
26 | P a g e
A model for a 4*1 multiplexer using a case statement is shown next.
entity MUX is
port (A, B, C, D: in BIT; CTRL: in BIT_VECTOR(0 to 1);
Z: out BIT);
end MUX;
architecture MUX_BEHAVIOR of MUX is
constant MUX_DELAY: TIME := 10 ns;
begin
PMUX: process (A, B, C, D, CTRL)
variable TEMP: BIT;
begin
case CTRL is
when "00" => TEMP := A:
when "01" => TEMP := B;
when "10" => TEMP := C;
when "11" => TEMP := D;
end case;
Z <= TEMP after MUX_DELAY;
end process PMUX;
end MUX_BEHAVIOR;
CASE versus WHEN
27 | P a g e
CASE versus IF
Though in principle the presence of ELSE in the IF/ELSE statement might infer the
implementation of a priority decoder (which would never occur with CASE), this will
generally not happen. For instance, when IF (a sequential statement) is used to implement
a fully combinational circuit, a multiplexer might be inferred instead. Therefore,
after optimization, the general tendency is for a circuit synthesized from a
VHDL code based on IF not to di¤er from that based on CASE.
NULL
The statement “null;” is a sequential statement that does not cause any action to take place
and execution continues with the next statement. One example of this statement's use is in an
if statement or in a case statement where for certain conditions, it may be useful or necessary
to explicitly specify that no action needs to be performed.
LOOP
A loop statement is used to iterate through a set of sequential statements. The syntax of a loop
statement is
[ loop-label : ] iteration-scheme loop
sequential-statements
end loop [ loop-label ] ;
There are three types of iteration schemes.
FOR / LOOP: The loop is repeated a fixed number of times.
[label:] FOR identifier IN range LOOP
(sequential statements)
END LOOP [label];
WHILE / LOOP: The loop is repeated until a condition no longer holds.
[label:] WHILE condition LOOP
(sequential statements)
END LOOP [label];
28 | P a g e
EXIT: Used for ending the loop.
[label:] EXIT [label] [WHEN condition];
NEXT: Used for skipping loop steps
[label:] NEXT [loop_label] [WHEN condition];
Bad Clocking
The compiler will generally not be able to synthesize codes that contain assignments
to the same signal at both transitions of the reference (clock) signal (that is, at the
rising edge plus at the falling edge). This is particularly true when the target technology
contains only single-edge flip-flops (CPLDs, for example—appendix A). In
this case, the compiler might display a message of the type ‘‘signal does not hold
value after clock edge’’ or similar.
Using Sequential Code to Design Combinational Circuits
We have already seen that sequential code can be used to implement either sequential
or combinational circuits. In the former case, registers are necessary, so will be inferred
by the compiler. However, this should not happen in the latter case. Moreover,
if the code is intended for a combinational circuit, then the complete truth-table
should be clearly specified in the code.
In order to satisfy the criteria above, the following rules should be observed:
Rule 1: Make sure that all input signals used (read) in the PROCESS appear in its
sensitivity list.
Rule 2: Make sure that all combinations of the input/output signals are included in
the code; that is, make sure that, by looking at the code, the circuit’s complete truthtable
can be obtained (indeed, this is true for both sequential as well as concurrent
code).
Failing to comply with rule 1 will generally cause the compiler to simply issue a
warning saying that a given input signal was not included in the sensitivity list, and
then proceed as if the signal were included. Even though no damage is caused to the
design in this case, it is a good design practice to always take rule 1 into consideration.
With respect to rule 2, however, the consequences can be more serious because
incomplete specifications of the output signals might cause the synthesizer to infer
latches in order to hold their previous values. This fact is illustrated in the example
below.
29 | P a g e
VHDL PROGRAMMING
By Prashant Pacific
Module IV
Standard combinational modules, Design of a Serial Adder with Accumulator, State
Graph for Control Network, design of a Binary Multiplier, Multiplication of a Signed
Binary Number, Design of a Binary Divider.
30 | P a g e
VHDL PROGRAMMING
By Prashant Pacific
Module V
Micro programmed Controller, Structure of a micro programmed controller, Basic
component of a micro system, memory subsystem. Overview of PAL, PLA, FPGA,
CPLD.
Microprogramming is an orderly method of designing the control unit of a conventional
computer (Wilkes 1951). The term microprogramming is based on the analogy between
sequence of transfer required to execute a machine instruction and the sequence of individual
instructions in conventional user program. Each step is called microinstruction and complete
set of steps required to process a machine instruction is called the micro program.
Block diagram for a MCU
MAR - a-bit address
register
ROM - memory with 2a wbit words
MIR - w- bit instruction
register
AGP - address generating
logic
In a microprogrammed control unit, the values of control signals are read from an
appropriate address location in a ROM (instead of being generated by combinational logic
gates). The contents of each address in the ROM are called a control word.
Basic microprogrammed control unit (example)
We use two-way branching address generation Each control word contains 64 bits of data
The condition select field (CW(63:40)) contains information needed to select the input
condition signal that is used to compute the address of the next instruction. In the BMCU we
use a “one-hot” code to select the condition signal.
31 | P a g e
If Ci is selected and Ci = 1 then address NAD field is the address of the next control word to
be fetched. If Ci = 0, then the memory address [MAR] is incremented to compute the next
address.
Control word
Every designer must observe the constraints imposed by the controller. These constraints
include such things as the number of control signals that can be generated, the number of
status signals that can be handled, and limits imposed by the address generation logic.
The maximum number of control signals is 32. ROM size is 256 words.
Address generation logic
The correct sequence of control signals is obtained by generating the proper sequence of
addresses at the ROM inputs.
The address generating logic varies considerably from design to design and is a major
contributor to the constraints imposed by the controller.
Timing signals for the control unit and the data unit must be closely coordinated.
32 | P a g e
The controller works best if the sequencing of addresses is relatively simple. Usually, the
address generating logic circuit (AG) is a counter with the option to parallel load a new
address when one wishes to jump to a new point in the control sequence. If the controller
usually goes to the next higher sequential address for the next set of control signal values
(increment) with just an occasional need to parallel load a new address (branch), the AG can
be a low complexity circuit.
Address generation logic organization (example)
Address Generation Logic for BMCU can be designed using a vector multiplexer.
Synthesis of microprogrammed controllers
1. Prepare a table showing all transitions from each state and the conditions that define
each transition by scanning the statements in the VHDL description.
2. Make a list of the conditions from step 1. After the assignment of ROM addresses to
states, some of these conditions may not be needed.
3. Identify a reset state.
33 | P a g e
4. Assign a ROM address to each state.
5. Remove the redundant signals from the condition list created in step2 and assign the
condition signals to the condition inputs in an arbitrary manner.
6. Create a list of transfers during each state and a list of outputs required during each
state.
7. From the list of transfers and outputs created in step 6, generate a list of control
signals needed to time the transfers and outputs.
8. Draw a block diagram showing the condition and control signals produced.
9. Determine the ROM program using the information in the lists produced in steps 1-8.
This procedure is similar to that performed by an assembler program.
BASIC LAYOUT OF A MICROPROGRAMMED CONTROL
UNIT
Control memory stores a microprogram corresponding to each op-code of a conventional
instruction.
34 | P a g e
FPGA
Key Points
1. ON-CHIP STATIC RAM LOADED WITH
CONFIGURATION BIT PATTERNS (sram-fpgas). (volatile)
2. ANTIFUSE-PROGRAMMED DEVICES PROGRAMMED
ELECTRICALLY TO PROVIDE CONNECTIONS THAT DEFINE CHIP CONFIGURATION
3. ARRAY-STYLE eprom and eeprom PROGRAMMED DEVICES
USING SEVERAL plas AND A SHARED INTERCONNECT
MECHANISM
A field-programmable gate array (FPGA) is an integrated circuit designed to be configured
by the customer or designer after manufacturing—hence "field-programmable". The FPGA
configuration is generally specified using a hardware description language (HDL), similar to
that used for an application-specific integrated circuit (ASIC) (circuit diagrams were
previously used to specify the configuration, as they were for ASICs, but this is increasingly
rare). FPGAs can be used to implement any logical function that an ASIC could perform. The
ability to update the functionality after shipping, partial re-configuration of the portion of the
design and the low non-recurring engineering costs relative to an ASIC design (not
withstanding the generally higher unit cost), offer advantages for many applications.
FPGAs contain programmable logic components called "logic blocks", and a hierarchy of
reconfigurable interconnects that allow the blocks to be "wired together"—somewhat like a
35 | P a g e
one-chip programmable breadboard. Logic blocks can be configured to perform complex
combinational functions, or merely simple logic gates like AND and XOR. In most FPGAs,
the logic blocks also include memory elements, which may be simple flip-flops or more
complete blocks of memory.
In addition to digital functions, some FPGAs have analog features. The most common analog
feature is programmable slew rate and drive strength on each output pin, allowing the
engineer to set slow rates on lightly loaded pins that would otherwise ring unacceptably, and
to set stronger, faster rates on heavily loaded pins on high-speed channels that would
otherwise run too slow. Another relatively common analog feature is differential comparators
on input pins designed to be connected to differential signaling channels. A few "mixed
signal FPGAs" have integrated peripheral Analog-to-Digital Converters (ADCs) and Digitalto-Analog Converters (DACs) with analog signal conditioning blocks allowing them to
operate as a system-on-a-chip. Such devices blur the line between an FPGA, which carries
digital ones and zeros on its internal programmable interconnect fabric, and fieldprogrammable analog array (FPAA), which carries analog values on its internal
programmable interconnect fabric.
Applications of FPGAs include digital signal processing, software-defined radio, aerospace
and defense systems, ASIC prototyping, medical imaging, computer vision, speech
recognition, cryptography, bioinformatics, computer hardware emulation, radio astronomy,
metal detection and a growing range of other areas.
FPGAs originally began as competitors to CPLDs and competed in a similar space, that of
glue logic for PCBs. As their size, capabilities, and speed increased, they began to take over
larger and larger functions to the state where some are now marketed as full systems on chips
(SoC). Particularly with the introduction of dedicated multipliers into FPGA architectures in
the late 1990s, applications which had traditionally been the sole reserve of DSPs began to
incorporate FPGAs instead.
FPGAs especially find applications in any area or algorithm that can make use of the massive
parallelism offered by their architecture. One such area is code breaking, in particular bruteforce attack, of cryptographic algorithms.
FPGAs are increasingly used in conventional high performance computing applications
where computational kernels such as FFT or Convolution are performed on the FPGA instead
of a microprocessor.
36 | P a g e
PAL
Programmable
AND Plane
Fixed OR
Plane
The term Programmable Array Logic (PAL) is used to describe a family of programmable
logic device semiconductors used to implement logic functions in digital circuits introduced
by Monolithic Memories, Inc. (MMI) in March 1978.[1]
PAL devices consisted of a small PROM (programmable read-only memory) core and
additional output logic used to implement particular desired logic functions with few
components.
Using specialized machines, PAL devices were "field-programmable". Each PAL device was
"one-time programmable" (OTP), meaning that it could not be updated and reused after its
initial programming. (MMI also offered a similar family called HAL, or "hard array logic",
which were like PAL devices except that they were mask-programmed at the factory.)
37 | P a g e
PAL Architecture
The PAL architecture consists of two main components: a logic plane and output logic
macrocells.
Programmable logic plane
The programmable logic plane is a programmable read-only memory (PROM) array that
allows the signals present on the devices pins (or the logical complements of those signals) to
be routed to an output logic macrocell.
PAL devices have arrays of transistor cells arranged in a "fixed-OR, programmable-AND"
plane used to implement "sum-of-products" binary logic equations for each of the outputs in
terms of the inputs and either synchronous or asynchronous feedback from the outputs.
Output logic
The early 20-pin PALs had 10 inputs and 8 outputs. The outputs were active low and could
be registered or combinational. Members of the PAL family were available with various
output structures called "output logic macrocells" or OLMCs. Prior to the introduction of the
"V" (for "variable") series, the types of OLMCs available in each PAL were fixed at the time
of manufacture. (The PAL16L8 had 8 combinational outputs and the PAL16R8 had 8
registered outputs. The PAL16R6 had 6 registered and 2 combinational while the PAL16R4
had 4 of each.) Each output could have up to 8 product terms (effectively AND gates),
however the combinational outputs used one of the terms to control a bidirectional output
buffer. There were other combinations that had fewer outputs with more product term per
output and were available with active high outputs. The 16X8 family or registered devices
had an XOR gate before the register. There were also similar 24-pin versions of these PALs.
PALs were programmed electrically using binary patterns (as JEDEC ASCII/hexadecimal
files) and a special electronic programming system available from either the manufacturer or
a third-party, such as DATA/IO. In addition to single-unit device programmers, device
feeders and gang programmers were often used when more than just a few PALs needed to be
programmed. (For large volumes, electrical programming costs could be eliminated by
having the manufacturer fabricate a custom metal mask used to program the customers'
patterns at the time of manufacture; MMI used the term "hard array logic" (HAL) to refer to
devices programmed in this way.)
38 | P a g e
PLA
39 | P a g e
A programmable logic array (PLA) is a programmable device used to implement
combinational logic circuits. The PLA has a set of programmable AND gate planes, which
link to a set of programmable OR gate planes, which can then be conditionally complemented
to produce an output. This layout allows for a large number of logic functions to be
synthesized in the sum of products (and sometimes product of sums) canonical forms.
One application of a PLA is to implement the control over a datapath. It defines various states
in an instruction set, and produces the next state (by conditional branching). [eg. if the
machine is in state 2, and will go to state 4 if the instruction contains an immediate field; then
the PLA should define the actions of the control in state 2, will set the next state to be 4 if the
instruction contains an immediate field, and will define the actions of the control in state 4].
Programmable Logic Arrays should correspond to a state diagram for the system.
Other commonly used programmable logic devices are PAL, CPLD and FPGA.
Note that the use of the word "programmable" does not indicate that all PLAs are fieldprogrammable; in fact many are mask-programmed during manufacture in the same manner
as a mask ROM. This is particularly true of PLAs that are embedded in more complex and
numerous integrated circuits such as microprocessors. PLAs that can be programmed after
manufacture are called FPLA (Field-programmable PLA).
40 | P a g e
CPLD
A complex programmable logic device (CPLD) is a programmable logic device with
complexity between that of PALs and FPGAs, and architectural features of both. The
building block of a CPLD is the macrocell, which contains logic implementing disjunctive
normal form expressions and more specialized logic operations.
Features in common with PALs:

Non-volatile configuration memory. Unlike many FPGAs, an external configuration
ROM isn't required, and the CPLD can function immediately on system start-up.

For many legacy CPLD devices, routing constrains most logic blocks to have input
and output signals connected to external pins, reducing opportunities for internal state
storage and deeply layered logic. This is usually not a factor for larger CPLDs and
newer CPLD product families.
Features in common with FPGAs:

Large number of gates available. CPLDs typically have the equivalent of thousands to
tens of thousands of logic gates, allowing implementation of moderately complicated
data processing devices. PALs typically have a few hundred gate equivalents at most,
while FPGAs typically range from tens of thousands to several million.

Some provisions for logic more flexible than sum-of-product expressions, including
complicated feedback paths between macro cells, and specialized logic for
implementing various commonly-used functions, such as integer arithmetic.
The most noticeable difference between a large CPLD and a small FPGA is the presence of
on-chip non-volatile memory in the CPLD. This distinction is rapidly becoming less relevant,
as several of the latest FPGA products also offer models with embedded configuration
memory.
The characteristic of non-volatility makes the CPLD the device of choice in modern digital
designs to perform 'boot loader' functions before handing over control to other devices not
having this capability. A good example is where a CPLD is used to load configuration data
for an FPGA from non-volatile memory.
CPLDs were an evolutionary step from even smaller devices that preceded them, PLAs (first
shipped by Signetics), and PALs. These in turn were preceded by standard logic products,
that offered no programmability and were "programmed" by wiring several standard logic
chips together.
The main distinction between FPGA and CPLD device architectures is that FPGAs are
internally based on Look-up tables (LUTs) while CPLDs form the logic functions with seaof-gates (e.g. sum of products).
Download