VHDL Coding For Fpgas Unit 7: Digital System Design
VHDL Coding For Fpgas Unit 7: Digital System Design
DATAPATH CIRCUIT
Inputs
FINITE STATE Outputs
resetn MACHINE
clock
CONTROL CIRCUIT
Daniel Llamocca
✓EXAMPLE: STOPWATCH
▪ The Stopwatch that counts in increments of 1/100th of a second.
Circuit design and VHDL implementation.
▪ Inputs: Pause, resetn, clock
▪ Outputs: Count on four 7-segment displays
▪ Target Board: DIGILENT NEXYS-4 Board
resetn
pause DIGITAL
CIRCUIT
clock
Daniel Llamocca
✓EXAMPLE: STOPWATCH
▪ Datapath design: We need four counters. Tree counters modulo-10
and one counter module-6.
resetn
clock
4 4 4 4
clock
resetn
n resetn
E COUNTER Q
modulo-N z
clock 0 to N-1 z
Q 0000 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 0000 0001
0 0 1 2 3 4 5 6 7 8 9 0 1
Daniel Llamocca
library ieee;
✓ DIGITAL COUNTER use ieee.std_logic_1164.all;
DESIGN use ieee.std_logic_unsigned.all;
entity my_genpulse is
generic (COUNT: INTEGER:= 10);
port ( clock, resetn, E: in std_logic;
Q: out std_logic_vector(integer(ceil(log2(real(COUNT))))-1 downto 0);
z: out std_logic);
end my_genpulse;
Daniel Llamocca
✓ COUNTER DESIGN: PARAMETRIC CODE
▪ This parametric counter is not only useful to
generate pulses, but also to generate counters with any arbitrary
counts.
...
begin
process (resetn,clock,E)
begin
if resetn = '0' then Qt <= (others => '0');
elsif (clock'event and clock='1') then
if E = '1' then
if Qt = conv_std_logic_vector(COUNT-1,nbits) then
Qt <= (others => '0');
else
Qt <= Qt + conv_std_logic_vector(1,nbits);
end if;
end if;
end if;
end process;
z <= '1' when Qt = conv_std_logic_vector (COUNT-1, nbits) else '0';
Q <= Qt;
end bhv;
Daniel Llamocca
✓EXAMPLE: STOPWATCH
▪ Datapath design: A cascade interconnection allows the counters to
behave as desired.
pause
resetn
clock
4 QD 4 QC 4 QB 4 QA
clock
resetn
pause
QA 0 0 1 2 3 4 5 6 7 8 9 0 1 2 3 3 4 5
zA
QB 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
Daniel Llamocca
✓ EXAMPLE: STOPWATCH
▪ ‘pause’ input: If the user asserts this input, the count must freeze.
This is achieved by using not(pause) to enable all the counters.
▪ Note that it is possible to come up with this circuit by designing an
FSM that controls the four enable inputs of the counters.
▪ Timing diagram: note what needs to happen so that the third
counter (QC) increments its count.
clock
pause
QA 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
zA
QB 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9 0 0
zB
QC 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
Daniel Llamocca
✓STOPWATCH DESIGN
▪ NEXYS-4 Board: 100 MHz clock. Thus, the
counter QA will increment its count every 10 ns.
▪ We want QA to increment its count every 0.01s (10 ms).
▪ Straightforward solution: Change the input clock to 100 Hz
(period 10 ms). This can be a hard problem if precise input clock
is required. If we modify the frequency using counters, we might
have FPGA clock skew since the 100 Hz clock will not go in the
clock tree (among other problems).
▪ Efficient solution: We use the counter that generates a pulse
every 10 ms. The output ‘z’ is then connected to every enable
input of the counters. This way, we get the same effect as
modifying the clock frequency to 100 Hz.
▪ The pulse is of duration of the input clock period (10 ns). To
generate a pulse every 10 ms, we need a counter that counts up
to (10ms/10ns) -1 = 106 -1. Note that our generic counter with
COUNT=106 allows for a quick implementation of this circuit.
Daniel Llamocca
✓STOPWATCH DESIGN
▪ Datapath circuit: The figure shows the stopwatch with the
counter up to 106 (named 0.01s counter).
▪ Note how the output ‘z’ of the 0.01s counter is now connected
to all the enables in the counters. This way we make sure that
every transition in the counter only occurs every 0.01 s (10 ms)
pause
E Counter z
z
(0.01s)
resetn
clock
4 4 4 4
Daniel Llamocca
✓STOPWATCH DESIGN
▪ Datapath circuit: Final system with four 7-segment decoders
so that the counter outputs can be seen in the displays.
pause
E z
Counter z
(0.01s)
resetn
clock
4 4 4 4
7 7 7 7
Daniel Llamocca
✓STOPWATCH DESIGN
▪ NEXYS-4 Board: It has eight 7-segment displays, but all the
displays share the same inputs. We can also enable (negative
logic) a particular 7-segment display via the common anode
(see Seven Display section in NEXYS4 datasheet).
▪ Why do we have then eight 7-seg displays, if apparently all of
them will display the same pattern?
▪ OUTPUT SERIALIZATION: With an enable for each 7-segment
display, we can use one 7-segment display at a time. In order
for each digit to appear bright and continuously illuminated, we
illuminate each digit for only 1ms every 4 ms.
▪ We need only one 7-segment decoder, a Multiplexor, and an
FSM that control the selector of the multiplexor.
▪ If we want the multiplexor selector to transition only 1 ms every
4 ms, we connect the output ‘z’ of a new counter (to 0.001s,
COUNT = 105) to the enable input of the FSM.
▪ In our design, we only use four 7-segment displays.
Daniel Llamocca
✓STOPWATCH DESIGN
▪ Final Design: Datapath Circuit + FSM resetn=0
pause
E Counter z S1
z
(0.01s) s 00
resetn
0
E
Counter E BCD E BCD E BCD E
z modulo-6 z counter z counter z counter 1
S2
clock s 01
4 4 4 4
0
3 2 1 0 E
1
7-segment S3
Decoder Counter z s 10
(0.001s)
7 7 7 7 0
E
2
1
S4
s 11
1 0
E
s
EN(3) EN(2) EN(1) EN(0) 4 2-to-4 E
EN decoder FSM
Daniel Llamocca
✓STOPWATCH DESIGN
▪ FSM Timing Diagram:
clock
resetn
state S1 S1 S1 S2 S2 S2 S2 S3 S3 S3 S3 S4 S4
s 00 00 00 01 01 01 01 10 10 10 10 11 11
1
5
4
stop
resetn
?
2 3 clock
sel
00
01
10
11
Daniel Llamocca
✓EXAMPLE: LIGTHS PATTERN
▪ Entire System:
x stop sel
resetn
clock
Q ?? 2 2
On the NEXYS4, only one 7-segment
7 display can be used at a time
z dseg 0
0
8 8 7
counter (1.5s) D Q
E FINITE STATE
1 MACHINE Esg
E 7
1
Q ?? 2
3
z
E
Q ?? FINITE STATE 1-to-2 buf buf(1) buf(0)
MACHINE s decoder
z
counter (0.5s) x = 00 → Lights change every 1.5 s
x = 01 → Lights change every 1.0 s
x = 10 → Lights change every 0.5 s
Q ??
x = 11 → Lights change every 0.25 s
counter (0.25s)
Daniel Llamocca
✓EXAMPLE: LIGTHS PATTERN resetn=0
▪ FSMs:
S1
0
E resetn=0
1
S1
00 11
sel s0
01 10
1
S2
0 0 0 0
E E E E s1
1 1 1 1
0 0 0 0
E E E E
1 1 1 1
0 0 0 0
E E E E
1 1 1 1
➢ lights_pattern.zip:
dseg00111000, Esg1 dseg01000001, Esg1 dseg10001000, Esg1 dseg11111001, Esg1
S5a S5d lights_pattern.vhd,
dseg01110000, Esg1
1
E
0
E
0 my_genpulse.vhd,
S6a 1
my_rege.vhd,
tb_lights_pattern.vhd,
dseg10000111, Esg1
0 1 S6d
E dseg11100000, Esg1
S7a
0
lights_pattern.ucf
E
1 0 1
dseg11000001, Esg1 E
dseg01111000, Esg1
S8a
0
E
1
Daniel Llamocca dseg10000011, Esg1
✓EMBEDDING COUNTERS AND
REGISTER IN ASM diagrams
▪ FSMs usually require counters and registers for proper control. In VHDL
code, this requires integrating the fsm description with port map/generic
map to instantiate the counters and registers.
▪ Example: digsys_ex: An FSM, a counter, a register, and a shift register.
▪ Asserting EQ or sclrQ can update the counter output Q, which can only be
updated (Q0, QQ+1) at the clock edge. For example: after asserting
EQ1, we must wait until the clock edge for QQ+1. For the register,
asserting ED 1 means that QD D on the next clock cycle.
QD
4
S FSM
S1
resetn=0
Shift Register:
4 4
0
LEFT
SCLK 0
ES 1: After this signal is
D D Q
E
din
EL
dout
zQ
0
EQ 1 asserted, the shift register
ED
4
4 1 (Q Q+1) shifts data on the next clock
ES
QS
LS
SCLK
EQ, sclrQ 1 (Q 0)
ED, ES, LS 1 (QD D, QS S)
cycle.
FSM
S2 ES 1, LS 1: After these 2
SCLK 1
signals are asserted, the shift
sclrQ
EQ
3
E Q Q
sclr z zQ
zQ
0 EQ 1
ES 1
(Q Q+1) register will load parallel data
(shift QS)
counter
0 to 7
1 on the next clock
Daniel Llamocca
EQ, sclrQ 1 (Q 0) cycle.
✓EMBEDDING COUNTERS AND
REGISTER IN ASMs ➢ dig_sys_ex.zip: my_digsys_ex.vhd,
my_genpulse_sclr.vhd, my_rege.vhd,
▪ Timing diagram: digsys_ex. my_pashiftreg.vhd, tb_digsys_ex.vhd.
clk
resetn
EQ
sclrQ
Q 0 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1
zQ
state S1 S1 S1 S1 S1 S1 S1 S1 S1 S2 S2 S2 S2 S2 S2 S2 S2 S1 S1
SCLK
ED
ES
LS
QD 0000 0101
Daniel Llamocca
✓EMBEDDING COUNTERS AND
REGISTER IN ASM diagrams
▪ Alternative coding style: we can embed counters and registers inside
the ASM description in VHDL (no need of port map). Note that the
resulting circuit is not technically an FSM, since now some of the outputs
are registered. For digsys_ex, only SCLK is now a combinational output.
▪ Procedure: Include the statements to infer counters and registers in the
State Transitions process. We need to clear their outputs when resetn=0.
▪ New circuit: It is functionally the same as the previous circuit, but the
representation is different.
FSMemb resetn=0
S1
SCLK 0
Updated ASM Diagram (FSMemb): It is
QD S a bit misleading. The statements
4 4 Q=7
0
Q Q+1 indicating updates to the counter,
D
4
4
SCLK 1
These statements register, and shift register outputs do not
FSMemb Q 0, QD D,
take effect immediately, but rather on
QS are executed on the
QS S clock edge
S2 Technically,
not an FSM the immediate clock edge.
SCLK 1
Q0
Daniel Llamocca
✓EMBEDDING COUNTERS AND
REGISTER IN ASM diagrams
▪ VHDL code: Use this coding style sparingly, as it is difficult to debug when
there are too many inferred counters and registers.
▪ The output signals QD, QS, sclk, behave exactly the same as in the original
digsys_ex circuit (the one with FSM and port map/generic map).
library ieee;
use ieee.std_logic_1164.all;
Note that Q is defined as an use ieee.std_logic_unsigned.all;
integer to simplify coding.
QSt: we need this auxiliary entity digsys_ex is
port ( clock, resetn: in std_logic;
signal as we cannot D,S: in std_logic_vector(3 downto 0);
feedback the output QS QD,QS: out std_logic_vector(3 downto 0);
back to the circuit (we need sclk: out std_logic);
this for shifting). end digsys_ex;
begin
Daniel Llamocca ...
✓EMBEDDING COUNTERS AND
REGISTER IN ASM diagrams
...
Transitions: process (resetn, clock)
begin
if resetn = '0' then -- asynchronous signal
y <= S1; QD<="0000"; Q <= 0; QSt<="0000" -- values on reset
Note how easy elsif (clock'event and clock='1') then
case y is
it is to update a when S1 =>
counter, a if Q=7 then y<=S2; Q<=0; QD <= D; QSt <= S;
register, or shift else y<=S1; Q <= Q+1; end if;
when S2 =>
register. if Q=7 then y<=S1; Q<=0;
else
Do not forget to y<=S2; Q <= Q+1; QSt(0) <= '0';
assign the QSt(3 downto 1) <= QSt(2 downto 0);
values on reset. end if;
end case;
This avoids end if;
having to use end process;
Q <= QSt;
port map Outputs: process (y,Q)
instructions. begin
sclk <= '0';
case y is
when S1 =>
when S2 => sclk <= '1';
end case;
end process;
Daniel Llamocca end bhv;