分频器设计

一、偶数分频(等占空比)

偶数分频:假设为N分频,由待分频的时钟触发计数器进行计数,计数器从0计数到N/2-1,输出时钟进行翻转并给计数器一个复位信号,使其从下一个时钟从零开始计数。依次循环。

另外有一种方法适合对2^n分频。就是使用触发器进行分频,先利用第一个触发器的输出Q取反给输入D,这样完成2分频。然后将2分频后的时钟作为下一级触发器的时钟,用同样的方法完成4分频,依次类推,3个触发器完成8分频,4个触发器完成16分频…
在这里插入图片描述

//8分频
moudle fenpin_even(
	input clk,
	input rst_n,
	output reg clk_div8
);

reg [3:0] cnt;
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		cnt <= 4'b0;
	end
	else if(cnt==4'd3) begin
		cnt <= 4'd0;
	end
	else begin
		cnt <= cnt + 1'b1;
	end
end

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		clk_div8 <= 1'b0;
	end
	else if(cnt==4'd4) begin
		clk_div8 <= ~clk_div8;
	end
end

endmodule

使用第二种方法完成8分频

//8分频
module clk_even8(
	input clk,
	input rst_n,
	output reg clk_div8
);

reg clk_div2;
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		clk_div2 <= 1'b0;
	end
	else begin
		clk_div2 <= ~clk_div2;
	end
end

reg clk_div4;
always @ (posedge clk_div2 or negedge rst_n) begin
	if(!rst_n) begin
		clk_div4 <= 1'b0;
	end
	else begin
		clk_div4 <= ~clk_div4;
	end
end

always @ (posedge clk_div4 or negedge rst_n) begin
	if(!rst_n) begin
		clk_div8 <= 1'b0;
	end
	else begin
		clk_div8 <= ~clk_div8;
	end
end
endmodule

二、奇数分频(等占空比)

通过计数器实现,比如3分频,通过待分频时钟上升沿触发计数器进行模3计数,当计数器计数到邻近值进行两次翻转,可以在计数到邻近值进行两次翻转,在计数到1时,输出进行翻转,计数到2再翻转,这样实现了占空比为1/3或2/3。
要实现占空比为50%的奇数分频器,在待分频的时钟的上升沿触发计数器,在模n时候进行翻转,再在(n-1)/2再进行翻转,这样得到一个非50%的n倍奇数分频。再利用下降沿触发模n计数,在(n-1)的时候进行一次翻转,再在(n-1)/2,的时候进行一次翻转,得到另一个奇数分频。最后将两个奇数分频相或运算,就能得到占空比为50%的奇数分频了。

//占空比50%的7分频
module clk_div7(
	input clk,
	input rst_n,
	output clk_div7
);
reg [2:0] cnt1;
reg [2:0] cnt2;
reg clk_pos;
reg clk_neg;

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		cnt1 <= 3'd0;
	end
	else if(cnt1==3'd6) begin
		cnt1 <= 3'd0;
	end
	else begin
		cnt1 <= cnt1 + 1'b1;
	end
end

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		clk_pos <= 1'b0;
	end
	else if(cnt1==3'd2) begin
		clk_pos <= ~clk_pos;
	end
	else if(cnt1==3'd6) begin
		clk_pos <= ~clk_pos;
	end
end

always @ (negedge clk or negedge rst_n) begin
	if(!rst_n) begin
		cnt2 <= 3'd0;
	end
	else if(cnt2==3'd6) begin
		cnt2 <= 3'd0;
	end 
	else begin
		cnt2 <= cnt2 + 1'b1;
	end
end
 
always @ (negedge clk or negedge rst_n) begin
	if(!rst_n) begin
		clk_neg <= 1'b0;
	end
	else if(cnt2==3'd2) begin
		clk_neg <= ~clk_neg;
	end
	else if(cnt2==3'd6)begin
		clk_neg <= ~clk_neg;
	end
end
assign clk_div7 = clk_pos & clk_neg;

endmodule

关于最后是用&还是用|,这个跟在上面进行计数时是用(n-1)/2进行翻转,还是用“剩下的数”进行翻转。

进行奇数n分频时钟,首先进行n/2分频(带小数,即等于(n-1)/2+0.5),然后再进行二分频得到占空比为50%的奇数倍分频。

三、 小数分频

半整数分频
如何进行n+0.5分频,这种分频需要对输入时钟进行操作。基本的设计思想是:对于进行n+0.5分频,首先要进行模n的计数,在计数到n-1的时候,输出时钟赋值为1,回到计数0时,又赋值给0,因此可以知道,当计数值为n-1的时,输出时钟才为1.因此只要保持计数值n-1为半个输入时钟周期,即实现了n+0.5分频时钟,因此保持n-1为半个时钟周期即是一个难点。从中可以发现,因为计数器是通过时钟上升沿计数,因此可以在计数为n-1时,对计数触发时钟进行翻转,那么时钟的下降沿就变成了时钟的上升沿。即在计数值为n-1期间的时钟下降沿变成了上升沿,则计数值n-1只保持了半个时钟周期,由于时钟翻转下降沿变成上升沿,因此计数值变为0。因此,每产生一个n+0.5分频时钟周期,触发时钟都要翻转一次。

计数值是通过上升沿触发,故在计数为N-1时对计数触发进行翻转,时钟的下降沿变成上升沿,因此计数值为0,所以每产生n+0.5分频时钟的周期,触发时钟都要翻转一次。

第二种方法:N+0.5分频,如N=3进行3.5分频。
先将clk时钟周期的一半记做clk_half,即一个高电平或一个低电平的时间。
对2 * (N+0.5)=2N + 1.这个数一定是奇数,按照奇数分频的思路,也取clk_p和clk_n,但是计数的值不一样,一个计数N个clk时钟周期(2N)个clk_half周期,一个计数2N+2个clk_half,两者位置关系如图所示,这样,两者相与,则所得信号一个周期的高低电平共有2N+1个clk_half周期,即(N+0.5)个clk周期。
在这里插入图片描述

//2.5分频
module clk_div_half(
	input clk,
	input rst_n,
	output clk_out
);

reg [2:0] count_p;
reg [2:0] count_n;
reg clk_p;
reg clk_n;

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		count_p <= 3'd0;
	end
	else if(count_p==3'd4) begin
		count_p <= 3'd0;
	end
	else begin
		count_p <= count_p + 1'b1;
	end
end

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		clk_p <= 1'b0;
	end
	else if(count_p==3'd3 || count_p==3'd0) begin
		clk_p <= ~clk_p;
	end
end

always @ (negedge clk or negedge rst_n) begin
	if(!rst_n) begin
		count_n <= 3'd0;
	end
	else if(count_n==3'd4) begin
		count_n <= 3'd0;
	end
	else begin
		count_n <= count_n + 1'b1;
	end
end

always @ (negedge clk or negedge rst_n) begin
	if(!rst_n) begin
		clk_n <= 1'b1;
	end
	else if(count_n==3'd2 || count_n==3'd0) begin
		clk_n <= ~clk_n;
	end

end

assign clk_out = clk_p & clk_n;

endmodule

在这里插入图片描述
首先来了解分频比的概念,分频比是指原频率和分频后的频率的比值,为了更好的理解后边的内容,也可以理解为一段时间内原时钟出现的周期数和分频后的时钟所出现的周期数的比值(此处设为4.7),即满足关系:4.7*T1=T2。

只用verilog的话无法真正意义上的实现小数分频,比如说实现4.7分频,实际上是通过4分频和5分频来实现的,通过控制4分频和5分频的所占比例来调控交替产生4到5之间的任意分频比(准确的说这里的“任意”实际上要考虑精度的限制)。虽然短时间内看到的是4分频和5分频,但从更多的周期数来看的话(统计的周期数越多越精确)是4.7分频(分频比为周期数与周期数的比值)。

对照前面的关系式:4.7*T1=T2,可知,我们的目标是原时钟经过4.7个脉宽,分频后的时钟才经过1个脉宽,但是4.7个脉宽是无法实现的。那么我们再来转化一下目标,等式左右两边同时乘以10,化为整数(也可以乘以别的数,目标是化为整数,视分频比和精度而定),所以目标变为原时钟经过47个脉宽,分频后的时钟经过10个脉宽(其实这里的10个脉宽即周期不全是相等的,因为,有些是4分频的时钟,有些是5分频的时钟,只要满足公式就行了)。那么其中的脉宽哪些是4分频,哪些是5分频的呢,可以分别记为m和n,那么它们必须满足下面关系:
m+n=10

4m+5n=47

求得m=3,n=7,即在原时钟47个脉宽的时间内,要把其中的12个脉宽转化为3个4分频时钟的脉宽,即34=12,另外35个脉宽转化为7个5分频时钟的脉宽,即75=35。

值得注意的是,应当尽量使4分频时钟和5分频时钟均匀分配,所以,47个原时钟脉宽,你不能前35个脉宽产生5分频,后12个脉宽产生4分频,这样会使频谱出现更多的杂散,这点可以用MATLAB仿一下(待确认)。

最后,再来确认一下分频比,47/(3+7)=4.7,再次强调,这里的分频比是周期数除以周期数,前提是相同时间内。

值得思考的地方:

1、分频比4.7介于4到5之间,所以可以用4分频和5分频来交替产生,我们把范围扩展一下4.7也介于3到6之间,所以能用3分频和6分频来交替产生吗,推而广之,奇数分频产生比偶数分频产生更麻烦一点,那么为什么不用4分频和6分频呢,这个值得思考,个人认为可以从频谱的角度考虑。

猜你喜欢

转载自blog.csdn.net/weixin_43727437/article/details/107362652