本文介绍了偶数分频和奇数分频电路的设计,分别从简单的分频介绍开始,延伸到任意N分频电路的设计,做了详细的说明,并且附有verilog源程序,并有仿真结果。
在数字逻辑电路中,分频器是一种常用电路,通常用来对某个给定的频率进行分频,以得到所需的频率。
1.1、 偶数分频电路
偶数倍分频是最简单的一种分频模式,完全可以通过计数器计数实现,如果要进行N倍(N为偶数)偶数分频,可由待分频的时钟触发计数器计数,当计数器从0计数到N/2—1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数,以此循环下去。这种方法可以实现任意的偶数分频。下面的程序给出的是一个16分频电路,其他倍数的分频电路可以通过修改计数器的上限值得到。
用Verilog实现一个16分频电路,其源程序如下。
module clk_div16(clk_in,reset,clk_out);
input clk_in;
input reset;
output clk_out;
reg clk_out;
reg[2:0] cnt;
always@(posedge clk_in) begin
if(!reset) begin
cnt<=0;
clk_out<=0;
end
else
if(cnt==7) begin
clk_out<=~clk_out;
cnt<=0;
end
else begin
cnt<=cnt+1;
//clk_out<=clk_out;
end
end
endmodule
测试激励程序如下:
module clk_div16_tb;
reg clk_in;
reg reset;
wire clk_out;
clk_div16 uut (
.clk_in(clk_in),
.reset(reset),
.clk_out(clk_out)
);
initial begin
// Initialize Inputs
clk_in = 0;
reset = 0;
#10 reset=1;
end
always #2 clk_in=~clk_in;
endmodule
上述程序经过Synplify Pro 综合后,其RTL级结构如下图所示
在ModelSim6.5中完成仿真,结果如图所示。
总结:如果要实现任意N(偶数)分频电路。其程序如下
module clk_divN(clk_in,reset,clk_out);
input clk_in;
input reset;
output clk_out;
reg clk_out;
reg[2:0] cnt;
parameter N=8;//只需修改N的值即可
always@(posedge clk_in) begin
if(!reset) begin
cnt<=0;
clk_out<=0;
end
else
if(cnt==(N/2-1)) begin
clk_out<=~clk_out;
cnt<=0;
end
else begin
cnt<=cnt+1;
clk_out<=clk_out;
end
end
endmodule
1.2、 奇数分频电路
奇数分频电路有多种实现方式,下面介绍常用的错位“异或”法的原理。如果要进行3分频,通过待分频时钟上升沿触发计数器进行模3计数,当计数器计到邻近值时进行两次翻转。比如在计数器计计数到1时,输出时钟进行翻转;计数到2时,再次翻转,即在邻近的1和2时刻进行两次翻转,在0时刻不翻转。这样实现的3分频占空比为1/3或2/3。如果要实现占空比为50%的3分频时钟,可以通过待分频时钟下降沿触发计数,和上升沿同样的方法计数进行3分频,然后将下降沿产生的3分频时钟和上升沿产生的时钟进行相或运算,即可得到占空比为50%的3分频时钟。
这种错位“异或”法可以推广到实现任意的奇数分频:对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发的模N计数,计数到某一选定值时(0到N—1之间的任意数值,比如在计数为0)进行输出时钟翻转,然后经过(N-1)/2再次翻转,得到一个占空比非50%的奇数N分频电路。再者,同时进行下降触发沿的模N计数,和上升沿触发输出时钟翻转选定值相同的值时,进行输出时钟翻转,同样经过(N-1)/2,输出时钟再次翻转,生成占空比非50%的奇数N分频时钟。将两个占空比非50%的N分频时钟相或运算,得到占空比为50%的奇数N分频时钟。
使用Verilog程序实现3分频电路:
module clk_div3(clk_in,reset,clk_out);
input clk_in;
input reset;
output clk_out;
integer cnt1,cnt2;
reg clk_div3p;
reg clk_div3n;
always@(posedge clk_in) begin
if(!reset) begin
clk_div3p<=0;
cnt1<=0;
end
else
if(cnt1==2)
cnt1<=0;
else begin
cnt1<=cnt1+1;
clk_div3p<=~clk_div3p;
end
end
always@(negedge clk_in) begin
if(!reset) begin
clk_div3n<=0;
cnt2<=0;
end
else
if(cnt2==2)
cnt2<=0;
else begin
cnt2<=cnt2+1;
clk_div3n<=~clk_div3n;
end
end
assign clk_out=clk_div3p|clk_div3n;
endmodule
测试激励程序如下:
module clk_div3_tb;
// Inputs
reg clk_in;
reg reset;
// Outputs
wire clk_out;
// Instantiate the Unit Under Test (UUT)
clk_div3 uut (
.clk_in(clk_in),
.reset(reset),
.clk_out(clk_out)
);
initial begin
// Initialize Inputs
clk_in = 0;
reset = 0;
#10 reset=1;
end
always #2 clk_in=~clk_in;
endmodule
经ModleSim6.5仿真后的图形如下图
总结:如果要实现任意N(奇数)分频电路。其程序如下
module clk_divN(clk_in,reset,clk_out);
input clk_in;
input reset;
output clk_out;
integer cnt1,cnt2;
reg clk_div3p;
reg clk_div3n;
parameter n=19 ; //N一定要为奇数
always@(posedge clk_in) begin
if(!reset) begin
clk_div3p<=0;
cnt1<=0;
end
else
if(cnt1==(n-1))
cnt1<=0;
else
if((cnt1==1)|(cnt1==(1+(n-1)/2))) begin
cnt1<=cnt1+1;
clk_div3p<=~clk_div3p;
end
else
cnt1<=cnt1+1;
end
always@(negedge clk_in) begin
if(!reset) begin
clk_div3n<=0;
cnt2<=0;
end
else
if(cnt2==(n-1))
cnt2<=0;
else
if((cnt2==1)|(cnt2==(1+(n-1)/2))) begin
cnt2<=cnt2+1;
clk_div3n<=~clk_div3n;
end
else
cnt2<=cnt2+1;
end
assign clk_out=clk_div3p|clk_div3n;
endmodule
经ModleSim6.5仿真后的图形如下图
2012-5-13