Clock dividers
Counters and their use in frequency dividers
For stable operation, serial circuits need a reliable clock signal to ensure stable time synchronization. To provide a stable frequency source, the clock generator circuit uses a quartz resonator. Driver circuits amplify the signal from the crystal (or oscillator) into a digital signal that is distributed to other devices, such as storage devices, in the digital system.
Most digital circuits require several (or even dozens) of different clock signals to control various subsystems. For example, a system based FPGA can use a 48 kHz clock to generate an audio stream, a 1 kHz clock to run a timer, a 10 MHz clock to run a small processor, and a 12 kHz 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 clock signals they need from just one or two main clock inputs. For example, Blackboard uses only one external 100 MHz clock source.
The clock divider circuit produces low-frequency clock signals from the input clock source. The divider counts the input clock cycles and drives the output clock low and then high for a number of input clock cycles. For example, a clock divider could drive the output low while counting five 100 MHz input clock cycles, then drive the output high while counting five more cycles, and so on in an endlessly repeating sequence to produce a 10 MHz clock.
Note that in an FPGA (such as the ZYNQ chip on Blackboard), the clock signals that drive flip-flops can only come from two sources: the main clock input or directly from the flip-flop output. The clock signal cannot come from any logic gate or logic circuit.
A simple halving divider can use a single flip-flop, as shown below. Note that in the Verilog code the output of “clk_div” is cast to type 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 of type reg
. It is also worth mentioning that the module outputs can be of the type wire
or reg
but the inputs must be of type wire
.
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 output n divided clock signals, with each subsequent bit oscillating at half the frequency of its less significant neighbor. Each bit divides the input clock signal to a “power of 2”, where the exponent is (bit number + 1) in the counter.
In the Verilog code below – the “counterout” bus is cast to type reg
so any or all of the counter bits can be used as clock signals by other circuits.
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 the output bit, and then reset itself to create a free-running clock divider. Note that flip-flops in an FPGA (such as the chip on your board) can only use clock pulses coming from the main clock input or directly from the output of another flip-flop. The circuit below divides the main 100 MHz input clock by 100,000 to produce a 1 kHz clock.
The Verilog behavioral block for the clock divider is very similar to the Verilog code for the counter – the difference is one additional “if” statement to check whether the current counter value is equal to the final counter value – if they are, the counter value is set to zero. Note that the final counter value must be equal to half the total clock division constant. This allows the final counter value to toggle T-FFwith the T-FF output driven low for half the desired clock period and then driven high for half the desired clock period. The output of T-FF can be directly used as a clock by another circuit. Note also that the final counter value used is actually (final count – 1) since counting starts at 0.
The code below divides the input clock signal by 50,000, and so the terminal counter constant is set to 25,000 (actually 25,000 – 1). If this circuit were implemented on Blackboard, where the input clock signal is 100 MHz, the resulting output would be 2 kHz.
Try writing Verilog code for the clock divider and then compare your work with the example 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