本文介绍了偶数分频和奇数分频电路的设计,分别从简单的分频介绍开始,延伸到任意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