VHDL code for clock divider

A clock divider is used to get a divided version of a clock. Clock dividers are a very important component of digital design, and are used ubiquitously.

VHDL code for a configurable clock divider: Following is the VHDL code for a configurable divider. It can divide by any number with 50% duty cycle. It makes use of a dual edge-triggered decrement counter, with configurable load; thereby enabling it to divide by any number.

Following is the entity and architecture definitions of top module for clock divider. It takes generic parameter max_bits, which puts a limit on the maximum division that can be obtained with the help of this divider. It takes the divide_value as input, the division ratio of output clock with respect to input clock. The output clock is a divided version of input clock depending on the value of divide_value. We have instantiated a component decr_counter, which takes a parameter and counts downto 0 as discussed in further detail below.

-- This module is for a configurable divider that takes value from a counter and toggles the output clock whenever it receives all zero count.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_UNSIGNED.all;

ENTITY configurable_divider IS
    GENERIC (
        MAX_BITS : INTEGER := 10
            );
    PORT (
        in_clk : IN bit;
        rst : IN bit;
        out_clk : OUT bit;
        divide_value : IN bit_vector(MAX_BITS DOWNTO 0)
         );
END ENTITY;

ARCHITECTURE behavioral OF configurable_divider IS
    -- Declaring a component of configurable_decr_counter
    COMPONENT configurable_decr_counter
        GENERIC (
            MAX_BITS : INTEGER := 10
                );
        PORT (
            clk : IN bit;
            rst : IN bit;
            load_count : IN bit_vector (MAX_BITS DOWNTO 0);
            count : OUT bit_vector (MAX_BITS DOWNTO 0)
             );
    END COMPONENT;
    -- signal declarations
    SIGNAL load_count_reg : bit_vector (MAX_BITS DOWNTO 0);
    SIGNAL curr_count_value : bit_vector (MAX_BITS DOWNTO 0);
    signal out_clk_int : bit;
BEGIN
    PROCESS
    BEGIN
        WAIT UNTIL in_clk'EVENT;
            IF to_StdLogicVector(curr_count_value) = 1 THEN
                out_clk_int <= NOT out_clk_int;
            END IF;
    END PROCESS;
    out_clk <= out_clk_int;
    -- Instantiating configurable_decr_counter
    decr_counter : configurable_decr_counter GENERIC MAP (
                                                            MAX_BITS
                                                                      )
                                                          PORT MAP (
                                                            clk => in_clk,
                                                            rst => rst,
                                                            load_count => divide_value,
                                                            count => curr_count_value
                                                                   );

END ARCHITECTURE behavioral;


Given below is the entity and architecture definition of decr_counter module. It keeps on decrementing until it reaches value 0. On reaching zero, it loads itself with a pre-determined value that is provided as an input to the counter from its top module.

-- This is the VHDL code for a configurable dual edge-triggered decrement counter.
library IEEE;

use IEEE.std_logic_1164.all;
use IEEE.std_logic_UNSIGNED.all;

ENTITY configurable_decr_counter IS
    GENERIC (
        MAX_BITS : INTEGER := 10
            );
    -- Port definitions
    PORT (
        clk : IN bit;
        rst : IN bit;
        load_count : IN bit_vector (MAX_BITS DOWNTO 0);
        count : OUT bit_vector (MAX_BITS DOWNTO 0)
         );
END ENTITY;


ARCHITECTURE behavioral OF configurable_decr_counter IS
    SIGNAL count_value : std_logic_vector (MAX_BITS DOWNTO 0);
BEGIN
    PROCESS(clk,rst)
    BEGIN
        IF rst = '1' THEN
            count <= "000000";
            count_value <= "000001";
        ELSIF clk'EVENT THEN
            IF count_value = 1 THEN
                count_value <= to_StdLogicVector(load_count);
            ELSE
                count_value <= count_value - 1;
            END IF;
            count <= to_bitvector(count_value);
        END IF;
    END PROCESS;
END ARCHITECTURE behavioral;


By the way, this code is not synthesizable, although it will simulate perfectly. We have to make a simple modification to the code to make it synthesizable. Any guesses what makes this code not being synthesized by a synthesis tool? Hope you’ve found this post useful. Let us know what you think in the comments.

Also read:



Bubble errors and bubble error correction

Bubble error correction is a very common term associated to flash ADCs (see flash ADC block diagram) wherein the output produced by comparators stage is expected to be a thermometer code. However, due to multiple non-idealities and mismatches in comparators and their inputs, the output may not be a symbol of thermometer code, but has some irregularities. So, the thermometer to binary converter stage may not be able to convert it to binary code as it is generally a state machine that accepts only thermometer code as input and may produce a garbage output if provided some other input that is not thermometer code. There may be some zeroes in-between a series of ones. For example, the output may be “01011111” instead of “01111111”. “01011111”, when fed to thermometer to binary converter will produce garbage value. Either “01111111” should be given or “00111111” or “00011111”. This will reduce the error. The presence of zeroes in a series of ones or presence of ones in a series of zeroes in the comparators’ output is termed as bubble error. And the removal of these bubbles from near-thermometer code is termed as bubble error correction.

Kinds of bubble errors: Bubble errors are categorized by their order. A first order bubble error means there is only single ‘1’ between a series of zeroes or vice-versa. For example, “0010001101” has two first order bubbler, on second bit from right and third bit from left. Similarly, “01100001111” has a second order bubble. “00011100000000010111” has one third-order and one first-order bubble.


What circuit can be used to correct bubble errors? The simplest circuit that can be used to correct bubble errors is majority-of-three circuit. In it, each output is compared with one output on the left and one on the right. The majority of the three is finally produced at the output. This is how a near-thermometer code will be converted to a thermometer code. However, a majority of three circuit will be able to correct bubble errors of first order only. There are more sophisticated circuits for second and higher order bubble correction.

            Hope you’ve found this post useful. Let us know what you think in the comments.