Counter and Clock Divider

A lot of interesting things can be built by combining arithmetic circuits and sequential elements. In this project, we are going to provide arithmetic circuits with timing references by integrating arithmetic circuits with flip-flops. In the first part, we are going to use an adder with a register file (an array of flip-flops) to implement a counter that increases the number by 1 when the rising edge of the clock arrives. In the second part, we are going to revisit clock dividers. We will then implement a clock divider whose frequency can be more precisely calculated compared to the clock divider implemented in the previous projects.

Prerequisites

Software

Hardware

Procedure

1. Design an 8-bit Counter

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.

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=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=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.

To describe the circuit 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, we can use the similar always block as the one we used to describe a D flip-flop. To implement the counter behaviorally, there are three statements we 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 is shown as follows:

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

2. Clock Divider

In the previous project, we explained how to use a flip-flop with an inverter to implement a clock divider that divides the frequency in half. In this section, we 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.

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, we are going to use this clock divider to implement a signal of exactly 1 Hz frequency. First, we will need to calculate the constant. As an example, the input clock frequency of the Nexys3 is 100 MHz. We want our 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 we need to choose here is 50000000. Now we will start to describe the circuit:

Create a Verilog module for clock divider.

module ClkDivider (
    input clk,
    input rst,
    output reg <em>clk_div</em>
    );
 
 
endmodule

Define the constant as a local parameter:

localparam constantNumber = 50000000;

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

Now that we have a counter that increases by 1 when the clock rising edge arrives and a clock divider that can provide a clock signal that is exactly 1 Hz, we can now write a wrapper module. In the wrapper, we can use the output of this clock divider to provide the clock signal for the 8-bit counter we designed in Step 1. Thus, we get a counter that increases every second. Tie the outputs of the counter to the LEDs.

Challenges

  1. Can you implement a counter that counts every 100 ms?
  2. Can you display the output of the counter on a seven segment display?