Creating a Clock Divider

Introduction to counter based clock dividers

3631

Background

A counter is no more than an adder with a flip-flop for each of the output bits. The block diagram of a counter is shown below in Fig. 1.

Figure 1. Block diagram of 8-bit counter.
Figure 1. Block diagram of 8-bit counter.

When reset signal rst is asserted, the outputs of the counter Q[7:0] are 0. The outputs of flip-flops feed back to the input of the ripple-carry adder and present 0+1=10+1=1 at the input of the flip-flops. When the reset signal is de-asserted, the outputs turn to 1 after the rising edge of the clock arrives. And 1+1=21+1=2 will be presented at the inputs of the flip-flops. After the second rising edge of the clock arrives, 2 will show up on the outputs of the counter. As a result of the analysis, the flip-flops provide a timing reference (clock) to the adder so that the output of the counter is increased by 1 every time the rising edge of clock arrives.

Step 1: Design an 8-bit Counter

To describe the circuit shown in figure 1 structurally in Verilog, you can use the RCA and the flip-flops you implemented in previous projects. Actually, it is a lot easier to code it behaviorally. To describe any sequential circuit, you can use the similar always block as the one you used to describe a D flip-flop. To implement the counter behaviorally, there are three statements you need to make:

  • When will the always block be triggered? The output of the counter will be updated at the rising edge of the clock (functionality of FF) or the rising edge of the reset signal (asynchronous reset).
  • How does output react when reset is asserted? The output of the counter will be reset to ‘0’ when reset is asserted.
  • How does output react when the rising edge of clock arrives? The output is updated to the output of the adder, which is the output of the counter before the rising edge arrives, plus 1.

So, the code for a counter can be seen by clicking the button below, you can try to write your own counter first before checking the example code.

module counter(
    input clk,
    input rst,
    output reg [7:0] Q
    );

always @ (posedge(clk), posedge(rst))	// When will Always Block Be Triggered
begin
    if (rst == 1'b1)
        // How Output reacts when Reset Is Asserted
        Q <= 8'b0;
    else
        // How Output reacts when Rising Edge of Clock Arrives?
        Q <= Q + 1'b1;
end

endmodule

Step 2: Design a Clock Divider

In the previous module, you learned how to use a flip-flop with an inverter to implement a clock divider that divides the frequency in half. In this section, you can use a counter with a comparator to condition a flip-flop with an inverter to implement a clock divider that can control the output frequency more precisely. The block diagram of such a clock divider is shown in Fig. 2.

Figure 2. Clock divider with a counter and a comparator.
Figure 2. Clock divider with a counter and a comparator.

In the block diagram, the counter increases by 1 whenever the rising edge of clk arrives. It also resets its output to ‘0’ when it reaches the constant number defined in the constant block. The comparator compares the output of the counter with the pre-defined constant and asserts EQ if the output of counter is equal to the pre-defined constant. When EQ is asserted, the output of the clock divider flips.

Let’s assume that the pre-defined number is 3, and the output of clock divider (clk_div) is initialized to 0. It takes three clock cycles before the output of the counter equals the pre-defined constant, 3. When it reaches 3, the output of clock divider (clk_div) turns to 1, and the counter resets itself. It takes another three cycles before the output of the counter equals the pre-defined constant, 3. When it reaches 3 again, clk_div turns back to 0. So it takes 6 clock cycles before clk_div goes to 1 and returns to 0 again. As a result, the frequency of clk_div is one sixth of the frequency of original clk.

In this example, you are going to use this clock divider to implement a signal of exactly 1 Hz frequency. First, you will need to calculate the constant. As an example, the input clock frequency of the Blackboard is 100 MHz. You want your clk_div to be 1 Hz. So it should take 100000000 clock cycles before clk_div goes to ‘1’ and returns to ‘0’. In another words, it takes 50000000 clock cycles for clk_div to flip its value. So the constant you need to choose here is 50000000. Now start to describe the circuit:

Declare Inputs and Outputs

Create a Verilog module for clock divider.

module ClkDivider (
    input clk,
    input rst,
    output reg clk_div
    );

endmodule

Declare Local Parameter

Define the constant as a local parameter

localparam constantNumber = 50000000;

Implement the clock Divider Behaviorally

Describe the counter in an always block.

reg [31:0] count;

always @ (posedge(clk), posedge(rst))
begin
    if (rst == 1'b1)
        count <= 32'b0;
    else if (count == constantNumber - 1)
        count <= 32'b0;
    else
        count <= count + 1;
end

Describe the flip-flop together with the comparator as follows:

always @ (posedge(clk), posedge(rst))
begin
    if (rst == 1'b1)
        clk_div <= 1'b0;
    else if (count == constNumber - 1)
        clk_div <= ~clk_div;
    else
        clk_div <= clk_div;
end

Check Your Clock Divider Code

Double check your clock divider code by clicking:

module ClkDivider (
    input clk,
    input rst,
    output reg clk_div
    );
localparam constantNumber = 50000000;
reg [31:0] count;

always @ (posedge(clk), posedge(rst))
begin
    if (rst == 1'b1)
        count <= 32'b0;
    else if (count == constantNumber - 1)
        count <= 32'b0;
    else
        count <= count + 1;
end

always @ (posedge(clk), posedge(rst))
begin
    if (rst == 1'b1)
        clk_div <= 1'b0;
    else if (count == constNumber - 1)
        clk_div <= ~clk_div;
    else
        clk_div <= clk_div;
end

endmodule