You are on page 1of 129

VHDL and Sequential

circuit Synthesis
VHDL constructs versus automatic synthesis
What is synthesis?
Building blocks
Issues and example
Tools and targets
Hardware Description
Language (HDL)
Describe hardware not software
Description structure
Language strong syntax and type declarations

Start with a block diagram


HDL Constructs & Key Ideas
Entity Concurrency
Architecture
Sequential
Port
Process Sensitivity List
Signal & types
Variable
Conditionals if, case, next,
while Principles are the same for most
After, wait (until) HDL languages and all
Component & port map practically used languages
Generate, block
Multiple Architectures for the same
entity
There are many ways to
describe the same circuit
Entity COMBO is architecture EG1 of COMBO is
port (A,B,C: in bit; Begin
D: out bit); D <= (A nand B) xor C;
End COMBO; End EG1;

Concurrent
equations
Multiple Architectures for the same
entity
Xor described
behaviorally architecture EG2 of COMBO is
inside the process Begin
process (A, B, C)
Entity COMBO is begin
port (A,B,C: in bit; if (C = 0) then
D: out bit); D <= A nand B;
End COMBO; else
D<= A and B;
end if;
end process;
end EG2;
Multiple Architectures for the same
entity
Mix concurrent
statements and
architecture EG3 of COMBO is
processes signal T : bit;
Entity COMBO is begin
port (A,B,C: in bit; T <= A nand B;
D: out bit); p1 : process (T,C)
End COMBO; begin
D <= T xor C;
end process p1;
end EG3;

As we see, even for a very small circuit there are several descriptions possible. In case of large sequential
systems, this number is extremely large, how to select best? How to program in such a way that the system
will generate the best?
What is Synthesis?
Generate hardware from HDL
Eg. C <= A nand B gives

A
C
B

Is it that simple?
No, it is a very complex process in which time and
space can be rearranged and trade-offs investigated,
especially for sequential circuits.
What is Synthesis?
Watch out for these statements!

Time expressions after


Assert, Text I/O Simulation
Configuration declarations purpose
Dynamic Loops
Initial values Affect
Sensitivity lists synthesized
structures
Basic Sequential elements
Latches
Cheaper than FFs

Troubles with timing analysis and synchronization

Possible implication of undesired latches when you assign improper


modeling type

Flip-flops
Edge sensitive

Asynchronous and synchronous set and reset


Descriptions 4s5ng
3atches
You have to distinguish between combinational,
latches and synchronized Flip-Flops

Lack of understanding is a common source of errors.

We will first cover latches,

Next we will cover flip-flops


Description with Latches
Data input: D; enable: LE; output: Q.
signal D, LE, Q: bit ;
... b2 : block (LE=1)
b1 : process (D, LE) begin
begin Q <= GUARDED D;
if (LE = 1) then end block ;
Q <= D;
end if ; These are two equivalent
end process ;
descriptions of latch

Observe that these two


syntax examples involve
storing the signal in a
memory
Description using Latches
These are two equivalent descriptions
library IEEE;
use IEEE.std_logic_1164.all;
Example: entity LATCHES is
library IEEE; port (D1, D2, LE: in std_logic;
use IEEE.std_logic_1164.all; Q : out std_logic);
end LATCHES;
entity LATCHES is
architecture EG of LATCHES is
port (D1, D2, LE: in std_logic; begin
Q : out std_logic); b1: block (LE = '1')
end LATCHES; begin
Q <= guarded D1 xor D2;
architecture EG of LATCHES is end block;
end EG;
begin
process (D1, D2, LE)
begin
if (LE = '1') then
Q <= D1 xor D2;
end if ;
end process;
end EG;

This is Logic Enable


NOT clock
Modeling Latches
library IEEE;
when:
Q <= D when En=1 else Q; use IEEE.Std_Logic_1164.all;
... entity Latch is
Q <= D when En=1 else port (D, En : in Std_Logic;
unaffected;
(VHDL 93) Q : out Std_Logic);
end Latch;
if controlled by Enable
architecture RTL of Latch is
begin
L1: process(D, En)
begin
if En=1 then Q <= D;
end if;
end process;
end RTL;
Description using Edge
Triggered Flip Flops
Flip Flop is based on a clock signal.
Rising/Falling edge triggered.
signal D, Q, clk : bit ;
.... Rising edge
process (clk)
begin
if (clkevent and clk=1) then
Q <= D;
end if ;
end process ;
Description using Edge Triggered Flip
Flops with complex excitation function
Example:
library IEEE;
use IEEE.std_logic_1164.all;

entity FLIPFLOP is

port (D1, D2, clk: in std_logic;


Q : out std_logic);
end FLIPFLOP;

architecture EG of FLIPFLOP is

begin
process (clk)
begin
if (clkevent and clk='1') then
Q <= D1 xor D2;
end if ;
end process;
end EG;
Descriptions of Synchronous
Set/Reset Flip Flops
Data and reset is NOT on sensitivity list.

signal D, Q, clk, reset : bit ;


...
process (clk)
begin
if (clkevent and clk = 1) then
if reset = 1 then
D <= 0 ;
else
Q <= D ;
D is symbol
end if ;
end if ; of next state,
end process ; not current
state
Synchronous Set/Reset Flip
Flops
No sensitivity list.

signal D, Q, clk, reset : bit ;


...
b3 : block (clkevent and clk=1)
begin
Q <= GUARDED 0 when reset = 1 else D ;
end block ;

Role of GUARDED
in synchronous FF
Synchronous Set/Reset Flip
Flops
Example:
library IEEE;
use IEEE.std_logic_1164.all;

entity FLIPFLOP is
Synchronous
port (D1, D2, reset, clk: in std_logic; reset
Q : out std_logic);
end FLIPFLOP;

architecture EG of FLIPFLOP is
begin
process (clk)
begin
if (clk'event and clk='1') then
if reset = '1' then
Q <= '0' ;
else
Q <= D1 xor D2;
end if ;
end if;
end process;
end EG;
Asynchronous Set/Reset Flip
Flops
Reset is ON sensitivity list.

signal D, Q, clk, reset : bit ;


...
process (clk, reset)
begin
if (reset = 1) then
Q <= 0 ;
elsif (clkevent and clk = 1) then
Q <= D ;
end if ;
end process ;
Asynchronous Set/Reset Flip Flops
And now full Example of asynchronous ff with excitation equation for D:

library IEEE;
use IEEE.std_logic_1164.all;

entity FLIPFLOP is

port (D1, D2, reset, clk: in std_logic;


Q : out std_logic);
end FLIPFLOP;

architecture EG of FLIPFLOP is

begin
process (clk, reset)
begin
if reset = '1' then
Q <= '0' ;
elsif (clk'event and clk='1') then
Q <= D1 xor D2;
end if;
end process;
end EG;
Clock Enable Flip Flops
signal D, Q, enable, clk : bit ; enable
...
process (clk)
begin
if (clkevent and clk=1) then D Q
if (enable=1) then
D
Q <= D ;
end if ; clk
end if ;
end process ;

b4: block (clkevent and clk=1)


begin
Q <= GUARDED D when enable=1 else Q ;
end block ;
Flip Flops inferred by Wait
Until
signal D, Q, clk : bit ;
...
process
begin
wait until clkevent and clk=1 ;
Q <= D ;
end process ;

No sensitivity lists
No asynchronous reset D D Q

clk
Avoid undesired memory
elements
Assign values to variables before using them:
a := b and c;
d := a or b;
-- combinational network

Assign value in each branch to signals


Assign value to signals at the beginning of the
process
Flip Flops inferred by
Variables
architecture EG of FLIPFLOP is This assignment of signal
begin needs to have a FF with
process (clk) output a
variable a,b : std_logic;
begin
Here variable b has no value, it is
if (clk'event and clk='1') then created only after a has value and a
Q <= b; only after D has value
b := a;
a := D;
end if;
end process;
end EG;

We obtain a 3 bits
shift register
Explain why it is so This is strange For every variable
we have a ff.
Flip Flops inferred by
Variables
architecture EG of FLIPFLOP is The only difference here is
begin
order of assignments in
process (clk)
variable a,b : std_logic; process, here we have
begin variable assignments first.
if (clk'event and clk='1') then
a := D;
b := a;
Q <= b;
end if;
end process;
end EG; Remember that variables
are assigned immediately

Variable assignment order FF created when assigned


before use.
Edge Synchronization using function
RISING_EDGE
Synchronized D Flip-Flop
In simulation: X -> 1 ???
Edge Detection:
FUNCTION rising_edge
(SIGNAL s : std_ulogic)
Clock in sensitivity list... RETURN BOOLEAN IS
If CLKEVENT and CLK=1
then ... BEGIN
RETURN (s'EVENT AND
(To_X01(s) = '1') AND
(To_X01(s'LAST_VALUE)='0'));
Process with no sensitivity list: END;
...
wait until
CLKEVENT and CLK = 1

Here we declare function


rising_edge
Flip-flop with synchronous reset
architecture dFF_a of dFF is
entity dFF is begin
port(Reset: in Bit; dFF_Lbl: process(Clk)
D : in Bit; begin
Clk : in Bit; if Clk'event and Clk='1'
then
Q : out Bit);
if Reset = '1' then
end dFF; Q <= '0';
else
Q <= D;
end if;
Earlier we showed end if;
another way of using end process dFF_Lbl;
synchronous reset end dFF_a;
Asynchronous set and reset
architecture dFF_a of dFF is
begin
dFF_Lbl: process(Clk, Reset)
begin
if Reset = '1' then
entity dFF is
Q <= '0';
port(Reset: in Bit;
elsif
D : in Bit; Clk'event and Clk='1' then
Clk : in Bit; Q <= D;
Q : out Bit); end if;
end dFF; end process dFF_Lbl;
end dFF_a;
Why so many FF syntax?
Highlight the importance of writing good HDL code

Coding style affects synthesized structure directly

Internal working of synthesizers


Descriptions of Tristate
Buffers
3 output states: 0, 1, Z (high impedance)

entity tristate is p1 : process (en, D)


port ( D, en: in std_logic ; begin
Q : out std_logic); if (en=1) then
end tristate ; Q <= D ;
else
architecture EG of tristate is Q <= Z ;
begin end if ;
Q <= D when en = 1 else Z ; end process ;
end EG ;

Observe that because I used symbol Z the system


inferred tri-state circuit by itslef
Description of wired circuit using
Tristate Buffers
Simultaneous assignment to 1 signal
We do not specify if
Does not verify exclusivity this is wired OR or
wired AND or what

library IEEE;
use IEEE.std_logic_1164.all;

entity tristate is
port ( D1, D2 , en1, en2 : in std_logic ;
Q : out std_logic);
end tristate ;

architecture EG of tristate is
begin
Q <= D1 when en1 = '1' else 'Z' ;
Q <= D2 when en2 = '1' else 'Z' ;
end EG ;
Flip-flops with Tristate Buffers
If output of FF or latch is tristated, enable line is also
tristated.

entity tristate is
port ( D, en, clk: in std_logic ;
Q : out std_logic);
end tristate ;

architecture EG of tristate is
begin
process (en, clk)
begin
if (en = '0') then
Q <= 'Z';
elsif (clk'event and clk = '1') then This is one more
Q <= D;
end if;
argument for using
end process; standard logic
end EG ; STD_LOGIC
Tri-State Buffer at the FFs output
Avoid FF in the path to control
the buffer
architecture DTri_enff of DTri is
begin
DTri_Lbl: process(Clk)
begin
if Clk'event and Clk = '1' then
if TriEnb = 0' then
Dout <= 'Z'; Din
SET
DOut

else D Q
Dout <= Din;
end if; Q
CLR
end if; TriEnb
end process DTri_Lbl; D
SET
Q
end DTri_enff; Clk

CLR
Q
library IEEE;
use IEEE.Std_Logic_1164.all; Tri-State Buffer at
entity DTri is
port(TriEnb : in Std_Logic;
the FFs output
Din : in Std_Logic;
Clk : in Std_Logic;
Dout : out Std_Logic);
end DTri;

architecture DTri_encom of DTri is


begin
DTri_Lbl: process(Clk, TriEnb)
begin Din DOut
SET
if TriEnb = 0' then D Q
Dout <= 'Z';
elsif Clk'event and Clk = '1' then
Dout <= Din; CLR
Q
end if; Clk

end process DTri_Lbl;


end DTri_encom; TriEnb
Busses with tri-state
buffers
Use arrays in the declarations
entity tristate is
port ( D1, D2: in std_logic_vector (7 downto 0);
en1, en2 : in std_logic;
Q : out std_logic_vector (7 downto 0) );
end tristate ;

architecture EG of tristate is
begin
Q <= D1 when en1 = '1' else "ZZZZZZZZ" ;
Q <= D2 when en2 = '1' else "ZZZZZZZZ" ;
end EG ;

This description and circuit describes selector


circuit realized with tri-state buffers on a bus this
is an important circuit
State Machines
Finite State Machines (FSM)
are a key tool of logic design
0
A synthesizer can perform 1

state optimization on FSMs


0 1
to minimize the circuit area / start wait found
delay 0 0 0 1

This optimization is only 1


available if the FSM model
fits templates State Diagram for Pulse Generator

clk

sig

result

state start start wait found start

Timing Diagram for Pulse Generator


entity pulseGen is
generic ( clkEdge :
edge :
port ( clk, resetn,
result : out
std_logic := '1';
std_logic := '1');
sig : in std_logic;
std_logic );
State Machine Example
end entity pulseGen;

architecture state_machine of pulseGen is


type states is (start, waitForSig, found);
signal current_state, next_state : states;
begin
state_logic : process(current_state, sig) is
begin
case current_state is
when start =>
result <= '0';
if sig = (not edge) then
next_state <= waitForSig;
inputs combinational outputs
else logic
next_state <= start;
end if;
when waitForSig =>
result <= '0';
if sig = (not edge) then current next
next_state <= waitForSig;
else --we have had a transition state state
next_state <= found;
end if;
when found =>
next_state <= start; State
result <= '0;
when others => Regs
next_state <= start;
end case;
end process; Clk
state_register : process(clk, resetn)
begin
if resetn = '0' then
current_state <= start;
elsif clk'event and clk = clkEdge then
current_state <= next_state;
end if;
end process;
end architecture state_machine;
Implementation of Pulsegen
FPGA Implementation of Pulse Generator

1 0 what is state
encoding?
0 1
start wait found
0 0 0 1

State Diagram for Pulse Generator


Modeling FSM (automata)
Type of automaton (Moore or Mealy)
Mix output types of Moore and Mealy
Synchronisation of outputs in Mealy machines (spike elimination)
Style of modeling the machine:
How many processes (one, two, three)
State register local variable or signal?
Clearing and self-correction of automata
State Minimization
Encoding
Concurrent communicating automata
Hierarchical Automata
Automaton of Moorea
signal I1, I2, I3 : BIT;
signal RESET, CLK : BIT;
signal state_reg, next_state : process (state_reg)
BIT_VECTOR (0 to 2); begin
case state_reg (0 to 2) is
begin
when 000 => Dout <= ..... ;
...
if I1 ... then
Next_state <= .....
process (Clk, Reset) end if;
when 001 => Dout <= .....
begin
if (I2 and I3) ... then
if RESET then Next_state <= .....
state_reg <= 000; end if;
elsif CLK=1 and CLKEvent then end case;
state_reg <= next_state;
end if;
end process;

...
Automaton of Mealy
signal RESET, CLK : BIT;
signal state_reg, next_state :
BIT_VECTOR (0 to 2);
...
process (Clk, Reset)

begin
if RESET then
state_reg <= 000; process (state_reg, I1, I2 ...)
elsif CLK=1 and CLKEvent then begin
state_reg <= next_state; case state_reg (0 to 2) is
end if; when 000 => if (I1 and ...) then
Next_state <= .....; Dout <= ..... ; end if;
when 001 => if (I1 and ...) then
end process;
Next_state <= .....; Dout <= ..... ; end if;
....
end case;
end process;
transitions : process
(present_state, input1)
Finite States Machine begin
case present_state is
when s0 =>
output1 <= '1' ;
entity test is
if (input1 = '1') then
port ( clk, input1, reset : in bit ;
next_state <= s0 ;
output1 : out bit );
else
end test ;
next_state <= s1 ;
end if ;
architecture EG of test is
type state_type is (s0, s1, s2) ; when s1 =>
output1 <= '0' ;
signal present_state, next_state :
next_state <= s2 ;
state_type ;
when s2 =>
begin
output1 <= '0' ;
registers : process (clk, reset)
if (input1 = '1') then
begin
next_state <= s0 ;
if (reset='1') then
else
present_state <= s0 ;
elsif clk'event and clk = '1' then next_state <= s2 ;
end if ;
present_state <= next_state;
end case ;
end if ;
end process ;
end process ;
end EG ;

Circuit
generated
Finite States Machine
Moore machine (shown) vs Mealy machine
State encoding control
Recommended type of FSM modeling
STATE_TYPE - Synchronous state change
process (Clk, Reset)
begin
Separate combinational and if RESET then
sequential to two processes state_reg <= S0;
elsif CLK=1 and CLKEvent then
state_reg <= next_state;
Separate transition function end if;
end process;
from output function (three
processes)
- Excitation and output functions
process (State_reg, I1, I2, .....)
signal state_reg, next_state : begin
STATE_TYPE;
case state_reg is
signal RESET, CLK : BIT;
when S1 => Next_state <= .....
....
Dout <= .....
when S2 => Next_state <= .....
Dout <= .....
.....
end case;
end process;
Finite States Machine
Case is better than if-then-else

Others will cause extra logic

Assign next_state and output in every state under


every conditions, otherwise latches result.

Reset is very important. Asynchronous vs


synchronous
Output Synchronisation f6r
state 0ach5nes
Outputs in Mealy machine change their states
by each change of inputs, independently of the
clock

Spikes can be removed synchronizing changes


of outputs using an additional latch
Counters
Counter with asynchronous read, synchronous reset and
count and no variables in sensitivity list
library IEEE; architecture Count_a of Count is
use signal Count1_s :
IEEE.Std_Logic_1164.all; Unsigned(3 downto 0);
use begin
IEEE.std_logic_arith.all; Count1_Lbl: process
begin
entity Count is wait until
Clock'event and Clock = '1';
port
if ResetF = '1' then
(ResetF: in Std_Logic;
Count1_s <= (Count1_s+1);
Clock : in Std_Logic; else
Count : out Unsigned Count1_s <= "0000";
(3 downto end if;
0));
end process Count1_Lbl;
end Count; count <= Count1_s;
end Count_a;
Synthesizable model of counter with reading initial state
Declaration of variable
library IEEE, COMPASS_LIB;
use IEEE.STD_LOGIC_1164.all;
architecture SYNT of OUR_COUNTER is
use COMPASS_LIB.COMPASS.all;
begin
entity OUR_COUNTER is
port (RESET, CLOCK: in STD_LOGIC; process (CLOCK, RESET) --
LIMIT: in STD_LOGIC_VECTOR (0 to 3); variable cnt : STD_LOGIC_VECTOR (0 to 3);
COUNT: out begin -- specific process construction
STD_LOGIC_VECTOR(0to3)); if RESET = 0 then asynchronous reset
end entity OUR_COUNTER; cnt := 0000; COUNT <= cnt;
elsif CLOCKEVENT and CLOCK = 1 then
-- leading slope of CLOCK used,

if cnt = LIMIT then


cnt := 0000;
elsif cnt := cnt + 1; -- overloading operator +
LIMIT [0:3] COUNT [0:3] end if; -- for type STD_LOGIC
COUNT <= cnt;
OUR_COUNTER
end if;
CLOCK end process;
Use
RESET variable end architecture SYNT;

Change variable
This is behavioral specification which is to signal
synthesizable to FPGAs and perhaps many PLDs
A word of caution.
Hardware realization of VHDL objects

Implementation of TMP :
wire

Implementation of TMP :
latch. Do you real want it?
Types / Operators 4 Rules
Unsigned, signed are arrays of std_logic (just like Std_Logic_Vector)

use closely related type conversion functions to convert between above


My_slv <= std_logic_vector(my_unsigned)
My_unsigned <= unsigned(my_slv);
Assignments are still strongly typed, so lhs, rhs need to be same length, and this
conversion must be done

numeric_std overloads operators for use on types signed, unsigned, and their
combinations with integers. SLV is NOT in the picture.

Std_logic_vectors have no numeric representation at all even when you include


the arithmetic libraries (numeric_std, or std_logic_arith).

The only library that lets you treat slvs as numbers is std_logic_unsigned (or
signed) which essentially just does the closely related type conversion for you.

conversion between integer,signed,unsigned is done with to_signed,


to_unsigned, to_integer
Lab4 SUPER Simple TB
gen_clk : process
begin
clk <= '1';
wait for 10 ns;
clk <= '0';
wait for 10 ns;
end process gen_clk;

tb : PROCESS

variable address : unsigned(2 downto 0) := "000";


variable opcode : unsigned(3 downto 0) := "0000";

BEGIN

-- wait for the rising edge of the clock to make it


-- easier to interpret on the WAVE window
wait until rising_edge(clk);
write_enable <= '1';
adr <= "000";
databus <= x"12";
wait until rising_edge(clk);
adr <= "001";
databus <= x"01";
wait until rising_edge(clk);
adr <= "010";
databus <= x"5a";
wait until rising_edge(clk);
adr <= "011";
databus <= x"00";
-- a = x0112, b=x005a
wait until rising_edge(clk);
adr <= "100";
databus <= x"03"; --shift left by 3
wait until rising_edge(clk);
adr <= "100";
databus <= x"80"; -- add a+b
wait; -- wait forever
END PROCESS;
-- *** End Test Bench - User Defined Section ***
Worked Example : Statemachines
Use traffic light example
Consider two templates
State Encoding
type traffic_states is (red, yellow, green, fl_yellow, f_red, turn_arrow );
signal current_state, next_state : traffic_states;

Sequential: encodes the states as a binary number (frequently in order of long paths)
000,001,010,011,100,101
Only one flip-flop is active, or hot, at any one time.
100000, 010000, 001000, 000100, 000010, 000001
One-Hot - The "One-Hot" encoding option will ensure that an individual state
register is dedicated to one state.
Only one flip-flop is active, or hot, at any one time.
One-hot encoding is very appropriate with most FPGA targets where a large
number of flip-flops are available.
It is also a good alternative when trying to optimize speed or to reduce power
dissipation.
State Encoding

Binary code
Gray code
Johnson code
one hot code
N 0f K code
Good guess
Additional software
Fail safe
State Encoding

Compact - The "Compact" encoding option will


minimizing the number of state variables and flip-flops.
This technique is based on hypercube immersion.
Compact encoding is appropriate when trying to
optimize area..
State Encoding
Gray - The "Gray" encoding option will guarantee that only one state variable
switches between two consecutive states.
It is appropriate for controllers exhibiting long paths without branching.
In addition, this coding technique minimizes hazards and glitches.
Very good results can be obtained when implementing the state register with T or JK
flip-flops.
State reg might go 000,001,011,010,110,111

specify encoding style to


synthesis tool
State Encoding
Why might state encoding make a difference?
Speed : combinatorial decode of the state variable to determine outputs and next state
can be made simpler via. one-hot for instance.

State transitions : if combinatorial decode of output is desired to have no glitches, the


encoding makes a difference.

Size : how many FFs are required to represent all your states?

inputs combinational outputs


logic

current next
state state

State
Regs
Clk
Onehot Encoding
DFFs
readrq waiting High Energy
particle may
disrupt the
readcmd_latch_start
state of a FF
Comb leaving us in
Logic an illegal state.
readcmd_latch_wait

readcmd_latch_wehigh


If timing of readrq is such that it is right before the clock, if
delay paths are not matched, then we could enter illegal state
(wait ff could say Im zero but readcmd.. may not update to 1
Now we are wedged with current state = all zeros.
Illegal States
given our states : (red,yellow,green,fyellow,fred,turn_arrow)

000 001 010 011 100 101


if they are encoded as above, we have 2 illegal states. What will
logic do when those states are encountered?

case current_state is
when red => next_State <= turn_arrow;
when turn_arrow => next_state <= green;
when green => next_state <= yellow.
etc.

We dont really know..


Dealing with State Machine
Faulty Reset Circuitry (or none) could have you
power-up in an illegal state

Single-Event-Upsets in radiation environments


can cause a flop to toggle, leaving your state
machine in an illegal state

Synchronization Errors on inputs


setup/hold violation
metastability

Consequences of illegal state entering is unknown, but


frequently result is wedged machine, which doesnt recover
Example Machine
SIMPLIFIED Flash Memory reading interface :

entity flashif is idea of this is so that


port ( external environment
clk : in std_logic; -- assume 50 MHz
reset : in std_logic; -- active low can read flash by
simply putting an adr
address : in std_logic_vector(22 downto 0);
readrq : in std_logic; on the line, and pulling
readrq high. The state
datardy : out std_logic;
machine must go off,
--- signals to flash and send commands
iobus : out std_logic_vector(7 downto 0); to the flash to get that
ale : out std_logic; piece of data, and the
cle : out std_logic;
we : out std_logic; datardy signal will go
re : out std_logic; high when the data is rdy
ready_busy_b: in std_logic
); on the flash pins.
State Diagram
type state_type is (waiting, -- waits for readrq
readcmd_latch_start, -- steps through these states once per clock
readcmd_latch_wait,
readcmd_latch_wehigh, -- writes a read command
readcmd_latch_clelow, -- disables the command latch
adr0_latch_start, -- now tells the flash the address
adr0_latch_wait,
adr0_latch_wehigh,
adr9_latch_start,
adr9_latch_wait,
adr9_latch_wehigh,
adr17_latch_start,
adr17_latch_wait,
adr17_latch_wehigh,
adr_latch_deassert,
waitfor_busy, -- stays here till flash busy
waitfor_notbusy, -- stays here till flash not busy
read_relow, -- tells flash to drive databus
read_wait, -- waits for slow access time
read_rehigh -- this state makes data re go high
);
Next_State Decoding
statelogic : process (current_state,seq_access,readrq,sync_busy)
begin
case current_state is
when waiting =>
if readrq = '1' then
if seq_access = '1' then
next_state <= read_relow;
else Purely combinational
next_state <= readcmd_latch_start; process, only 1 output
end if;
else next_state
next_state <= waiting;
end if;
when readcmd_latch_start =>
next_state <= readcmd_latch_wait;
when readcmd_latch_wait =>
next_state <= readcmd_latch_wehigh;
when readcmd_latch_wehigh =>
next_state <= readcmd_latch_clelow;
when readcmd_latch_clelow =>
etc
Decoding States for output signals
datardy <= '1' when (current_state = read_rehigh) else '0';
-- decode states for re signal
re_reg : process(clk,reset)
begin
if (reset = '0') then
re_int <= '1';
elsif (clk = '1' and clk'event) then
re_int <= next_re; Output signals look
end if; at current_state to determine
end process re_reg;
their values. If signal is to
re_logic : process(current_state,re_int) be treated as a clock by
begin
case (current_state) is outside device, register it
when read_relow => (like re here)
next_re <= '0';
when read_rehigh =>
next_re <= '1';
when others =>
next_re <= re_int;
end case;
end process re_logic;
Reset Circuitry
statemach : process(clk,reset) Without this, state machine may
power up in illegal state (in onehot
begin it almost certainly will.. since all
0s and and 1s are not valid states)
if (reset = '0') then
current_state <= waiting;
elsif (clk = '1' and clk'event) then
current_state <= next_state;
end if;
end process statemach;
Dealing with illegal states
These problems are not specific to Onehot encoding.
They are simply magnified with the scheme, since there are far more
illegal states!

Have a reset state obviously


carefully synchronize all inputs
U32
synchronized to
asynchronous signal use in rest of design
D Q

CLK

system clk DF1_CC


use two dff for metastability issues

If design is in an inaccessible place and can


not be rebooted..etc.
Make a safe state machine
Safe state machines
Others clause is typically not implemented by the FSM extractor..
(there are no others, since every one in the ennumerrated type is
covered) The synthesizer may call this the result of reachability
analysis. So it may be up to you to generate reset logic which will
reset the machine and place it in a known state.
i.e. sync_reset_machine <= 0 when (state = a) or (state=b) else 1;

Some synthesis tools provide attributes for encoding machines that include :
safe,onehot ; safe,grey etc.

This is hit-or-miss though, when REALLY important. -->


architecture state_machine of pulseGen is
State Machine Example
signal current_state, next_state : std_logic_vector(1 downto 0);
constant start : std_logic_vector(current_state'range) :=
constant waitForSig : std_logic_vector(current_state'range) :=
constant found : std_logic_vector(current_state'range) :=
"00";
"01";
"10";
(2)
constant error : std_logic_vector(current_state'range) := "11";
begin
state_logic : process(current_state, sig) is
begin
case current_state is
when start =>
Notice the alternative way to define
result <= '0'; the states, as std_logic_vectors.
if sig = (not edge) then
next_state <= waitForSig; There are certain circumstances,
else
next_state <= start; such as when a circuit will be
end if; exposed to a harsh environment,
when waitForSig =>
result <= '0'; when it may not be desirable to
if sig = (not edge) then
next_state <= waitForSig; allow the synthesizer to optimize
else --we have had a transition the state machine
next_state <= found;
end if;
when found =>
This optimization may create
result <= '1'; a state-machine where if a
if sig = (not edge) then
next_state <= waitForSig; single bit of a state register
else were to change, the state
next_state <= start;
end if; machine could enter an
when error =>
result <= '0'; invalid state and not return.
next_state <= start;
when others => By explicitly defining all the states,
next_state <= start; we remove this possibility.
end case;
end process;
state_register : process(clk, resetn, next_state)
In general this is NOT need it is
begin recommended that enumerated
if resetn = '0' then
current_state <= start; types be used to define states.
elsif clk'event and clk = clkEdge then
current_state <= next_state;
end if;
end process; TURN FSM Extraction OFF
end architecture state_machine;
Exam Material
all material covered in class, homeworks, and assigned book
chapters is fair , however here are some particulars

you should be able to quickly construct basic design


elements in synthesizable vhdl.
e.g. make a d-flipflop w/ enable
state machines
simulation vs. synthesis
mechanics of a process
given simple design constraints, make synthesizable
entity/architecture pair
Architecture review
architecture behavior of simplecircuit is
component and2
port (a, b : in std_logic; c: out std_logic);
end component;
signal andout1, andout2 : std_logic;
begin
U6: and2 port map (a1,b1,andout1);
U7: and2 port map (a2,b2,andout2);
sigout <= andout1 or andout2;
end behavior; U6
A1 1
A 3
andout1
Y
B1 2
B
U8

AND2
1
A 3
sigout
2 Y
U7 B
A2 1
A 3
OR2
Y
B2 2
B
AND2
andout2
Architecture pieces
begin
U6: and2 port map (a1,b1,andout1); component
U7: and2 port map (a2,b2,andout2); instantiations

sigout <= andout1 or andout2;


CSA conditional
signal assigments
-- ????
process (though this one
isnt conditional)
end behavior;
U6
A1 1
A 3
andout1
Y
B1 2
B
U8

AND2
1
A 3
sigout
2 Y
U7 B
A2 1
A 3
OR2
Y
B2 2
B
AND2
andout2
Anatomy of a CSA
sigout <= andout1 or andout2 after 5 ns;

From a Modelling Perspective :

Output events are created based on input events.

Statement is executed by simulator whenever signals on right-hand


side change

This execution may schedule an event on the left hand side signal
(even at a later time if specified)
Anatomy of a CSA
sigout <= andout1 or andout2 after 5 ns;
From a Synthesizer Perspective :

The writer has written VHDL code that behaves a certain way (in this case, every
time either of the rhs signals change, sigout will be changed to be equal to the
logical or of the two. Computer : As a synthesizer my goal is to make some
hardware that acts this way also

an OR gate will do this but the synthesizer cant create a precise delay in any
target hardware, thus this is an error.
rewrite as : sigout <= andout1 or andout2;

Creating hardware that behaves a certain way is a difficult job, the writer has to
constrain what he writes so that it is possible for the
synthesis tool.
Processes
VHDL domains :

concurrent domain architecture


describes activities that happen simultaneously
component instances, CSAs, processes

sequential domain -- within a process


describes activities that happen in a defined order
similar to standard programming languages

Definition : a process is a series of sequential statements that must


be executed in order. *(talking from simulator perspective)
Process anatomy

specifies when to
process (sensitivity list)
execute the process
declarations;
begin signals, variables valid
statements; inside the process
end process;
Process Examples
optional label
a
dougs_or : process(a,b)
begin b
c <= a or b;
end process dougs_or ; c

weird_or : process(b)
a
begin
b
c <= a or b;
end process weird_or ; c

What will synthesizer make for case 1? What hw would you make for case 2?
What will synthesizer make for case 2?
Process Examples
examp : process(b)
begin
b
c <= not b;
d <= not c; c
c <= b;
c <= not b; d
end process examp;

Process Executes in zero time, and signals are not updated until the process
suspends
Variables
signals are not useful for storing an intermediate computation in
the middle of a process, since they are not updated until the end.
For this, we use a variable.
process (x,y,z)
variable var_s1, var_s2 : std_logic;
begin
var_s1 := x and y;
var_s2 := var_s1 xor z;
sig_out <= var_s1 nand var_s2;
end process;
Signals
A signal defined at the architecture level is visible (readable and
writeable) in the processes defined in that architecture.

since variables cant be used outside process, signals are used to


communicate between processes and CSAs, and components
that is, with the rest of the architecture.

In general, use signals for values that go outside the process, and
variables for things that are just used to compute signal values.

signals represent hardware signals, and processes are describing a


sequence of computations to determine what values to assign to
those signals.
Other process statements
show_if : process(a,b) show_case : process(sel,a,b)
variable a_is_bigger : std_logic; begin
begin case sel is
a_is_bigger := 0; when 00 =>
if a > b then nibble_out <= a(3 downto 0);
a_is_bigger := 1; when 01 =>
end if; nibble_out <= a(7 downto 4);
if a=b then when 10 =>
dataout <= 11111111; nibble_out <= b(3 downto 0);
elsif a_is_bigger = 1 then when others =>
dataout <= a; nibble_out <= b(7 downto 4);
else end case;
dataout <= b; end process show_case;
end if;
end process show_if;
latching (sometimes accidental)
show_latch : process(sel,a,b) when sel is not one of the
begin three choices nibble_out
case sel is stays the same regardless of
when 00 => changing a,b
nibble_out <= a(3 downto 0);
when 01 => could specify default
nibble_out <= a(7 downto 4); condition :
when 10 => nibble_out <= 0000;
nibble_out <= b(3 downto 0); -- or whatever
end case;
end process show_latch;
Latch Inference (Synthesis)
1) synthesizer detects signals which are to be latched (those that
arent assigned under every condition
2) extract the set of conditions that cause each signal to be assigned
a value, and use the or of those conditions to enable the latch
3) done on each signal independently, so each process can have a
mixture of combinational and latched outputs.
4) synthesizers typically have a limit of complexity for which they
can analyze for latching.
5) For simplicity and clarity specify latching when desired very
clearly :
if en=1 then
if sel=0 then z<= a;
else z<= b;
end if
end if;
Illustrating Latch Inference
case sel is
when 00 =>
nibble_out <= a(3 downto 0);
when 01 =>
nibble_out <= a(7 downto 4);
when 10 =>
nibble_out <= b(3 downto 0);
end case;
4

6
a(3..0) 1
D0 S1
a(7..4) 2 S0
D1
b(3..0) 3 Y
5
D2
4
D3
4
U11
MX4 U10
4
sel(0) 1
U9
D Q

sel(1)
A 3 nibble_out
2 Y G
B
NAND2 DL1
Microprocessor I/O port
enable output drive

value from output register U12


D E PAD
Y
BIBUF

BUFF
2 Y 1
A

value if read U13

Registers :
DDR (Data Direction Register) 1 if port is an output, 0 if input
Output Data Register : if output, value in register is written to the port
if ddr = 1 then
outport <= data;
else
outport <= Z;
end if;
Looping to Replicate Hardware
mpu_porta : process (ddr,porta_reg)
begin
for i in 7 downto 0 loop
if ddr(i) = 1 then
porta_driver(i) <= porta_reg(i);
else
porta_driver(i) <= Z;
end if;
end loop;
end process mpu_porta;
Not necessary to define i, its definition was implicit (in this case
defaulted to integer)
complete form : for i in integer range 0 to 7 loop
Range Attributes
Specifying loop bounds explicitly is very inflexible when traversing
through an array.

for I in vecrange loop


visits elements in the array from left to right that is, exactly how you
specified the range when defining the array

for I in vecreverse_range loop


in reverse order in which they were specified

for I in veclow to vechigh loop


low to high, regardless of how they were specified
For loop (cont)
value must be a constant : I.e. no for I in 0 to current_count loop

you may not modify the loop counter within the loop

exit, next solve the problem of wanting to run through the loop a
variable number of times.
I dont recommend using these much, because as far as I can
tell, the XST synthesizer doesnt handle them well. Plus, they get
confusing as to what hardware you are making.

while loop not synthesizable


For loop (example)

begin
-- some other stuff here ---
carry := '0';
BV := B;

for i in 0 to A'left loop


sum(i) := A(i) xor BV(i) xor carry;
carry := (A(i) and BV(i)) or
(A(i) and carry) or
(carry and BV(i));
end loop;
return sum;
end;
Exit Statement
entity count_trail is
Port (vec: in std_logic_vector(15 downto 0);
count : out std_logic_vector(4 downto 0)); 16 5-bit full adders
end count_trail; 16 5-bit multiplexers
(before any
architecture Behavioral of count_trail is minimization)
begin
process(vec)
variable result : std_logic_vector(4 downto 0);
begin
for i in vec'reverse_range loop
exit when vec(i) = '1';
result := result + "00001";
end loop;
count <= result;
next has same syntax and
end process; simply skips this iteration of
end Behavioral; the loop
While Loop Syntax
must have defined range at compile time to be synthesized

process(vec)
variable result : std_logic_Vector(4 downto 0);
variable i : integer;
begin
result := "00000";
i := 0;
while i< 16 loop
exit when vec(i) = '1';
result := result + 1;
i := i + 1;
end loop;
count <= result;
end process;
Wait Statement
wait reserved word specifies when to suspend execution of the process and under
what conditions execution is to resume outputs are recomputed on wait:

wait for 20 ns; -- suspends the process, and waits for 20 ns.

Wait on clk,reset; -- suspends process until an event on clk or reset

Wait until enable = 1;

You can either use wait statements or a sensitivity list, NOT BOTH. For the rest of
the class, excluding some special circumstances, I will use the sensitivity list form.
Some Synthesis Limitations
Process constraints:

1) no while loops (with variable limits), no simple loops (loop


forever)

2) no incomplete sensitivity lists for comb logic

3) no time specs (e.g. wait for 5 ns, a<=b after 2 ns)

see the Menu : Edit -> Language Templates in Webpack for


examples of how to describe common pieces of hardware
Registers (FlipFlops)
U14

1 3
D Q
2
CLK

DF1

simple edge-triggered D type Flip-Flop

process(clk) synthesizer also recognizes


begin this template and will happily
if clk=1 and clkevent then build a D-Flop for us.
Q <= D;
end if; if rising_edge(clk) then
end process; or..
if falling_edge(clk) then
D-Flop variants
U16
U15 DFE3A
DFC1B
D Q
D Q
E
CLK
CLK
CLR CLR

process(clk)
begin
if (clr = 0) then ?
q<=0;
elsif rising_edge(clk) then
Q <= D;
end if;
end process;
Synchronous Design
In a purely synchronous system, all flipflops in the design are
clocked by the same clock.

Asynchronous Preset / Clear are not used except for initialization


U27
U31
Y
A D Q
INV U32 CLK INV
CLK
Y
A D Q
CLK U33
DF1_CC

CLK

DF1_CC
U32
U31
Y
A D Q
INV U32
INV

A
Y
D Q vs E

CLK
U33 CLK
DFE

DF1_CC U31
Y
A
INV U32
INV U32
U33
Y 1 D Q
A D Q A 3
2 Y E
U33 CLK B
CLK
AND2
DF1_CC DFE
Typical Synchronous System
Synchronous System Issues
Why Synchronous Logic? We can reduce the millions of steps
of analysis and timing verification of our system to a few
manageable ones:

What is maximum clock frequency that design can run at?


Logic propagation delay + setup time can not exceed time
between clock edges. luckily this is a pretty easy
job for the synthesizer and
Clock Skew p+r tools to figure out.

Identify limited asynchronous inputs and deal accordingly


Clock Skew
U32 U33 U34 U35

D Q D Q D Q D Q

CLK CLK CLK CLK

DF1_CC DF1_CC DF1_CC DF1_CC

if flops u32 and u33 get clocked


significantly earlier than U34, the
value in U33 may be lost, since
by the time U34 is clocked to
take U33s old data, U33s new
data has already made it to its Q
output.
Global Clock Buffers

Xilinx provides hardware


resources to guarantee
negligible clock-skew for
limited number of clocks.

Signals for these buffers


come in on special pins or
are buffered from the logic
via special cell.

All FPGAs have some sort of solution like this. Global clocks are
obviously limited in number by the hardware. Making our designs
synchronous also helps us fit into this architecture.
Input Synchronization
Synchronize asynchronous inputs to system so that entire system
can be designed in a synchronous manner.

asynchronous signal

x32 x32
4

U34
1
A S 3
Y D Q
2
B
CLK
U33
MX2 DF1_CC
system clk 32 bit wide register

U32
synchronized to
asynchronous signal use in rest of design
D Q

CLK

system clk DF1_CC


Simple example : 2 digit BCD ctr
to get a feel for using processes to make registers and counters we
will design a counter that will count 2 digits in decimal, for simple
display to a 2-digit LED screen.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
Inputs : use IEEE.STD_LOGIC_ARITH.ALL;
reset, clock, enable use IEEE.STD_LOGIC_UNSIGNED.ALL;
Outputs : entity bcdctr is
LSDigit, MSDigit (4 Port ( clk : in std_logic;
bits) reset : in std_logic;
en : in std_logic;
bcd : out std_logic_vector(7 downto 0));
end bcdctr;
Simple example : 2 digit BCD ctr
this is the hardware that we envision. Knowing what hardware you
want to build is preferable to cranking VHDL.
architecture behavior of bcdctr is
signal mdigit : std_logic_vector(3 downto 0);
en signal ldigit : std_logic_vector(3 downto 0);
ldigit
begin
counter 0-9 lcnt : process(clk,reset)
clk
begin
if reset = 0 then
en and ldigit <= 0000;
elsif rising_edge(clk) then
ldigit =9 if en = 1 then
mdigit
if ldigit = 1001 then
counter 0-9 ldigit <= 0000;
clk
else ldigit <= ldigit + 0001;
end if;
end if;
end if;
end process lcnt;
Simple example : 2 digit BCD ctr
en and mcnt : process (clk,reset)
ldigit =9 begin
mdigit if reset='0' then
counter 0-9 mdigit <= "0000";
clk elsif clk='1' and clk'event then
if (ldigit="1001") and (en='1') then
if mdigit = 1001 then
mdigit <= 0000";
else mdigit <= mdigit + 0001;
end if;
end if;
end if;
end process mcnt;

bcd(3 downto 0) <= ldigit;


bcd(7 downto 4) <= mdigit;

end behavior;
In Webpack (Synthesis Rept)
Synthesizing Unit <bcdctr>.
Related source file is
C:/WINDOWS/Desktop/school/vhdlclass/projectsolutions/demo/demo.vhd.
Found 4-bit up counter for signal <ldigit>.
Found 4-bit up counter for signal <mdigit>.
Summary:
inferred 2 Counter(s).
Unit <bcdctr> synthesized.

=========================================================================
HDL Synthesis Report

Macro Statistics
# Counters : 2
4-bit up counter : 2

=========================================================================
In Webpack (Rough Timing)
TIMING REPORT

NOTE: THESE TIMING NUMBERS ARE ONLY A SYNTHESIS ESTIMATE.


FOR ACCURATE TIMING INFORMATION PLEASE REFER TO THE TRACE REPORT
GENERATED AFTER PLACE-and-ROUTE.

Clock Information:
------------------
-----------------------------------+------------------------+-------+
Clock Signal | Clock buffer(FF name) | Load |
-----------------------------------+------------------------+-------+
clk | BUFGP | 8 |
-----------------------------------+------------------------+-------+

Timing Summary:
---------------
Speed Grade: -5

Minimum period: 6.644ns (Maximum Frequency: 150.512MHz)


Minimum input arrival time before clock: 6.166ns
Maximum output required time after clock: 8.699ns
Maximum combinational path delay: No path found

Timing Detail:
--------------
All values displayed in nanoseconds (ns)
To run functional simulation
Enter text commands here
In Command Window :

force signal_name value (forces an input to be a value)


force resetn 0
force databus 11110000
run runtime (advances simulation time)
run 100 ns
run 1 sec
To force a clock : highlight clk signal first, then Edit->Clock
After forcing clock :
force reset 0
run 50
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
# Time: 0 ps Iteration: 0 Instance: /bcdctr
force en 0
force reset 1
run 100
force en 1
run 200
Sequential VHDL
Rushton Ch 8
Processes
Ref : Ashenden Ch5, (for mechanics)
Edit->Languge Templates (in
Webpack)