Clock Dividers

Counters and their use in clock dividers

18060

Sequential circuits need a reliable clock signal to provide a stable time base for circuit operations. Clock signals originate from oscillator circuits that use a quartz crystal or silicon resonator to provide a stable frequency source. Driver circuits amplify the crystal (or oscillator) waveform into a digital signal that is distributed to the memory devices in a digital system.

Most digital systems need several (or even dozens of) different clock signals to drive different subsystems. For example, an FPGA-based system might use a 48KHz clock to produce an audio stream, a 1KHz clock to run a timer, a 10MHz clock to run a small processor, and a 12KHz clock to run a motor controller. It would be too expensive to use separate external oscillator circuits to create so many different clock signals, so systems typically produce the clocks they need from just one or two main clock inputs. The Blackboard, for example, uses just a single 100MHz external clock source.

A clock divider circuit creates lower frequency clock signals from an input clock source. The divider circuit counts input clock cycles, and drives the output clock low and then high for some number of input clock cycles. For example, a clock divider could drive an output low while counting five 100MHz input clock cycles, then drive the signal high while counting another five cycles, and so on in an endlessly repeating sequence to create a 10MHz clock.

Note that in an FPGA (like the ZYNQ chip on the Blackboard), clock signals that drive flip-flops can only come from two sources: the main clock input, or directly from the output of a flip-flop. A clock signal cannot come from any sort of logic gate or logic circuit.

A simple “divide by 2” clock divider can use a single flip-flop as shown below. Note that in the Verilog code, the output “clk_div” is typecast to a reg in the module port statement. This must be done because “clk_div” is assigned in a procedural assignment statement, and all procedural assignment targets must be reg type. It is also worth mentioning that module outputs can be type wire or reg, but inputs must be type wire.

Figure 1. A flip-flop with an inverter feedback can divide a clock by 2
Figure 1. A flip-flop with an inverter feedback can divide a clock by 2
module dividebytwo (
    input clk, rst,
    output reg clk_div
    );

always @ (posedge(clk), posedge(rst))
begin
    if (rst) clk_div <= 0;
    else clk_div <= !clk_div;
end
endmodule

An n-bit counter can produce n divided clock signals, with each successive bit oscillating at one-half the frequency of is less significant neighbor. Each bit divides the input clock by a “power of 2”, where the exponent is the (bit number +1) in the counter.

Figure 2. The bits of a binary counter divide the input clock by increasing powers of 2
Figure 2. The bits of a binary counter divide the input clock by increasing powers of 2

In the Verilog code below, the “counterout” bus is typecast to reg, so any or all of the counter bits can be used as clocks by other cirucits.

module counter1(
    input clk, rst,
    output reg [7:0] counterout
    );
    
 always @ (posedge(clk), posedge(rst))
 begin
     if (rst) counterout <= 0;
     else counterout <= counterout + 1;
end
endmodule

A more general counter-based circuit can count any number of clock cycles, toggle an output bit, and then reset itself to create a free-running clock divider. Note that flip-flops in FPGA’s (like the chip on your Blackboard) can only use clocks that come from the main clock input, or directly from the output of another flip-flop. The circuit below divides the main 100MHZ input clock by 100,000 to produce a 1KHz clock.

Figure 2. A general clock divider circuit
Figure 2. A general clock divider circuit

Behavioral Verilog for a clock divider strongly resembles Verilog for a counter – the difference is one additional “if” statement to check whether the current count value is equal to the terminal count – if they are equal, the count value is set to zero. Note the terminal count value must be one-half the total clock divide constant. This allows the terminal count value to toggle a T-FF, with the T-FF output being driven low for one-half the desired clock period, and then high for one-half the desired clock period. The T-FF output can be directly used as a clock by another circuit. Note also the terminal count value used is actually the (terminal count – 1), because the counter starts at 0.

The code below divides the input clock by 50000, and so the terminal count constant is set to 25000 (actually, 25000 -1). If this circuit were implemented on the Blackboard, where the input clock is 100MHz, the resulting output would be 2KHz.

See if you can write the Verilog code for a clock divider before comparing your work with the sample code here.

module ClkDivider (
    input clk, rst,
    output reg clk_div
    );
	
localparam terminalcount = (25000 - 1);
reg [15:0] count;
wire tc;

assign tc = (count == terminalcount);	// Place a comparator on the counter output

always @ (posedge(clk), posedge(rst))
begin
    if (rst) count <= 0;
    else if (tc) count <= 0;		// Reset counter when terminal count reached
    else count <= count + 1;
end

always @ (posedge(clk), posedge(rst))
begin
    if (rst) clk_div <= 0;
    else if (tc) clk_div = !clk_div;	// T-FF with tc as input signal
end
endmodule