How to Design Clock Divider in Verilog: Simple Guide
To design a clock divider in
Verilog, create a counter that increments on each clock pulse and toggles an output clock when it reaches a set value. This output clock runs at a slower frequency, effectively dividing the input clock frequency by a chosen factor.Syntax
A basic clock divider uses a reg counter and an output clock signal. The counter increments on every rising edge of the input clock. When the counter reaches a preset value, the output clock toggles and the counter resets.
Key parts:
input clk: The original fast clock signal.output reg clk_out: The slower divided clock output.reg [N:0] counter: A register to count clock cycles.always @(posedge clk): Trigger block on clock rising edge.
verilog
module clock_divider(
input clk,
output reg clk_out
);
reg [3:0] counter = 0; // 4-bit counter
always @(posedge clk) begin
if (counter == 9) begin
counter <= 0;
clk_out <= ~clk_out; // toggle output clock
end else begin
counter <= counter + 1;
end
end
endmoduleExample
This example divides the input clock frequency by 20. The counter counts from 0 to 9, toggling the output clock every 10 input cycles, resulting in a clock output frequency that is 1/20th of the input.
verilog
module clock_divider_example(
input clk,
output reg clk_out
);
reg [3:0] counter = 0;
always @(posedge clk) begin
if (counter == 9) begin
counter <= 0;
clk_out <= ~clk_out;
end else begin
counter <= counter + 1;
end
end
endmodule
// Testbench to simulate the clock divider
module testbench();
reg clk = 0;
wire clk_out;
clock_divider_example uut(.clk(clk), .clk_out(clk_out));
// Generate input clock with period 10 time units
always #5 clk = ~clk;
initial begin
$dumpfile("clock_divider.vcd");
$dumpvars(0, testbench);
#200 $finish;
end
endmoduleOutput
Simulation waveform shows clk toggling every 10 input clock cycles, clk_out toggling every 20 input clock cycles.
Common Pitfalls
Common mistakes when designing clock dividers include:
- Not resetting the counter properly, causing incorrect frequency.
- Using blocking assignments (
=) insidealways @(posedge clk)blocks instead of non-blocking (<=), which can cause timing issues. - Not initializing the output clock signal, leading to unknown startup state.
- Choosing a counter size too small for the division factor, causing overflow.
verilog
/* Wrong way: blocking assignment and no reset */ always @(posedge clk) begin if (counter == 9) begin counter = 0; // blocking assignment - wrong clk_out = ~clk_out; // blocking assignment - wrong end else begin counter = counter + 1; end end /* Right way: non-blocking assignment and reset */ always @(posedge clk or posedge reset) begin if (reset) begin counter <= 0; clk_out <= 0; end else if (counter == 9) begin counter <= 0; clk_out <= ~clk_out; end else begin counter <= counter + 1; end end
Quick Reference
- Use a counter to track input clock cycles.
- Toggle output clock when counter reaches half the division factor.
- Use non-blocking assignments (
<=) inside clockedalwaysblocks. - Initialize signals to avoid unknown states.
- Choose counter width to cover the division range.
Key Takeaways
Use a counter to divide the input clock frequency by toggling output after a set count.
Always use non-blocking assignments inside clocked
always blocks for correct timing.Initialize your output clock and counter to avoid unknown startup states.
Choose the counter size based on the division factor to prevent overflow.
Reset logic helps keep the clock divider stable and predictable.