In digital logic design, clock dividers are fundamental building blocks used to derive lower-frequency clocks from a reference signal. While FPGAs often support dedicated clock management resources like PLLs or DLLs for high-quality clock generation, simple counter-based division remains useful for non-critical timing paths. This article explains how to implement even-integer, odd-integer, and fractional clock division using HDL.
Even-Integer Division
For an even division factor N, a straightforward approach uses a counter that toggles the output every N/2 input clock cycles, yielding a 50% duty cycle.
module even_divider (
input clk,
input rst_n,
output reg clk_out
);
parameter DIV = 4; // Example: divide by 4
reg [31:0] cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt <= 0;
else if (cnt == DIV/2 - 1)
cnt <= 0;
else
cnt <= cnt + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
clk_out <= 0;
else if (cnt == DIV/2 - 1)
clk_out <= ~clk_out;
end
endmodule
Odd-Integer Division with 50% Duty Cycle
Achieving exact 50% duty cycle for odd N requires generating two phase-shifted clocks—one aligned to the rising edge and the other to the falling edge of the input clock—and combining them with a logical OR.
Each sub-clock toggles twice per full output period: once after (N-1)/2 cycles and again after N-1 cycles. The union of these signals produces a symmetrical waveform.
module odd_divider (
input clk,
input rst_n,
output clk_out
);
parameter DIV = 5; // Example: divide by 5
reg [31:0] cnt_rise, cnt_fall;
reg clk_p, clk_n;
// Rising-edge domain
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt_rise <= 0;
else if (cnt_rise == DIV - 1)
cnt_rise <= 0;
else
cnt_rise <= cnt_rise + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
clk_p <= 1'b1;
else if (cnt_rise == (DIV-1)/2 - 1 || cnt_rise == DIV - 1)
clk_p <= ~clk_p;
end
// Falling-edge domain
always @(negedge clk or negedge rst_n) begin
if (!rst_n)
cnt_fall <= 0;
else if (cnt_fall == DIV - 1)
cnt_fall <= 0;
else
cnt_fall <= cnt_fall + 1;
end
always @(negedge clk or negedge rst_n) begin
if (!rst_n)
clk_n <= 1'b1;
else if (cnt_fall == (DIV-1)/2 - 1 || cnt_fall == DIV - 1)
clk_n <= ~clk_n;
end
assign clk_out = clk_p | clk_n;
endmodule
Fractional Division
Fractional division (e.g., dividing by 3.5) typically employs techniques such as pulse swallowing or delta-sigma modulation to approximate non-integer ratios over multiple cycles. Implementation details depend on requierd jitter tolerance and frequency resolution, and are often better handled by FPGA-integrated clocking primitives when available.