You are on page 1of 115

PROGRAMMABLE LOGIC DESIGN WITH VHDL Amlan Chakrabarti A.K.C.S.I.T.

, Calcutta University
acakcs@caluniv.ac.in

Introduction
VHDL is used to: document circuits simulate circuits synthesize design descriptions Synthesis is the reduction of a design description to a lowerlevel representation (such as a netlist or a set of equations). The lecture will at times draw upon the concepts of VHDL as a simulation language

Why Use VHDL?


Quick Time-to-Market Allows designers to quickly develop designs requiring tens of thousands of logic gates Provides powerful high-level constructs for describing complex logic Supports modular design methodology and multiple levels of hierarchy One language for design and simulation Allows creation of device-independent designs that are portable to multiple vendors. Good for ASIC Migration Allows user to pick any synthesis tool, vendor, or device

VHDL Design Descriptions


VHDL design descriptions consist of an ENTITY declaration and an ARCHITECTURE body The ENTITY declaration describes the design I/O

The ARCHITECTURE body describes the content or function of the design


Every architecture needs an entity so it is common to refer to them together as an ENTITY/ARCHITECTURE PAIR

Example Entity/Architecture Pair: A 2-Input And Function


ENTITY and2 IS PORT ( a,b : IN std_logic; f: OUT std_logic); END and2; ARCHITECTURE behavioral OF and2 IS BEGIN f <= a AND b; END behavioral;

The Entity
A BLACK BOX The ENTITY describes the periphery of the black box (i.e., the design I/O)
BLACK_BOX

rst
d[7:0] clk

q[7:0] co

Example Entity declaration


ENTITY black_box IS PORT ( clk, rst: IN std_logic; d: IN std_logic_vector(7 DOWNTO 0); q: OUT std_logic_vector(7 DOWNTO 0); co: OUT std_logic); END black_box; BLACK_BOX

What does all this mean?

rst d[7:0] clk

q[7:0]

co

The Entity Declaration


ENTITY entity_name IS -- optional generics PORT ( name : mode type ; ... ) ; END entity_name;

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

Ports
The Entity (BLACK BOX) has PORTS
PORTS are the points of communication PORTS are usually the device pins PORTS have an associated name, mode, and type

Port Modes
A ports MODE indicates the direction that data is transferred:
Entity

IN OUT INOUT

Data goes into the entity only Data goes out of the entity only (and is not used internally) Data is bi-directional (goes into and out of the entity)

BUFFER Data that goes out of the entity and is also fed-back internally

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

IEEE TYPES (contd.)


INTEGER useful as index holders for loops, constants, generics, or high-level modeling BOOLEAN can take values TRUE or FALSE ENUMERATED has user defined set of possible values, e.g., TYPE traffic_light IS (green, yellow, red);

IEEE 1164
A package created to solve the limitations of the BIT type Nine values instead of just two ('0' and '1') Allows increased flexibility in VHDL coding, synthesis, and simulation STD_LOGIC and STD_LOGIC_VECTOR are used instead of BIT and BIT_VECTOR when a multi-valued logic system is required STD_LOGIC and STD_LOGIC _VECTOR must be used when tri-state logic (Z) is required To be able to use this new type, you need to add 2 lines to your code: LIBRARY ieee; USE ieee.std_logic_1164.ALL;

1164 Types
std_logic and std_logic_vector are the industry standard logic type for digital design Values for Simulation & Synthesis 0 -- Forcing 0 1 -- Forcing 1 Z -- High Impedance L -- Weak 0 H -- Weak 1 - -- Dont care Values for Simulation only (std_ulogic): U -- Uninitialized X -- Forcing Unknown W -- Weak Unknown

Entity Declaration Example


LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY black_box IS PORT ( clk, rst: IN std_logic; d: IN std_logic_vector(7 DOWNTO 0); q: OUT std_logic_vector(7 DOWNTO 0); co: OUT std_logic); END black_box; BLACK_BOX MODE TYPE rst d[7:0] clk q[7:0]

co

Exercise #1: The Entity - A Walk through


Write an entity declaration for the following:

Port D is a 12-bit bus, input only Port OE and CLK are each input bits Port AD is a 12-bit, three-state bi-directional bus Port A is a 12-bit bus, output only Port INT is a three-state output Port AS is an output also used internally
my_design d[11:0] oe clk

ad[11:0]
a[11:0] int as

Exercise #1: Solution


LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY my_design IS PORT ( d: IN std_logic_vector(11 DOWNTO 0); oe, clk: IN std_logic; ad: INOUT std_logic_vector(11 DOWNTO 0); a: OUT std_logic_vector(11 DOWNTO 0); int: OUT std_logic; my_design as: BUFFER std_logic); END my_design; ad[11:0] d[11:0] -- In this presentation, VHDL keywords a[11:0] oe -- are highlighted in bold, CAPITALS; int clk as -- however, VHDL is not case sensitive: -- clock, Clock, CLOCK all refer to the -- same signal, -- means a comment

The Architecture
Architectures describe what is in the black box (i.e., the structure or behavior of entities) Descriptions can be either a combination of Structural descriptions Instantiations (placements of logic-much like in a schematic-and their connections) of building blocks referred to as components Behavioral/Dataflow descriptions Algorithmic (or high-level) descriptions:
IF a = b THEN state <= state5;

Boolean equations (also referred to as dataflow):


x <= a OR (b AND c);

The Architecture Declaration


ARCHITECTURE arch_name OF entity_name IS -- optional signal declarations, etc. BEGIN --VHDL statements END arch_name;

arch_name is an arbitrary name optional signal declarations are used for signals local to the architecture body (that is, not the entitys I/O). entity_name is the entity name statements describe the function or contents of the entity

Architecture Body Styles : Behavioral


ENTITY compare IS PORT ( a, b: IN std_logic_vector(0 TO 3); equals: OUT std_logic); END compare; ARCHITECTURE behavior OF compare IS BEGIN comp: PROCESS (a,b) BEGIN IF a = b THEN equals <= '1' ; ELSE equals <= '0' ; END IF ; END PROCESS comp; END behavior;

Architecture Body Styles : Dataflow


ENTITY compare IS PORT ( a, b: IN std_logic_vector(0 TO 3); equals: OUT std_logic); END compare; ARCHITECTURE dataflow OF compare IS BEGIN equals <= '1' WHEN a = b ELSE '0' ; END dataflow;

Architecture Body Styles : Structural


ENTITY compare IS PORT ( a, b: IN std_logic_vector(0 TO 3); equals: OUT std_logic); END compare; USE WORK.gatespkg.ALL ; ARCHITECTURE structure OF compare IS SIGNAL x : std_logic_vector (0 to 3) ; BEGIN u0: xnor2 PORT MAP (a(0),b(0),x(0)) ; u1: xnor2 PORT MAP (a(1),b(1),x(1)) ; u2: xnor2 PORT MAP (a(2),b(2),x(2)) ; u3: xnor2 PORT MAP (a(3),b(3),x(3)) ; u4: and4 PORT MAP (x(0),x(1),x(2),x(3),equals) ; END structure;

Mixing Architecture Styles


The various styles may be mixed in one architecture.
ENTITY logic IS PORT ( a,b,c: IN std_logic; f: OUT std_logic); END logic; LOGIC

a b

d f

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

g1

Comparing Architecture Styles


These examples synthesize to equivalent circuits In more elaborate designs, some descriptions may yield more efficient circuits sloppy code = inefficient results Use styles that make your designs easier to describe and maintain Behavioral/Dataflow exploit module generation (described later) Structural descriptions may make the design less portable (may rely on a library of vendor-specific components)

A Simple Counter
LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE WORK.std_arith.ALL; clk ENTITY count8 IS PORT ( clk: IN std_logic; count: BUFFER std_logic_vector(7 DOWNTO 0)); END count8 ; ARCHITECTURE arch_count8 OF count8 IS BEGIN upcount: PROCESS (clk) BEGIN IF clkEVENT and clk=1 THEN count <= count + 1; END IF; END PROCESS upcount; END arch_count8;
count

VHDL Statements
There are two types of statements, Concurrent and Sequential
Concurrent Statements (means in parallel) Concurrent statements are executed concurrently (at the same time)

The order of concurrent statements is not important Most of the examples we have seen so far have been concurrent statements: Boolean Equations WHEN-ELSE WITH-SELECT-WHEN

VHDL Statements (cont.)


Sequential Statements (means in series) Sometimes we need to model complex functions. In that case, we can use an algorithm or model to describe the function. This is done with Sequential Statements

With Sequential statements, the ORDER of the statements is important (example later)

Therefore, we use a process to mark the beginning and end of a block of sequential statements
Each completed process is considered to be one big concurrent statement (there can be many processes inside one architecture)

What is a VHDL Process ?


Processes are either awake or asleep (active or inactive)
A process normally has a sensitivity list When a signal in that sensitivity list changes value, the process wakes up and all of the sequential statements are executed For example, a process with a clock signal in its sensitivity list will become active on changes of the clock signal At the end of the process, all outputs are assigned and the process goes back to sleep until the next time a signal changes in the sensitivity list

The Process (contd.)


label: PROCESS (sensitivity list) -- variable declarations BEGIN -- sequential statements END PROCESS label ; The process label and variable declarations are optional The process executes when one of the signals in the sensitivity list has an event

Combinational Logic
Can be described with concurrent statements boolean equations when-else with-select-when component instantiatons Can be described with sequential statements if-then-else case-when

Combinational Logic w/ Boolean Equations


Boolean Equations can be used in both concurrent and sequential signal assignment statements. A 4-1 multiplexer is shown below
s

x <= (a AND NOT(s(1)) AND NOT(s(0))) OR (b AND NOT(s(1)) AND s(0)) OR (c AND s(1) AND NOT(s(0))) OR (d AND s(1) AND s(0)) ;

a b c d

mux

Selective Signal Assignment: with-select-when


Assignment based on a selection signal WHEN clauses must be mutually exclusive Use a WHEN OTHERS when all conditions are not specified Only one reference to the signal, only one assignment operator (<=)

WITH selection_signal SELECT signal_name <= value_1 WHEN value_1 of selection_signal, value_2 WHEN value_2 of selection_signal, ... value_n WHEN value_n of selection_signal, value_x WHEN OTHERS;

Combinational Logic w/ Selective Signal Assignment


The same 4-1 multiplexer is shown below with s select x <= a when 00 , b when 01 , c when 10 , d when others ;
s
2

a b c d

mux

More on with-select-when
You can use a range of values with int_value select x <= a when 0 to 3, b when 4 | 6 | 8 , c when 10 , d when others ;

Conditional Signal Assignment: when-else


Signal is assigned a value based on conditions Any simple expression can be a condition Priority goes in order of appearance Only one reference to the signal, only one assignment operator (<=) Use a final ELSE to avoid latches
signal_name <= value_1 value_2 ... value_n value_x WHEN condition1 ELSE WHEN condition2 ELSE WHEN condition N ELSE ;

Combinational Logic w/ Conditional Signal Assignment


The same 4-1 multiplexer is shown below x <= a when (s = 00) else b when (s = 01) else c when (s = 10) else d;
s
2

a b c d

mux

Combinational Logic w/ Conditional Signal Assignment


The when conditions do not have to be mutually exclusive (as in with-select-when) A priority encoder is shown below j <= w when (a = 1) else x when (b = 1) else y when (c = 1) else z when (d = 1) else 000 ;

Combinatorial Logic w/ Sequential Statements


Grouped together with Processes Processes are concurrent with one another and with concurrent statements Order of sequential statements does make a difference in synthesis

Sequential Statements: if-then-else


Used to select a set of statements to be executed Selection based on a boolean evaluation of a condition or set of conditions Absence of ELSE results in implicit memory IF condition(s) THEN do something; ELSIF condition_2 THEN -- optional do something different; ELSE -- optional do something completely different; END IF ;

if-then-else
4-1 mux shown below mux4_1: process (a, b, c, d, s) begin if s = 00 then x <= a ; elsif s = 01 then x <= b ; elsif s = 10 then x <= c ; else x <= d ; end if; end process mux4_1 ;

s
2

a b c d

mux

Sequential Statements: Case-When


CASE selection_signal IS WHEN value_1_of_selection_signal => (do something) -- set of statements 1 WHEN value_2_of_selection_signal => (do something) -- set of statements 2 ... WHEN value_N_of_selection_signal => (do something) -- set of statements N WHEN OTHERS => (do something) -- default action END CASE ;

The CASE Statement: 4-1 Mux


ARCHITECTURE archdesign OF design IS SIGNAL s: std_logic_vector(0 TO 1); BEGIN mux4_1: PROCESS (a,b,c,d,s) BEGIN CASE s IS WHEN "00" => x <= a; WHEN "01" => x <= b; WHEN "10 => x <= c; WHEN OTHERS => x <= d; END CASE; END PROCESS mux4_1; END archdesign;

s
2

a b c d

mux

Signal Assignment in Processes


Which Circuit is Correct?
ARCHITECTURE arch_reg OF reg IS SIGNAL b: std_logic reg2: PROCESS BEGIN WAIT UNTIL clock = '1' ; -- implied sensitivity list
b <= a; c <= b; -- after the rising clock edge, a goes to b -- after the rising clock edge, b goes to c

END PROCESS reg2; END arch_reg a a c b c

clock
clock

Signal Assignment in Processes


Inside processes, signals are not updated immediately. Instead, they are scheduled to be updated The signals are not actually updated until the END PROCESS statement is reached

Therefore, on the previous slide, two registers will be synthesized (c <= b will be the old b)
In some cases, the use of a concurrent statement outside the process will fix the problem, but this is not always possible So how else can we fix this problem ?

Variables
When a concurrent signal assignment outside the process cannot be used, the previous problem can be avoided using a variable Variables are like signals, BUT they can only be used inside a PROCESS. They cannot be used to communicate information between processes Variables can be of any valid VHDL data type The value assigned to a variable is available immediately Assignment of variables is done using a colon (:), like this:
c := a AND b;

Using Variables vs. Signals


Solution using a variable within a process:
-- assume a and c are signals defined elsewhere ARCHITECTURE arch_reg OF reg IS PROCESS VARIABLE b: std_logic ; BEGIN WAIT UNTIL clock = '1' ; b := a ; -- this is immediate c <= b ; -- this is scheduled END PROCESS ; END arch_reg;

Native Operators
Logical - defined for type bit, bit_vector, boolean* AND, NAND OR, NOR XOR, XNOR NOT Relational - defined for types bit, bit_vector, integer* = (equal to) /= (not equal to) < (less than) <= (less than or equal to) > (greater than) >= (greater than or equal to) * overloaded for std_logic, std_logic_vector

Native Operators (contd.)


Unary Arithmetic - defined for type integer* - (arithmetic negate) Arithmetic - defined for type integer* + (addition), * (multiplication) - (subtraction) Concatenation - defined for strings & Note, a STRING is any sequence of characters, therefore a std_logic_vector is an example of a STRING * overloaded for std_logic, std_logic_vector

Overloaded Operators
In VHDL, the scope of all of the previous operators can be extended (or overloaded) to accept any type supported by the language, e.g.,
-----

assume a declaration of a 16-bit vector as SIGNAL pc IS std_logic_vector(15 DOWNTO 0); then a valid signal assignment is pc <= pc + 3; assuming the '+' operator has been overloaded to accept std_logic_vector and integer operands

The std_logic_1164 package defines overloaded logical operators (AND, OR, NOT, etc.,) for the std_logic and std_logic_vector types In this training, you will learn to use overloaded operators, but not to define them

Legal VHDL Identifiers


Letters, digits, and underscores only (first character must be a letter) The last character cannot be an underscore Two underscores in succession are not allowed Using reserved words is not allowed (the VHDL editor will highlight reserved words for this reason) Examples Legal tx_clk, Three_State_Enable, sel7D, HIT_1124 Not Legal _tx_clk, 8B10B, large#num, case, clk_

Exercise #2: Architecture Declaration of a Comparator


The entity declaration is as follows:
a(3:0) LIBRARY ieee; USE ieee.std_logic_1164.ALL; b(3:0) ENTITY compare IS PORT ( a, b: IN std_logic_vector(3 DOWNTO 0); aeqb: OUT std_logic); END compare; aeqb

Write an architecture that causes aeqb to be asserted when a is equal to b Multiple solutions exist

Three possible solutions


Concurrent statement solution using a conditional assignment:
ARCHITECTURE arch_compare OF compare IS BEGIN aeqb <= '1' WHEN a = b ELSE '0'; END arch_compare;

Concurrent statement solution using boolean equations:


ARCHITECTURE arch_compare OF compare IS BEGIN aeqb <= NOT( (a(0) XOR b(0)) OR (a(1) XOR b(1)) OR (a(2) XOR b(2)) OR (a(3) XOR b(3))); END arch_compare;

Three possible solutions (contd.)


Solution using a process with sequential statements:
ARCHITECTURE arch_compare OF compare IS BEGIN comp: PROCESS (a, b) BEGIN IF a = b THEN aeqb <= '1'; a(0 TO 3) ELSE aeqb <= '0'; b(0 TO 3) END IF; END PROCESS comp; END arch_compare;

aeqb

Using Tri-State Logic


ENTITY test_three IS PORT( oe : IN std_logic; data : OUT std_logic_vector(0 to 7)); END test_three; ARCHITECTURE archtest_three OF test_three IS BEGIN PROCESS (oe) BEGIN IF (oe = '1') THEN data <= "01100100"; ELSE data <= "ZZZZZZZZ"; END IF; END PROCESS; END archtest_three;

Behavioral Dont Cares


Warp uses explicit "dont care" conditions to produce optimal logic equations
IF (a = '1') AND (b = '1') THEN x <= c; ELSE x <= '-'; END IF;

Produces the equation x = c To assign dont cares in VHDL: mysig <= '-'; 'X' means "unknown" and is not useful for synthesis

Comparing Vectors to Strings -more on don't cares Comparing "1101" to "11-1" will return FALSE Use std_match(a,"string") Must include std_arith package Example:

... signal a : std_logic_vector (1 to 4) ; ... IF std_match(a,"10-1") THEN x <= '1' ; END IF ;

Aggregates and Subscripts


An aggregate assignment concatenates signals together Good for creating a bus from several inputs The concatenation operator can be used as well
tmp <= (a,b,c,d); tmp <= a & b & c & d;

Signals can be pulled from larger vectors Good for grouping outputs as an alias Sizes on both sides of assignment must match
rw <= ctrl(0); ce <= ctrl(1); oe <= ctrl(2); highcount <= count(7 DOWNTO 4);

Synchronous Logic
PLDs work well in synchronous applications Two methods of creating synchronous logic Structurally instantiating components with registers Behaviorally Using a processes with a clock signal in the sensitivity list

Registers in Behavioral VHDL


Example: a D-type flip-flop
ENTITY registered IS PORT ( d, clk: IN std_logic; q: OUT std_logic); END registered; ARCHITECTURE archregistered OF registered IS BEGIN flipflop: PROCESS (clk) BEGIN IF rising_edge(clk) THEN q <= d; END IF; END PROCESS flipflop; END archregistered;

Registers in Behavioral VHDL


The synthesis compiler infers that a register is to be created for which signal q is the output because The clock (clk) is in the sensitivity list The construct, rising_edge(clk), falling_edge(clk) or clkevent AND clock=1 appears in the process The rising_edge(clk) or falling_edge(clk) statement implies that subsequent signal assignments occur on the rising/falling edge of the clock The absence of an else clause in the if-then statement implies that if the clkevent and clk = 1 condition is not fulfilled (i.e. not a rising-edge), q will retain its value until the next assignment occurs (this is referred to as implied memory)

Rising/Falling Edge Functions


The 1164 package defines 2 functions for edge detection rising_edge (signal) similar to (signalevent and signal =1) falling_edge (signal) similar to (signalevent and signal =0) if rising_edge(clk) then q <= d; end if;

A Registered Process (1)


A 4-bit counter with synchronous reset
USE WORK.std_arith.ALL; ... count upcount: PROCESS (clk) clk BEGIN rst IF rising_edge(clk) THEN IF reset = '1' THEN count <= "0000"; -- or x"0" instead ELSE count <= count + 1; END IF; END IF; END PROCESS upcount;

This process is only sensitive to changes in clk, i.e., it will become active only when the clock transitions

A Registered Process (2)


A 4-bit counter with asynchronous reset
USE WORK.std_arith.ALL; ...
count
clk rst

upcount: PROCESS (clk, reset) BEGIN IF reset = '1' THEN count <= x"0"; ELSIF rising_edge(clk) THEN count <= count + 1; END IF;

END PROCESS upcount;

This process is sensitive to changes in both clk and rst, i.e., it will become active during clock or reset transitions.

A Registered Process (3)


A 4-bit loadable counter with asynchronous reset
USE WORK.std_arith.ALL; ... data load upcount: PROCESS (clk, reset) clk BEGIN IF reset = '1 rst THEN count <= x"0" ; ELSIF rising_edge(clk) THEN IF load = '1' THEN count <= data; ELSE count <= count + 1; END IF; END IF; END PROCESS upcount;
count

Creating a level-sensitive latch


Instead of using the rising_edge or falling_edge function, replace it with clk=1 or clk=0 and put d in the sensitivity list latch: PROCESS (clk, d) BEGIN IF clk = '1' THEN q <= d; END IF; END PROCESS latch;
d clk q

Instantiating a registered component


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

ARCHITECTURE archregistered OF registered IS BEGIN flipflop: Mff generic map (lpm_width=>4,lpm_fftype=>lpm_dff) PORT MAP (data=>d,clock=>clk,enable=>one,q=>q); END archregistered;

The WAIT statement


This is another method to activate a process The WAIT statement is a sequential statement which suspends the execution of a process until the condition specified becomes valid (true) i.e., an implied sensitivity list, e.g.,
sync: PROCESS BEGIN WAIT UNTIL clock='1'; IF enable='1' THEN q_out <= d_in; ELSE q_out <= '0'; END IF; END PROCESS sync;

enable d_in clock


D
Q

q_out

Implicit memory
Signals in VHDL have a current value and may be scheduled for a future value If the future value of a signal cannot be determined, a latch will be synthesized to preserve its current value Advantages: Simplifies the creation of memory in logic design Disadvantages: Can generate unwanted latches, e.g., when all of the options in a conditional sequential statement are not specified

Implicit memory: Example of incomplete specification


ARCHITECTURE archincomplete OF incomplete IS
BEGIN im_mem: PROCESS (a,b) BEGIN

a c

IF a = '1'
THEN c <= b; END IF; END PROCESS im_mem; END archincomplete;

Note: the incomplete specification of the IF...THEN... statement causes a latch to be synthesized to store the previous state of c

Implicit memory: Example of complete specification


ARCHITECTURE archcomplete OF complete IS BEGIN no_mem: PROCESS (a, b) BEGIN IF a = '1' THEN c <= b; ELSE c <= '0'; END IF; END PROCESS no_mem; END archcomplete;

a b

The conditional statement is fully specified, and this causes the process to synthesize to a single gate

The rules to avoid implicit memory


To avoid the generation of unexpected latches always terminate an IF...THEN... statement with an ELSE clause cover all alternatives in a CASE statement define every alternative individually, or terminate the CASE statement with a WHEN OTHERS... clause, e.g.,
CASE coin_inserted IS WHEN quarter => WHEN dime => WHEN nickel => WHEN OTHERS => END CASE; total<=total+25; total<=total+10; total<=total+5; total<=total; error<=1;

Exercise #4
Making use of the previous examples, write an entity/architecture pair for the following design:
ENC
COUNTER

DATA LD CLOCK

DIN LD ENC RST

COUNT

4
COMPARATOR

P P=Q Q

RESET (sync)
REGISTER

DIN ENR Q ENR


4

Exercise #4: Solution


LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY ex4 IS PORT ( clock, reset, enc, enr, ld: IN std_logic; data: IN std_logic_vector (3 DOWNTO 0); count: BUFFER std_logic_vector(3 DOWNTO 0)); END ex4; USE WORK.std_arith.ALL; -- for counter and Ultragen ARCHITECTURE archex4 OF ex4 IS SIGNAL comp: std_logic; SIGNAL regout: std_logic_vector (3 DOWNTO 0); BEGIN reg: PROCESS (clock) BEGIN IF RISING_EDGE(clock) THEN IF enr = '1' THEN regout <= data; END IF; END IF; END PROCESS reg;

Exercise #4: Solution (contd.)


cntr: PROCESS (clock) BEGIN IF RISING_EDGE(clock) THEN IF reset = '1' THEN count <= "0000"; ELSIF ld = '1' THEN count <= data; ELSIF enc = '1' AND comp = '0' THEN count <= count + 1; END IF; END IF; END PROCESS cntr; comp <= '1' WHEN regout = count ELSE '0'; END archex4;

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

Moore machines
Outputs may change only with a change of state Multiple implementations include: Arbitrary state assignment outputs must be decoded from the state bits combinatorial decode registered decode Specific state assignment outputs may be encoded within the state bits one-hot encoding

Example: A Traffic Light Controller


Lets take a look at an example state machine and see how to describe it using the 3 types of implementations:
TIMER2 RESET (asynchronous) TIMER1 RED GREEN TIMER2 YELLOW TIMER3

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

Moore state machine implementations (1)


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

Inputs

Next State Logic

Next State

State Registers

Output Logic

Outputs

Tco + tpd

Example: The Entity Declaration


The entity declaration remains exactly the same for each implementation. For example:
LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY state_machine IS PORT ( clock, reset: std_logic; timer1, timer2, timer3: r, y, g: OUT std_logic); END state_machine;

IN IN std_logic;

Example: Solution 1
Combinatorial outputs decoded from the state registers
ARCHITECTURE arch_1 OF state_machine IS TYPE traffic_states IS (red, yellow, green); -- enumerated type SIGNAL sm: traffic_states; BEGIN

fsm: PROCESS (clock, reset) -- the process describes the BEGIN -- state machine only IF reset = '1' THEN sm <= red; ELSIF rising_edge(clock) THEN CASE sm IS WHEN red => IF timer1=1 THEN sm <= green; ELSE sm <= red; END IF;
WHEN green => IF timer2=1' THEN sm <= yellow; ELSE sm <= green; END IF;

Example: Solution 1 (contd.)


IF timer3=1 THEN sm <= red; ELSE sm <= yellow; END IF; WHEN others => sm <= red; END CASE; END IF; END PROCESS fsm;
-- the outputs are decoded from the state machine -- registers using combinatorial logic r <= '1' WHEN (sm = red) ELSE '0'; g <= '1' WHEN (sm = green) ELSE '0'; y <= '1' WHEN (sm = yellow) ELSE '0'; END arch_1;

WHEN yellow =>

Moore state machine implementations (2)


Outputs decoded from state bits using REGISTERS registered output logic is in parallel with state registers outputs are a function of the previous state and the inputs tco is shorter, but you need more registers
Next State Logic Output Logic State Registers Output Registers

Present State

Inputs

Outputs

tco

Example: Solution 2
Registered outputs decoded from the state registers
ARCHITECTURE arch_2 OF state_machine IS TYPE traffic_states IS (red, yellow, green); SIGNAL sm: traffic_states; BEGIN

fsm: PROCESS (clock, reset) -- the process describes the BEGIN -- state machine AND the outputs IF reset = '1' THEN sm <= red; r<=1; g<=0; y<=0; ELSIF rising_edge(clock) THEN CASE sm IS WHEN red => IF timer1=1 THEN sm <= green; r<=0; g<=1; y=0; ELSE sm <= red; r<=1; g<=0; y=0; END IF;

Example: Solution 2 (contd.)


WHEN green => IF timer2=1' THEN sm <= yellow; r<=0; g<=0; y<=1; ELSE sm <= green; r<=0; g<=1; y<=0; END IF;

WHEN yellow => IF timer3=1' THEN sm <= red; r<=1; g<=0; y<=0; ELSE sm <= yellow; r<=0; g<=0; y<=1; END IF; WHEN others => sm <= red; END CASE; END IF; END PROCESS fsm; END arch_2;

Moore State Machine Implementations (3)


We encoded the outputs within the state registers
State S0 S1 S2 Red 1 0 0 Green 0 1 0 Yellow 0 0 1 State Encoding 100 010 001

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

Inputs

Logic

State Registers

Outputs

Tco

Example: Solution 3
Outputs encoded inside the state registers
ARCHITECTURE arch_3 OF state_machine IS SIGNAL CONSTANT CONSTANT CONSTANT sm: red: green: yellow: std_logic_vector(2 std_logic_vector(2 std_logic_vector(2 std_logic_vector(2 DOWNTO DOWNTO DOWNTO DOWNTO 0) 0) 0) 0) ; := 100" ; := "010" ; := "001" ;

BEGIN
fsm: PROCESS (clock, reset) -- the process describes the BEGIN -- state machine only IF reset = '1' THEN sm <= red; ELSIF rising_edge(clock) THEN CASE sm IS WHEN red => IF timer1=1 THEN sm <= green; ELSE sm <= red; END IF;

Example: Solution 3 (contd.)


WHEN green => IF timer2=1' THEN sm <= yellow; ELSE sm <= green; END IF;

WHEN yellow => IF timer3=1 THEN sm <= red; ELSE sm <= yellow; END IF; WHEN others => sm <= red; END CASE; END IF; END PROCESS fsm;
r <= sm(2); g <= sm(1); y <= sm(0); END arch_3; -- the outputs are just taken from -- the state machine registers -- (no decode logic required)

Mealy Machines
Outputs may change with a change of state OR with a change of inputs Mealy outputs are non-registered because they are functions of the present inputs

State Registers

Inputs

Logic

Outputs

Example: The Wait State Generator


State diagram:
PWAIT
RESET (async) REQ RETRY_OUT='1' if, ENABLE='0' REQ PWAIT

IDLE

RETRY

Example: Mealy Machine Solution


ARCHITECTURE archmealy1 OF mealy1 IS TYPE fsm_states IS (idle, retry); SIGNAL wait_gen: fsm_states; BEGIN fsm: PROCESS (clock, reset) BEGIN IF reset = '1' THEN wait_gen <= idle; ELSIF FALLING_EDGE(clock) THEN CASE wait_gen IS WHEN idle => IF req = '0'

THEN wait_gen <= retry; ELSE wait_gen <= idle;

END IF; WHEN retry => IF pwait = '1' THEN wait_gen <= idle; ELSE wait_gen <= retry; END IF; WHEN OTHERS => wait_gen <= idle; END CASE; END IF; END PROCESS fsm; retry_out <= '1' WHEN (wait_gen = retry AND enable='0') ELSE '0'; END archmealy1;

Exercise #5
Design a state machine to implement the function shown below:

RESET (sync) POS

hold
POS

sample

extend

clear='0'

track='1'

track='1'

Hierarchical (Modular) Designs


A hierarchical design is one which is broken down into many levels, with a top level design bringing all the lower-level components together This allows very complex designs to be divided down into smaller, more easily managed modules

In the past, this was the major advantage of schematic capture tools
But, VHDL also supports hierarchical designs !!

Hierarchical Design Methodology


Advantages: Components (VHDL models) can be created, tested and stored for later use Allows the re-use of common building blocks Allows you to purchase 3rd Party off-the-shelf modules (e.g. UART, PCIbus Interface etc) Makes the design more readable and easier to understand Complex design tasks can be split across many designers in a team

VHDL Hierarchy Decomposition


In VHDL, hierarchy is composed of:
COMPONENTs entity/architecture pairs which can be instantiated (placed) within other designs PACKAGEs a collection of one or more COMPONENTs and other declarations LIBRARIES a collection of COMPILED design units e.g. packages, components, entity/architecture pairs etc.

Packages: How it all fits together


a c b p q r mux2to1
a

i
b sel

s sel schematic entity/architecture mux2to1 toplevel

mux2to1
a c b sel symbol component

schematic entity/architecture

library package

Hierarchy Management
Libraries are used to store re-usable components, type definitions,
overloaded operators etc. You add the LIBRARY and USE clauses to your code to get access to them
Your Design (VHDL)
LIBRARY ieee; USE ieee.std_logic_1164.. USE work.std_arith.all

Library (Compiled) Packages (VHDL) ieee


std_logic_1164

Others (VHDL)
std_logic type definitions

Library (Compiled) Packages (VHDL)

Others (VHDL)
overloaded operators

work

std_arith

Package and Component Declarations


When you have created a working entity/architecture pair, you need to add a component declaration to make it a re-usable COMPONENT COMPONENTS need to be stored in PACKAGES, so you need to write a package declaration to store all your components When you compile your package with no errors, the components will be stored in the WORK library WORK is the default library where everything YOU compile gets stored. Because it is the default library, you do NOT need to add: LIBRARY WORK; -- not required

LIBRARY ieee; USE ieee.std_logic_1164.ALL; PACKAGE mymuxpkg IS COMPONENT mux2to1 PORT ( a, b, sel: IN std_logic; c: OUT std_logic); END COMPONENT; END mymuxpkg; LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY mux2to1 IS PORT ( a, b, sel: IN std_logic; c: OUT std_logic); END mux2to1;

Package and Component Declarations: An Example


Package and Component Declaration File (VHDL)

ARCHITECTURE archmux2to1 OF mux2to1 IS BEGIN c <= (a AND NOT sel) OR (b AND sel); END archmux2to1;

Entity/Architecture File (VHDL)

Hierarchical design: Example


Signals are connected via a PORT MAP that associates signals with the component's I/O Port map association can be either explicit (named) or implicit (positional)
LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY toplevel IS PORT ( s: IN std_logic; p, q, r: IN std_logic_vector(2 DOWNTO 0); t: OUT std_logic_vector(2 DOWNTO 0)); END toplevel; USE WORK.mymuxpkg.ALL; ARCHITECTURE arch_top_level OF toplevel IS SIGNAL i: std_logic_vector(2 DOWNTO 0); Named Association BEGIN m0: mux2to1 PORT MAP (a=>i(2), b=>r(0), sel=>s, c=>t(0)); m1: mux2to1 PORT MAP (c=>t(1), b=>r(1), a=>i(1), sel=>s); m2: mux2to1 PORT MAP (i(0), r(2), s, t(2)); i <= p AND NOT q; Positional Association END arch_top_level;

Schematic of example
mux2to1
i(2) a

t(0) i(1)

mux2to1
a

t(1) i(0)

mux2to1
a

t(2)

m0 c
r(0) b sel r(1) b

m1 c
sel r(2) b

m2 c
sel

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

DATA LD CLOCK

DIN LD ENC RST

COUNT

4
COMPARATOR

P P=Q Q

RESET (sync)
REGISTER

DIN ENR Q ENR


4

Exercise 6 Solution: package.vhd


LIBRARY ieee; USE ieee.std_logic_1164.ALL;

PACKAGE ex6_pkg IS
COMPONENT comp4 PORT ( p, q : IN std_logic_vector (3 DOWNTO 0); peqq : OUT std_logic); END COMPONENT; COMPONENT reg4 PORT ( clk, enr : IN std_logic; din : IN std_logic_vector(3 DOWNTO 0); q : OUT std_logic_vector(3 DOWNTO 0)); END COMPONENT;

Exercise 6 Solution: package.vhd (cont)

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

Exercise 6 Solution: Top Level File - ex6.vhd


LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY ex6 IS PORT ( load, clock, reset enr, enc data count END ex6;

: : : :

IN IN IN BUFFER

std_logic; std_logic; std_logic_vector(3 downto 0); std_logic_vector(3 downto 0));

USE work.ex6_pkg.ALL; ARCHITECTURE ex6_arch OF ex6 IS

-- get access to your components

SIGNAL regout : std_logic_vector(3 downto 0); SIGNAL peqq : std_logic; SIGNAL not_peqq : std_logic;

-- internal bus -- internal net -- internal net

Exercise 6 Solution :Top Level File - ex6.vhd


BEGIN U1: count4 PORT MAP (din=>data, ld=>load, enc=>not_peqq, clk=>clock, rst=>reset, q=>count); U2: reg4 PORT MAP (din=>data, enr=>enr, clk=>clock, q=>regout); U3: comp4 PORT MAP (p=>count, q=>regout, peqq=>peqq); not_peqq <= enc AND NOT(peqq); END ex6_arch; -- create the inverter

Exercise 6: Summary
We created entity/architectures for each component. We stored those
components in a package so that we could RE-USE them We included ALL components in the ex6_pkg package which was compiled into the work library
Your Design (VHDL)
LIBRARY ieee; USE ieee.std_logic_1164.. USE work.ex6_pkg.all

Library (Compiled) Packages (VHDL) ieee std_logic_1164

Others (VHDL)
std_logic type definitions

Library (Compiled) Packages (VHDL) work ex6_pkg.vhd count4 reg4 comp4

Components(VHDL) count4.vhd reg4.vhd comp4.vhd

Creating repetitive structures


e.g., a 32-bit serial to parallel converter:
reset si
q(31) q(30) q(29)

q(1)

q(0)

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

The GENERATE statement


Used to specify repetitive or conditional execution of a set of concurrent statements Useful for instantiating arrays of components
USE WORK.rtlpkg.ALL; -- User-defined package containing dsrff ENTITY sipo IS PORT ( clk, reset: IN std_logic; si: IN std_logic; po: BUFFER std_logic_vector(31 DOWNTO 0)); END sipo; ARCHITECTURE arch_sipo OF sipo IS SIGNAL p_temp: std_logic_vector(31 DOWNTO 0); SIGNAL zero: std_logic := 0; BEGIN gen: FOR i IN 0 TO 30 GENERATE nxt: dsrff PORT MAP (p_temp(i+1), zero, reset, clk, p_temp(i)); END GENERATE; beg: dsrff PORT MAP (si, zero, reset, clk, p_temp(31)); po <= p_temp; END arch_sipo;

LIBRARY ieee ; USE ieee.std_logic_1164.ALL; USE WORK.std_arith.all ; ENTITY ldcnt IS PORT ( clk, ld, oe: IN std_logic; count: INOUT std_logic_vector(7 DOWNTO 0)); END ldcnt; ARCHITECTURE archldcnt OF ldcnt IS SIGNAL int_count: std_logic_vector(7 DOWNTO 0); BEGIN cnt: PROCESS (clk) BEGIN IF RISING_EDGE(clock) THEN IF ld = '1' THEN int_count <= count; -- count as "IN" ELSE int_count <= int_count + 1; END IF; END IF; END PROCESS cnt ; outen: PROCESS (oe, int_count) BEGIN IF oe = '1 THEN count <= int_count ; -- count as "OUT" ELSE count <= (OTHERS => 'Z') ;-- count as "OUT" END IF ; -- equivalent to count <= "ZZZZZZZZ" END PROCESS outen; END archldcnt;

Multiplexing I/O pins:

Exercise #7
Design a Moore Machine to implement the Output Enable Controller shown below:
68040
DRAM BANK A DRAM BANK B

DRAM BANK C

DRAM BANK D

Output Enable

DRAM Controller

Controller

Exercise #7: The FSM chart


Use the following FSM chart:
RAM

RESET IDLE
OE=1111

/RAM

CHOOSE
OE=1111 /EOC /A3 AND /A2 /A3 AND A2 A3 AND /A2 A3 AND A2

BANK A
OE=1110

EOC

BANK B
OE=1101

EOC

BANK C
OE=1011

EOC

BANK D
OE=0111

EOC

Exercise #7: Solution


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

ARCHITECTURE archex7 OF ex7 IS


TYPE oe_states IS (idle, choose, banka, bankb, bankc, bankd); ATTRIBUTE state_encoding OF oe_states : TYPE IS gray ; SIGNAL present_state, next_state : oe_states ; SIGNAL oe_out : std_logic_vector(3 DOWNTO 0) ;

BEGIN

Exercise #7: Solution (contd.)


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

Exercise #7: Solution (contd.)


WHEN bankb => IF eoc = '1' THEN next_state <= ELSE next_state <= END IF ; WHEN bankc => IF eoc = '1' THEN next_state <= ELSE next_state <= END IF ; WHEN bankd => IF eoc = '1' THEN next_state <= ELSE next_state <= END IF ; WHEN OTHERS => next_state <= idle; END CASE; END IF ; END IF; END PROCESS fsm;

bankc ; idle ; bankd ; idle ; banka ; idle ;

Exercise #7: Solution (contd).


output_logic: PROCESS (next_state) BEGIN CASE next_state IS WHEN idle => oe_out <= "1111" ; WHEN choose => oe_out <= "1111" ; WHEN banka => oe_out <= "1110" ; WHEN bankb => oe_out <= "1101" ; WHEN bankc => oe_out <= "1011" ; WHEN bankd => oe_out <= "0111" ; WHEN OTHERS => oe_out <= "1111" ; END CASE; END PROCESS output_logic ; advance_state: PROCESS (clk) BEGIN IF RISING_EDGE(clock) THEN present_state <= next_state ; oe <= oe_out ; END IF; END PROCESS ; END archex7;

You might also like