You are on page 1of 193

Advanced VHDL Design

Techniques

2012 Altera CorporationConfidential


Objectives

Write synthesizable RTL code


Create state machines and control their encoding
Optimize designs to improve resource usage and
performance
Develop simple testbenches to perform RTL debugging
Create parameterizable VHDL modules
Synthesize and place & route design using the
Quartus II software
Analyze designs in ModelSim-Altera software

2012 Altera CorporationConfidential


2
Agenda

Writing synthesizable VHDL


Inferring common logic functions
Coding state machines
Improving logic utilization & performance
Introduction to testbenches
Writing parameterized code

2012 Altera CorporationConfidential


3
Advanced VHDL Design
Techniques
Introduction to Altera Devices & Design Software

2012 Altera CorporationConfidential


A Complete Solutions Portfolio

CPLDs Low-cost FPGAs High-density, Low-cost Transceiver FPGAs Structured


high-performance FPGAs ASICs

Embedded Intellectual Design Development


soft processors Property (IP) software kits

2012 Altera CorporationConfidential


5
Quartus II Software Two Editions

Subscription Edition Web Edition


Devices Supported All Selected Devices
Features 100% 95%
Distribution Internet & DVD Internet & DVD
Price Paid Free

Feature Comparison available on Altera web site

2012 Altera CorporationConfidential


6
Advanced VHDL Design
Techniques

VHDL Basics Review

2012 Altera CorporationConfidential


VHDL Basics Review
These topics covered in the VHDL introductory
course

Design units
ENTITY
ARCHITECTURE,
CONFIGURATION
PACKAGE (LIBRARY)
Behavioral vs. structural modeling
Implicit vs. explicit processes
i.e. Concurrent signal assignment vs. PROCESS statement

* See appendix for examples

2012 Altera CorporationConfidential


8
VHDL Basics Review (cont.)

Signal delay
AFTER clause
Inertial vs. transport delays
Delta delays

Sequential process statements


IF-THEN-ELSE, CASE, LOOP & WAIT statements

Signals vs. variables


Building hierarchy
Component instantiation

* See appendix for examples

2012 Altera CorporationConfidential


9
Advanced VHDL Design
Techniques

Writing Synthesizable VHDL

2012 Altera CorporationConfidential


Simulation vs. Synthesis

Simulation
Code executed in the exact way it is written
User has flexibility in writing
Initialization of logic supported

Synthesis
Code is interpreted & hardware created
Knowledge of PLD architecture is important
Synthesis tools require certain coding to generate correct logic
Subset of VHDL language supported
Coding style is important for fast & efficient logic
Initialization controlled by device
Logic implementation can be adjusted to support initialization

Pre- & post-synthesis logic should operate the same

2012 Altera CorporationConfidential


11
Writing Synthesizable VHDL

Synthesizable VHDL Constructs


Sensitivity lists
Latches vs. registers
IF-THEN-ELSE structures
CASE statements
Variables
Synthesizable subprograms
Combinatorial loops
Gated clocks

2012 Altera CorporationConfidential


12
Some Synthesizable VHDL Constructs

ENTITY Component & direct instantiation


ARCHITECTURE GENERATE
CONFIGURATION FUNCTION
PACKAGE PROCEDURE
Concurrent signal assignments ASSERT (constant false)
PROCESS WAIT (one per process)
SIGNAL TYPE
VARIABLE (non-shared) SUBTYPE
CONSTANT
IF-ELSE
CASE Synthesis tools may place certain
Loops (fixed iteration)
restrictions on supported
Multi-dimensional arrays
PORT
constructs
GENERIC (constant) See the online help in Quartus II
COMPONENT (or your target synthesis tool) for
a complete list

2012 Altera CorporationConfidential


13
Some Non-Synthesizable VHDL Constructs

ACCESS
These are some of the constructs
ASSERT not supported by Quartus II
DISCONNECT synthesis
See the online help in Quartus II
FILE (or your target synthesis tool) for
GROUP a complete list

NEW
Physical delay types
PROTECTED
SHARED VARIABLE
Signal assignment delays

2012 Altera CorporationConfidential


14
Two Types of RTL PROCESS Statements
Combinatorial PROCESS
Sensitive to all signals used on right-
hand side of assignment statements a
c
Example b
PROCESS (a, b, sel)
sel
Sensitivity list includes all inputs used
In the combinatorial logic

Sequential PROCESS d q
Sensitive to a clock and
clk
control signals
Example
aclr_n
PROCESS (clr, clk)
Sensitivity list does not include the d input,
only the clock or/and control signals
2012 Altera CorporationConfidential
15
Sensitivity Lists
Incomplete sensitivity list in combinatorial PROCESS blocks may
result in differences between RTL & gate-level simulations
Synthesis tool synthesizes as if sensitivity list complete

PROCESS
PROCESS (a, (a, b)
b) Incorrect Way the simulated behavior is not
yy <=
<= aa AND
AND b b AND
AND c;
c; that of the synthesized 3-input AND gate

PROCESS
PROCESS (a, (a, b,
b, c)
c)
yy <=
<= aa AND
AND b b AND
AND c;
c;
or Correct way for the intended AND logic !
PROCESS
PROCESS (all)
(all)
yy <=
<= aa AND
AND b b AND
AND c;
c;

2012 Altera CorporationConfidential


16
Latches vs. Registers

Altera devices have registers in logic elements, not


latches
Latches are implemented using combinatorial logic & can
make timing analysis more complicated
Look-up table (LUT) devices use LUTs in combinatorial loops
Product-term devices use more product-terms

Recommendations
Design with registers (RTL)
Watch out for inferred latches
Latches inferred on combinatorial outputs when results not specified for set of
input conditions
Lead to simulation/synthesis mismatches

2012 Altera CorporationConfidential


17
IF-ELSE Structure
IF-ELSE (like WHEN-ELSE concurrent assignment) structure implies
prioritization & dependency
Nth clause implies all N-1 previous clauses not true
Beware of needlessly ballooning logic

Logical Equation

(<cond1> A) + (<cond1> <cond2> B) + (<cond1> <cond2> cond3 C) +

Consider restructuring IF statements


May flatten the multiplexer and reduce logic

IF <cond1> THEN
IF <cond1> AND <cond2> THEN
IF <cond2> THEN

If sequential statements are mutually exclusive, individual IF


structures may be more efficient

2012 Altera CorporationConfidential


18
When Writing IF-ELSE Structures

Cover all cases


Uncovered cases in combinatorial processes result in
latches
For efficiency, consider
Using dont cares (- or X) for final ELSE clause (avoiding
unnecessary default conditions)
Synthesis tool has freedom to encode dont cares for maximum
optimization
Assigning initial values and explicitly covering only those results
different from initial values

2012 Altera CorporationConfidential


19
Unwanted Latches
Combinatorial processes that do not cover all possible input
conditions generate latches

PROCESS
PROCESS (sel,
(sel, a,
a, b,
b, c)
c)
BEGIN
BEGIN
IF
IF sel
sel == 001
001 THEN
THEN
sel(0) LOGIC
output
output <=
<= a;
a; sel(1) LATCH
sel(2) output
ELSIF
ELSIF sel
sel == 010
010 THEN
THEN A
B
output
output <=
<= b;
b; C
ELSIF
ELSIF sel
sel == 100
100 THEN
THEN
output
output <=
<= c;
c;
END
END IF;
IF;
END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


20
Unwanted Latches Removed
Close all IF-ELSE structures
If possible, assign dont cares to else clause for improved logic optimization

PROCESS
PROCESS (all)
(all)
BEGIN
BEGIN
IF
IF sel
sel == 001
001 THEN
THEN
output
output <= <= a;
a; sel(0)
LOGIC
ELSIF sel(1)
ELSIF selsel == 010
010 THEN
THEN sel(2)
output
output
output <= <= b;
b; A
B
ELSIF
ELSIF selsel == 100
100 THEN
THEN C
output
output <= <= c;
c;
ELSE
ELSE
output
output <= <= (OTHERS
(OTHERS =>
=> X);
X);
END
END IF;IF;
END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


21
Mutually Exclusive IF-ELSE Latches
Beware of building unnecessary dependencies
e.g. Outputs x, y, z are mutually exclusive, IF-ELSIF causes all outputs to be
dependant on all tests & creates latches

PROCESS
PROCESS (all)
(all)
BEGIN
BEGIN
sel(0) LOGIC LATCH
IF
IF sel
sel == 010
010 THEN
THEN sel(1) X
xx <=
<= a;a; sel(2)
A
ELSIF
ELSIF selsel == 100
100 THEN
THEN
yy <=
<= b;b;
sel(0) LOGIC LATCH
ELSIF
ELSIF selsel == 001
001 THEN
THEN sel(1) Y
zz <=
<= c;
c; sel(2)
B
ELSE
ELSE
xx <=
<= 0;
0;
sel(0) LOGIC LATCH
yy <=
<= 0;
0; sel(1) Z
zz <=
<= 0;
0; sel(2)
C
END
END IF;IF;
END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


22
Mutually Exclusive Latches Removed
Separate IF statements and close
PROCESS
PROCESS (sel,
(sel, a,
a, b,
b, c)
c)
BEGIN
BEGIN
PROCESS
PROCESS (sel,(sel, a,
a, b,
b, c)
c)
IF
IF sel
sel == 010
010 THEN
THEN
BEGIN
BEGIN
xx <=
<= a;
a;
xx <=
<= 0;
0;
ELSE
ELSE sel(0)
LOGIC
sel(1) yy <=
<= 0;
0;
xx <=
<= 0;
0; sel(2)
X
zz <=
<= 0;
0;
END
END IF;IF; A
IF
IF sel
sel == 010
010 THEN
THEN
IF
IF sel
sel == 100
100 THEN
THEN
xx <=
<= a;
a;
yy <=
<= b;
b; sel(0) LOGIC
sel(1) END
END IF;IF;
ELSE
ELSE sel(2)
Y
IF
IF sel
sel == 100
100 THEN
THEN
yy <=
<= 0;
0; B
yy <=
<= b;
b;
END
END IF;IF;
END
END IF;IF;
IF
IF sel
sel == 001
001 THEN
THEN sel(0) LOGIC
sel(1) IF
IF sel
sel == 001
001 THEN
THEN
zz <=
<= c;c; sel(2) Z
zz <=
<= c;
c;
ELSE
ELSE C
END
END IF;IF;
zz <=
<= 0;
0;
END
END PROCESS;
PROCESS;
END
END IF;IF;
END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


23
Nested IF Generating Unwanted Latches
Use nested IF statements with care
e.g. These nested IF statements do not cover all possible conditions (open IF
statements) & latch is created
ina inb out
1 1 1
0 0 0
PROCESS
PROCESS (ina,
(ina, inb)
inb) 0 1 0
BEGIN
BEGIN 1 0 ?
IF
IF ina
ina == '1'
'1' THEN
THEN
IF
IF inb
inb == '1'
'1' THEN
THEN
yy <=
<= '1';
'1'; ina y
END
END IF; IF;
ELSE inb
ELSE
yy <=
<= '0';
'0';
END
END IF;IF; Uncovered cases infer latches
END
END PROCESS;
PROCESS; No default value for objects
Equation
A1L3 = LCELL(ina & (A1L3 # inb));

2012 Altera CorporationConfidential


24
Nested IF Unwanted Latches Removed

PROCESS
ina inb out
PROCESS (ina,(ina, inb)
inb)
BEGIN
BEGIN 1 1 1
yy <=
<= 0;
0; 0 0 0
IF
IF ina
ina == '1'
'1' THEN
THEN 0 1 0
IF
IF inb
inb == '1'
'1' THEN
THEN 1 0 0
yy <=
<= '1';
'1';
END
END IF; IF; ina
END
END IF;IF;
inb out
END
END PROCESS;
PROCESS;

Using initialization to cover all cases; no


latch inferred
Equation
A1L3 = inb & ina;

2012 Altera CorporationConfidential


25
Case Statements

Case statements usually synthesize more


efficiently when mutual exclusivity exists

Define outputs for all cases


Undefined outputs for any given case generate latches

VHDL already requires all case conditions be


covered
Use WHEN OTHERS clause to close undefined cases (if any
remain)

2012 Altera CorporationConfidential


26
Case Statement Recommendations

Initialize all case outputs or ensure outputs


assigned in each case
Assign initialized or default values to dont cares
(X) for further optimization, if logic allows

2012 Altera CorporationConfidential


27
Unwanted Latches - Case Statements
Conditions where output is undetermined

output:
output: PROCESS
PROCESS (filter)
(filter)
BEGIN
BEGIN
Undetermined output
CASE
CASE filter
filter IS
IS conditions implies
WHEN
WHEN idleidle =>
=> memory
nxt
nxt <= '0';
<= '0';
first sel
sel missing
missing Latch generated for
first <= '0';
<= '0';
WHEN
WHEN tap1tap1 =>=> ALL 3 outputs
sel
sel <=
<= "00";
"00";
first
first <=
<= '1';
'1'; nxt
nxt missing
missing
WHEN
WHEN tap2tap2 =>=>
sel <= "01";
sel <= "01";
first
first <=
<= '0';
'0'; nxt
nxt missing
missing
WHEN
WHEN tap3tap3 =>=>
sel
sel <=
<= "10";
"10"; nxt
nxt &
& first
first missing
missing
WHEN
WHEN tap4tap4 =>=>
sel <= "11";
sel <= "11";
nxt
nxt <=<= '1';
'1'; first
first missing
missing
END
END CASE;
CASE;
END
END PROCESS
PROCESS output;
output;

2012 Altera CorporationConfidential


28
Latches Removed - Case Statements
Conditions where output is determined

output:
output: PROCESS(filter)
PROCESS(filter)
BEGIN
BEGIN To remove latches & ensure
first
first <=
<= 0;
0; outputs are never undetermined
nxt
nxt <=<= 0;
0; Signals
Signals Initialized
Initialized
sel
sel <=
<= 00;
00;
CASE
CASE filter
filter ISIS
Use signal initialization at
WHEN
WHEN idle idle =>
=> beginning of case statement
WHEN
WHEN tap1 tap1 =>=> (case statement only deals with
first
first <=
<= '1';
'1'; changes)
WHEN
WHEN tap2 tap2 =>=>
sel
sel <=
<= "01";
"01"; Use dont cares (-) for WHEN
WHEN
WHEN tap3 =>
tap3 => OTHERS clause, if design
sel <= "10";
sel <= "10"; allows (for better logic
WHEN
WHEN tap4 tap4 =>=>
sel
sel <=
<= "11";
"11";
optimization)
nxt
nxt <=
<= '1';
'1'; Manually set output in each
END CASE;
END CASE; case
END
END PROCESS output;
PROCESS output;

2012 Altera CorporationConfidential


29
Variables
May synthesize to hardware depending on use
Advantages vs. signals
Variables are a more behavioral construct as they dont have a direct
correlation to hardware (like signals) and may lead to more efficient logic
Simulate more efficiently as they require less memory
Signals not updated immediately, so simulator must store two values (current
and next value) for every changing signal
Variables updated immediately, so simulator stores single value
Disadvantages vs. signals
Must be assigned to signal before process ends
Do not represent physical hardware unless equated with signal
Must be handled with care
Requires fully understand assigning values to variables and signals in same
process and how dataflow is effected

2012 Altera CorporationConfidential


30
Variables & Latches (Recommendations)

Assign an initial value or signal to a variable


unless feedback is desired
If a variable is not assigned an initial value or
signal in a combinatorial process, a latch will be
generated
This could cause your design to not function as
intended

2012 Altera CorporationConfidential


31
Variable Uninitialized
ARCHITECTURE
ARCHITECTURE logic logic OF
OF cmb_vari
cmb_vari IS
IS
BEGIN
BEGIN
PROCESS(i0,
PROCESS(i0, i1, i1, a)
a)
VARIABLE
VARIABLE val val ::
INTEGER
INTEGER RANGE RANGE 00 TO
TO 1;
1; Variable
Variable used
used without
without
BEGIN
BEGIN
IF
initialization
initialization
IF (a
(a == '0')
'0') THEN
THEN
val
val :=:= val;
val;
ELSE
ELSE
val
val :=:= val
val ++ 1;
1;
END
END IF;IF;
0 case (val)
CASE
CASE val
val IS
IS
WHEN 1 ;
WHEN 00 => =>
qq <=
<= i0;
i0;
WHEN
WHEN OTHERS
OTHERS =>=>
qq <=
<= i1;
i1;
a
END
END CASE;
CASE;
END
END PROCESS;
PROCESS;
END
END ARCHITECTURE
ARCHITECTURE logic;
logic;

2012 Altera CorporationConfidential


32
Assign Initial Value to Variable
ARCHITECTURE
ARCHITECTURE logic logic OF
OF cmb_vari
cmb_vari IS
IS
BEGIN
BEGIN
PROCESS(i0,
PROCESS(i0, i1, i1, a)
a)
VARIABLE
VARIABLE val val ::
INTEGER
INTEGER RANGE RANGE 00 TO
TO 1;
1;
BEGIN
BEGIN Assign
Assign initial
initial value
value or
or
val
val :=
:= 0;
0; signal
signal to
to variable
variable
IF
IF (a
(a == '0')
'0') THEN
THEN
val
val := := val;
val;
ELSE
ELSE
val
val := := val
val ++ 1;
1; case (val)
END
END IF; IF;
;
CASE
CASE val
val IS
IS
WHEN
WHEN 00 => =>
qq <=
<= i0;
i0; a
WHEN
WHEN OTHERS
OTHERS =>=>
qq <=
<= i1;
i1;
END
END CASE;
CASE;
END
END PROCESS;
PROCESS;
END
END ARCHITECTURE
ARCHITECTURE logic;
logic;

2012 Altera CorporationConfidential


33
Exercise 1

2012 Altera CorporationConfidential


34
Synthesizable Subprograms

Make code more readable/reusable


Two types
Functions
Synthesize to combinatorial logic
Procedures
Can synthesize to combinatorial or sequential logic
Signal assignments in procedures called from clocked processes generate
registers
May test for clock edges
May not be supported by all synthesis tools
Must not contain WAIT statements

Each call generates a separate block of logic


No logic sharing
Implement manual resource sharing, if possible (discussed later)

2012 Altera CorporationConfidential


35
Combinational Loops
Common cause of instability
Behavior of loop depends on the
relative propagation delays PROCESS
PROCESS (clk,
(clk, clrn)
clrn)
through logic BEGIN
BEGIN
Propagation delays can change IF
IF clrn
clrn == 0
0 THEN
THEN
Simulation tools may not match qq <=
<= 0;
0;
hardware behavior ELSIF
ELSIF rising_edge
rising_edge (clk)
(clk) THEN
THEN
qq <=
<= d;
d;
Logic END
END IF;IF;
END
END PROCESS;
PROCESS;
d q clrn
clrn <=
<= (ctrl1
(ctrl1 XOR
XOR ctrl2)
ctrl2) AND
AND q;
q;
clk

2012 Altera CorporationConfidential


36
Combinational Loops
All feedback loops should
PROCESS
PROCESS (clk,
(clk, clrn)
clrn)
include registers BEGIN
BEGIN
IF
IF clrn
clrn == 0
0 THEN
THEN
Logic qq <=
<= 0;
0;
ELSIF
ELSIF rising_edge
rising_edge (clk)
(clk)
d qq <=
<= d;
d;
q END
END IF;IF;
clk END
END PROCESS;
PROCESS;

PROCESS
PROCESS (clk)
(clk)
BEGIN
BEGIN
IF
IF rising_edge
rising_edge (clk)
(clk) THEN
THEN
clrn
clrn <=
<= (ctrl1
(ctrl1 XOR
XOR ctrl2)
ctrl2) AND
AND q;
q;
END
END IF;IF;
clrn END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


37
Gated Clocks

Can lead to both functional and timing problems


Clock behavior subject to both synthesis and placement & routing
Can be a source of additional clock skew
Glitches on clock path possible

Recommendations:
Use clock enables for clock gating functionality
Use dedicated device resources (e.g. clock control blocks) to gate clocks
synchronously and reduce power
If you must build your own gating logic
Use a synchronous gating structure
Ensure global clock routing is used for clock signal
Gate the clock at the source

2012 Altera CorporationConfidential


38
Gated Clock Examples
g_clk <= gate AND clk; PROCESS (clk)
BEGIN
IF falling_edge (clk) THEN
PROCESS (g_clk, clrn) sgate <= gate;
BEGIN END IF;
IF clrn = 0 THEN END PROCESS;

q <= 0; g_clk <= sgate AND clk;


ELSIF rising_edge(g_clk) THEN
q <= d; PROCESS (g_clk, clrn)
BEGIN
END IF; IF clrn = 0 THEN
END PROCESS; q <= 0;
ELSIF rising_edge (g_clk) THEN
Poor clock gating Active clock q <= d;
END IF;
edges occurring near gate signal END PROCESS;
changes may result in glitches
Better clock gating Gate signal
clocked by falling edge clk, so gate
may only change on inactive clock
edge (Use OR gate when falling edge
is the active clock edge)

2012 Altera CorporationConfidential


39
Advanced VHDL Design
Techniques

Inferring Common Logic Functions

2012 Altera CorporationConfidential


Inferring Logic Functions
Using behavioral modeling to describe logic
blocks
Synthesis tools recognize description & insert
equivalent logic functions (e.g. megafunctions)
Functions typically pre-optimized for utilization or
performance over general purpose functionally
equivalent logic
Use synthesis tools templates (if available) as starting
point
Use synthesis tools graphic display to verify logic
recognition
Makes code vendor-independent

2012 Altera CorporationConfidential


41
Logic Inference Example
PROCESS
PROCESS (clock)
(clock)
BEGIN
BEGIN
IF
IF rising_edge
rising_edge (clock)
(clock) THEN
THEN
IF
IF wren
wren == 1
1 THEN
THEN
mem(conv_integer(address)
mem(conv_integer(address) <=
<= data;
data;
END
END IF;
IF; Synthesis tool sees
qq <=
<= mem(conv_integer(address);
mem(conv_integer(address);
Replaces with
END
END IF;IF;
END
END PROCESS;
PROCESS;

Altera megafunction and/or library cells

2012 Altera CorporationConfidential


42
Quartus II VHDL Templates

Preview window: edit


before inserting & save
as user template

Insert Template (Edit menu)

2012 Altera CorporationConfidential


43
43
Quartus II Software RTL Viewer

Graphically represents results of synthesis


Schematic View

Toolbar

Starting RTL Viewer


Hierarchy List 1. Run Analysis & Elaboration (Processing
menu or Task window)
Any processing that performs elaboration
2. Open RTL Viewer (Tools menu or Tasks
window)
Displays last successful analysis

2012 Altera CorporationConfidential


44
Inferring Common Functions

Latches
Registers
Counters
Tri-states
Memory

2012 Altera CorporationConfidential


45
Latch Inference Wanted Latch
LIBRARY IEEE; Latch in RTL Viewer
USE IEEE.std_logic_1164.ALL;

ENTITY latch IS
PORT (
data : IN std_logic;
gate : IN std_logic;
q : OUT std_logic); Latch in Technology
END ENTITY latch; Viewer

ARCHITECTURE behavior OF latch IS


BEGIN

label_1: PROCESS (data, gate)


BEGIN
IF gate = '1' THEN sensitivity list includes both inputs
q <= data;
END IF;
END PROCESS label_1; level sensitivenot edge

END ARCHITECTURE behavior;


What happens if gate = 0?
Implicit memory & feedback

2012 Altera CorporationConfidential


46
DFF Using rising_edge Function
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL; q
d
ENTITY dff_b IS
PORT (
clk
d : IN std_logic;
clk : IN std_logic;
q : OUT std_logic);
END ENTITY dff_b;

ARCHITECTURE behavior OF dff_b IS


BEGIN rising_edge
PROCESS(clk) IEEE function that is defined in
BEGIN the
IF rising_edge(clk) THEN
q <= d;
std_logic_1164 package
END IF; specifies that the signal value
END PROCESS; must be 0 to 1
END ARCHITECTURE behavior; X, Z to 1 transition is not allowed

2012 Altera CorporationConfidential


47
DFF Using clkevent and clk=1
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
d q
ENTITY dff_a IS
PORT ( clk
d : in std_logic;
clk : in std_logic;
q : out std_logic); aclr_n
END ENTITY dff_a;

ARCHITECTURE behavior OF dff_a IS


BEGIN clkevent and clk=1
PROCESS (clk) clk is the signal name (any name)
BEGIN event is a VHDL attribute,
IF (clk'event and clk = '1) THEN specifying that there needs
q <= d; to be a change in signal value
END IF;
clk=1 means positive-edge
END PROCESS;
END ARCHITECTURE behavior;
triggered

2012 Altera CorporationConfidential


48
Recommended DFF Inference

Use the rising_edge function for consistent


simulation
X to 1 transitions trigger the DFF when clkevent and
clk=1 is used, but not when rising_edge is used

Both clkevent and clk=1 & rising_edge produce


the same synthesis

Must use std_logic_1164 package for


rising_edge or falling_edge functions

2012 Altera CorporationConfidential


49
Secondary Control Signals

Register control signals vary between FPGA &


CPLD families
Clear, preset, load, clock enable, etc.

Avoid using signals not available in architecture


Functionality of design supported by creating extra logic cells
Less efficient, possibly slower results

2012 Altera CorporationConfidential


50
DFF with Secondary Control Signals
ARCHITECTURE behavior OF dff IS
BEGIN
PROCESS(clk, aclr, apre, aload, adata)
BEGIN This is how to implement all
IF aclr = 1' THEN
asynchronous and synchronous control
q <= '0';
ELSIF apre = 1 THEN signals for the Altera PLD registers
q <= 1; Conditions outside of the
ELSIF aload = 1 THEN rising_edge statement are
q <= adata;
ELSIF rising_edge(clk) THEN
asynchronous
IF ena = 1 THEN Conditions inside of the rising_edge
IF sclr = 1 THEN statement are synchronous
q <= 0;
Remove signals not required by your
ELSIF sload = 1 THEN
q <= sdata; logic
ELSE Synchronous controls are not included
q <= d; in sensitivity list
END IF;
END IF;
END IF;
END PROCESS;
END ARCHITECTURE behavior;

2012 Altera CorporationConfidential


51
Incorrect Control Signal Priority
ARCHITECTURE behavior OF dff_clr IS
BEGIN
PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN
IF sclr = 1 THEN
q <= 0;
ELSIF ena = 1 THEN
q <= d;
END IF; 2 control signals
END IF; Considerations
END PROCESS; Do the registers in the hardware have both
END ARCHITECTURE behavior; ports available?
How does hardware behave? Does clear
or enable have priority?
Sync clear has priority enable over in code
Enable has priority over sync clear in silicon
Additional logic needed to force code priority

2012 Altera CorporationConfidential


52
Control Signals Priority
1. Asynchronous clear (aclr)
2. Asynchronous preset (pre)
3. Asynchronous load (aload)
4. Enable (ena)
5. Synchronous clear (sclr)
6. Synchronous load (sload)

Same for all Altera FPGA families


All signals not supported by all families
Re-ordering generates extra logic

2012 Altera CorporationConfidential


53
Incorrect Control Logic
PROCESS (clk, clr_n)
BEGIN a x
IF clr_n = '0' THEN
x <= '0'; clk
ELSIF rising_edge(clk) THEN
x <= a;
y <= b;
clr_n
END IF;
END PROCESS;

y is not included in clr_n


condition b y
What is the behaviour
specified for y when clr_n is clk
asserted? clr_n
While clr_n clears x, it
acts like an enable for y

2012 Altera CorporationConfidential


54
DFF with Clock Enable

ARCHITECTURE behavior OF dff_all IS


SIGNAL ena : std_logic; d q
BEGIN
PROCESS (clk, clr_n) clk
BEGIN ena
IF clr_n = '0' THEN
q <= '0';
clr_n
ELSIF rising_edge(clk) THEN
IF ena = '1' THEN To ensure that this is synthesised using
q <= d; DFFE primitives (DFF with enable)
END IF; Place the enable statement directly
END IF; after the rising edge statement
END PROCESS; Place enable expressions in
separate process or assignment
ena <= (ena_a OR ena_b) XOR ena_c; If the synthesis tool does not recognize
this as an enable it will be implemented
END ARCHITECTURE behavior; using extra LUTs

2012 Altera CorporationConfidential


55
Shift Registers

ARCHITECTURE behavior OF shift IS


SIGNAL qi :
STD_LOGIC_VECTOR (7 DOWNTO 0);
BEGIN
PROCESS (clock, aclr)
BEGIN
IF aclr = 1' THEN
qi <= (OTHERS => '0);
ELSIF rising_edge(clock) THEN Shift register with parallel output,
IF enable = '1' THEN serial input, asynchronous clear
qi <= qi (6 DOWNTO 0) & shiftin; and enable which shifts left
END IF; Add or remove secondary controls
END IF; similar to DFF
END PROCESS;
q <= qi; Shift function (& = Concatenation)
END ARCHITECTURE behavior;

2012 Altera CorporationConfidential


56
Basic Counter

PROCESS (clock, aclr)


VARIABLE cnt :
std_logic_vector (7 DOWNTO 0);
BEGIN
IF aclr = 1' THEN Binary up counter with
cnt := (OTHERS => '0); asynchronous clear
ELSIF rising_edge(clock) THEN Add or remove secondary
cnt := cnt + 1; controls similar to DFF
END IF;
Count function
q <= cnt;
END PROCESS;

Note: These examples use the VARIABLE class as the count


variable but a SIGNAL could have been used just as easily

2012 Altera CorporationConfidential


57
Counter Using Integers
PROCESS
PROCESS (clock,
(clock, aclr)
aclr)
VARIABLE
VARIABLE cnt
cnt ::
INTEGER
INTEGER RANGE
RANGE 00 TO
TO 255;
255;
BEGIN
BEGIN
Range determines bit width for
IF
IF aclr
aclr == 1
1 THEN
THEN counter
cnt
cnt :=
:= 0;
0; If range is left out, counter will
ELSIF
ELSIF rising_edge(clock)
rising_edge(clock) THEN
THEN default to at least 32 bits
IF
IF cnt
cnt == 255
255 THEN
THEN Must manually account for rollover
cnt
cnt :=
:= 0;
0; No automatic rollover for integers
ELSE
ELSE (unlike std_logic)
cnt
cnt :=
:= cnt
cnt ++ 1;
1;
If missing, code causes end of
END
range errors in simulation
END IF;
IF;
(synthesizes correctly)
END
END IF;
IF;
qq <=
<= conv_std_logic_vector(cnt,8);
conv_std_logic_vector(cnt,8); conv_std_logic_vector(<integer_name_or_value>,
<bus_width>) converts integer to std_logic
END
END PROCESS;
PROCESS; Found in std_logic_arith package

2012 Altera CorporationConfidential


58
Up / Down Counter
PROCESS
PROCESS (clock,aclr)
(clock,aclr)
VARIABLE
VARIABLE cnt cnt :: std_logic_vector(7
std_logic_vector(7 DOWNTO
DOWNTO 0);0);
VARIABLE
VARIABLE direction
direction :: integer
integer RANGE
RANGE -1
-1 TO
TO 1;
1;
BEGIN
BEGIN
IF
IF aclr
aclr == 1
1 THEN
THEN
cnt
cnt :=:= (OTHERS
(OTHERS => => '0);
'0);
ELSIF
ELSIF rising_edge(clock)
rising_edge(clock) THEN THEN
IF
IF updown
updown == 1 1 THEN
THEN
direction
direction :=:= 1;
1;
ELSE
ELSE
direction
direction :=:= -1;
-1;
END
END IF; IF;
cnt
cnt :=:= cnt
cnt ++ direction;
direction;
END
END IF;
IF;
qq <=
<= cnt;
cnt;
END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


59
Modulus 200 Counter
PROCESS
PROCESS (clock,aclr)
(clock,aclr)
VARIABLE cnt :: std_logic_vector(7
VARIABLE cnt std_logic_vector(7 DOWNTO
DOWNTO 0);
0);
CONSTANT
CONSTANT modulus
modulus :: INTEGER
INTEGER :=
:= 200;
200;
BEGIN
BEGIN
IF
IF aclr
aclr == 1
1 THEN
THEN
cnt
cnt :=
:= (OTHERS
(OTHERS =>
=> '0);
'0);
ELSIF
ELSIF rising_edge(clock)
rising_edge(clock) THEN
THEN
IF
IF cnt
cnt == modulus-1
modulus-1 THEN
THEN
cnt
cnt :=
:= (OTHERS
(OTHERS =>
=> '0);
'0);
ELSE
ELSE
cnt
cnt :=
:= cnt
cnt ++ 1;
1;
END
END IF;
IF;
END
END IF;
IF;
qq <=
<= cnt;
cnt;
END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


60
Modulus 200 Counter Using Integers
PROCESS
PROCESS (clock,aclr)
(clock,aclr)
VARIABLE cnt :: INTEGER
VARIABLE cnt INTEGER RANGE
RANGE 00 TO
TO 199;
199;
CONSTANT
CONSTANT modulus
modulus :: INTEGER
INTEGER :=
:= 200;
200;
BEGIN
BEGIN
IF
IF aclr
aclr == 1
1 THEN
THEN
cnt
cnt :=
:= 0;
0;
ELSIF
ELSIF rising_edge(clock)
rising_edge(clock) THEN
THEN
IF
IF cnt
cnt == modulus-1
modulus-1 THEN
THEN
Cannot simply change range
cnt
cnt :=
:= 0;
0;
Same logic if range was 0 to
ELSE
ELSE 255
cnt
cnt :=
:= cnt
cnt ++ 1;
1; Range used by synthesis tool to
END
END IF;
IF; define bit width; Does not build
END
END IF;
IF; decode logic for synchronous
qq <=
reset
<= conv_std_logic_vector(cnt,8);
conv_std_logic_vector(cnt,8);
Logic must be defined explicitly
END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


61
Integers vs. Standard Logic Arrays
Integers Standard Logic Arrays
Represent numbers only Represent an array of 9 signal
Are more behavioral than standard values
logic Can be sliced
Synthesis tools more free to Are more structural than integers
generate resulting logic Structure must be optimized down
into efficient logic
May generate less logic
Can be set to bus widths wider
Integers use less storage than 32 bits
space during processing
Automatically roll over during
Simulate faster
calculations
Always use RANGE to Use for I/O ports & data path
constrain integers for synthesis
Defaults to 32 bits
Use for internal calculations
and describing internal logic

2012 Altera CorporationConfidential


62
Exercise 2

2012 Altera CorporationConfidential


63
Tri-states
IEEE defines Z value in STD_LOGIC package
Simulation: Behaves like high-impedance state
Synthesis: Converted to tri-state buffers

Altera devices have tri-state buffers only in I/O cells


Benefits:
Eliminates possible bus contention
Location of internal logic is a non-issue
Cost savings
Dont pay for unused tri-state buffers
Less testing required of devices
Internal tri-states must be converted to combinatorial logic
Complex output enable may cause errors or inefficient logic

2012 Altera CorporationConfidential


64
Inferring Tri-states Correctly

Conditional Signal Assignment


Device
ARCHITECTURE
ARCHITECTURE behavior
behavior OF
OF tri1
tri1 IS
IS ena
BEGIN
BEGIN
out_sig
out_sig <=
<= in_sig
in_sig WHEN
WHEN ena
ena == 1
1 ELSE
ELSE Z;
Z; in_sig out_sig
END
END ARCHITECTURE
ARCHITECTURE behavior;
behavior;

Process Statement I/O Cells


ARCHITECTURE
ARCHITECTURE behavior
behavior OF
OF tri2
tri2 IS
IS
BEGIN
BEGIN
driver1
driver1 :: PROCESS
PROCESS (ena,
(ena, in_sig)
in_sig)
BEGIN
BEGIN
IF
IF (ena=1)
(ena=1) THEN
THEN out_sig
out_sig <=
<= in_sig;
in_sig;
ELSE
ELSE out_sig
out_sig <=
<= Z;
Z;
Only 1 Assignment to Output
END
END IF;
IF;
Variable
END
END PROCESS;
PROCESS;
Uses Tri-State Buffer in I/O Cell
END
END ARCHITECTURE
ARCHITECTURE behavior;
behavior;

2012 Altera CorporationConfidential


65
Inferring Tri-states Incorrectly
ARCHITECTURE
ARCHITECTURE behavior
behavior OF
OF tri3
tri3 IS
IS
BEGIN
BEGIN
out_sig
out_sig <=
<= in_sig1
in_sig1 WHEN
WHEN ena1
ena1 == 1
1 ELSE
ELSE Z;
Z;
out_sig
out_sig <=
<= in_sig2
in_sig2 WHEN
WHEN ena2
ena2 == 1
1 ELSE
ELSE Z;
Z;
END
END ARCHITECTURE
ARCHITECTURE behavior;
behavior;

APEX II Device
Logic
ena1
ena2 out_sig
in_sig1
in_sig2

2 Assignments to Same Signal Not


I/O Cells
Allowed in Synthesis Unless Z Is
Used
Output Enable Logic Emulated in LEs
Simulation & Synthesis Do Not Match

2012 Altera CorporationConfidential


66
Bidirectional Pins
ENTITY
ENTITY bidir_pin
bidir_pin IS
IS ((
bidir
bidir :: INOUT
INOUT std_logic;
std_logic;
oe,
oe, clk,
clk, from_core
from_core :: IN
IN std_logic;
std_logic;
Declare pin as direction INOUT
to_core
to_core :: OUT
OUT std_logic;
std_logic;
Use INOUT as both input & tri-
stated output

Input side always on
END
END ENTITY
ENTITY bidir_pin;
bidir_pin;
For registered bidirectional I/O,
use separate process to infer
ARCHITECTURE
ARCHITECTURE behavior
behavior OF
OF bidir_pin
bidir_pin IS
IS
registers
BEGIN
BEGIN
bidir
bidir <=
<= from_core
from_core WHEN
WHEN oe=1
oe=1 ELSE
ELSE Z;
Z;
to_core
to_core <=
<= bidir;
bidir;



END
bidir
bidir as
as an
an tri-stated
tri-stated output
output
END ARCHITECTURE
ARCHITECTURE behavior;
behavior;

bidir
bidir as
as an
an input
input

2012 Altera CorporationConfidential


67
Memory
Synthesis tools have different capabilities for recognizing memories
Synthesis tools are sensitive to certain coding styles in order to
recognize memories
Usually described in the tool documentation
Tools and target devices may have limitations in architecture
implementation
Synchronous inputs only
Limitations in clocking schemes
Memory size limitations
Read-during-write support
Must declare an array data type to hold memory values

Recommendation: Read Quartus II Handbook, Volume 1, Chapter 6


for more information on inferring memories and read during write
behavior

2012 Altera CorporationConfidential


68
Inferred Single-Port Memory (1)

ARCHITECTURE logic OF sp_ram IS

TYPE mem_type IS ARRAY (0 TO 63) OF


std_logic_vector (7 DOWNTO 0);

SIGNAL mem: mem_type;


Code describes a 64 x 8 RAM
BEGIN with synchronous write &
asynchronous read
PROCESS (clock) BEGIN
IF rising_edge(clock) THEN
Cannot be implemented in
IF (wren = '1') THEN Altera embedded RAM due to
mem(conv_integer(address)) <= data; asynchronous read
END IF; Uses general logic and registers
END IF; conv_integer is a function
END PROCESS;
found in the std_logic_unsigned
q <= mem(conv_integer(address)); (or signed) package
Use TO_INTEGER if using
END ARCHITECTURE logic; numeric_std package

2012 Altera CorporationConfidential


69
Inferred Single-Port Memory (2)

ARCHITECTURE logic OF sp_ram IS

TYPE mem_type IS ARRAY (0 TO 63) OF


std_logic_vector (7 DOWNTO 0);

SIGNAL mem: mem_type;

BEGIN Code describes a 64 x 8 RAM with


synchronous write & synchronous
PROCESS (clock) BEGIN
read
IF rising_edge(clock) THEN
IF (wren = '1') THEN Old data read-during-write
mem(conv_integer(address)) <= data; behaviour
END IF; Memory read in same
q <= mem(conv_integer(address)); process/cycle as memory write
END IF;
END PROCESS;
Check target architecture for
support as unsupported features
END ARCHITECTURE logic; built using LUTs/registers

2012 Altera CorporationConfidential


70
Inferred Single-Port Memory (3)
ARCHITECTURE logic OF sp_ram IS

SUBTYPE byte IS std_logic_vector (7 DOWNTO 0); Using subtype for vector width

TYPE mem_type IS ARRAY (0 TO 63) OF byte;


SIGNAL mem: mem_type;

SIGNAL rdaddr_reg : byte;

BEGIN

PROCESS (clock) BEGIN Same memory with new data


IF rising_edge(clock) THEN read-during-write behaviour
IF (wren = '1') THEN Read performed by separate
mem(conv_integer(address)) <= data;
END IF; concurrent statement/process
rdaddr_reg <= address; Check target architecture for
END IF; support
END PROCESS; Use ramstyle attribute set to
q <= mem(conv_integer(rdaddr_reg));
no_rw_check to disable
checking and prevent extra logic
END ARCHITECTURE logic; generation

2012 Altera CorporationConfidential


71
Simple Dual-Port, Single-Clock Memory

ARCHITECTURE logic OF sdp_ram IS Code describes a simple dual-


port (separate read & write
TYPE mem_type IS ARRAY (63 DOWNTO 0) OF
std_logic_vector (7 DOWNTO 0);
addresses) 64 x 8 RAM with
single clock
SIGNAL mem: mem_type; Code implies old data read-
during-write behaviour
BEGIN
New data support in simple
PROCESS (clock) BEGIN dual-port requires additional
IF rising_edge(clock) THEN RAM bypass logic
IF (wren = '1') THEN
mem(conv_integer(wraddress)) <= data;
END IF;
q <= mem(conv_integer(rdaddress));
END IF;
END PROCESS;

END ARCHITECTURE logic;

2012 Altera CorporationConfidential


72
True Dual-Port, Dual-Clock Memory
ARCHITECTURE logic OF dp_dc_ram IS
TYPE mem_type IS ARRAY (63 DOWNTO 0) OF
std_logic_vector (7 DOWNTO 0); Code describes a true dual-port (two
SIGNAL mem: mem_type; individual addresses) 64 x 8 RAM
SIGNAL addr_reg_a, addr_reg_b :
May not be supported in all synthesis tools
std_logic_vector (7 DOWNTO 0);
BEGIN New data same-port read-during-write
PROCESS (clock_a) BEGIN behaviour shown
IF rising_edge(clock_a) THEN Mixed port behaviour undefined with
IF (wren_a = '1') THEN
mem(conv_integer(address_a)) <= data_a;
multiple clocks
END IF;
addr_reg_a <= address_a;
END IF;
q_a <= mem(conv_integer(addr_reg_a));
END PROCESS;

PROCESS (clock_b) BEGIN


IF rising_edge(clock_b) THEN
IF (wren_b = '1') THEN
mem(conv_integer(address_b)) <= data_b;
END IF;
addr_reg_b <= address_b;
END IF;
q_b <= mem(conv_integer(addr_reg_b));
END PROCESS;
END ARCHITECTURE logic;

2012 Altera CorporationConfidential


73
Initializing Memory Contents Using Files
ARCHITECTURE logic OF sp_ram IS

TYPE mem_type IS ARRAY (0 TO 63) OF Use VHDL attribute to assign


std_logic_vector (7 DOWNTO 0);
initial contents to inferred
SIGNAL mem: mem_type; memory
ATTRIBUTE ram_init_file : STRING; Store initialization data as
ATTRIBUTE ram_init_file OF mem : SIGNAL IS .HEX or .MIF
init_file_name.hex;
Contents of initialization file
BEGIN downloaded into FPGA during
configuration
PROCESS (clock) BEGIN
IF rising_edge(clock) THEN
IF (we = '1') THEN
mem(conv_integer(address)) <= data;
END IF;
q <= mem(conv_integer(address));
END IF;
END PROCESS;

END ARCHITECTURE logic;

2012 Altera CorporationConfidential


74
Initializing Memory Using Default
ARCHITECTURE logic OF sp_ram IS Assign default value when declaring
memory
TYPE mem_type IS ARRAY (0 TO 63) OF This example uses a function to establish
std_logic_vector (7 DOWNTO 0); memory values
Recommendation: Use when initializing
FUNCTION init_ram memory with patterned data
RETURN mem_type Is Can also use a constant (see ROM
VARIABLE mem_out : mem_type; example)
BEGIN Recommendation: Use when initializing
FOR I IN 0 TO 63 LOOP memory with non-patterned data or
mem_out(i) := conv_std_logic_vector(i, 8); single value
END FOR; (e.g. OTHERS => 11111111;)
RETURN mem_out; MIF file automatically generated during
END FUNCTION init_ram; synthesis due to initialization

SIGNAL mem: mem_type := init_ram; Loop used to assign each memory address

BEGIN
Default initial value for memory

2012 Altera CorporationConfidential


75
Unsupported Control Signals

e.g. Clearing RAM contents with reset

BEGIN
Memory content cannot be
PROCESS (clock, reset) cleared with reset
BEGIN Synthesizes to general logic
IF reset = 1 THEN resources
mem(conv_integer(address)) <=
Recommendations
(OTHERS => 0);
ELSIF rising_edge(clock) THEN 1. Avoid reset checking in
IF (we = '1') THEN RAM read or write
mem(conv_integer(address)) <= data; processes
END IF; 2. Be wary of other control
END IF;
END PROCESS;
signals (i.e. clock enable)
until validated with target
q <= mem(conv_integer(address)); architecture
END ARCHITECTURE logic;

2012 Altera CorporationConfidential


76
Inferred ROM (Case Statement)
SIGNAL
SIGNAL qq :: std_logic_vector
std_logic_vector (6
(6 DOWNTO
DOWNTO 0);
0);

BEGIN
Automatically converted to
BEGIN
ROM
PROCESS(clock)
PROCESS(clock) Tools generate ROM
BEGIN
BEGIN using embedded RAM &
IF
IF rising_edge(clock)
rising_edge(clock) THEN
THEN initialization file
CASE
CASE address
address IS
IS
WHEN
WHEN "0000" =>
"0000" => qq <=
<= "0111111";
"0111111";
Requires constant explicitly
WHEN
WHEN "0001"
"0001" =>
=> qq <=
<= "0011000";
"0011000"; defined for each choice in
WHEN
WHEN "0010"
"0010" =>
=> qq <=
<= "1101101";
"1101101"; CASE statement
WHEN
WHEN "0011"
"0011" =>
=> qq <=
<= "1111100";
"1111100"; May use romstyle
WHEN
WHEN "0100"
"0100" =>
=> qq <=
<= "1011010";
"1011010";

synthesis attribute to control

WHEN
WHEN "1101"
"1101" =>
=> qq <=
<= "1111001";
"1111001"; implementation
WHEN
WHEN "1110"
"1110" =>
=> qq <=
<= "1100111";
"1100111"; Like RAMs, address or
WHEN
WHEN "1111"
"1111" =>
=> qq <=
<= "1000111";
"1000111"; output must be registered to
WHEN
WHEN OTHERS
OTHERS => => qq <=
<= "XXXXXXX";
"XXXXXXX";
END
implement in Altera
END CASE;
CASE;
END
END IF;IF; embedded RAM
END
END process;
process;

2012 Altera CorporationConfidential


77
Inferred ROM (Constant)
ARCHITECTURE
ARCHITECTURE logic
logic OFOF rom16x7
rom16x7 IS IS BEGIN
BEGIN
TYPE
TYPE rom_type
rom_type IS
IS ARRAY
ARRAY (0 (0 TO
TO 15)
15) OF
OF PROCESS
PROCESS (clock)
(clock)
STD_LOGIC_VECTOR
STD_LOGIC_VECTOR (6 (6 DOWNTO
DOWNTO 0);0); BEGIN
BEGIN
CONSTANT
CONSTANT rom
rom :: rom_type
rom_type := := IF
IF rising_edge
rising_edge (clock)
(clock) THEN
THEN
0111111,
0111111, qa
qa <=
<= rom(CONV_INTEGER(addr_a));
rom(CONV_INTEGER(addr_a));
0011000,
0011000, qb
qb <=<= rom(CONV_INTEGER(addr_b));
rom(CONV_INTEGER(addr_b));
1101101,
1101101,
1111100, END
END IF;IF;
1111100,
1011010,
1011010, END
END PROCESS;
PROCESS;
1110110,
1110110, END
END ARCHITECTURE
ARCHITECTURE logic;logic;
1110111,
1110111,
0011100,
0011100,
1111111,
1111111, Needs 1 constant value for each
1111110,
1111110, ROM address
1011111,
1011111,
1110011,
1110011,
Example shows dual-port access
OTHERS
OTHERS => => 0000000
0000000 May place type & constant
);); declaration in package for re-use
Alternate: Create and use
initialization function routine (see
RAM example)
2012 Altera CorporationConfidential
78
Advanced VHDL Design
Techniques

Coding State Machines

2012 Altera CorporationConfidential


State Machine Coding
Enumerated data type is used to define the different states in the
state machine
Using constants for states may not be recognized as state machine

TYPE
TYPE state_type
state_type IS
IS (idle,
(idle, fill,
fill, heat_w,
heat_w, wash,
wash, drain);
drain);

One or two signals assigned to the name of the state-variable :

SIGNAL
SIGNAL current_state,
current_state, next_state
next_state :: state_type;
state_type;

Use CASE statement to do the next-state logic, instead of IF-THEN


statement
Synthesis tools recognize CASE statements for implementing state
machines
Use CASE or IF-THEN-ELSE for output logic

2012 Altera CorporationConfidential


80
Quartus II Software State Machine Viewer

Use to verify correct coding of state machine

Tools Menu
State Flow Diagram Use Drop-Down to
State Machine Viewer Select State Machine

Highlighting State in State


Transition Table Highlights
Corresponding State in State
Flow Diagram

State Transition/Encoding Table

2012 Altera CorporationConfidential


81
State Declaration
IDLE
Empty = 1 Door_closed = 1
Water = 0
Spin = 0
ENTITY wm IS Heat = 0
Pump = 0
PORT ( DRAIN FILL
clk, reset, door_closed, full : in std_logic; Water = 0 Water = 1
heat_demand, done, empty : in std_logic; Spin = 1
Heat = 0
Spin = 0
Heat = 0
water, spin, heat, pump : out std_logic); Pump = 1 Pump = 0

Full = 1
END ENTITY wm; Heat_demand = 1

WASH HEAT_W
ARCHITECTURE behave OF wm IS Done = 1
Water = 0 Water = 0
TYPE state_type IS Spin = 1
Heat = 0
Spin = 1
Heat = 1
(idle, fill, heat_w, wash, drain); Pump = 0 Pump = 0

SIGNAL current_state, next_state :


Heat_demand = 0
state_type;
BEGIN

2012 Altera CorporationConfidential


82
Next State Logic
IDLE
Empty = 1 Door_closed = 1
Water = 0
Spin = 0
Heat = 0
PROCESS (clk, reset) Pump = 0
DRAIN FILL
BEGIN
Water = 0 Water = 1
IF reset = 1 THEN Spin = 1 Spin = 0
Heat = 0 Heat = 0
current_state <= idle; Pump = 1 Pump = 0

ELSIF risting_edge(clk) THEN Heat_demand = 1


Full = 1

current_state <= next_state;


END IF; Done = 1
WASH HEAT_W

Water = 0 Water = 0
END PROCESS; Spin = 1 Spin = 1
Heat = 0 Heat = 1
Pump = 0 Pump = 0

PROCESS (current_state, door_closed, full,


Heat_demand = 0
heat_demand, done, empty)
BEGIN Sequential state
next_state <= current_state; transitions
CASE current_state IS
WHEN idle =>
IF door_closed = 1 THEN Default next state is
next_state <= fill;
current state
WHEN fill =>
IF full = 1 THEN
next_state <= heat_w;
Combinatorial next
state logic

2012 Altera CorporationConfidential


83
Moore Combinatorial Outputs
IDLE
PROCESS (current_state)
BEGIN Default output Empty = 1
Water = 0
Spin = 0
Door_closed = 1

water <= 0; conditions Heat = 0


Pump = 0

spin <= 0; DRAIN FILL

Water = 0 Water = 1
heat <= 0; Spin = 1 Spin = 0
Heat = 0 Heat = 0
pump <= 0; Pump = 1 Pump = 0
CASE current_state IS Heat_demand = 1
Full = 1

WHEN idle =>


WHEN fill => Done = 1
WASH HEAT_W

water <= 1; Water = 0


Spin = 1
Water = 0
Spin = 1
WHEN heat_w => Heat = 0
Pump = 0
Heat = 1
Pump = 0
spin <= 1;
heat <= 1; Heat_demand = 0

WHEN wash =>


spin <= 1;
WHEN drain => Output logic function of
spin <= 1;
current state only
pump <= 1;
END CASE;
END PROCESS;

2012 Altera CorporationConfidential


84
Mealy Combinatorial Outputs
IDLE
Empty = 1
Door_closed = 1
Water = 0
Spin = 0
PROCESS (current_state, heat_demand) Heat = 0
Pump = 0
BEGIN
DRAIN FILL
water <= 0;
spin <= 0; Water = 0
Spin = 1
Water = 1
Spin = 0
heat <= 0; Heat = 0
Pump = 1
Heat = 0
Pump = 0
pump <= 0; WASH
CASE current_state IS Water = 0
Spin = 1
WHEN idle => Heat = Full = 1
WHEN fill => Heat_demand
Pump = 0
Done = 1
water <= 1;
WHEN wash =>
spin <= 1;
heat <= heat_demand;
WHEN drain Output logic function of
spin <= 1;
current state only and
pump <= 1;
END CASE; input(s)
END PROCESS;

2012 Altera CorporationConfidential


85
State Machine Encoding Styles
Grey-
Binary One-Hot Custom
State Code
Encoding Encoding Encoding
Encoding
Idle 000 000 00001 ?

Fill 001 001 00010 ?


Heat_w 010 011 00100 ?
Wash 011 010 01000 ?

Drain 100 110 10000 ?

Quartus II default encoding styles for Altera devices


One-hot encoding for look-up table (LUT) devices
Architecture features lesser fan-in per cell and an abundance of registers
Binary (minimal bit) or grey-code encoding for product-term devices
Architecture features fewer registers and greater fan-in

2012 Altera CorporationConfidential


86
Quartus II Encoding Style

Options:
Apply Assignment to One-Hot
State Variable Gray
Minimal Bits
Sequential
User-Encoded
Johnson

2012 Altera CorporationConfidential


87
Undefined States

Noise and spurious events in hardware can cause state


machines to enter undefined states
If state machines do not consider undefined states, it can
cause mysterious lock-ups in hardware
Good engineering practice is to consider these states
To account for undefined states
Explicitly code for them (manual)
Use safe synthesis constraint (automatic)

2012 Altera CorporationConfidential


88
Safe Binary State Machine?
TYPE
TYPE state_type
state_type IS IS
(idle,
(idle, fill, heat_w, wash,
fill, heat_w, wash, drain);
drain); IDLE
Empty = 1
SIGNAL
SIGNAL current_state,
current_state, next_state
next_state :: state_type;
state_type; Water = 0
Door_closed =
1
Spin = 0
Heat = 0
PROCESS (current_state, door_closed,
PROCESS (current_state, door_closed, full, full, heat_demand,
heat_demand, done,
done, empty)
empty) Pump = 0
DRAIN FILL
BEGIN
BEGIN Water = 0 Water = 1
next_state
next_state <=
<= current_state;
current_state; Spin = 1 Spin = 0
Heat = 0 Heat = 0
CASE
CASE current_state
current_state is is Pump = 1 Pump = 0
WHEN
WHEN idle
idle =>=> Full = 1
Heat_demand = 1
IF
IF door_closed == 1
door_closed 1 THEN
THEN next_state
next_state <=<= fill;
fill;
END
END IF;IF; WASH HEAT_W
Done = 1
WHEN fill
WHEN fill =>
=> Water = 0 Water = 0
Spin = 1 Spin = 1
IF
IF full
full == 1
1 THEN
THEN next_state
next_state <= <= heat_w;
heat_w; Heat = 0 Heat = 1
END
END IF;IF; Pump = 0 Pump = 0

WHEN
WHEN heat_w
heat_w => =>
Heat_demand = 0
IF
IF heat_demand
heat_demand == 0 0 THEN
THEN next_state
next_state <=<= wash;
wash;
END
END IF;IF;
WHEN
WHEN wash
wash => =>
IF
IF heat_demand == 1
heat_demand 1 THEN
THEN next_state
next_state <=<= heat_w;
heat_w; This code does not consider
ELSIF done = 1 THEN next_state
ELSIF done = 1 THEN next_state <= drain; <= drain; undefined states
END
END IF;IF;
WHEN drain =>
WHEN drain =>
The when others statement
IF
IF empty
empty == 1 1 THEN
THEN next_state
next_state <=<= idle;
idle; only considers other
END
END IF;IF; enumerated states
WHEN
WHEN others
others => =>
next_state
next_state <= <= idle;
idle;
The states 101, 110 &
END CASE;
END CASE; 111 are not considered
END
END PROCESS;
PROCESS;

2012 Altera CorporationConfidential


89
Creating Safe State Machines

WHEN OTHERS clause does not make state machines


safe
Once state machine is recognized, synthesis tool only accounts for explicitly
defined states
Exception: Number of states equals power of 2 AND binary/grey encoding
enabled

Safe state machines created using synthesis constraints


Quartus II software uses
SAFE STATE MACHINE assignment applied project-wide and to individual FSMs
VHDL synthesis attribute
May increase logic usage

2012 Altera CorporationConfidential


90
Registered Outputs

Remove glitches by adding output registers


Adds a stage of latency

Current State

Next State

Outputs
Next
Inputs State Output Output
State
Registers Logic Registers
Logic

2012 Altera CorporationConfidential


91
Registered Outputs w/o Latency
Base outputs on next state vs. current state
Output logic uses next state to determine what the next outputs
will be
On next rising edge, outputs change along with state registers

Current State

Next State

Next
State
Inputs State
Registers
Logic

Next
State Output Outputs
Output Registers
Logic

2012 Altera CorporationConfidential


92
Registered Outputs w/o Latency
IDLE
PROCESS
PROCESS (clk)
(clk) Empty = 1
Water = 0
Door_closed = 1
BEGIN
BEGIN Spin = 0
Heat = 0
IF
IF rising_edge(clk)
rising_edge(clk) THEN THEN Pump = 0
DRAIN FILL
water
water <= <= 0;
0;
Water = 0 Water = 1
spin <= 0;
spin <= 0; Spin = 1 Spin = 0
Heat = 0 Heat = 0
heat
heat <=<= 0;
0; Pump = 1 Pump = 0

pump
pump <= <= 0;
0; Heat_demand = 1
Full = 1

CASE
CASE next_state
next_state IS IS
WHEN
WHEN idle idle =>
=> Done = 1
WASH HEAT_W

WHEN fill
WHEN fill => => Water = 0
Spin = 1
Water = 0
Spin = 1
water
water <= <= 1;
1; Heat = 0
Pump = 0
Heat = 1
Pump = 0
WHEN
WHEN heat_wheat_w => =>
spin
spin <= <= 1;
1; Heat_demand = 0
heat
heat <= <= 1;
1;
WHEN
WHEN wash wash =>=> Base output logic case statement
spin <= 1;
spin <= 1;
WHEN on next state variable (instead of
WHEN drain drain =>=>
spin
spin <= <= 1;
1; current state variable)
pump
pump <= <= 1;
1; Wrap output logic with a clocked
END
END CASE;
CASE; process
END IF;
END IF;
END PROCESS;
END PROCESS;

2012 Altera CorporationConfidential


93
Using Custom Encoding Styles
Remove glitches without
output registers
Outputs
Eliminate combinatorial Custom

Water

Pump
State

Spin
Heat
output logic Encoding

Outputs mimic state bits Idle 0 0 0 0 0000


Use additional state bits for Fill 1 0 0 0 1000
states that do have
Heat_w 0 1 1 0 0110
exclusive outputs
Wash 0 1 0 0 0100

Drain 0 1 0 1 0101

2012 Altera CorporationConfidential


94
Quartus II Custom State Encoding
ENTITY
ENTITY wm
wm ISIS
PORT (
PORT ( IDLE
Empty = 1
clk,
clk, reset,
reset, door_closed,
door_closed, full
full :: in
in std_logic;
std_logic; Water = 0
Door_closed =
1
Spin = 0
heat_demand,
heat_demand, done,
done, empty
empty :: in in std_logic;
std_logic; Heat = 0
Pump = 0
water,
water, spin,
spin, heat,
heat, pump
pump :: out
out std_logic);
std_logic); DRAIN FILL

END
END wm;
wm; Water = 0 Water = 1
Spin = 1 Spin = 0
Heat = 0 Heat = 0
Pump = 1 Pump = 0
ARCHITECTURE
ARCHITECTURE behave
behave OF OF wm wm IS
IS Full = 1
Heat_demand = 1
TYPE
TYPE state_type
state_type IS
IS (idle,
(idle, fill,
fill, heat_w,
heat_w, wash,
wash, drain);
drain);
ATTRIBUTE
ATTRIBUTE syn_encoding
syn_encoding :: STRING;
STRING; WASH HEAT_W
Done = 1
ATTRIBUTE
ATTRIBUTE syn_encoding
syn_encoding OF OF state_type
state_type :: TYPE
TYPE IS
IS Water = 0
Spin = 1
Water = 0
Spin = 1
"0000
"0000 1000
1000 0110
0110 01000100 0101;
0101; Heat = 0
Pump = 0
Heat = 1
Pump = 0
SIGNAL
SIGNAL current_state, next_state : state_type;
current_state, next_state : state_type;
BEGIN
BEGIN Heat_demand = 0

Must also set State Machine Processing assignment to User


Encoded
Output assignments are coded per previous examples (slides 85 or 86)
Synthesis automatically handles reduction of output logic
Some tools use VHDL attributes like enum_encoding OR
syn_enum_encoding to perform custom state encoding

2012 Altera CorporationConfidential


95
Writing Efficient State Machines

Remove counting, timing, arithmetic functions


from state machine & implement externally
Reduces overall logic & improves performance

2012 Altera CorporationConfidential


96
Exercise 3

2012 Altera CorporationConfidential


97
Advanced VHDL Design
Techniques
Improving Logic Utilization & Performance

2012 Altera CorporationConfidential


VHDL Logic Optimization & Performance

Balancing operators
Resource sharing
Logic duplication
Pipelining

2012 Altera CorporationConfidential


99
Operators

Synthesis tools replace operators with pre-


defined (pre-optimized) blocks of logic
Designer should control when & how many
operators
Ex. Dividers
Dividers are large blocks of logic
Every /, mod and rem inserts a divider block and leaves it up to
synthesis tool to optimize
Better resource optimization usually involves cleverly using
multipliers or shift operations to do divide

2012 Altera CorporationConfidential


100
Generating Logic from Operators

Synthesis tools
break down code 1 Comparator
into logic blocks <
They then assemble,
optimize & map to
hardware

IF
IF (sel
(sel << 10)
10) THEN
THEN 2 Adders
yy <=
<= aa ++ b;
b;
ELSE
ELSE
yy <=
<= aa ++ 10;
10; + +
END
END IF;IF;
1 Mulitplexer

2012 Altera CorporationConfidential


101
Balancing Operators
Use parenthesis to define logic groupings
Increases performance
May increase utilization
Balances delay from all inputs to output
Circuit functionality unchanged

Unbalanced Balanced

z <= a * b * c * d z <= (a * b) * (c * d)

a a

X X
b
X b

c X z c
X z

d X
d

2012 Altera CorporationConfidential


102
Balancing Operators: Example

a, b, c, d: 4-bit vectors
Unbalanced Balanced

z <= a * b * c * d z <= (a * b) * (c * d)
a 4x4 a 4x4

X 8x4
X 8x8
b
X 12 x 4 b

c X z c 4x4
X z
16-bit
d 16-bit
X
d
Delay through 3
stages of multiply Delay through 2
stages of multiply

2012 Altera CorporationConfidential


103
Resource Sharing

Reduces number of operators needed


Reduces area
Two types
Sharing operators among mutually exclusive functions
Sharing common subexpressions
Synthesis tools can perform automatic resource sharing
Feature can be enabled or disabled

2012 Altera CorporationConfidential


104
Mutually Exclusive Operators

Up/down counter
process(rst, clk) 2 adders are mutually
variable tmp_q : std_logic_vector(7 DOWNTO 0); exclusive & can be shared
begin
(typically IF-THEN-ELSE
if rst = '0' then
with same operator in both
choices)
tmp_q := (OTHERS => 0);
elsif rising_edge(clk) then
if updn = '1' then clk rst
tmp_q := tmp_q + 1;
else +1

end if;
tmp_q := tmp_q - 1;
+
end if; q
q <= tmp_q; Registers
-1
end process;
+

2012 Altera CorporationConfidential


105
Sharing Mutually Exclusive Operators

process(rst, clk)
variable tmp_q : std_logic_vector(7 DOWNTO 0); Up/down counter
variable dir : integer range -1 to 1; Only one adder required
begin
if rst = '0' then
tmp_q := (OTHERS => 0);
elsif rising_edge(clk) then
if updn = '1' then clk rst
dir := 1;
else
dir := -1;
end if; +1
-1
end if;
tmp_q := tmp_q + dir;
+ Registers
q

q <= tmp_q;
end process;

2012 Altera CorporationConfidential


106
How Many Multipliers?

y <= a * b * c
z <= b * c * d

2012 Altera CorporationConfidential


107
How Many Multipliers? (Answer)

y <= a * b * c
z <= b * c * d
a

X
b
X y
c
4 Multipliers!
X
X z
d

2012 Altera CorporationConfidential


108
How Many Multipliers Again?

y <= a * (b * c)
z <= (b * c) * d

2012 Altera CorporationConfidential


109
How Many Multipliers Again? (Answer)

y <= a * (b * c)
z <= (b * c) * d
b 3 Multipliers!
X
c
X y This is called sharing
a common subexpressions
Some synthesis tools do this
automatically, but some
dont!
Parentheses guide synthesis
tools
X z
If (b*c) is used repeatedly,
d assign to temporary signal

2012 Altera CorporationConfidential


110
Pipelining

Purposefully inserting register(s) into middle of


combinatorial data (critical) path
Increases clocking speed
Adds levels of latency
More clock cycles needed to obtain output
Some tools perform automatic pipelining
Same advantages/disadvantages as automatic fan-out

2012 Altera CorporationConfidential


111
Adding Single Pipeline Stage

25 MHz System
Counter, Decode
Decode
State Value
Value Logic
Logic
Machine xx

40 ns

50 MHz System
Counter, Decode
Decode
State Value
Value Logic
Logic
Machine x-1
x-1

20 ns 20 ns

2012 Altera CorporationConfidential


112
Adding Single Pipeline Stage In VHDL
Non-Pipelined Pipelined
mult_ : PROCESS (clk, clr) mult_pipe : PROCESS (clk, clr)
BEGIN BEGIN
IF (clr = 0) THEN IF (clr = 0) THEN
atemp <= (OTHERS => 0); atemp <= (OTHERS => 0);
btemp <= (OTHERS => 0);
btemp <= (OTHERS => 0);
ctemp <= (OTHERS => 0);
ctemp <= (OTHERS => 0);
dtemp <= (OTHERS => 0);
dtemp <= (OTHERS => 0);
int1 <= (OTHERS => 0);
result <= (OTHERS => 0);
int2 <= (OTHERS => 0);
ELSIF rising_edge(clk) result <= (OTHERS => 0);
atemp <= a; ELSIF rising_edge(clk)
btemp <= b; atemp <= a;
ctemp <= c; btemp <= b;
dtemp <= d; ctemp <= c;
result <= (atemp * btemp) dtemp <= d;
* (ctemp * dtemp); int1 <= atemp * btemp;
END IF; int2 <= ctemp * dtemp;
END PROCESS; result <= int1 * int2;
END IF;
END PROCESS;

2012 Altera CorporationConfidential


113
Pipelined 4-input Multiplier

a
X
b
X z
c
X
d

2012 Altera CorporationConfidential


114
Exercise 4

2012 Altera CorporationConfidential


115
Advanced VHDL Design
Techniques

Introduction to Testbenches

2012 Altera CorporationConfidential


Introduction to Testbenches

Purpose of testbench
Three classes of traditional testbenches
General testbench methods
Self verification methods
Arrays for stimulus & results
TEXTIO for stimulus & results

2012 Altera CorporationConfidential


117
Purpose of Testbench

Generate stimulus to test design for normal


transactions, corner cases and error conditions
Direct tests
Random tests
Automatically verify design to spec and log all
errors
Regression tests
Log transactions in a readable format for easy
debugging

2012 Altera CorporationConfidential


118
Three Classes of Traditional Testbenches

I. Test bench applies stimulus to target code


and outputs are manually reviewed
II. Test bench applies stimulus to target code
and verifies outputs functionally
Requires static timing analysis

III. Test bench applies stimulus to target code


and verifies outputs with timing
Does not require full static timing analysis
Code and test bench data more complex
Not covered

2012 Altera CorporationConfidential


119
Advantages/Disadvantages

Testbench Type Advantages Disadvantages Recommendation

Simple to write Requires manual verification Great for verifying simple


Takes longer for others (not code
Class I original designer) to verify Not intended for re-use
Easy for others to miss errors

Easy to perform Takes longer to write Better for more


verification once More difficult to debug initially complicated designs,
complete designs with complicated
Class II Set and forget it stimulus/outputs and
higher-level designs
Promotes re-usability
Most in-depth Takes longest to write Might be overkill for many
Guarantees design Most difficult to debug FPGA designs
Class III operation, if successful Physical changes (i.e. target Required for non-Altera
(subject to model device, process) requires ASIC designs
accuracy) changing testbench

2012 Altera CorporationConfidential


120
General Testbench Methods
Create test harness code to instantiate the device under test (DUT)
or target code
Create stimulus signals to connect to DUT
mycode_tb.vhd
clk_assignment mycode.vhd
clk
datagen_process in1
Single Process
to Control each in2 out1
Signal in3
out2
reset_assignment rst

2012 Altera CorporationConfidential


121
Test Vector Generation

Develop sequence of fixed input values


Test vector development from bottom up
Write basic tasks
Write more complex tasks based on basic tasks
Perform tests

Example memory testing


Basic tasks: readmem, writemem
2nd level tasks: initmem, copymem, comparemem
Generation of tests based on tasks

2012 Altera CorporationConfidential


122
Concurrent Statements
Signals with regular or limited transitions can be created with concurrent
statements
These statements can begin a testbench and reside outside any processes

ARCHITECTURE logic OF test_b IS

-- Use clkperiod constant to create 50 MHz clock


CONSTANT clkperiod : TIME := 20 ns;

-- clk initialized to 0
SIGNAL clk : std_logic := 0;

SIGNAL reset : std_logic;


CLK
BEGIN

--clock must be initialized when declared to use RESET


-- this notation
clk <= NOT clk AFTER clkperiod/2; ns 0 5 10 15 20 25 30 35 40 45 50 55
reset <= 1, 0 AFTER 20 ns, 1 AFTER 40 ns;

END ARCHITECTURE logic;

2012 Altera CorporationConfidential


123
Sequential Statements
clkgen: PROCESS -- Another clock generation example
CONSTANT clkperiod : TIME := 20 ns; More complex
BEGIN combinations can
clk <= 0; -- Initialize clock
WAIT FOR 500 ns; -- Delay clock for 500 ns be created using
LOOP -- Infinite loop to create free-running clock
clk <= 1;
sequential
WAIT FOR clkperiod/2; statements (i.e.
clk <= 0;
WAIT FOR clkperiod/2;
LOOP, WAIT, IF-
END LOOP; THEN, CASE)
END PROCESS clkgen;
Statements
buscount: PROCESS (clk) -- Generate counting pattern dependent on clock
BEGIN edges
IF rising_edge (clk) THEN
inbus <= count; Multiple processes
count <= count + 1; & loops executing
END IF; at once
END PROCESS buscount;

2012 Altera CorporationConfidential


124
Sequential Statements (cont.)
bus_gray:
bus_gray: PROCESS
PROCESS (clk)
(clk)
CONSTANT
CONSTANT buswidth:
buswidth: INTEGER
INTEGER :=:= 16;
16;
BEGIN
BEGIN
inbus
inbus <=
<= (OTHERS
(OTHERS => => 0);
0);
FOR
FOR nn IN
IN 00 TO
TO 131072
131072 LOOP
LOOP
inbus
inbus <=
<= TO_UNSIGNED(n,
TO_UNSIGNED(n, buswidth)
buswidth) XOR
XOR
shift_right(TO_UNSIGNED(n,
shift_right(TO_UNSIGNED(n, buswidth)),
buswidth)), 1);
1);
WAIT
WAIT UNTIL
UNTIL rising_edge(clk);
rising_edge(clk);
END
END LOOP;
LOOP;
END
END PROCESS;
PROCESS;

Example shows more complex stimulus generation


Process uses sensitivity list and WAITs (not allowed in synthesis)

(uses IEEE.numeric_std.all)

2012 Altera CorporationConfidential


125
Sample VHDL Class I Testbench
LIBRARY ieee; -- Process to generate stimulus; Note operations
USE ieee.std_logic_1164.all; -- take place on inactive clock edge
USE ieee.std_logic_unsigned.all; PROCESS
CONSTANT period : TIME := 40 ns;
ENTITY addtest IS -- Top-level entity with no ports VARIABLE ina, inb : std_logic_vector(3 DOWNTO 0);
END ENTITY addtest; BEGIN
WAIT UNTIL falling_edge (clk);
ARCHITECTURE stimulus OF addtest IS ina := (OTHERS => 0);
inb := (OTHERS => 0);
-- Declare design being tested
COMPONENT adder stim_loop: LOOP
PORT ( -- Apply generated stimulus to inputs
clk : IN std_logic; a <= ina;
a, b: IN std_logic_vector(3 DOWNTO 0); b <= inb;
sum : OUT std_logic_vector(3 DOWNTO 0) WAIT FOR period;
);
END COMPONENT; -- Exit loop once simulation reaches 1 us
EXIT stim_loop WHEN NOW > 1 us ;
-- Signals to assign values and observe results
SIGNAL a, b, sum: std_logic_vector(3 DOWNTO 0); -- Use equations below to generate new stimulus
SIGNAL clk : std_logic := 0; -- values
WAIT UNTIL falling_edge (clk);
-- Constants for timing values ina := ina + 2;
CONSTANT clkperiod : TIME := 20 ns; inb := inb + 3;
END LOOP stim_loop;
BEGIN
-- Final wait to keep process from repeating
-- Create clock to synchronize actions WAIT;
clk <= NOT clk AFTER clkperiod/2; END PROCESS;
END ARCHITECTURE stimulus;
-- Instantiate design being tested
add1: adder PORT MAP (
clk => clk, a => a, b => b, sum => sum);

2012 Altera CorporationConfidential


126
Example Results

2012 Altera CorporationConfidential


127
Class II (& III) Methods
Add a compare process so that DUT outputs can
be monitored
Allows testbench to do self-verification
mycode_tb.vhd

clk_assignment mycode.vhd
clk
wavegen_process compare_process
in1
in2 out1
in3
out2
reset_assignment clk

2012 Altera CorporationConfidential


128
Self Verification Methods

Use compare_process or equivalent to check


results generated by design against expected
results
Single simulation can use one or multiple
testbench files
Single testbench file containing all stimulus and all expected
results
Multiple testbench files based on stimulus, expected results or
functionality (e.g. data generator, control stimulus)
Many times signaling is too complicated to model
without using vectors saved in time-slices

2012 Altera CorporationConfidential


129
Simple Self Verifying Test Benches
clk <= NOT clk AFTER clkperiod/2;

add1 : adder PORT MAP (


clk => clk, a => a, a => b, sum => sum);

stim: PROCESS
VARIABLE error : BOOLEAN; Code repeated for each test case
BEGIN Result checked
WAIT UNTIL falling_edge(clk);
a <= (OTHERS => 0);
b <= (OTHERS => 0);
WAIT FOR 40 ns;
IF (sum /= 0) THEN
Simple self verifying test bench
error := TRUE; Each sub-block within process
END IF;
assigns values to a,b and waits
WAIT UNTIL falling_edge(clk); to compare sum to its
a <= 0010;
b <= 0011;
predetermined result
WAIT FOR 40 ns; Code not very efficient
IF (sum /= 5) THEN
error := TRUE;
Each test case may require a
END IF; lot of repeated code
-- repeat above varying values of a and b
Improve this code by introducing
a procedure
WAIT;
END PROCESS stim;

2012 Altera CorporationConfidential


130
Simplifying Test Bench with Procedure
PROCEDURE test (
SIGNAL clk : IN std_logic;
inval_a, inval_b, result : IN INTEGER RANGE 0 TO 15;
Procedure used to simplify test bench
SIGNAL in_a, in_b : OUT std_logic_vector(3 DOWNTO 0); Each procedure call passes in
SIGNAL sum_out : IN std_logic_vector(3 DOWNTO 0); clock
SIGNAL error : INOUT BOOLEAN) IS
BEGIN 3 integers representing input
WAIT UNTIL falling_edge(clk); stimulus and expected result
in_a <= conv_std_logic_vector(inval_a,4);
in_b <= conv_std_logic_vector(inval_b,4);
ports connecting to adder
WAIT FOR 40 ns; error flag
IF sum_out /= result THEN
error <= TRUE;
ELSE Procedure improves efficiency and
error <= FALSE;
END IF; readability of testbench
END PROCEDURE;
Advantage: Easier to write
BEGIN architecture begin Disadvantages
clk <= NOT clk AFTER clkperiod/2; Each procedure call (like last
add1 : adder PORT MAP (clk => clk, a => a, a => b, sum => sum);
example) assigns values to a, b then
waits to compare sum to its
PROCESS
BEGIN predetermined result
test(clk, 0, 0, 0, a, b, sum, error); Very difficult to do for complicated
test(clk, 2, 3, 5, a, b, sum, error);
test(clk, 4, 6, 10, a, b, sum, error); signaling
test(clk, 6, 9, 15, a, b, sum, error);
test(clk, 8, 12, 4, a, b, sum, error);
WAIT ;
END PROCESS;
END ARCHITECTURE;

2012 Altera CorporationConfidential


131
Time-Slice Vectors

Allows you to apply input stimulus and check


results at specific simulation times
Two methods for storage
Internal arrays
Faster simulation times
Harder to write, creates very large VHDL file
External files
Slower simulation times
Easier to write
Use TEXTIO or STD_LOGIC_TEXTIO package
TEXTIO for reading/writing built-in data types
STD_LOGIC_TEXTIO for reading/writing standard logic

2012 Altera CorporationConfidential


132
Useful VHDL Constructs for Testbenches

Record data types


Assert & report statements
Type conversion to STRING
TEXTIO/File operations

2012 Altera CorporationConfidential


133
Record Data Types
Declares a new data type with multiple elements
Allows grouping of related data types/objects
Each element may be of any previously defined data type, including
arrays, enumerated types and even other records
Similar to a struct in C
Using in a testbench
Set each record to the values for one time slice
Cycle through records to apply stimulus and check results
Examples
Store input and output values in different elements
Store different inputs in different elements

TYPE test_record_type IS RECORD


element names element data types
a, b : std_logic_vector(3 DOWNTO 0);
sum : std_logic_vector(3 DOWNTO 0);
END RECORD;

2012 Altera CorporationConfidential


134
Accessing Values in a Record

VARIABLE
VARIABLE vector
vector :: test_record_type;
test_record_type;

Use selected name to access single record


element vector.a
vector.a :=
:= 0010;
0010;
vector.b
vector.b :=
:= 0011;
0011;
vector.sum
vector.sum :=:= 0101;
0101;

Use aggregate to access entire record

vector
vector :=
:= (a
(a =>
=> 0010,
0010, b
b =>
=> 0011,
0011, sum
sum =>
=> 0101);
0101);

2012 Altera CorporationConfidential


135
Using Internal Arrays for Stimulus & Results

Create array to store values (e.g. array of records)


--
-- Create
Create unconstrained
unconstrained array
array so
so the
the array
array depth
depth can
can be
be set
set when
when object
object is
is
--
-- declared of the array type
declared of the array type
TYPE
TYPE test_array_type
test_array_type IS
IS ARRAY
ARRAY (POSITIVE
(POSITIVE RANGE
RANGE <>)
<>) OF
OF test_record_type;
test_record_type;

Assign values to array


--
-- Constant
Constant array
array with
with 66 records
records
CONSTANT
CONSTANT test_patterns
test_patterns :: test_array_type
test_array_type :=
:= ((
(a
(a =>=> 0000",
0000", bb =>
=> 0000,
0000, sum
sum =>
=> 0000),
0000),
(a
(a =>=> 0010",
0010", bb =>
=> 0011,
0011, sum
sum =>
=> 0101),
0101),
(a => 0100", b => 0110, sum => 1010),
(a => 0100", b => 0110, sum => 1010),
(a
(a =>=> 0110",
0110", bb =>
=> 1001,
1001, sum
sum =>
=> 1111),
1111),
(a
(a =>=> 1000",
1000", bb =>
=> 1100,
1100, sum
sum =>
=> 0100),
0100),
(a
(a =>=> 1010",
1010", bb =>
=> 1111,
1111, sum
sum =>
=> 1001)
1001)
););

* POSITIVE is INTEGER data type with range of 1 to highest integer value

2012 Altera CorporationConfidential


136
Assert Statements
Checks condition expression and executes assertion if condition
evaluates to false
Use as concurrent or sequential statement
Syntax
ASSERT
ASSERT <condition_expression>
<condition_expression>
REPORT
REPORT <text_string>
<text_string>
SEVERITY
SEVERITY <expression>;
<expression>;

Report (optional)
Displays text in simulator window
Must be type string
Enclose character strings in
Other data types must be converted (discussed later)
Severity (optional)
Expression choices: NOTE, WARNING, ERROR, FAILURE
ERROR is the default
Results of severity depend on simulator
e.g. By default, ModelSim tool ends simulation on failure only

2012 Altera CorporationConfidential


137
Report Statements

Displays message without ASSERT statement


No expression to check
Sequential statement only

Test must be type string


Enclose character strings in
Other data types must be converted (next slide)

Syntax
REPORT
REPORT <text_string>
<text_string>
SEVERITY
SEVERITY <expression>;
<expression>;

Severity (optional)
Same options as ASSERT except NOTE is the default

2012 Altera CorporationConfidential


138
Type Conversions to STRING
Use to display formatted messages

<data_type>IMAGE(obj)
Type attribute that converts obj of type <data_type> to its string
equivalent with no leading or trailing whitespace
Examples
INTEGERIMAGE(integer_variable)
TIMEIMAGE(time_variable)
std_logicIMAGE(1_bit_std_logic_variable)
Conversion utilities
Cannot use IMAGE for vectors
<data_type> must be a scalar type or subtype
Simple web search can provide most (if not all) required conversion
utilities

2012 Altera CorporationConfidential


139
Sample Testbench Using Internal Array
-- entity and some of architecture declaration not shown test: PROCESS
VARIABLE vector : test_record_type;
SIGNAL testclk : std_logic := '0'; VARIABLE found_error : BOOLEAN := FALSE;
SIGNAL a, b : std_logic_vector (3 DOWNTO 0); BEGIN
SIGNAL sum : std_logic_vector (3 DOWNTO 0); -- Loop through all the values in test_patterns
CONSTANT clk_period : time := 20 ns; FOR i IN test_patternsRANGE LOOP
vector := test_patterns(i);
TYPE test_record_type IS RECORD
a, b : std_logic_vector(3 DOWNTO 0); -- apply the stimulus on a falling edge clock
sum : std_logic_vector(3 DOWNTO 0); WAIT UNTIL falling_edge(testclk);
END RECORD; a <= vector.a;
b <= vector.b;
TYPE test_array_type IS ARRAY(POSITIVE RANGE <>) OF
test_record_type; -- check result on next falling edge of clock
WAIT UNTIL falling_edge(testclk);
CONSTANT test_patterns : test_array_type := ( IF (sum /= vector.sum) THEN
(a => 0000", b => 0000, sum => XXXX), REPORT TIMEIMAGE(NOW) & : Calc= " &
(a => 0010", b => 0011, sum => 0000), slv_to_string(sum) & ", Exp= " & slv_to_string(vector.sum);
(a => 0100", b => 0110, sum => 0101), found_error := TRUE;
(a => 0110", b => 1001, sum => 1010), END IF;
(a => 1000", b => 1100, sum => 1111),
(a => 1000", b => 1100, sum => 0100) END LOOP;
);
ASSERT NOT found_error
BEGIN -- beginning of architecture body REPORT "---VECTORS FAILED---"
SEVERITY FAILURE;
-- instantiate unit under test (adder) ASSERT found_error
add1 : adder PORT MAP REPORT "---VECTORS PASSED---"
( clk => testclk, a => a, b => b, sum => sum); SEVERITY FAILURE;

-- free-running clock process -- END PROCESS;


testclk <= NOT testclk AFTER clk_period/2; END ARCHITECTURE;

2012 Altera CorporationConfidential


140
Example Results

Testbench fails (expected results actual


results)
ModelSim Transcript Window
**
** Note:
Note: 72
72 ns
ns :: Calc
Calc == 0100,
0100, Exp=
Exp= 1001
1001
Time:
Time: 72
72 ns
ns Iteration:
Iteration: 00 Instance:
Instance: /record_add_tb
/record_add_tb
**
** Failure:
Failure: ---VECTORS
---VECTORS FAILED---
FAILED---
Time:
Time: 288
288 ns
ns Iteration:
Iteration: 00 Process:
Process: /record_add_tb/test
/record_add_tb/test File:
File:

Break
Break inin Process
Process test
test at
at record_tb.vhd
record_tb.vhd line
line 56
56

Testbench passes
ModelSim Transcript Window
**
** Failure:
Failure: ---VECTORS
---VECTORS PASSED---
PASSED---
Time:
Time: 288
288 ns
ns Iteration:
Iteration: 00 Process:
Process: /record_add_tb/test
/record_add_tb/test File:
File:

Break
Break inin Process
Process test
test at
at record_tb.vhd
record_tb.vhd line
line 59
59

2012 Altera CorporationConfidential


141
TEXTIO/FILE Operations
FILE declaration
Creates file handle to represent file
Opens file in READ_MODE, WRITE_MODE or APPEND_MODE
LINE declaration
Creates line variable for reading and writing to files
READLINE(<file_handle>,<line_variable>)
Reads a line from a file and stores information in a variable of type LINE
READ(<line_variable>,<data_object>)
Reads text from line variable and writes to data object depending on size/type of data objec
Use STD_LOGIC_TEXTIO package to read directly into std_logic data objects
Only built-in data types supported by TEXTIO package READ (BIT, BOOLEAN, STRING, TIME)
WRITE(<line_variable>,<data_object>)
Writes data object to a variable of type LINE as text
Use STD_LOGIC_TEXTIO package to write directly from std_logic data objects
Only built-in data types supported by TEXTIO package WRITE (BIT, BOOLEAN, STRING, TIME)
WRITELINE(<file_handle>,<line_variable>)
Writes information from variable of type LINE to file

2012 Altera CorporationConfidential


142
Sample Testbench Using External File
-- Declare packages to enable file operations
LIBRARY ieee;
USE STD.TEXTIO.ALL;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_textio.ALL;

ENTITY file_tb IS
END ENTITY file_tb;

ARCHITECTURE stimulus OF file_tb IS

COMPONENT adder
PORT (clk : IN std_logic;
a, b: IN std_logic_vector(3 DOWNTO 0);
sum: OUT std_logic_vector(3 DOWNTO 0));
END COMPONENT;

-- create file handles to access text files, one for reading vectors and
-- another to write output messages
FILE vectorfile: TEXT OPEN READ_MODE IS vectors.txt;
FILE results: TEXT OPEN WRITE_MODE IS results.txt;

SIGNAL a, b, sum : std_logic_vector (3 DOWNTO 0);


SIGNAL testclk : std_logic := 0;
CONSTANT clk_period : TIME := 20 ns;

BEGIN -- beginning of architecture body

-- instantiate unit under test (adder)


add1 : adder PORT MAP
( clk => testclk, a => a, b => b, sum => sum);

-- free-running clock process --


testclk <= NOT testclk AFTER clk_period/2;

2012 Altera CorporationConfidential


143
Sample Testbench Using External File (cont.)
test: PROCESS END LOOP;
VARIABLE found_error : BOOLEAN := FALSE;
VARIABLE a_var, b_var, sum_var : std_logic_vector (3 DOWNTO 0); ASSERT NOT found_error
VARIABLE vectorline, resultsline : LINE; REPORT "---VECTORS FAILED---"
BEGIN SEVERITY FAILURE;
WHILE NOT ENDFILE (vectorfile) LOOP ASSERT found_error
-- read file into line and line into variables REPORT "---VECTORS PASSED---"
READLINE (vectorfile, vectorline); SEVERITY FAILURE;
READ (vectorline, a_var);
READ (vectorline, b_var); END PROCESS test;
READ (vectorline, sum_var); END ARCHITECTURE stimulus;

-- apply the stimulus on a falling edge clock


WAIT UNTIL falling_edge(testclk);
a <= a_var;
b <= b_var;

-- check result on next falling clock edge


WAIT UNTIL falling_edge(testclk);
IF (sum /= sum_var) THEN
-- write current simulation time to line variable
WRITE (resultsline, NOW);
-- write string
WRITE (resultsline, string'(" : Calc= "));
-- write result value
WRITE (resultsline, sum);
-- write string
WRITE (resultsline, string'(", Exp= "));
-- write expected value
WRITE (resultsline, sum_var);
-- write entire line to text file
WRITELINE (results, resultsline);
found_error := TRUE;
END IF;

2012 Altera CorporationConfidential


144
Example Files
0000
0000 0000
0000 0000
0000
vectors.txt 0010
0010
0100
0100
0011
0011
0110
0110
0101
0101
1010
1010
No inherent formatting excepting 0110
0110 1001
1001 1111
1111
white-space skipping 1000
1000 1100
1100 0100
0100
1010
1010 1111
1111 1001
1001
Options
Use separate files for stimulus and expected results
Design custom tasks to extend capabilities (e.g. support comments)

results.txt (failure example)

240
240 ns
ns Calc=
Calc= 0100,
0100, Exp=
Exp= 1001
1001

2012 Altera CorporationConfidential


145
Example Test Plans

Develop high-level behavioral (i.e. non-


synthesizable) model of design
Create stimulus/test vectors to simulate model
Generate expected results from behavioral model
simulation
Replace behavioral blocks with RTL model
blocks
Simulate each RTL block with other behavioral blocks to ensure
functionality is the same

2012 Altera CorporationConfidential


146
Exercise 5

2012 Altera CorporationConfidential


147
Advanced VHDL Design
Techniques

Parameterized Code

2012 Altera CorporationConfidential


Parameterized Code

Logic blocks that are made scalable for reuse


Code is written for flexibility
Different configurations of same model
4 constructs
Pre-defined attributes
Generics
For generate
If generate

2012 Altera CorporationConfidential


149
Pre-Defined Attributes
Return information regarding associated object
Object changes will automatically be reflected in returned
values
Uses
Improving readability of code
Creating parameterized models
Improve flexibility of code, especially using loops
Limit hard-coding logic resources
Examples
Array attributes
Signal attributes (not discussed)
e.g. EVENT, STABLE

2012 Altera CorporationConfidential


150
Pre-Defined Array Attributes
a : IN STD_LOGIC_VECTOR(7 DOWNTO 0)
aHIGH = 7
Upper bound of array index
aLOW = 0 - These array attributes are
Lower bound of array index
aRIGHT = 0 synthesizable
Right-most bound of array index
aLEFT = 7
Left-most bound of array index
aRANGE = 7 DOWNTO 0
Range declared for object, either TO or DOWNTO
aREVERSE = 0 TO 7
Reverse of the range declared for object
aLENGTH = 8
Number of values in range index
aASCENDING = FALSE
Returns TRUE if array range uses TO and FALSE if array range uses DOWNTO

2012 Altera CorporationConfidential


151
Generics (Review)
Used to pass information to an entity instance
Timing values (for simulation)
Scalable code

ENTITY
ENTITY reg_bank
reg_bank IS IS
GENERIC
GENERIC ((
tplh
tplh ,, tphl
tphl :: time
time :=
:= 55 ns;
ns;
tphz,
tphz, tplz
tplz :: time
time :=
:= 33 ns;
ns;
size
size :: integer
integer :=:= 1;
1;
);
);
PORT
PORT ((
clk
clk :: IN
IN std_logic;
std_logic;
dd :: IN
IN std_logic_vector
std_logic_vector (size (size -- 11 DOWNTO
DOWNTO 0);
0);
qq :: OUT
OUT std_logic_vector
std_logic_vector (size (size -- 11 DOWNTO
DOWNTO 0)
0)
);
);
END
END ENTITY
ENTITY shift_reg;
shift_reg;

2012 Altera CorporationConfidential


152
Parameterized Counter
ENTITY counter IS
GENERIC (width : INTEGER);
PORT (
clk, clr, sload, cnt_en : IN std_logic;
data : IN std_logic_vector (width - 1 DOWNTO 0);
q : OUT std_logic_vector (width - 1 DOWNTO 0));
END ENTITY counter;
ARCHITECTURE logic OF counter IS
BEGIN
PROCESS
BEGIN Generic
Generic
PROCESS (clk, clr) width
width used
used to
to
VARIABLE cnt : std_logic_vector (width - 1 DOWNTO 0; scale
scale counter
counter
IF clr = 1 THEN
cnt := 0;
ELSIF rising_edge(clk) THEN
IF sload = 1' THEN
cnt := data;
ELSIF cnt_en = '1' THEN
cnt := cnt + 1;
END IF;
END IF;
q <= cnt;
END PROCESS;
END ARCHITECTURE logic;

2012 Altera CorporationConfidential


153
Using A Parameterized Function
Must map to generics & port
Generic & port resolution done at compile time

u1
u1 :: counter
counter
GENERIC
GENERIC MAP
MAP (width
(width =>
=> 16)
16)
PORT
PORT MAP
MAP (clk
(clk =>
=> tclk,
tclk, clr
clr =>
=> tclr,
tclr, sload
sload =>
=> tsload,
tsload,
cnt_en
cnt_en =>=> tcnt_en,
tcnt_en, data
data =>
=> tdata,
tdata, qq =>
=> tq);
tq);

top_counter
16

counter
clk sload
tclk tsload
clr data
tclr data
cnt_en q
cnt_en tq

2012 Altera CorporationConfidential


154
Complete Code
LIBRARY
LIBRARY IEEE;
IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_1164.all;
USE
USE IEEE.std_logic_arith.all;
IEEE.std_logic_arith.all;

ENTITY
ENTITY top_counter
top_counter IS IS
PORT
PORT ((
tclk,
tclk, tclr,
tclr, tsload,
tsload, tcnt_en
tcnt_en :: IN
IN std_logic;
std_logic;
tdata
tdata :: IN
IN std_logic_vector
std_logic_vector (15 (15 DOWNTO
DOWNTO 0);0);
tq : OUT std_logic_vector (15
tq : OUT std_logic_vector (15 DOWNTO 0)DOWNTO 0)
););
END
END ENTITY
ENTITY top_counter;
top_counter;
ARCHITECTURE
ARCHITECTURE logic logic OF
OF top_counter
top_counter ISIS

COMPONENT
COMPONENT pcounter
pcounter
GENERIC
GENERIC (width
(width :: INTEGER);
INTEGER);
PORT
PORT ((
clk,
clk, clr,
clr, sload,
sload, cnt_en
cnt_en :: IN
IN std_logic;
std_logic;
data
data :: IN
IN std_logic_vector
std_logic_vector (width
(width -- 11 DOWNTO
DOWNTO 0);
0);
qq :: OUT std_logic_vector (width - 1
OUT std_logic_vector (width - 1 DOWNTO 0)DOWNTO 0)
););
END
END COMPONENT;
COMPONENT;

BEGIN
BEGIN

u1
u1 :: pcounter
pcounter
GENERIC
GENERIC MAP
MAP (width
(width =>
=> 16)
16)
PORT
PORT MAP (clk => tclk, clr =>
MAP (clk => tclk, clr => tclr,
tclr, sload
sload =>
=> tsload,
tsload,
cnt_en
cnt_en =>=> tcnt_en,
tcnt_en, data
data =>
=> tdata,
tdata, qq =>
=> tq);
tq);

END
END ARCHITECTURE
ARCHITECTURE logic;
logic;

2012 Altera CorporationConfidential


155
Parameterized with Missing Ports

What if top level does not require a synchronous load &


data controls?

u1
u1 :: counter
counter
GENERIC
GENERIC MAP
MAP (width
(width =>
=> 16)
16)
PORT
PORT MAP
MAP (clk
(clk =>
=> tclk,
tclk, clr
clr =>
=> tclr,
tclr, ,,
cnt_en
cnt_en =>=> tcnt_en,
tcnt_en, ,, qq =>
=> tq);
tq);

Error Messages Result Because


sload & data Are Not Assigned
to Signals

2012 Altera CorporationConfidential


156
Parameterized with Defaults

Initialize ports & generics in entity declaration


Ports & generics become optional

ENTITY counter IS
GENERIC (width : INTEGER := 8); Initialized
Initialized to
to 88
PORT (
clk, clr, cnt_en : IN std_logic;
sload : IN std_logic := 0;
data : IN std_logic_vector (width - 1 DOWNTO 0) := (OTHERS => 0); Initialized
Initialized to
to Zeros
Zeros
q : OUT std_logic_vector (width - 1 DOWNTO 0)
);
END ENTITY counter;
ARCHITECTURE logic OF counter IS
BEGIN
VARIABLE cnt : INTEGER RANGE 0 TO (2**width)-1;

2012 Altera CorporationConfidential


157
Using Default Parameters

u1
u1 :: counter
counter
GENERIC
GENERIC MAP
MAP (width
(width =>
=> 16)
16)
PORT
PORT MAP
MAP (clk
(clk =>
=> tclk,
tclk, clr
clr =>
=> tclr,
tclr,
cnt_en
cnt_en =>=> tcnt_en,
tcnt_en, qq =>
=> tq);
tq);

top_counter
16 No error messages (warnings
counter
possible) since sload & data are
clk
8
sload
initialized
tclk 0 May map to OPEN for clarity
clr data
tclr 0 Setting width to 16 overrides
cnt_en cnt_en q
tq default setting of 8

2012 Altera CorporationConfidential


158
Generate Statements
Used to create structural blocks
Resolved at compile time
Reduce amount of code
Can be nested
For-generate
Creates zero or a set number of duplicates of a structure
No need to individual instantiate each duplicate
If-generate
Conditionally selects whether structure is made or not
Case-generate
Conditionally selects which structure from multiple choices is made

2012 Altera CorporationConfidential


159
For-Generate

Syntax
label
label :: FOR
FOR <identifier>
<identifier> IN
IN <range>
<range> GENERATE
GENERATE
--concurrent
--concurrent statements
statements
END
END GENERATE
GENERATE label;label;

Sets the number of structures created


Similar to FOR loop
Can only use concurrent statements
Label is required

2012 Altera CorporationConfidential


160
For Generate Example
ENTITY ram16x8 IS
PORT (
tclk, twe : IN std_logic;
tdata : IN std_logic_vector (7 DOWNTO 0); ENTITY
ENTITY ramram IS
IS
taddress : IN std_logic_vector (3 DOWNTO 0); GENERIC
GENERIC (width_ad :: INTEGER);
(width_ad INTEGER);
tq : OUT std_logic_vector (7 DOWNTO 0) PORT
PORT ((
); clk,
clk, we,
we, data
data :: IN
IN std_logic;
std_logic;
END ENTITY ram16x8; address
address : IN std_logic_vector(width_ad-1 DOWNTO
: IN std_logic_vector(width_ad-1 DOWNTO 0);
0);
qq :: OUT
OUT std_logic
std_logic
ARCHITECTURE logic OF ram16x8 IS ););
END
END ENTITY
ENTITY ram; ram;
COMPONENT ram IS Signal
Signal Bit
Bit RAM
RAM
GENERIC (width_ad : INTEGER);
PORT (
clk, we, data : IN std_logic;
address : IN std_logic_vector(width_ad-1 DOWNTO 0);
q : OUT std_logic
);
END COMPONENT;

BEGIN
RAM_GEN : FOR i IN 7 DOWNTO 0 GENERATE
u : ram
GENERIC MAP (width_ad => taddress'high+1)
PORT MAP (clk => tclk, we => twe, data => tdata(i), 88 RAMs
RAMs Generated
Generated
address => taddress, q => tq(i));
END GENERATE;

END ARCHITECTURE logic;

2012 Altera CorporationConfidential


161
8 - 16x1 RAM Functions
tdata0
Addr
we
X1 RAM q0

clk

tdata1

X1 RAM q1

tdata2

X1 RAM q2

tdata3

X1 RAM q3

tdata4

X1 RAM q4

tdata5

X1 RAM q5

tdata6

X1 RAM q6

tdata7

X1 RAM q7

2012 Altera CorporationConfidential


162
For Generate Example
ENTITY ram16x8 IS
PORT (
tclk, twe : IN std_logic; ENTITY
ENTITY ramram IS
IS
tdata : IN std_logic_vector (7 DOWNTO 0); GENERIC
GENERIC (width_ad :: INTEGER);
(width_ad INTEGER);
taddress : IN std_logic_vector (3 DOWNTO 0); PORT
PORT ((
tq : OUT std_logic_vector (7 DOWNTO 0) clk,
clk, we,
we, data
data :: IN
IN std_logic;
std_logic;
); address
address : IN std_logic_vector(width_ad-1 DOWNTO
: IN std_logic_vector(width_ad-1 DOWNTO 0);
0);
END ENTITY ram16x8; qq :: OUT
OUT std_logic
std_logic
););
ARCHITECTURE logic OF ram16x8 IS END
END ENTITY
ENTITY ram; ram;
Signal
Signal Bit
Bit RAM
RAM
COMPONENT ram IS
GENERIC (width_ad : INTEGER);
PORT (
clk, we, data : IN std_logic;
address : IN std_logic_vector(width_ad-1 DOWNTO 0);
q : OUT std_logic);
END COMPONENT;

BEGIN
RAM_GEN : FOR i IN tdataRANGE GENERATE
u : ram
GENERIC MAP (width_ad => taddressHIGH+1)
PORT MAP (clk => tclk, we => twe, data => tdata(i), RANGE
RANGE attribute
attribute used
used
address => taddress, q => tq(i));
END GENERATE; for
for increased
increased flexibility
flexibility
END ARCHITECTURE logic;

2012 Altera CorporationConfidential


163
If Generate

Syntax
label
label :: IF
IF <expression>
<expression> GENERATE
GENERATE
//// generated
generated structure
structure
ELSE
ELSE GENERATE
GENERATE
//// alternate
alternate generate
generate structure
structure
END
END GENERATE
GENERATE label;label;

Condition controls whether a structure is created


Can only use concurrent statements
Label is required
Same syntax as procedural block if-else
else and elseif generates are supported in 2008 VHDL

2012 Altera CorporationConfidential


164
If Generate Example 1
ENTITY counter IS
GENERIC (width : INTEGER;
rise_or_fall : INTEGER);
PORT ( u1
u1 :: pcounter3
pcounter3
clk, clr, sload, cnt_en : IN std_logic; GENERIC
GENERIC MAP
MAP (width
(width =>=> 16,
16, rise_or_fall
rise_or_fall =>=> 0)
0)
data : IN std_logic_vector (width - 1 DOWNTO 0); PORT
PORT MAP
MAP (clk
(clk =>
=> tclk,
tclk, clr
clr =>
=> tclr,
tclr,
q : OUT std_logic_vector (width - 1 DOWNTO 0)
sload
sload => => tsload,
tsload, data
data =>=> tdata,
tdata,
);
END ENTITY counter; cnt_en => tcnt_en, q
cnt_en => tcnt_en, q => tq);=> tq);
ARCHITECTURE logic OF counter IS
SIGNAL clk_buf : std_logic; END
END ARCHITECTURE
ARCHITECTURE logic;
logic;
BEGIN
clock : IF (rise_or_fall > 0) GENERATE
clk_buf <= clk;
END GENERATE;
selects
selects rising
rising or
or falling
falling
not_clock : IF (rise_or_fall <= 0) GENERATE
clk_buf <= NOT clk;
edge
edge clock
clock behavior
behavior
END GENERATE;
PROCESS (clk_buf, clr)
VARIABLE cnt : INTEGER RANGE 0 TO (2**width)-1; One code slice can implement
BEGIN
IF clr = 1 THEN both a rising & falling edge
cnt := 0;
ELSIF rising_edge(clk_buf) THEN counter
IF sload = 1' THEN
cnt := conv_integer(data);
Different (& better) than using
ELSIF cnt_en = '1' THEN
cnt := cnt + 1;
IF-THEN-ELSE
END IF; No clock mux is created;
END IF;
q <= conv_std_logic_vector(cnt,width); either clock inversion is
END PROCESS;
END ARCHITECTURE logic; implemented or it is not

2012 Altera CorporationConfidential


165
If Generate Example 2
ENTITY counter IS
GENERIC (width : INTEGER;
rise_or_fall : INTEGER);
PORT ( u1
u1 :: pcounter3
pcounter3
clk, clr, sload, cnt_en : IN std_logic; GENERIC
GENERIC MAP
MAP (width
(width =>=> 16,
16, rise_or_fall
rise_or_fall =>=> 0)
0)
data : IN std_logic_vector (width - 1 DOWNTO 0); PORT
PORT MAP
MAP (clk
(clk =>
=> tclk,
tclk, clr
clr =>
=> tclr,
tclr,
q : OUT std_logic_vector (width - 1 DOWNTO 0)
sload
sload => => tsload,
tsload, data
data =>=> tdata,
tdata,
);
END ENTITY counter; cnt_en => tcnt_en, q
cnt_en => tcnt_en, q => tq);=> tq);
ARCHITECTURE logic OF counter IS
SIGNAL clk_buf : std_logic; END
END ARCHITECTURE
ARCHITECTURE logic;
logic;
BEGIN
clock : IF (rise_or_fall > 0) GENERATE
clk_buf <= clk;
ELSE GENERATE
selects
selects rising
rising or
or falling
falling
clk_buf <= NOT clk;
END GENERATE clock;
edge
edge clock
clock behavior
behavior

PROCESS (clk_buf, clr)


VARIABLE cnt : INTEGER RANGE 0 TO (2**width)-1; One code slice can implement
BEGIN
IF clr = 1 THEN
both a rising & falling edge
cnt := 0;
ELSIF rising_edge(clk_buf) THEN
counter
IF sload = 1' THEN Different (& better) than using
cnt := conv_integer(data);
ELSIF cnt_en = '1' THEN IF-THEN-ELSE
cnt := cnt + 1;
END IF; No clock mux is created;
END IF;
q <= conv_std_logic_vector(cnt,width);
either clock inversion is
END PROCESS;
END ARCHITECTURE logic;
implemented or it is not

2012 Altera CorporationConfidential


166
If Generate Example 2

From LPM_ADD_SUB Function


L1:
L1: ifif LPM_REPRESENTATION
LPM_REPRESENTATION == "UNSIGNED"
"UNSIGNED" generate
generate

U:
U: LPM_ADD_SUB_UNSIGNED
LPM_ADD_SUB_UNSIGNED
generic
generic map
map (LPM_WIDTH
(LPM_WIDTH =>
=> LPM_WIDTH,
LPM_WIDTH, LPM_DIRECTION
LPM_DIRECTION =>=> LPM_DIRECTION,
LPM_DIRECTION,
LPM_PIPELINE
LPM_PIPELINE =>
=> LPM_PIPELINE,
LPM_PIPELINE, LPM_TYPE
LPM_TYPE =>
=> LPM_TYPE,
LPM_TYPE,
LPM_HINT => LPM_HINT)
LPM_HINT => LPM_HINT)
port
port map
map (DATAA
(DATAA =>=> DATAA,
DATAA, DATAB
DATAB =>
=> DATAB,
DATAB, ACLR
ACLR =>
=> ACLR,
ACLR, CLOCK
CLOCK =>
=> CLOCK,
CLOCK,
CIN
CIN => CIN, ADD_SUB => ADD_SUB, RESULT =>
=> CIN, ADD_SUB => ADD_SUB, RESULT => RESULT,
RESULT, COUT
COUT =>
=> COUT,
COUT,
OVERFLOW => OVERFLOW, CLKEN => CLKEN);
OVERFLOW => OVERFLOW, CLKEN => CLKEN);
end
end generate;
generate;

L2: LPM_REPRESENTATION == "SIGNED"


L2: ifif LPM_REPRESENTATION "SIGNED" generate
generate

V:
V: LPM_ADD_SUB_SIGNED
LPM_ADD_SUB_SIGNED
generic
generic map
map (LPM_WIDTH
(LPM_WIDTH =>
=> LPM_WIDTH,
LPM_WIDTH, LPM_DIRECTION
LPM_DIRECTION =>=> LPM_DIRECTION,
LPM_DIRECTION,
LPM_PIPELINE
LPM_PIPELINE =>
=> LPM_PIPELINE,
LPM_PIPELINE, LPM_TYPE
LPM_TYPE =>
=> LPM_TYPE,
LPM_TYPE,
LPM_HINT => LPM_HINT)
LPM_HINT => LPM_HINT)
port
port map
map (DATAA
(DATAA =>=> DATAA,
DATAA, DATAB
DATAB =>
=> DATAB,
DATAB, ACLR
ACLR =>
=> ACLR,
ACLR, CLOCK
CLOCK =>
=> CLOCK,
CLOCK,
CIN
CIN => CIN, ADD_SUB => ADD_SUB, RESULT =>
=> CIN, ADD_SUB => ADD_SUB, RESULT => RESULT,
RESULT, COUT
COUT =>
=> COUT,
COUT,
OVERFLOW => OVERFLOW, CLKEN => CLKEN);
OVERFLOW => OVERFLOW, CLKEN => CLKEN);
end
end generate;
generate;

end
end LPM_SYN;
LPM_SYN;

2012 Altera CorporationConfidential


167
Case Generate Statements

Syntax
label:
label: case <expression> GENERATE
case <expression> GENERATE
when
when <condition1>
<condition1> =>
=> //// generated
generated structure
structure
when
when <condition2>
<condition2> =>
=> //// generated
generated structure
structure
when
when <conditionN>
<conditionN> =>
=> //// generated
generated structure
structure
END
END GENERATE
GENERATE label;
label;

Condition controls which structure is created


Same syntax as procedural block case
Each structure may contain only one item
Surround multiple statements with begin/end

Supported in VHDL 2008

2012 Altera CorporationConfidential


168
Case Generate Example
ENTITY data_converstion IS
GENERIC (DATA_PATH: INTEGER);
PORT (
clk, reset, clk_en: IN std_logic;
data : IN std_logic_vector (DATA_PATH-1 DOWNTO 0); Case statement performs test to
result : OUT std_logic_vector (DATA_PATH-1 DOWNTO 0)
);
see which of the byte conversion
END ENTITY data_converstion ; blocks get instantiated in the
ARCHITECTURE logic OF data_converstion IS
BEGIN design
// Data conversion of bytes received serially
convert: CASE(DATA_PATH) GENERATE
Notice all 3 possible instances
WHEN 8 =>
BEGIN
named u1
byte_convert: component u1 Legal as only one will exist in
PORT MAP (datain=>data, dataout=>result, clk=>clk,
clken=>clken, clr=>reset); compiled design
END;
WHEN 16 =>
BEGIN
hword_convert: component u1
PORT MAP (.);
END;
WHEN 32 =>
BEGIN
word_convert: component u1
PORT MAP (.);
END;
END GENERATE convert;
END ARCHITECTURE logic;

2012 Altera CorporationConfidential


169
Nested Generate Statements
ENTITY shift_reg IS
GENERIC (length : INTEGER := 8);
PORT (input, clk : IN std_logic; Code generates
output : OUT std_logic);
END shift_reg; a shift register
ARCHITECTURE logic OF shift_reg IS length
COMPONENT dff
PORT (d, clk : IN std_logic;
input output
q : OUT std_logic);
END COMPONENT;
SIGNAL int : std_logic_vector(length-1 DOWNTO 1);
BEGIN
for_gen : FOR i IN (length-1) DOWNTO 0 GENERATE
case_gen: CASE i GENERATE
when 0 => generates
generates first
first register
register
dffn : dff PORT MAP (q => int(i+1), clk => clk, d => input);
when (length -1) =>
dffn : dff PORT MAP (q => output, clk => clk, d => int(i)); generates
generates last
last register
register
when others=>
dffn : dff PORT MAP (q => int(i+1), clk => clk, d => int(i));
END GENERATE case_gen; generates
generates intermediate
intermediate register(s)
register(s)
END GENERATE for_gen;
END logic;

2012 Altera CorporationConfidential


170
Exercise 6

2012 Altera CorporationConfidential


171
Advanced VHDL Design
Techniques

Summary

2012 Altera CorporationConfidential


Summary

Writing synthesizable VHDL


Inferring common logic functions
Coding state machines
Improving logic utilization & performance
Introduction to testbenches
Writing parameterized code

2012 Altera CorporationConfidential


173
Learn More Through Technical Training

Instructor-Led Online
Training Training

With Altera's instructor-led training With Altera's online training courses,


courses, you can: you can:
Listen to a lecture from an Altera technical training Take a course at any time that is convenient for you
engineer (instructor)
Take a course from the comfort of your home or office
Complete hands-on exercises with guidance from an (no need to travel as with instructor-led courses)
Altera instructor Each online course will take approximate one to three
Ask questions and receive real-time answers from an hours to complete.
Altera instructor
Each instructor-led class is one or two days in length
(8 working hours per day).

http://www.altera.com/training
View training class schedule and register for a class
2012 Altera CorporationConfidential
174
Altera Technical Support

Reference Quartus II software on-line help


Altera forum: http://www.alteraforum.com/
Discuss issues, ask questions, and share solutions with other Altera users
Consult Altera applications (factory applications engineers)
MySupport: http://www.altera.com/mysupport
Hotline: (800) 800-EPLD (7:00 a.m. - 5:00 p.m. PST)
Field applications engineers: contact your local Altera sales office
World-wide web: http://www.altera.com
Use solutions to search for answers to technical problems
View design examples

2012 Altera CorporationConfidential


175
Advanced VHDL Design
Techniques

Appendix

2012 Altera CorporationConfidential


VHDL Basics Review Examples
Design units
ENTITY
ARCHITECTURE,
CONFIGURATION
PACKAGE (LIBRARY)
Behavioral vs. structural modeling
Implicit vs. explicit processes
i.e. Concurrent signal assignment vs. PROCESS statement
Signal delay
AFTER clause
Inertial vs. transport delays
Delta delays
Sequential process statements
IF-THEN-ELSE, CASE, LOOP & WAIT statements
Signals vs. variables
Building hierarchy
Component instantiation

2012 Altera CorporationConfidential


177
VHDL Design Units

ENTITY
Used to define external view of a model. i.e. symbol
ARCHITECTURE
Used to define the function of the model. i.e. schematic
CONFIGURATION
Used to associate an architecture with an entity
PACKAGE
Collection of information that can be referenced by VHDL models.
i.e. LIBRARY
Consists of two parts: PACKAGE declaration and PACKAGE
body

2012 Altera CorporationConfidential


178
Using VHDL Design Units
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY cmpl_sig IS
PORT ( a, b, sel : IN std_logic;
x, y : OUT std_logic);
END ENTITY cmpl_sig;

ARCHITECTURE logic OF cmpl_sig IS


BEGIN
x <= (a AND NOT sel) OR (b AND sel);
y <= a WHEN sel='0' ELSE b;

END ARCHITECTURE logic;

CONFIGURATION cmpl_sig_conf OF cmpl_sig IS


FOR logic
END FOR;
END CONFIGURATION cmpl_sig_conf;

2012 Altera CorporationConfidential


179
Modeling Logic

Behavioral modeling
A component is described by its input/output response

Structural modeling
A component is described by interconnecting lower-level
components/ primitives

2012 Altera CorporationConfidential


180
Behavioral Modeling

Only the functionality of the circuit, no structure


No specific hardware intent

output1, .., outputn


input1, .., inputn
IF shift_left THEN
FOR j IN high DOWNTO low LOOP
shft(j) := shft(j-1);
END LOOP;
output1 <= shft AFTER 5ns;

Left bit shifter

2012 Altera CorporationConfidential


181
Structural Modeling

Functionality and structure of the circuit


Call out the specific hardware

Higher-level component
input1 output1

Lower-level
Component1

Lower-level
Component0

inputn outputn

2012 Altera CorporationConfidential


182
Processes
Implied Process
Concurrent signal assignment statements
Component instantiations
Sensitive to all inputs (right-hand side of expression)
Explicit process
Process statements
Contains sequential statements only
Specified sensitivity

Explicit Process
Implied Processes proc1: PROCESS(a, b)
c <= a and b; BEGIN
y <= c; c <= a AND b;
END PROCESS proc1;

2012 Altera CorporationConfidential


183
Signal Assignment - Delay
Signal assignments can delay updating their target by
using a delay construct
Signal assignments can incur delay
Two types of delays
Inertial delay (default)
Schedules output to be changed after delay passes unless input
changes again
Input must remain stable while delay expires (i.e. switching circuit)
a <= b AFTER 10 ns;
identical statements
a <= INERTIAL b AFTER 10 ns;
Transport delay
Always schedules output to be changed after delay passes
Any transition on input transmitted to output (i.e. transmission line)
c <= TRANSPORT d AFTER 10 ns

2012 Altera CorporationConfidential


184
Evaluating Model Behavior*
Initialize signals
Simulation cycle
Wall clock time
Delta Initialization
PROCESS execution phase
Execute Phase
Signal update phase all
When does a delta cycle end? processes
After all processes end execution
End of the process (with sensitivity list)
Process encounters WAIT statement
After which, any signals written to
Advance time
during delta cycle are updated
When does a simulation cycle Simulation
end? Execute Delta Cycle
When updating signals to new values at sensitive
the end of delta cycle does not cause a processes
brand new delta cycle (i.e. new
processes arent triggered by changing
signals)
Update signals
Signals get updated at the end
of the delta cycle (delay)
*Note: Both VHDL simulation and synthesis tools evaluate models the same way.

2012 Altera CorporationConfidential


185
Sequential Statements

Indicate behavior and express order


Must be used inside explicit processes

Sequential statements
IF-THEN statement
CASE statement
Looping statements
WAIT statements

Note: Simple signal assignment is considered both a sequential statement and a concurrent statement

2012 Altera CorporationConfidential


186
IF-THEN Statements
Format: Example:
IF <condition1> THEN PROCESS (sela, selb, a, b, c)
{sequence of statement(s)} BEGIN
ELSIF <condition2> THEN IF sela=1 THEN
{sequence of statement(s)} q <= a;

ELSIF selb=1 THEN
q <= b;
ELSE
ELSE
{sequence of statement(s)}
q <= c;
END IF; END IF;
END PROCESS;
c
b q
a
selb
sela
2012 Altera CorporationConfidential
CASE Statement
Format: Example:
CASE {expression} IS PROCESS (sel, a, b, c, d)
WHEN <condition1> => BEGIN
{sequence of statements} CASE sel IS
WHEN 00 =>
WHEN <condition2> =>
q <= a;
{sequence of statements} WHEN 01 =>
q <= b;
WHEN OTHERS => -- (optional) WHEN 10 =>
{sequence of statements} q <= c;
WHEN OTHERS =>
END CASE;
q <= d;
END CASE;
a END PROCESS;
b q
c
d
sel
2
2012 Altera CorporationConfidential
Sequential LOOPS
Infinite Loop
Infinite loop [Loop_label]: LOOP
Loops forever --Sequential statement
While loop EXIT loop_label ;
Loops until conditional test is false END LOOP;
For loop
Loops for certain number of While Loop
Iterations WHILE <condition> LOOP
Note: Iteration identifier not
required to be previously declared
--Sequential statements
END LOOP;
Additional loop commands
(each requires loop label) For Loop
NEXT / NEXT WHEN FOR <identifier> IN <range> LOOP
Skips to next loop iteration --Sequential statements
EXIT / EXIT WHEN END LOOP;
Cancels loop execution

2012 Altera CorporationConfidential


189
WAIT Statements
Pauses execution of process until WAIT statement is
satisfied
Types
WAIT ON <signal>
Pauses until signal event occurs
WAIT ON a, b;
WAIT UNTIL <boolean_expression>
Pauses until boolean expression is true
WAIT UNTIL (int < 100);
WAIT FOR <time_expression>
Pauses until time specified by expression has elapsed
WAIT FOR 20 ns;
Combined WAIT
WAIT UNTIL (a = 1) FOR 5 us;

* Wait statement usage limited in synthesis

2012 Altera CorporationConfidential


190
Signals vs. Variables

Signals (<=) Variables (:=)

Assign assignee <= assignment assignee := assignment

Utility Represent circuit interconnect Represent local storage

Architecture scope
Local Scope
Scope (communicate between
(inside processes)
processes within architecture)

Updated at end of
current delta cycle
Behavior (new value not immediately
Updated immediately
available)

2012 Altera CorporationConfidential


191
Component Declaration and Instantiation
Component declaration - used to declare the port types
and the data types of the ports for a lower-level design
COMPONENT <lower-level_design_name>
PORT (
<port_name> : <port_type> <data_type>;
...
<Port_name> : <port_type> <data_type>
);
END COMPONENT;

Component instantiation - used to map the ports of a


lower-level design to that of the current-level design
<Instance_name> : <lower-level_design_name>
PORT MAP(<lower-level_port_name> => <current_level_port_name>,
, <lower-level_port_name> => <current_level_port_name>);

2012 Altera CorporationConfidential


192
Component Declaration and Instantiation (1)
LIBRARY IEEE;
USE IEEE. STD_LOGIC_1164.ALL; Upper-level of hierarchy design must have
a component declaration for a lower-
ENTITY tolleab IS level design before it can be instantiated
PORT (
tclk, tcross, tnickel, tdime, tquarter : IN STD_LOGIC;
tgreen, tred : OUT STD_LOGIC
);
END ENTITY tolleab; Component declaration
ARCHITECTURE tolleab_arch OF tolleab IS
COMPONENT tollv
PORT( Lower-level port
clk, cross, nickel, dime, quarter : IN STD_LOGIC;
green, red : OUT STD_LOGIC;
);
END COMPONENT;
Dime => tdime
BEGIN
U1 : tollv PORT MAP (clk => tclk, cross => tcross,
nickel => tnickel, dime => tdime, quarter => tquarter, Current-level port
green => tgreen, red => tred);
END ARCHITECTURE tolleab_arch; Named Association
Instance label/name Component instantiation

2012 Altera CorporationConfidential


193

You might also like