ECE 4110/5110
Digital Systems Design
J.W. Bruce, Ph.D.
Department of Electrical & Computer Engineering
Reading: Mano & Ciletti 6/e, Chapter 6 online resources on VHDL
Skim: continue to skim Verilog examples
Counters
• any clocked sequential circuit whose states are a repeating sequence, i.e. its state diagram is contains at least one loop
• there are many types of “counters”, each suited for particular applications
• Counters are simply FSMs with a particular state pattern.
– Design as any other FSM
– Can use the state pattern to invoke simplifications (usually) to design
An input-less Moore machine Q: Is a counter a Mealy machine, a
Moore machine, both, or neither?
Q: What is the output function G() of a counter?
Binary Counters
• state machine that produces a binary counting sequence
– for n-flip-flops, 2n counts can be produced
• the maximum number of counts for n-flip flops
– the next state logic function F() is a combinational SOP/POS/other circuit
– the speed will be limited by the setup/hold time of the flip-flops and combinational delay of F()
What is this?
• Consider the D flip-flip where D = Qn.
TOGGLE
Describe the behavior of this circuit.
How could it be
useful?
Ripple Counters
• Cascaded toggles can be used to form rippled counter
• no next state logic F() required
– Sort of.
• slower than a binary counter due to waiting for complete result to form by “ripple” through chain
• good for low-power, low-speed applications
TOGGLE TOGGLE TOGGLE TOGGLE
Ripple Counter
entity ripple_counter is
generic (n : natural := 4);
port ( clk : in std_logic;
clear : in std_logic;
dout : out std_logic_vector(n-1 downto 0) );
end ripple_counter;
architecture arch_rtl of ripple_counter is
signal clk_i : std_logic_vector(n-1 downto 0);
signal q_i : std_logic_vector(n-1 downto 0);
begin
clk_i(0) <= clk;
clk_i(n-1 downto 1) <= q_i(n-2 downto 0);
gen_cnt: for i in 0 to n-1 generate dff: process(clear, clk_i)
begin
if (clear = '1') then q_i(i) <= '1';
elsif (clk_i(i)'event
and clk_i(i) = '1') then q_i(i) <= not q_i(i);
end if;
end process dff;
end generate;
dout <= not q_i;
end arch_rtl;
Synchronous Counter
• An enable can be included in a “synchronous” binary counter using a toggle with enable (or equivalently, a T flip-flop)
– enable is implemented by AND-ing the Q output prior to the next toggle flop – gives the "ripple" effect, but also gives the ability to run synchronously
– a little faster than ripple counter, and has fewer gates than a straight binary counter circuit
TOGGLE TOGGLE TOGGLE TOGGLE
Modulo-n ripple counter
• Modify the ripple counter to be a modulo-10 counter
– a.k.a. truncated ripple counter
• What additional features would your toggle require?
TOGGLE TOGGLE TOGGLE TOGGLE
Q: How would you implement your new toggle using a D flip-flop?
a SR flip-flop?
a JK flip-flop?
Shift Registers
• Shift register is a chain of DFFs that pass data to one another
• For n flip-flops, the data is present at the final state after n clocks
• Used for serial-to-parallel conversion.
How?
• What about parallel-to-serial conversion?
What would be required of the hardware?
Shift Registers
architecture rtl of shift_register is
signal reg, nxt : std_logic_vector(n-1 downto 0);
begin
dff_shifter: process(arst, clk) begin if (arst = '1') then
reg <= (others => '0');
elsif (clk'event and clk = '1') then if (en = '1') then
reg <= nxt;
end if;
end if;
end process;
cmb_shifter: process(reg, din) begin nxt <= reg(n-2 downto 0) & din;
end process;
dout <= reg_shifter;
end rtl;
declaration of signals inside this block State storage process
reset is asynch of clk
synchronous with clk and with enable store next state
Next state combinational “logic”
Function F(). (See last lecture on FSMs) compute the shift
Output “logic” G() update dout
Ring Counters
• Shift register based counter
• Feed output of a shift register back into itself
– Another name for this hardware?
• Creates a “one-hot” counter value
• Ring counter with n flip-flops will produce n counts
• Note
– First flip-flop needs to reset to 1, while the others need to reset to 0
Ring Counter
• Consider this VHDL code snippet for a ring counter. Explain its operation.
architecture … begin
0 <= Q3;
Q1 <= Q0;
Q2 <= Q1;
Q3 <= Q2;
end architecture…
Ring Counter
• Since processes do not assign the signal values until suspension, use this to model the "before and after" behavior of a clock event.
• The signals DO NOT appear in the sensitivity list. If they did the process would continually execute and not be synthesized as a flip-flop structure
process (Clock, Reset) begin if (Reset = ‘1') then
Q0<='1'; Q1<='0';
Q2<='0'; Q3<='0';
elsif (Clock'event and Clock='1') then Q0<=Q3; Q1<=Q0;
Q2<=Q1; Q3<=Q2;
end if;
end process
Johnson Counter
• Shift register based counter
• Feeds inverted shift register output back into shift register
– gives more states with the same reduced gate count
– all flip-flops can reset to 0
• Johnson Counter with n flip-flops will create 2n counts
Using ring counter as an example,
specify a Johnson counter in VHDL
Johnson Counter
process (Clock, Reset)begin if (Reset = ‘1') then
Q0 <= '0'; Q1 <= '0';
Q2 <= '0'; Q3 <= '0';
elsif (Clock'event and Clock='1') then Q0 <= not Q3; Q1 <= Q0;
Q2 <= Q1; Q3 <= Q2;
end if;
end process
Linear Feedback Shift Register Counter
• Shift register based counter
– Other shift register based counters give far less states than the 2n counts that are possible
– LFSRs based on finite fields theory created by French mathematician Evariste Galois (1811-1832) – a feedback equation F() is sum modulo 2 of a certain set of output bits
– F() generates the input to the shift register
– can produce 2n-1 counts, nearly the maximum possible, if F() is chosen correctly
• all-zeros state always loops back to itself
Q Qn D2
EN
Q Qn D1
EN
Q Qn D0
EN F()
X2 X1 X0
CLK
LFSR Counter
• Some maximum length LFSR feedback equations F() are given below
– Others are found in Galois field theory texts. Some are shown in Wikipedia.
• Defined that bits always shift from X
n-1(MSb) to X
0(LSb)
• use XOR gates (sum modulo 2) of particular bits in the register chain
– Example:
n Feedback Equation 2 X2 = D1 = X1 X0 3 X3 = D2 = X1 X0 4 X4 = D3 = X1 X0 5 X5 = D4 = X2 X0 6 X6 = D5 = X1 X0 7 X7 = D6 = X3 X0
8 X8 = D7 = X4 X3 X2 X0
: :
: :
LFSR Counter
• Draw the state constellation for a four-bit LFSR counter using the feedback equation
F() = X4 = D3 = X1 X0
Q Qn D2
EN
Q Qn D1
EN
Q Qn D0
EN F()
X2 X1 X0
CLK
Q Qn D3
EN
X3
LFSR Counter
• 4-bit LFSR Counter with F()= X4 = D3 = X1 X0
# Q(3:0) Sin 0 1000 0 1 0100 0 2 0010 1 3 1001 1 4 1100 0 5 0110 1 6 1011 0 7 0101 1 8 1010 1 9 1101 1 10 1110 1 11 1111 0 12 0111 0 13 0011 0 14 0001 1
repeats with 1000
1000
0100
0010 1001
1100
0110 1011
0101 1010
1101 1110
1111 0111
0011
0001
0000
LFSR Counter
• For our four-bit LFSR where
F() = D3 =X1 X0
process (Clock, Reset) begin if (Reset = ‘1') then
Q0 <= ‘1'; Q1 <= '0';
Q2 <= '0'; Q3 <= '0';
elsif (Clock'event and Clock='1') then Q0 <= Q3 xor Q2; Q1 <= Q0;
Q2 <= Q1; Q3 <= Q2;
end if;
end process
Q Qn D2
EN
Q Qn D1
EN
Q Qn D0
EN F()
X2 X1 X0
CLK
Q Qn D3
EN
X3
Exploiting VHDL to Specify Counters
• Counters in VHDL are simply a FSM
• But can be designed implicitly
• Strong type casting in VHDL can make modeling counters difficult (at first glance)
– STANDARD and STD_LOGIC Packages do not define "+", "-", or inequality operators for BIT_VECTOR or STD_LOGIC_VECTOR types
Exploiting VHDL to Specify Counters (1)
• there are a couple of ways to get around this
– Use the STD_LOGIC_UNSIGNED Package
• this package defines "+" and "-"
functions for STD_LOGIC_VECTOR
• we can use +1 just like normal
• the vector will wrap as suspected (1111 - 0000)
• one catch is that we can't assign to a Port
• we need to create an internal signal of STD_LOGIC_VECTOR for counting
• we then assign to the Port at the end
use IEEE.STD_LOGIC_ARITH.ALL;
entity counter is Port ( clock : in STD_LOGIC;
reset : in STD_LOGIC;
direction : in STD_LOGIC;
count_out : out STD_LOGIC_VECTOR (3 downto 0));
end counter;
Exploiting VHDL to Specify Counters (1)
architecture counter_arch of counter is
signal count_temp : unsigned (3 downto 0);
process (clock, reset) begin if (reset = '0') then
count_temp <= "0000";
elsif (clock='1' and clock'event) then if (direction='0') then
count_temp <= count_temp + '1';
else
count_temp <= count_temp - '1';
end if;
end if;
end process;
Count_Out <= std_logic_vector(count_temp);
end counter_arch;
internal signal to hold the “count” as a STD_LOGIC_UNSIGNED signal
assign our internal signal to the port count_temp can be used
on both LHS and RHS
Up/down Binary Counter Design
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ud_cntr is
generic ( n : natural := 8 );
port (
dout : out std_logic_vector(n-1 downto 0);
dir : in std_logic;
clk, arst, en : in std_logic );
end;
• Using the STD_LOGIC_UNSIGNED approach, design the behavioral architecture for an eight-bit binary counter with
– up/down control, asynchronous reset, and enable
Up/down Binary Counter Design
architecture rtl of cnt_bindir is
signal reg_cnt, nxt_cnt : std_logic_vector(n-1 downto 0);
begin
dff_cnt: process(arst, clk) begin if (arst = '1') then
reg_cnt <= (others => '0');
elsif (clk'event and clk = '1') then if (en = '1') then
reg_cnt <= nxt_cnt;
end if;
end if;
end process;
cmb_cnt: process(reg_cnt, dir) begin if (dir = '0') then
nxt_cnt <= reg_cnt + 1;
else
nxt_cnt <= reg_cnt - 1;
end if;
end process;
dout <= reg_cnt;
end rtl;
declaration of signals inside this block State storage process
reset is asynch of clk
synchronous with clk, store next state
Next state combinational “logic”
Function F(). (See last lecture on FSMs) increment/decrement based on
direction signal
Output “logic” G() update dout
Conversion functions
Source: http://www.bitweenie.com/listings/vhdl-type-conversion/
Contained in STD_LOGIC_ARITH package Converts between VHDL integer types
and the STD_LOGIC types
Exploiting VHDL to Specify Counters (2)
• Use VHDL integers for the counter state and then convert back to
STD_LOGIC_VECTOR
– STD_LOGIC_ARITH defines conversion functions
– the function is:
conv_std_logic_vector (ARG, SIZE)
• ARG can be
– integer, unsigned, signed, STD_ULOGIC
• SIZE is the number of bits in the vector to convert to, given as an integer
– Note that engineer needs to keep track of the range and overflow
use IEEE.STD_LOGIC_ARITH.ALL;
entity counter is Port ( Clock : in STD_LOGIC;
Reset : in STD_LOGIC;
Direction : in STD_LOGIC;
Count_Out : out STD_LOGIC_VECTOR(3 downto 0));
end counter;
Exploiting VHDL to Specify Counters (2)
architecture counter_arch of counter is
signal count_temp : integer range 0 to 15;
begin
process (Clock, Reset) begin if (Reset = '0') then
count_temp <= 0;
elsif (Clock='1' and Clock'event) then if (count_temp = 15) then
count_temp <= 0;
else
count_temp <= count_temp + 1;
end if;
end if;
end process;
Count_Out <= conv_std_logic_vector (count_temp, 4);
end counter_arch;
internal integer signal specified with range
convert integer into a 4-bit STD_LOGIC_VECTOR must manually check for overflow
integer assignment doesn't requires quotes
Counter Testbenches
• Create testbench machines to control the start/stop/load/reset of counters
– each are independent processes that interact with each other through signals – a common task for a state machine is
1. at a certain state, load and enable a counter
2. go to a state and wait until the counter reaches a certain value
3. when it reaches the certain value, disable the counter and continue to the next state
– since the counter runs off of a clock, we know how long it will count between the start and stop
Counter Testbenches
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use IEEE.STD_LOGIC_ARITH.ALL;
entity oneHzblink is port ( Clk, Rst_L : in std_logic;
LED_out: buffer std_logic);
end oneHzblink;
entity counter is port ( Clock : in STD_LOGIC;
Reset : in STD_LOGIC;
Direction : in STD_LOGIC;
Count_Out : out STD_LOGIC_VECTOR(3 downto 0));
end counter;
note port mode is buffer
A review of VHDL port modes:
in : can be read but not updated within the module out : can be updated but not read within the module
buffer : carries information out of a module, but can be both updated and read within the module inout : bidirectional and can be both read and updated, with multiple update sources possible
NOTE: A buffer is strictly output, while inout is truly bidirectional with drivers both within and external to the module.
Counter Testbenches
architecture behavioral of oneHzblink is
signal count: integer range 50000000 downto 0;
begin
process (Clk) begin
if (Clk'event and Clk='1') then if (Rst_L='0') then
count<=50000000;
elsif (count >0) then count<=count-1;
else
count<=50000000;
end if;
end if;
end process;
process (count, RST_L) begin if (Rst_L = '0') then
LED_out <= '0';
elsif (count =0 ) then LED_out <= not LED_out;
end if;
end process;
end behavioral ;
assume Clk is 50MHz
loop back starting from maximum count reset active low
count down
implied latch desired, that is why LED_out is port mode buffer
Counters Testbenches
architecture behavioral of test_oneHzblink is signal Clk, Rst_L, LED_out: std_logic;
Component oneHzblink port ( Clk, Rst_L :in std_logic;
LED_out: buffer std_logic);
end component oneHzblink;
begin
UUT: oneHzblink port map (Clk, Rst_L, LED_out);
clk_gen: process begin
Clk<='0'; wait for 10 ns;
Clk<='1'; wait for 10 ns;
end process;
Stim: process begin
Rst_L<='0'; wait for 100 ns;
Rst_L<='1'; wait for 2000 ms;
end process;
end behavioral;
Create TB processes to “drive” our counter Our 50MHz clock…
Controlling counter reset…