You are on page 1of 115

PROGRAMMABLE LOGIC DESIGN

WITH VHDL
Introduction
 VHDL is used to:
 document circuits
 simulate circuits
 synthesize design descriptions
 Synthesis is the reduction of a design description to a lower-
level representation (such as a netlist or a set of equations).
 The lecture will at times draw upon the concepts of VHDL as a
simulation language
Why Use VHDL?
 Quick Time-to-Market
 Allows designers to quickly develop designs requiring
tens of thousands of logic gates
 Provides powerful high-level constructs for describing
complex logic
 Supports modular design methodology and multiple levels
of hierarchy
 One language for design and simulation
 Allows creation of device-independent designs that are
portable to multiple vendors. Good for ASIC Migration
 Allows user to pick any synthesis tool, vendor, or device
VHDL Design Descriptions
 VHDL design descriptions consist of an ENTITY
declaration and an ARCHITECTURE body

 The ENTITY declaration describes the design I/O

 The ARCHITECTURE body describes the


content or function of the design

 Every architecture needs an entity so it is common


to refer to them together as an
ENTITY/ARCHITECTURE PAIR
Example Entity/Architecture Pair:
A 2-Input And Function
ENTITY and2 IS PORT (
a,b : IN std_logic;
f: OUT std_logic);
END and2;

ARCHITECTURE behavioral OF and2 IS


BEGIN
f <= a AND b;
END behavioral;
The Entity

 A “BLACK BOX”
 The ENTITY describes the periphery of the
black box (i.e., the design I/O)

BLACK_BOX

rst
q[7:0]
d[7:0]
co
clk
Example Entity declaration
ENTITY black_box IS PORT (
clk, rst: IN std_logic;
d: IN std_logic_vector(7 DOWNTO 0);
q: OUT std_logic_vector(7 DOWNTO 0);
co: OUT std_logic);
END black_box;

 What does all this mean?

BLACK_BOX

rst
q[7:0]
d[7:0]
co
clk
The Entity Declaration
ENTITY entity_name IS
-- optional generics
PORT (
name : mode type ;
...
) ;
END entity_name;

 entity_name is an arbitrary name


 generics are used for defining parameterized components
 name is the signal/port identifier and may be a comma
separated list for ports of identical modes and types
 mode describes the direction the data is flowing
 type indicates the set of values name may be assigned
Ports

 The Entity (“BLACK BOX”) has PORTS


 PORTS are the points of communication
• PORTS are usually the device pins

 PORTS have an associated name, mode, and type


Port Modes
A port’s MODE indicates the direction that data is transferred:
Entity
 IN Data goes into the entity only

 OUT Data goes out of the entity only (and is not used
internally)

 INOUT Data is bi-directional (goes into and out of the


entity)

 BUFFER Data that goes out of the entity and is also


fed-back internally
IEEE Types
 VHDL is a strongly typed language (you cannot assign a signal of
one type to the signal of another type)
 bit - a signal of type bit that can only take values of '0' or '1'
 bit_vector - a grouping of bits (each can be '0' or '1')
SIGNAL a: BIT_VECTOR(0 TO 3); -- ascending range
SIGNAL b: BIT_VECTOR(3 DOWNTO 0); -- descending range
a <= "0111"; -- double quotes used for vectors
b <= "0101";
This means that: a(0) = '0' b(0) = '1'
a(1) = '1' b(1) = '0'
a(2) = '1' b(2) = '1'
a(3) = '1' b(3) = '0'
IEEE TYPES (contd.)

 INTEGER
• useful as index holders for loops, constants, generics,
or high-level modeling
 BOOLEAN
• can take values ‘TRUE’ or ‘FALSE’
 ENUMERATED
• has user defined set of possible values, e.g.,
• TYPE traffic_light IS (green, yellow, red);
IEEE 1164
 A package created to solve the limitations of the BIT type
 Nine values instead of just two ('0' and '1')
 Allows increased flexibility in VHDL coding, synthesis, and
simulation
 STD_LOGIC and STD_LOGIC_VECTOR are used instead of
BIT and BIT_VECTOR when a multi-valued logic system is
required
 STD_LOGIC and STD_LOGIC _VECTOR must be used
when tri-state logic (Z) is required
 To be able to use this new type, you need to add 2 lines to
your code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
1164 Types
 std_logic and std_logic_vector are the industry
standard logic type for digital design
 Values for Simulation & Synthesis
 ‘0’ -- Forcing ‘0’
 ‘1’ -- Forcing ‘1’
 ‘Z’ -- High Impedance
 ‘L’ -- Weak ‘0’
 ‘H’ -- Weak ‘1’
 ‘-’ -- Don’t care
 Values for Simulation only (std_ulogic):
 ‘U’ -- Uninitialized
 ‘X’ -- Forcing Unknown
 ‘W’ -- Weak Unknown
Entity Declaration Example
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY black_box IS PORT (
clk, rst: IN std_logic;
d: IN std_logic_vector(7 DOWNTO 0);
q: OUT std_logic_vector(7 DOWNTO 0);
co: OUT std_logic);
END black_box;
BLACK_BOX
MODE rst
TYPE q[7:0]
d[7:0]
co
clk
Exercise #1: The Entity - A Walk through
 Write an entity declaration for the following:
Port D is a 12-bit bus, input only
Port OE and CLK are each input bits
Port AD is a 12-bit, three-state bi-directional bus
Port A is a 12-bit bus, output only
Port INT is a three-state output
Port AS is an output also used internally
my_design

d[11:0] ad[11:0]
oe a[11:0]
clk int
as
Exercise #1: Solution
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY my_design IS PORT (
d: IN std_logic_vector(11 DOWNTO 0);
oe, clk: IN std_logic;
ad: INOUT std_logic_vector(11 DOWNTO 0);
a: OUT std_logic_vector(11 DOWNTO 0);
int: OUT std_logic;
my_design
as: BUFFER std_logic);
END my_design; d[11:0] ad[11:0]
-- In this presentation, VHDL keywords oe a[11:0]
-- are highlighted in bold, CAPITALS; clk int
-- however, VHDL is not case sensitive: as
-- clock, Clock, CLOCK all refer to the
-- same signal, -- means a comment
The Architecture
 Architectures describe what is in the black box (i.e., the
structure or behavior of entities)
 Descriptions can be either a combination of
 Structural descriptions
• Instantiations (placements of logicmuch like in a
schematicand their connections) of building blocks
referred to as components
 Behavioral/Dataflow descriptions
• Algorithmic (or “high-level”) descriptions:
IF a = b THEN state <= state5;
• Boolean equations (also referred to as dataflow):
x <= a OR (b AND c);
The Architecture Declaration
ARCHITECTURE arch_name OF entity_name IS
-- optional signal declarations, etc.
BEGIN
--VHDL statements
END arch_name;

 arch_name is an arbitrary name


 optional signal declarations are used for signals local to
the architecture body (that is, not the entity’s I/O).
 entity_name is the entity name
 statements describe the function or contents of the entity
Architecture Body Styles : Behavioral
ENTITY compare IS PORT (
a, b: IN std_logic_vector(0 TO 3);
equals: OUT std_logic);
END compare;
ARCHITECTURE behavior OF compare IS
BEGIN
comp: PROCESS (a,b)
BEGIN
IF a = b THEN
equals <= '1' ;
ELSE
equals <= '0' ;
END IF ;
END PROCESS comp;
END behavior;
Architecture Body Styles : Dataflow

ENTITY compare IS PORT (


a, b: IN std_logic_vector(0 TO 3);
equals: OUT std_logic);
END compare;

ARCHITECTURE dataflow OF compare IS


BEGIN
equals <= '1' WHEN a = b ELSE '0' ;
END dataflow;
Architecture Body Styles : Structural
ENTITY compare IS PORT (
a, b: IN std_logic_vector(0 TO 3);
equals: OUT std_logic);
END compare;
USE WORK.gatespkg.ALL ;
ARCHITECTURE structure OF compare IS
SIGNAL x : std_logic_vector (0 to 3) ;
BEGIN
u0: xnor2 PORT MAP (a(0),b(0),x(0)) ;
u1: xnor2 PORT MAP (a(1),b(1),x(1)) ;
u2: xnor2 PORT MAP (a(2),b(2),x(2)) ;
u3: xnor2 PORT MAP (a(3),b(3),x(3)) ;
u4: and4 PORT MAP (x(0),x(1),x(2),x(3),equals) ;
END structure;
Mixing Architecture Styles
 The various styles may be mixed in one architecture.

ENTITY logic IS PORT ( LOGIC


a,b,c: IN std_logic; a
f: OUT std_logic); d
b
END logic;

f
USE WORK.gatespkg.ALL; c g1
ARCHITECTURE archlogic OF logic IS
SIGNAL d: std_logic;
BEGIN
d <= a AND b; Behavioral/Dataflow
g1: nor2 PORT MAP (c, d, f); Structural
END archlogic;
Comparing Architecture Styles

 These examples synthesize to equivalent circuits


 In more elaborate designs, some descriptions may yield
more efficient circuits
 sloppy code = inefficient results Use styles that
make your designs easier to describe and maintain
 Behavioral/Dataflow exploit module generation
(described later)
 Structural descriptions may make the design less
portable (may rely on a library of vendor-specific
components)
A Simple Counter
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE WORK.std_arith.ALL; count

ENTITY count8 IS PORT ( clk


clk: IN std_logic;
count: BUFFER std_logic_vector(7 DOWNTO 0));
END count8 ;
ARCHITECTURE arch_count8 OF count8 IS
BEGIN
upcount: PROCESS (clk)
BEGIN
IF clk’EVENT and clk=‘1’
THEN count <= count + 1;
END IF;
END PROCESS upcount;
END arch_count8;
VHDL Statements
 There are two types of statements, Concurrent and Sequential

 Concurrent Statements (means in parallel)


 Concurrent statements are “executed” concurrently (at
the same time)
 The order of concurrent statements is not important
 Most of the examples we have seen so far have been
concurrent statements:
– Boolean Equations
– WHEN-ELSE
– WITH-SELECT-WHEN
VHDL Statements (cont.)
 Sequential Statements (means in series)
 Sometimes we need to model complex functions.
In that case, we can use an “algorithm” or model
to describe the function. This is done with
Sequential Statements
 With Sequential statements, the ORDER of the
statements is important (example later)
 Therefore, we use a process to mark the beginning
and end of a block of sequential statements
 Each completed process is considered to be one
big concurrent statement (there can be many
processes inside one architecture)
What is a VHDL “Process” ?
 Processes are either awake or asleep (active or inactive)

 A process normally has a sensitivity list


 When a signal in that sensitivity list changes value, the
process wakes up and all of the sequential statements
are “executed”
 For example, a process with a clock signal in its
sensitivity list will become active on changes of the
clock signal

 At the end of the process, all outputs are assigned and the
process goes back to sleep until the next time a signal
changes in the sensitivity list
The Process (contd.)

label: PROCESS (sensitivity list)


-- variable declarations
BEGIN
-- sequential statements
END PROCESS label ;

 The process label and variable declarations are


optional
 The process executes when one of the signals in the
sensitivity list has an event
Combinational Logic

 Can be described with concurrent statements


 boolean equations
 when-else
 with-select-when
 component instantiatons
 Can be described with sequential statements
 if-then-else
 case-when
Combinational Logic w/ Boolean Equations

 Boolean Equations can be used in both concurrent


and sequential signal assignment statements.
 A 4-1 multiplexer is shown below
s
2
x <= (a AND NOT(s(1)) AND NOT(s(0))) OR
a
(b AND NOT(s(1)) AND s(0)) OR b x
mux
(c AND s(1) AND NOT(s(0))) OR c
(d AND s(1) AND s(0)) ; d
Selective Signal Assignment:
with-select-when
 Assignment based on a selection signal
 WHEN clauses must be mutually exclusive
 Use a WHEN OTHERS when all conditions are not specified
 Only one reference to the signal, only one assignment operator (<=)

WITH selection_signal SELECT


signal_name <= value_1 WHEN value_1 of selection_signal,
value_2 WHEN value_2 of selection_signal,
...
value_n WHEN value_n of selection_signal,
value_x WHEN OTHERS;
Combinational Logic w/
Selective Signal Assignment
 The same 4-1 multiplexer is shown below

with s select s
x <= a when “00” , 2

b when “01” , a
c when “10” , b x
mux
c
d when others ;
d
More on with-select-when

 You can use a range of values

with int_value select


x <= a when 0 to 3,
b when 4 | 6 | 8 ,
c when 10 ,
d when others ;
Conditional Signal Assignment:
when-else
 Signal is assigned a value based on conditions
 Any simple expression can be a condition
 Priority goes in order of appearance
 Only one reference to the signal, only one assignment
operator (<=)
 Use a final ELSE to avoid latches
signal_name <= value_1 WHEN condition1 ELSE
value_2 WHEN condition2 ELSE
...
value_n WHEN condition N ELSE
value_x ;
Combinational Logic w/
Conditional Signal Assignment
 The same 4-1 multiplexer is shown below

x <= a when (s = “00”) else s


b when (s = “01”) else 2

c when (s = “10”) else a


d; b x
mux
c
d
Combinational Logic w/
Conditional Signal Assignment
 The when conditions do not have to be mutually
exclusive (as in with-select-when)
 A priority encoder is shown below

j <= w when (a = ‘1’) else


x when (b = ‘1’) else
y when (c = ‘1’) else
z when (d = ‘1’) else
“000” ;
Combinatorial Logic
w/ Sequential Statements

 Grouped together with Processes


 Processes are concurrent with one another and with
concurrent statements
 Order of sequential statements does make a
difference in synthesis
Sequential Statements: if-then-else
 Used to select a set of statements to be executed
 Selection based on a boolean evaluation of a condition or set
of conditions
 Absence of ELSE results in implicit memory
IF condition(s) THEN
do something;
ELSIF condition_2 THEN -- optional
do something different;
ELSE -- optional
do something completely different;
END IF ;
if-then-else

 4-1 mux shown below


mux4_1: process (a, b, c, d, s)
begin
if s = “00” then x <= a ; s
2
elsif s = “01” then x <= b ;
elsif s = “10” then x <= c ; a
b x
else x <= d ; mux
c
end if; d
end process mux4_1 ;
Sequential Statements: Case-When
CASE selection_signal IS
WHEN value_1_of_selection_signal =>
(do something) -- set of statements 1
WHEN value_2_of_selection_signal =>
(do something) -- set of statements 2
...
WHEN value_N_of_selection_signal =>
(do something) -- set of statements N
WHEN OTHERS =>
(do something) -- default action
END CASE ;
The CASE Statement: 4-1 Mux
ARCHITECTURE archdesign OF design IS
SIGNAL s: std_logic_vector(0 TO 1);
BEGIN
mux4_1: PROCESS (a,b,c,d,s)
BEGIN s
CASE s IS
2
WHEN "00" => x <= a;
WHEN "01" => x <= b; a
WHEN "10” => x <= c; b x
mux
WHEN OTHERS => x <= d; c
END CASE; d
END PROCESS mux4_1;
END archdesign;
Signal Assignment in Processes
Which Circuit is Correct?
ARCHITECTURE arch_reg OF reg IS
SIGNAL b: std_logic
reg2: PROCESS
BEGIN
WAIT UNTIL clock = '1' ; -- implied sensitivity list
b <= a; -- after the rising clock edge, a goes to b
c <= b; -- after the rising clock edge, b goes to c
END PROCESS reg2;
END arch_reg
a b c
a c

clock

clock
Signal Assignment in Processes
 Inside processes, signals are not updated immediately.
Instead, they are scheduled to be updated
 The signals are not actually updated until the END
PROCESS statement is reached
 Therefore, on the previous slide, two registers will be
synthesized (c <= b will be the old b)
 In some cases, the use of a concurrent statement outside
the process will fix the problem, but this is not always
possible
 So how else can we fix this problem ?
Variables
 When a concurrent signal assignment outside the
process cannot be used, the previous problem can be
avoided using a variable
 Variables are like signals, BUT they can only be
used inside a PROCESS. They cannot be used to
communicate information between processes
 Variables can be of any valid VHDL data type
 The value assigned to a variable is available
immediately
 Assignment of variables is done using a colon (:),
like this:
c := a AND b;
Using Variables vs. Signals

 Solution using a variable within a process:


-- assume a and c are signals defined elsewhere

ARCHITECTURE arch_reg OF reg IS


PROCESS
VARIABLE b: std_logic ;
BEGIN
WAIT UNTIL clock = '1' ;
b := a ; -- this is immediate
c <= b ; -- this is scheduled
END PROCESS ;
END arch_reg;
Native Operators
 Logical - defined for type bit, bit_vector, boolean*
 AND, NAND
 OR, NOR
 XOR, XNOR
 NOT
 Relational - defined for types bit, bit_vector, integer*
 = (equal to)
 /= (not equal to)
 < (less than)
 <= (less than or equal to)
 > (greater than)
 >= (greater than or equal to)
 * overloaded for std_logic, std_logic_vector
Native Operators (contd.)
 Unary Arithmetic - defined for type integer*
 - (arithmetic negate)
 Arithmetic - defined for type integer*
 + (addition), * (multiplication)
 - (subtraction)
 Concatenation - defined for strings
 &
Note, a STRING is any sequence of characters, therefore a
std_logic_vector is an example of a STRING

 * overloaded for std_logic, std_logic_vector


Overloaded Operators
 In VHDL, the scope of all of the previous operators
can be extended (or overloaded) to accept any type
supported by the language, e.g.,
-- assume a declaration of a 16-bit vector as
SIGNAL pc IS std_logic_vector(15 DOWNTO 0);
-- then a valid signal assignment is
pc <= pc + 3;
-- assuming the '+' operator has been overloaded to
--- accept std_logic_vector and integer operands

 The std_logic_1164 package defines overloaded


logical operators (AND, OR, NOT, etc.,) for the
std_logic and std_logic_vector types
 In this training, you will learn to use overloaded
operators, but not to define them
Legal VHDL Identifiers
 Letters, digits, and underscores only (first character must be a
letter)
 The last character cannot be an underscore
 Two underscores in succession are not allowed
 Using reserved words is not allowed (the VHDL editor will
highlight reserved words for this reason)
 Examples
 Legal
• tx_clk, Three_State_Enable, sel7D, HIT_1124
 Not Legal
• _tx_clk, 8B10B, large#num, case, clk_
Exercise #2: Architecture
Declaration of a Comparator
 The entity declaration is as follows:
LIBRARY ieee; a(3:0)
aeqb
USE ieee.std_logic_1164.ALL;
b(3:0)
ENTITY compare IS PORT (
a, b: IN std_logic_vector(3 DOWNTO 0);
aeqb: OUT std_logic);
END compare;

 Write an architecture that causes aeqb to be asserted


when a is equal to b
 Multiple solutions exist
Three possible solutions
 Concurrent statement solution using a conditional assignment:

ARCHITECTURE arch_compare OF compare IS


BEGIN
aeqb <= '1' WHEN a = b ELSE '0';
END arch_compare;

 Concurrent statement solution using boolean


equations:
ARCHITECTURE arch_compare OF compare IS
BEGIN
aeqb <= NOT(
(a(0) XOR b(0)) OR
(a(1) XOR b(1)) OR
(a(2) XOR b(2)) OR
(a(3) XOR b(3)));
END arch_compare;
Three possible solutions (contd.)

 Solution using a process with sequential statements:


ARCHITECTURE arch_compare OF compare IS
BEGIN
comp: PROCESS (a, b)
BEGIN
IF a = b THEN
aeqb <= '1';
a(0 TO 3)
ELSE aeqb
aeqb <= '0'; b(0 TO 3)
END IF;
END PROCESS comp;
END arch_compare;
Using Tri-State Logic
ENTITY test_three IS
PORT( oe : IN std_logic;
data : OUT std_logic_vector(0 to 7));
END test_three;
ARCHITECTURE archtest_three OF test_three IS
BEGIN
PROCESS (oe)
BEGIN
IF (oe = '1')
THEN data <= "01100100";
ELSE data <= "ZZZZZZZZ";
END IF;
END PROCESS;
END archtest_three;
Behavioral Don’t Cares

 Warp uses explicit "don’t care" conditions to produce


optimal logic equations
IF (a = '1') AND (b = '1') THEN
x <= c;
ELSE
x <= '-';
END IF;
 Produces the equation x = c
 To assign don’t cares in VHDL: mysig <= '-';
 'X' means "unknown" and is not useful for
synthesis
Comparing Vectors to Strings
-more on don't cares-
 Comparing "1101" to "11-1" will return FALSE
 Use std_match(a,"string")
 Must include std_arith package
 Example:
...
signal a : std_logic_vector (1 to 4) ;
...
IF std_match(a,"10-1") THEN
x <= '1' ;
END IF ;
Aggregates and Subscripts
 An aggregate assignment concatenates signals together
 Good for creating a bus from several inputs
 The concatenation operator can be used as well
tmp <= (a,b,c,d);
tmp <= a & b & c & d;
 Signals can be “pulled” from larger vectors
 Good for grouping outputs as an “alias”
 Sizes on both sides of assignment must match
rw <= ctrl(0); ce <= ctrl(1); oe <= ctrl(2);
highcount <= count(7 DOWNTO 4);
Synchronous Logic

 PLDs work well in synchronous applications


 Two methods of creating synchronous logic
 Structurally
• instantiating components with registers
 Behaviorally
• Using a processes with a clock signal in the
sensitivity list
Registers in Behavioral VHDL
 Example: a D-type flip-flop

ENTITY registered IS PORT (


d, clk: IN std_logic;
q: OUT std_logic);
END registered;
ARCHITECTURE archregistered OF registered IS
BEGIN
flipflop: PROCESS (clk)
BEGIN
IF rising_edge(clk)
THEN q <= d;
END IF;
END PROCESS flipflop;
END archregistered;
Registers in Behavioral VHDL
 The synthesis compiler infers that a register is to be created for
which signal q is the output because
 The clock (clk) is in the sensitivity list
 The construct, rising_edge(clk), falling_edge(clk) or
clk’event AND clock=‘1’ appears in the process
 The rising_edge(clk) or falling_edge(clk) statement implies that
subsequent signal assignments occur on the rising/falling edge of
the clock
 The absence of an “else” clause in the “if-then” statement implies
that if the clk’event and clk = ‘1’ condition is not fulfilled (i.e. not
a rising-edge), q will retain its value until the next assignment
occurs (this is referred to as implied memory)
Rising/Falling Edge Functions

 The 1164 package defines 2 functions for edge detection


 rising_edge (signal)
• similar to (signal’event and signal =‘1’)
 falling_edge (signal)
• similar to (signal’event and signal =‘0’)

if rising_edge(clk) then
q <= d;
end if;
A Registered Process (1)
 A 4-bit counter with synchronous reset
USE WORK.std_arith.ALL;
... count
upcount: PROCESS (clk) clk
BEGIN
IF rising_edge(clk) THEN rst

IF reset = '1'
THEN count <= "0000"; -- or x"0" instead
ELSE count <= count + 1;
END IF;
END IF;
END PROCESS upcount;

 This process is only sensitive to changes in “clk”, i.e.,


it will become active only when the clock transitions
A Registered Process (2)
 A 4-bit counter with asynchronous reset
USE WORK.std_arith.ALL;
... count
upcount: PROCESS (clk, reset) clk
BEGIN
rst
IF reset = '1'
THEN count <= x"0";
ELSIF rising_edge(clk)
THEN count <= count + 1;
END IF;
END PROCESS upcount;

 This process is sensitive to changes in both clk and


rst, i.e., it will become active during clock or reset
transitions.
A Registered Process (3)
 A 4-bit loadable counter with asynchronous reset
USE WORK.std_arith.ALL;
... data count
upcount: PROCESS (clk, reset) load
clk
BEGIN
IF reset = '1’ rst
THEN count <= x"0" ;
ELSIF rising_edge(clk)
THEN
IF load = '1'
THEN count <= data;
ELSE count <= count + 1;
END IF;
END IF;
END PROCESS upcount;
Creating a level-sensitive latch
 Instead of using the rising_edge or falling_edge function,
replace it with clk=‘1’ or clk=‘0’ and put d in the
sensitivity list

latch: PROCESS (clk, d) d q

BEGIN clk

IF clk = '1'
THEN q <= d;
END IF;
END PROCESS latch;
Instantiating a registered component
 Example: Using LPM library

LIBRARY ieee; d q
USE ieee.std_logic_1164.ALL;
clk
USE WORK.lpmpkg.all ;
ENTITY registered IS PORT (
d: IN std_logic;
clk: IN std_logic_vector(3 DOWNTO 0);
q: OUT std_logic _vector(3 DOWNTO 0));
END registered;

ARCHITECTURE archregistered OF registered IS


BEGIN
flipflop: Mff generic map (lpm_width=>4,lpm_fftype=>lpm_dff)
PORT MAP (data=>d,clock=>clk,enable=>one,q=>q);
END archregistered;
The WAIT statement
 This is another method to activate a process
 The WAIT statement is a sequential statement which
suspends the execution of a process until the
condition specified becomes valid (true)
i.e., an implied sensitivity list, e.g.,
sync: PROCESS
BEGIN
enable
WAIT UNTIL clock='1'; q_out
IF enable='1' d_in D Q

THEN q_out <= d_in;


ELSE q_out <= '0'; clock
END IF;
END PROCESS sync;
Implicit memory
 Signals in VHDL have a current value and may be
scheduled for a future value
 If the future value of a signal cannot be determined, a
latch will be synthesized to preserve its current value
 Advantages:
 Simplifies the creation of memory in logic design
 Disadvantages:
 Can generate unwanted latches, e.g., when all of
the options in a conditional sequential statement
are not specified
Implicit memory:
Example of incomplete specification
ARCHITECTURE archincomplete OF
incomplete IS
BEGIN a
im_mem: PROCESS (a,b)
BEGIN
c
IF a = '1'
THEN c <= b; b
END IF;
END PROCESS im_mem;
END archincomplete;
 Note: the incomplete specification of the IF...THEN...
statement causes a latch to be synthesized to store
the previous state of ‘c’
Implicit memory:
Example of complete specification
ARCHITECTURE archcomplete OF
complete IS
BEGIN
no_mem: PROCESS (a, b)
a
c
BEGIN
IF a = '1'
b
THEN c <= b;
ELSE c <= '0';
END IF;
END PROCESS no_mem;
END archcomplete;

 The conditional statement is fully specified, and this


causes the process to synthesize to a single gate
The rules to avoid implicit memory
 To avoid the generation of unexpected latches
 always terminate an IF...THEN... statement with an ELSE
clause
 cover all alternatives in a CASE statement
• define every alternative individually, or
• terminate the CASE statement with a WHEN
OTHERS... clause, e.g.,
CASE coin_inserted IS
WHEN quarter => total<=total+25;
WHEN dime => total<=total+10;
WHEN nickel => total<=total+5;
WHEN OTHERS => total<=total;
error<=‘1’;
END CASE;
Exercise #4
 Making use of the previous examples, write an
entity/architecture pair for the following design:

ENC

COUNTER
DATA
4
DIN
LD COUNT
LD Q 4
ENC COMPARATOR
CLOCK P
RST
RESET (sync) P=Q
Q
REGISTER
DIN
Q
ENR 4
ENR
Exercise #4: Solution
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY ex4 IS PORT (
clock, reset, enc, enr, ld: IN std_logic;
data: IN std_logic_vector (3 DOWNTO 0);
count: BUFFER std_logic_vector(3 DOWNTO 0));
END ex4;
USE WORK.std_arith.ALL; -- for counter and Ultragen
ARCHITECTURE archex4 OF ex4 IS
SIGNAL comp: std_logic;
SIGNAL regout: std_logic_vector (3 DOWNTO 0);
BEGIN
reg: PROCESS (clock)
BEGIN
IF RISING_EDGE(clock)
THEN
IF enr = '1' THEN
regout <= data;
END IF;
END IF;
END PROCESS reg;
Exercise #4: Solution (contd.)
cntr: PROCESS (clock)
BEGIN
IF RISING_EDGE(clock) THEN
IF reset = '1'
THEN count <= "0000";
ELSIF ld = '1'
THEN count <= data;
ELSIF enc = '1' AND comp = '0'
THEN count <= count + 1;
END IF;
END IF;
END PROCESS cntr;
comp <= '1' WHEN regout = count ELSE '0';
END archex4;
State machines

 Moore Machines
 A finite state machine in which the outputs
change due to a change of state

 Mealy Machines
 A finite state machine in which the outputs can
change asynchronously i.e., an input can cause
an output to change immediately
Moore machines

 Outputs may change only with a change of state


 Multiple implementations include:
 Arbitrary state assignment
• outputs must be decoded from the state bits
• combinatorial decode
• registered decode
 Specific state assignment
• outputs may be encoded within the state bits
• one-hot encoding
Example: A Traffic Light Controller
 Let’s take a look at an example state machine and
see how to describe it using the 3 types of
implementations:
TIMER2 TIMER3

RESET
(asynchronous)
TIMER1 TIMER2
RED GREEN YELLOW

TIMER1
R='1' G='1' Y='1'

TIMER3
Moore state machine implementations (1)
 Outputs decoded from state bits COMBINATORIALLY
 combinatorial output logic is in series with state registers
 outputs are a function of the present state only
 time from clock to output (tco) is long
Present State

Next Next State Outputs


State Output
Inputs State
Registers Logic
Logic

Tco + tpd
Example: The Entity Declaration

 The entity declaration remains exactly the same for each


implementation.
 For example:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY state_machine IS PORT (
clock, reset: IN std_logic;
timer1, timer2, timer3: IN std_logic;
r, y, g: OUT std_logic);
END state_machine;
Example: Solution 1
 Combinatorial outputs decoded from the state registers
ARCHITECTURE arch_1 OF state_machine IS
TYPE traffic_states IS (red, yellow, green); -- enumerated type
SIGNAL sm: traffic_states;
BEGIN
fsm: PROCESS (clock, reset) -- the process describes the
BEGIN -- state machine only
IF reset = '1' THEN
sm <= red;
ELSIF rising_edge(clock) THEN
CASE sm IS
WHEN red => IF timer1=‘1’
THEN sm <= green;
ELSE sm <= red;
END IF;

WHEN green => IF timer2=’1'


THEN sm <= yellow;
ELSE sm <= green;
END IF;
Example: Solution 1 (contd.)
WHEN yellow => IF timer3=’1’
THEN sm <= red;
ELSE sm <= yellow;
END IF;
WHEN others => sm <= red;
END CASE;
END IF;
END PROCESS fsm;

-- the outputs are decoded from the state machine


-- registers using combinatorial logic
r <= '1' WHEN (sm = red) ELSE '0';
g <= '1' WHEN (sm = green) ELSE '0';
y <= '1' WHEN (sm = yellow) ELSE '0';

END arch_1;
Moore state machine implementations (2)
 Outputs decoded from state bits using REGISTERS
 registered output logic is in parallel with state registers
 outputs are a function of the previous state and the inputs
 tco is shorter, but you need more registers

Next Present State


State
State
Inputs State
Registers
Registers
Logic

Output Output Outputs


Logic Registers

tco
Example: Solution 2
 Registered outputs decoded from the state registers
ARCHITECTURE arch_2 OF state_machine IS
TYPE traffic_states IS (red, yellow, green);
SIGNAL sm: traffic_states;
BEGIN
fsm: PROCESS (clock, reset) -- the process describes the
BEGIN -- state machine AND the outputs
IF reset = '1' THEN
sm <= red;
r<=‘1’; g<=‘0’; y<=‘0’;
ELSIF rising_edge(clock) THEN
CASE sm IS
WHEN red => IF timer1=‘1’
THEN sm <= green;
r<=‘0’; g<=‘1’; y=‘0’;
ELSE sm <= red;
r<=‘1’; g<=‘0’; y=‘0’;
END IF;
Example: Solution 2 (contd.)
WHEN green => IF timer2=’1'
THEN sm <= yellow;
r<=‘0’; g<=‘0’; y<=‘1’;
ELSE sm <= green;
r<=‘0’; g<=‘1’; y<=‘0’;
END IF;
WHEN yellow => IF timer3=’1'
THEN sm <= red;
r<=‘1’; g<=‘0’; y<=‘0’;
ELSE sm <= yellow;
r<=‘0’; g<=‘0’; y<=‘1’;
END IF;
WHEN others => sm <= red;
END CASE;
END IF;
END PROCESS fsm;

END arch_2;
Moore State Machine Implementations (3)
 We encoded the outputs within the state registers

State Red Green Yellow State Encoding


S0 1 0 0 100
S1 0 1 0 010
S2 0 0 1 001

Note: Both bits of the state encoding are used as outputs

Logic
State Outputs
Inputs Registers

Tco
Example: Solution 3
 Outputs encoded inside the state registers
ARCHITECTURE arch_3 OF state_machine IS
SIGNAL sm: std_logic_vector(2 DOWNTO 0) ;
CONSTANT red: std_logic_vector(2 DOWNTO 0) := ”100" ;
CONSTANT green: std_logic_vector(2 DOWNTO 0) := "010" ;
CONSTANT yellow: std_logic_vector(2 DOWNTO 0) := "001" ;
BEGIN
fsm: PROCESS (clock, reset) -- the process describes the
BEGIN -- state machine only
IF reset = '1' THEN
sm <= red;
ELSIF rising_edge(clock) THEN
CASE sm IS
WHEN red => IF timer1=‘1’
THEN sm <= green;
ELSE sm <= red;
END IF;
Example: Solution 3 (contd.)
WHEN green => IF timer2=’1'
THEN sm <= yellow;
ELSE sm <= green;
END IF;

WHEN yellow => IF timer3=’1’


THEN sm <= red;
ELSE sm <= yellow;
END IF;
WHEN others => sm <= red;
END CASE;
END IF;
END PROCESS fsm;

r <= sm(2); -- the outputs are just taken from


g <= sm(1); -- the state machine registers
y <= sm(0); -- (no decode logic required)

END arch_3;
Mealy Machines

 Outputs may change with a change of state OR with


a change of inputs
 Mealy outputs are non-registered because they
are functions of the present inputs

State
Registers
Logic Outputs
Inputs
Example: The Wait State Generator

 State diagram:
PWAIT
RESET
(async)

REQ
RETRY_OUT='1'
IDLE RETRY
if, ENABLE='0'

REQ
PWAIT
Example: Mealy Machine Solution
ARCHITECTURE archmealy1 OF mealy1 IS
TYPE fsm_states IS (idle, retry);
SIGNAL wait_gen: fsm_states;
BEGIN
fsm: PROCESS (clock, reset)
BEGIN
IF reset = '1' THEN
wait_gen <= idle;
ELSIF FALLING_EDGE(clock) THEN
CASE wait_gen IS
WHEN idle => IF req = '0' THEN wait_gen <= retry;
ELSE wait_gen <= idle;
END IF;
WHEN retry => IF pwait = '1' THEN wait_gen <= idle;
ELSE wait_gen <= retry;
END IF;
WHEN OTHERS => wait_gen <= idle;
END CASE;
END IF;
END PROCESS fsm;
retry_out <= '1' WHEN (wait_gen = retry AND enable='0') ELSE '0';
END archmealy1;
Exercise #5
 Design a state machine to implement the function
shown below:

RESET
(sync)
POS
hold sample extend

POS
clear='0' track='1'

track='1'
Hierarchical (Modular) Designs

 A hierarchical design is one which is broken down


into many levels, with a top level design bringing all
the lower-level components together

 This allows very complex designs to be divided


down into smaller, more easily managed modules

 In the past, this was the major advantage of


schematic capture tools

 But, VHDL also supports hierarchical designs !!


Hierarchical Design Methodology
 Advantages:
 Components (VHDL models) can be created, tested
and stored for later use
 Allows the re-use of common building blocks
 Allows you to purchase 3rd Party off-the-shelf
modules (e.g. UART, PCIbus Interface etc)
 Makes the design more readable and easier to
understand
 Complex design tasks can be split across many
designers in a team
VHDL Hierarchy Decomposition
 In VHDL, hierarchy is composed of:
 COMPONENTs
• entity/architecture pairs which can be
instantiated (placed) within other designs
 PACKAGEs
• a collection of one or more COMPONENTs and
other declarations
 LIBRARIES
• a collection of COMPILED design units
• e.g. packages, components, entity/architecture
pairs etc.
Packages: How it all fits together
a p mux2to1
q a

c i c
t
b r b
sel

s
sel toplevel
mux2to1

• schematic • schematic
• entity/architecture mux2to1 • entity/architecture

a
• library
c • package
b • symbol
sel • component
Hierarchy Management
 Libraries are used to store re-usable components, type definitions,
overloaded operators etc. You add the ‘LIBRARY’ and ‘USE’
clauses to your code to get access to them
Your Design (VHDL) Library (Compiled) Packages (VHDL) Others (VHDL)
LIBRARY ieee; ieee
std_logic_1164 std_logic
USE ieee.std_logic_1164..
type
USE work.std_arith.all
definitions

Library (Compiled) Packages (VHDL) Others (VHDL)


work
std_arith overloaded
operators
Package and Component Declarations
 When you have created a working entity/architecture
pair, you need to add a component declaration to
make it a re-usable COMPONENT
 COMPONENTS need to be stored in PACKAGES, so
you need to write a package declaration to store all
your components
 When you compile your package with no errors, the
components will be stored in the WORK library
 WORK is the default library where everything YOU
compile gets stored. Because it is the default library,
you do NOT need to add:
LIBRARY WORK; -- not required
Package and Component
Declarations: An Example
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
PACKAGE mymuxpkg IS
COMPONENT mux2to1 PORT (
a, b, sel: IN std_logic;
Package and Component
c: OUT std_logic); Declaration File
END COMPONENT;
END mymuxpkg; (VHDL)
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY mux2to1 IS PORT (
a, b, sel: IN std_logic;
c: OUT std_logic);
END mux2to1;
Entity/Architecture
ARCHITECTURE archmux2to1 OF mux2to1 IS File (VHDL)
BEGIN
c <= (a AND NOT sel) OR (b AND sel);
END archmux2to1;
Hierarchical design: Example
 Signals are connected via a PORT MAP that associates signals with the
component's I/O
 Port map association can be either explicit (named) or implicit (positional)
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY toplevel IS PORT (
s: IN std_logic;
p, q, r: IN std_logic_vector(2 DOWNTO 0);
t: OUT std_logic_vector(2 DOWNTO 0));
END toplevel;
USE WORK.mymuxpkg.ALL;
ARCHITECTURE arch_top_level OF toplevel IS
SIGNAL i: std_logic_vector(2 DOWNTO 0); Named Association
BEGIN
m0: mux2to1 PORT MAP (a=>i(2), b=>r(0), sel=>s, c=>t(0));
m1: mux2to1 PORT MAP (c=>t(1), b=>r(1), a=>i(1), sel=>s);
m2: mux2to1 PORT MAP (i(0), r(2), s, t(2));
i <= p AND NOT q;
Positional Association
END arch_top_level;
Schematic of example

mux2to1 t(0)
mux2to1 t(1)
mux2to1 t(2)
i(2) a i(1) a i(0) a

m0 c
m1 c
m2 c
r(0) b r(1) b r(2) b
sel sel sel

s
Exercise #6
 Making use of exercise #4, we will use a separate
entity/architecture for each block and use VHDL hierarchy

ENC

COUNTER
DATA
4
DIN
LD COUNT
LD Q 4
ENC COMPARATOR
CLOCK P
RST
RESET (sync) P=Q
Q
REGISTER
DIN
Q
ENR 4
ENR
Exercise 6 Solution: package.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

PACKAGE ex6_pkg IS

COMPONENT comp4 PORT (


p, q : IN std_logic_vector (3 DOWNTO 0);
peqq : OUT std_logic);
END COMPONENT;

COMPONENT reg4 PORT (


clk, enr : IN std_logic;
din : IN std_logic_vector(3 DOWNTO 0);
q : OUT std_logic_vector(3 DOWNTO 0));
END COMPONENT;
Exercise 6 Solution: package.vhd (cont)

COMPONENT count4 PORT(


clk, enc, ld, rst : IN std_logic;
din : IN std_logic_vector(3 downto 0);
q : BUFFER std_logic_vector(3 downto 0));
END COMPONENT;

END ex6_pkg;
Exercise 6 Solution: Top Level File - ex6.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY ex6 IS PORT (


load, clock, reset : IN std_logic;
enr, enc : IN std_logic;
data : IN std_logic_vector(3 downto 0);
count : BUFFER std_logic_vector(3 downto 0));
END ex6;

USE work.ex6_pkg.ALL; -- get access to your components


ARCHITECTURE ex6_arch OF ex6 IS

SIGNAL regout : std_logic_vector(3 downto 0); -- internal bus


SIGNAL peqq : std_logic; -- internal net
SIGNAL not_peqq : std_logic; -- internal net
Exercise 6 Solution :Top Level File - ex6.vhd

BEGIN

U1: count4 PORT MAP (din=>data, ld=>load, enc=>not_peqq,


clk=>clock, rst=>reset, q=>count);

U2: reg4 PORT MAP (din=>data, enr=>enr, clk=>clock,


q=>regout);

U3: comp4 PORT MAP (p=>count, q=>regout, peqq=>peqq);

not_peqq <= enc AND NOT(peqq); -- create the inverter

END ex6_arch;
Exercise 6: Summary
 We created entity/architectures for each component. We stored those
components in a package so that we could RE-USE them
 We included ALL “components” in the “ex6_pkg” package which
was compiled into the “work” library
Your Design (VHDL) Library (Compiled) Packages (VHDL) Others (VHDL)
LIBRARY ieee; ieee std_logic_1164
std_logic
USE ieee.std_logic_1164..
type
USE work.ex6_pkg.all
definitions

Library (Compiled) Packages (VHDL) Components(VHDL)


work ex6_pkg.vhd count4.vhd
count4 reg4.vhd
reg4 comp4.vhd
comp4
Creating repetitive structures

 e.g., a 32-bit serial to parallel converter:

reset
q(31) q(30) q(29) q(1) q(0)
si
•••

clock

po(31) po(30) po(29) po(1) po(0)


The GENERATE statement
 Used to specify repetitive or conditional execution of
a set of concurrent statements
 Useful for instantiating arrays of components
USE WORK.rtlpkg.ALL; -- User-defined package containing dsrff
ENTITY sipo IS PORT (
clk, reset: IN std_logic;
si: IN std_logic;
po: BUFFER std_logic_vector(31 DOWNTO 0));
END sipo;

ARCHITECTURE arch_sipo OF sipo IS


SIGNAL p_temp: std_logic_vector(31 DOWNTO 0);
SIGNAL zero: std_logic := ‘0’;
BEGIN
gen: FOR i IN 0 TO 30 GENERATE
nxt: dsrff PORT MAP (p_temp(i+1), zero, reset, clk, p_temp(i));
END GENERATE;
beg: dsrff PORT MAP (si, zero, reset, clk, p_temp(31));
po <= p_temp;
END arch_sipo;
LIBRARY ieee ;
Multiplexing I/O pins:
USE ieee.std_logic_1164.ALL;
USE WORK.std_arith.all ;
ENTITY ldcnt IS PORT (
clk, ld, oe: IN std_logic;
count: INOUT std_logic_vector(7 DOWNTO 0));
END ldcnt;
ARCHITECTURE archldcnt OF ldcnt IS
SIGNAL int_count: std_logic_vector(7 DOWNTO 0);
BEGIN
cnt: PROCESS (clk)
BEGIN
IF RISING_EDGE(clock) THEN
IF ld = '1' THEN int_count <= count; -- count as "IN"
ELSE int_count <= int_count + 1;
END IF;
END IF;
END PROCESS cnt ;
outen: PROCESS (oe, int_count) BEGIN
IF oe = '1’ THEN count <= int_count ; -- count as "OUT"
ELSE count <= (OTHERS => 'Z') ;-- count as "OUT"
END IF ; -- equivalent to count <= "ZZZZZZZZ"
END PROCESS outen;
END archldcnt;
Exercise #7
 Design a Moore Machine to implement the Output Enable
Controller shown below:

68040 DRAM BANK A DRAM BANK B

DRAM BANK C DRAM BANK D

Output
DRAM
Enable
Controller
Controller
Exercise #7: The FSM chart
 Use the following FSM chart:
RAM RESET

IDLE

OE=1111

/RAM

CHOOSE

OE=1111

/EOC

/A3 AND /A2 /A3 AND A2 A3 AND /A2 A3 AND A2

BANK A EOC BANK B EOC BANK C EOC BANK D

OE=1110 OE=1101 OE=1011 OE=0111

EOC
Exercise #7: Solution
ENTITY ex7 IS PORT (
clk, reset: IN std_logic;
ram, eoc: IN std_logic;
a3a2: IN std_logic_vector(1 DOWNTO 0) ;
oe: OUT std_logic_vector(3 DOWNTO 0));
END ex7;

ARCHITECTURE archex7 OF ex7 IS

TYPE oe_states IS (idle, choose, banka, bankb, bankc, bankd);


ATTRIBUTE state_encoding OF oe_states : TYPE IS gray ;
SIGNAL present_state, next_state : oe_states ;
SIGNAL oe_out : std_logic_vector(3 DOWNTO 0) ;

BEGIN
Exercise #7: Solution (contd.)
fsm: PROCESS (clk)
BEGIN
IF RISING_EDGE(clock) THEN
IF reset = '1' THEN
next_state <= idle;
ELSE
CASE present_state IS
WHEN idle => IF ram = '0'
THEN next_state <= choose ;
ELSE next_state <= idle ;
END IF ;
WHEN choose =>
CASE a3a2 IS
WHEN "00" => next_state <= banka ;
WHEN "01" => next_state <= bankb ;
WHEN "10" => next_state <= bankc ;
WHEN "11" => next_state <= bankd ;
WHEN OTHERS => next_state <= banka ;
END CASE ;
WHEN banka => IF eoc = '1'
THEN next_state <= bankb ;
ELSE next_state <= idle ;
END IF ;
Exercise #7: Solution (contd.)

WHEN bankb => IF eoc = '1'


THEN next_state <= bankc ;
ELSE next_state <= idle ;
END IF ;
WHEN bankc => IF eoc = '1'
THEN next_state <= bankd ;
ELSE next_state <= idle ;
END IF ;
WHEN bankd => IF eoc = '1'
THEN next_state <= banka ;
ELSE next_state <= idle ;
END IF ;
WHEN OTHERS => next_state <= idle;
END CASE;
END IF ;
END IF;
END PROCESS fsm;
Exercise #7: Solution (contd).
output_logic: PROCESS (next_state)
BEGIN
CASE next_state IS
WHEN idle => oe_out <= "1111" ;
WHEN choose => oe_out <= "1111" ;
WHEN banka => oe_out <= "1110" ;
WHEN bankb => oe_out <= "1101" ;
WHEN bankc => oe_out <= "1011" ;
WHEN bankd => oe_out <= "0111" ;
WHEN OTHERS => oe_out <= "1111" ;
END CASE;
END PROCESS output_logic ;

advance_state: PROCESS (clk)


BEGIN
IF RISING_EDGE(clock)
THEN present_state <= next_state ;
oe <= oe_out ;
END IF;
END PROCESS ;

END archex7;

You might also like