概念:
分频器是指使输出信号频率为输入信号频率整数分之一的电子电路(2分频就是1/2,4分频就是1/4)。在许多电子设备中如电子钟、频率合成器等,需要各种不同频率的信号协同工作,常用的方法是以稳定度高的晶体振荡器为主振源,通过变换得到所需要的各种频率成分,分频器是一种主要变换手段。早期的分频器多为正弦分频器,随着数字集成电路的发展,脉冲分频器(又称数字分频器)逐渐取代了正弦分频器。
一般数字电路中的分频指脉冲分频,其指标包括频率和占空比。频率为周期的倒数,占空比为在一个周期中高电平占的时间比例。根据分频倍数,可分为偶数分频和奇数分频,根据占空比要求,可分为50%占空比分频和任意占空比分频。
偶数分频:
偶数分频指分频系数为2,4,6,8等偶数整数的分频电路,并且一般认为其分频后的占空比为50%。一种基本思路是每次时钟上升沿时令分频信号翻转,则得到了2分频信号,再以得到的2分频信号的上升沿触发新的分频信号翻转,则得到了4分频信号。这种方式的好处是不需要计数器,但局限性是只能得到2^n的分频系数的信号。
偶数分频较奇数分频更为常见,通过一个计数器就完全可以实现了。如需要N分频(N为偶数,则N/2为整数),可通过一个计数器在待分频时钟的触发下循环。当计数器从0计数至N/2 -1时,输出时钟翻转。
- module div6(clk_in,rst_n,clk_out);
- output clk_out; //输出 6 分频信号
- input clk_in,rst_n; //时钟信号
- parameter N=6;
- reg[3:0] cnt
- always @(posedge clk_in or negedge rst_n)
- begin
- if(!rst_n)
- begin cnt=4'b0000; clk_out=1'b0;end
- else if(cnt==(N/2-1))
- begin cnt=4'b0000; clk_out=~clk_out;end
- else cnt<=cnt+1;
- end
- endmodule
奇数分频:
由于奇分频需要保持分频后的时钟占空比为 50% ,所以不能像偶分频那样直接在分频系数的一半时使时钟信号翻转(高电平一半,低电平一半)。
在此我们需要利用输入时钟上升沿和下降沿来进行设计。
例子:接下来我们设计一个 5 分频(频率为之前的1/5)的模块,占空比为40%,设计思路如下:
实现方法为:
Step1: 双沿计数器计数;
使用2个计数器:cnt_up和cnt_down,分别在时钟的上升沿触发计数器cnt_up和cnt_down。
Step2:生成两个控制信号Clk_up和Clk_down;
cnt_up计数到(N-1)/2-1电平翻转信号Clk_up,再计数到N-1电平翻转信号Clk_up,同时cnt_down计数到(N-1)/2-1电平翻转信号Clk_down,再计数到N-1电平翻转信号Clk_down。
Step3: 求出分频后时钟;
如果Clk_up和Clk_down信号与Clk_out的关系与Clk_up和Clk_down信号中高低电平比有关(占空比):
(1)如果高 / 低电平比例为N-1/2 : N-1/2 + 1 ,则分频时钟 clk_div = clk_up || clk_down (如图 1 所示)。
(2)如果高 / 低电平比例为 N-1/2 +1 :N/2 ,则分频时钟 clk_div = clk_up && clk_down(如图 2 所示)。
- module div(clk_out, clk_in, rstn);
- output clk_out;
- input clk_in;
- input rstn;
-
- reg clk_out, clk_pos, clk_neg;
- reg [3:0] cnt_pos, cnt_neg;
- parameter N = 7;
- assign clk_out = clk_pos || clk_neg;
- always @(posedge clk_in or negedge rstn)
- if(!rstn) begin
- clk_pos <= 1'b0;
- cnt_pos <= 4'b0;
- end
- else if(cnt_pos == (N-1)/2) begin
- clk_pos <= ~clk_pos;
- cnt_pos <= cnt_pos + 1'b1;
- end
- else if(cnt_pos == N-1) begin
- cnt_pos <= 4'b0;
- clk_pos <= ~clk_pos;
- end
- else cnt_pos <= cnt_pos + 1'b1;
-
-
- always @(negedge clk_in or negedge rstn)
- if(!rstn) clk_neg <= 1'b0;
- else clk_neg <= clk_pos;
- endmodule
实现3.5分频
- module half_divide (clk,rst_n,clk_out);
-
- input clk;
- input rst_n;
- output clk_out;
-
- reg [3:0] p_cnt;
- reg [3:0] n_cnt;
-
- wire p_out;
- wire n_out;
-
- always@(posedge clk or negedge rst_n)
- if(!rst_n)
- p_cnt <= 4'd0;
- else if(p_cnt < 4'd6)
- p_cnt <= p_cnt + 1'b1;
- else
- p_cnt <= 4'd0;
-
-
- always@(negedge clk or negedge rst_n)
- if(!rst_n)
- n_cnt <= 4'd0;
- else if(n_cnt < 4'd6)
- n_cnt <= n_cnt + 1'b1;
- else
- n_cnt <= 4'd0;
-
- assign p_out = p_cnt == 4'd0 ? 1 : 0;
- assign n_out = n_cnt == 4'd4 ? 1 : 0;
-
- assign clk_out = p_out || n_out;
-
-
- endmodule
-