6、任意小数分频
小数分频器是分频器中最难的一种,而且不能像整数分频那样得到均匀且占空比为50%的分频输出。
以8.7分频为例:
小数分频,8.7分频,87个输入上升沿对应10个输出上升沿
87 = 10 * 8.7
87 = 9 * 9 + 1 * 6
87 = 8 * 9 + 2 * 7.5
87 = 7 * 9 + 3 * 8
87 = 6 * 9 + 4 * …
87 = 5 * 9 + 5 * …
然后采用若干种(一般是两种)整数分频在87个原周期clk_in内产生10个新时钟周期clk_out。整数分频的分频系数有很多种选择,但要尽可能接近,提高clk_out的均匀度。一般推荐在小数分频系数 N的附近选取。因为 8 < N < 9 , 所以两个整数分频系数是8和9。接着要计算87个clk_out周期分别有多少个是8分频和9分频的。设每10个clk_out中有x个8分频输出和y个9分频输出,则可列出如下方程:
x + y = 10;
8x+9y = 87;
可得x = 3,y=7。3个8分频和7个9分频一组,循环输出,就等效于8.7分频。
`timescale 1ns/1ns
module div_M_N
(
input wire clk_in,
input wire rst,
output wire clk_out
);
parameter M_N = 8'd87;
parameter c89 = 8'd24; // 8/9时钟切换点
parameter div_e = 5'd8; // 偶数周期
parameter div_o = 5'd9; // 奇数周期
//*************code***********//
reg [7:0] cnt;
reg [4:0] cnt1,cnt2;
reg clk_temp;
//总计数器
always@(posedge clk_in or negedge rst)begin
if(!rst)
cnt <= 0;
else if(cnt == M_N-1) //计数到最大值清零
cnt <= 0;
else
cnt <= cnt + 1;
end
//分开计数器
always@(posedge clk_in or negedge rst)begin
if(!rst)begin
cnt1 <= 0;
cnt2 <= 0;
end
else if(cnt < c89)begin
if(cnt1 == div_e-1) //计数到偶数最大值清零
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
else begin
if(cnt2 == div_o-1) //计数到奇数最大值清零
cnt2 <= 0;
else
cnt2 <= cnt2 + 1;
end
end
//判断输出
always@(posedge clk_in or negedge rst)begin
if(!rst)
clk_temp <= 0;
else if(cnt < c89)begin
if(cnt1 < 3'd4) //在0~24之间,计数0~3翻转,8分频
clk_temp <= 1;
else
clk_temp <= 0;
end
else begin
if(cnt2 < 3'd4) //在24~87之间,计数0~3翻转,9分频
clk_temp <= 1;
else
clk_temp <= 0;
end
end
assign clk_out = clk_temp;
//*************code***********//
endmodule