Cascaded Counters - red-bote/VHDL_Demos GitHub Wiki

A 16-bit binary counter constructed from a series of 4-bit counters.

Class notes for Electrical Computer Engineering at The University of Alabama in Huntsville 2.12 VHDL Model for A 74163 Counter provided helpful insights for developing this demo.

Project Setup

In a new Vivado project, create a top VHDL file, and copy the Basys3 constraints into the project. External ports are created for clk and reset, and enabled in the constraints file.

Add (copy) counters_5.vhd to the project from the XSTUG examples repo. counters_5 is a 4-bit Unsigned Up Counter with Asynchronous Reset and Clock Enable.

counters_5 is instantiated as u_cntr5_0 to implement the first (lowest-order) counter, with its CE port connected to logic high (1) to increment on every clk edge. The output port Q connected to the 4-bit signal cntr5_out_n0.

architecture Behavioral of rtl_project_top is
    signal cntr5_ce0 : std_logic;
    signal cntr5_ce1 : std_logic;
    signal cntr5_out_n0 : std_logic_vector(3 downto 0);
    signal cntr5_out_n1 : std_logic_vector(3 downto 0);
    signal count_reg : std_logic_vector(7 downto 0);
begin
    cntr5_ce0 <= '1';

    u_cntr5_0 : entity work.counters_5
    port map(
        C => clk,
        CLR => reset,
        CE => cntr5_ce0,
        Q => cntr5_out_n0
        );

Successive instances of counters_5 are added, with a carry-in bit simulated on the CE input port. The carry-out bit is generated from the previous counter when its clock enable CE becomes logic high AND has reached its modulus count and therefore has all ones "1111" on its output Q.

   cntr5_ce1 <= cntr5_out_n0(3) and cntr5_out_n0(2) and cntr5_out_n0(1) and cntr5_out_n0(0) and cntr5_ce0;

   u_cntr5_1 : entity work.counters_5
   port map(
       C => clk,
       CLR => reset,
       CE => cntr5_ce1,
       Q => cntr5_out_n1
       );
   count_reg <= cntr5_out_n1 & cntr5_out_n0;
   led(7 downto 0) <= x"00" & count_reg;

The simulation waveform shows that the cascade counter provides an 8-bit count.

LEDs from counter

This part of the demo uses the previously demonstrated Counter with Modulo Maximum to slow the overall counter rate. The modulo-maximum counter is applied to the clock-enable input of the first element of the counter-cascade series. The modulo-maximum counter becomes a prescaler that reduces the base counter frequency. The prescaler effectively allows the Basys3 system clock of 100 Mhz to be reduced by some power-of-10 to attain counting cycles of e.g. 10ths, 100ths 1000ths of a second and so on.

In this demo, the generic CNT_MAX is specified as 10,000,000 to setup counters_8 for a counter modulus of 1/10th second. The logic to the clock-enable of the first counters_5 element is held at '0' until the counter modulus is reached, so the cascaded series is incremented only when the u_clk_div reaches 10. Finally, the individual 4-bit groups are merged by the bitwise concatenation operator & into a 16-bit register that is output to the LED array.

entity rtl_project_top is
    generic(constant CNT_MAX : integer := 10000000); -- 1/10th second
    Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           led : out STD_LOGIC_VECTOR (15 downto 0));
end rtl_project_top;

architecture Behavioral of rtl_project_top is
    signal clk_mod_cnt : integer range 0 to CNT_MAX-1;
    signal count_n0 : std_logic_vector (3 downto 0);
.
.
.
    signal ce_n3 : std_logic;
    signal count_outp : std_logic_vector (15 downto 0);
begin
    u_clk_div : entity work.counters_8
    generic map(MAX => CNT_MAX)
    port map(
        C => clk,
        CLR => reset,
        Q  => clk_mod_cnt -- integer range 0 to MAX-1
    );

    ce_n0 <= '0' when clk_mod_cnt < CNT_MAX-1 else '1';

    u_cntr_0 : entity work. counters_5
    port map(
        C => clk,
        CLR => reset,
        CE => ce_n0,
        Q  => count_n0
    );
.
.
.
    ce_n3 <= count_n2(3) and count_n2(2) and count_n2(1) and count_n2(0) and ce_n2;
    u_cntr_3 : entity work. counters_5
    port map(
        C => clk,
        CLR => reset,
        CE => ce_n3,
        Q  => count_n3
    );

    count_outp <= count_n3 & count_n2 & count_n1 & count_n0;
    led <= count_outp;

The simulation waveform demonstrates the modulus counter with the prescaler CNT_MAX set to 10 in order to shorten the simulation time.

images/counter/Ctf4I2.png

Next