Frequency Divider: An Overview
A frequency divider is a digital circuit that reduces the frequency of the main clock by a certain factor. They are typically used in clock generation circuits, timers, counters, etc. Frequency dividers can be categorized into two even and odd frequency dividers based on the factor N. If N is an even number the frequency divider is categorized under an even frequency divider and when N is an odd number it is categorized as an odd frequency divider.
Frequency Divider: Even
N = 2, 4, 8
Even frequency dividers divide the input frequency by an even integer, it can be designed using simple counters. Figure shows an example of even frequency dividers where the factor N is 2, 4, 8.
The waveform is even frequency dividers is shown below:
N = 6
The above-designed frequency dividers are simple to design since the dividing factor is in powers of 2. When the dividing factor is not a power of 2, a mod-N counter should be implemented rather a than simple counter and additional logic should be added to achieve the required frequency. Below is an example of N = 6 frequency divider.
The figure below shows the waveform for frequency divided by 6.
Verilog Code: Even
module freq_div_even #(parameter n = 4) (/*AUTOARG*/
// Outputs
div2, div4, div6,
// Inputs
clk, rst
);
input clk;
input rst;
output div2;
output div4;
output div6;
/*AUTOREG*/
/*AUTOWIRE*/
reg [$clog2(n)-1:0] cnt_reg, cnt_reg6;
wire [$clog2(n)-1:0] cnt_nxt, cnt_nxt6;
reg cnt6_q1;
always@(posedge clk)
begin
if(!rst)begin
cnt_reg <= 'h0;
cnt_reg6 <= 'h0;
end else begin
cnt_reg <= cnt_nxt; //
cnt_reg6 <= cnt_nxt6;
end
end // always@ (posedge clk)
assign cnt_nxt = cnt_reg + 'h1; // simple counter
assign cnt_nxt6 = (cnt_reg6 == 5) ? 'h0 : cnt_reg6 + 'h1;
// frequency divided by 2
assign div2 = cnt_reg[1];
// frequency divided by 4
assign div4 = cnt_reg [2];
// frequency divided by 6
always@(posedge clk)
begin
cnt6_q1 <= cnt_reg6[1];
end
assign div6 = cnt_reg6[2] | cnt6_q1;
endmodule // freq_div_even
Frequency Divider: Odd
When designing frequency divider is odd number, it is necessary to use mod-n counter and additional logic similar to frequency divider where N = 6.
Verilog Code: Odd
module freq_div_odd #(parameter n = 3) (/*AUTOARG*/
// Outputs
div3, div5, div7,
// Inputs
clk, rst
);
input clk;
input rst;
output div3;
output div5;
output div7;
/*AUTOREG*/
/*AUTOWIRE*/
reg [$clog2(n)-1:0] cnt_reg3, cnt_reg5, cnt_reg7;
wire [$clog2(n)-1:0] cnt_nxt3, cnt_nxt5, cnt_nxt7;
reg cnt3_q1, cnt5_q1, cnt7_q2;
always@(posedge clk)
begin
if(!rst)begin
cnt_reg3 <= 'h0;
cnt_reg5 <= 'h0;
cnt_reg7 <= 'h0;
end else begin
cnt_reg3 <= cnt_nxt3;
cnt_reg5 <= cnt_nxt5;
cnt_reg7 <= cnt_nxt7;
end
end
assign cnt_nxt3 = (cnt_reg3 == 2) ? 'h0 : cnt_reg3 + 'h1;
assign cnt_nxt5 = (cnt_reg5 == 4) ? 'h0 : cnt_reg5 + 'h1;
assign cnt_nxt7 = (cnt_reg7 == 6) ? 'h0 : cnt_reg7 + 'h1; // redundant
// frequency divided by 3
always@(negedge clk)
begin
cnt3_q1 <= cnt_reg3[1];
end
assign div3 = cnt_reg3[1] | cnt3_q1;
//frequency divided by 5
always@(negedge clk)
begin
cnt5_q1 <= cnt_reg5[1];
end
assign div5 = cnt_reg5[1] | cnt5_q1;
//frequency divided by 7
always@(negedge clk)
begin
cnt7_q2 <= cnt_reg7[2];
end
assign div7 = cnt_reg7[2] | cnt7_q2;
endmodule // freq_div_odd