任意小数分频
题目描述
请设计一个可以实现任意小数分频的时钟分频器,比如说8.7分频的时钟信号
注意rst为低电平复位
提示:
其实本质上是一个简单的数学问题,即如何使用最小公倍数得到时钟周期的分别频比。
设小数为nn,此处以8.7倍分频的时钟周期为例。
首先,由于不能在硬件上进行小数的运算(比如2.1个时钟这种是不现实的,也不存在3.3个寄存器),小数分频不能做到分频后每个时钟周期都是源时钟的nn倍,也无法实现占空比为1/2,因此,考虑小数分频,其实现方式应当为53个clkout时钟周期是10个clkin时钟周期的8.7倍。
信号示意图:
题目解读
其实本质上是一个简单的数学问题,即如何使用最小公倍数得到时钟周期的分别频比。
设小数为nn,此处以8.7倍分频的时钟周期为例。
首先,由于不能在硬件上进行小数的运算(比如2.1个时钟这种是不现实的,也不存在3.3个寄存器),小数分频不能做到分频后每个时钟周期都是源时钟的nn倍,也无法实现占空比为1/2,因此,考虑小数分频,其实现方式应当为87个clkout时钟周期是10个clkin时钟周期的8.7倍。
所以很简单,根据提示,我们可以进行如下假设:首先设置有两个整数分频电路,一个是奇数一个是偶数,设其分频比为a和b,然后其分别的时钟占N/M个周期。则我们可以得到:
aN+bM = 87
N+M = 10
如果使用 8 和 9分频,则有:
8N+9M = 87
N+M = 10
因此 M为7, N为3。
具体步骤:
1)设计一个计数次数87的计数器,即0-86
2)分别生成8分频和9分频的计数器,计数次数分别为0-6和0-2
3)输出波形根据总计数器和8、9分频计数器的数值控制输出脉冲翻转
`timescale 1ns/1nsmodule 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; //奇数周期reg [6:0] cnt;
reg [3:0] cnt_e;
reg [3:0] cnt_o;
reg clk_MN;
assign clk_out = clk_MN;//总计数器
always @(posedge clk_in or negedge rst) beginif(!rst)cnt <= 6'b0;else beginif(cnt == M_N - 1'b1)cnt <= 6'b0;elsecnt <= cnt + 1'b1;end
end always @(posedge clk_in or negedge rst) begin if(!rst) begincnt_e <= 4'b0;cnt_o <= 4'b0;end else if(cnt<=c89-1'b1) begincnt_o <= 4'd0;if(cnt_e == div_e - 1'b1)cnt_e <= 4'd0;elsecnt_e <= cnt_e + 1'b1;end else if(cnt>c89-1'b1) begincnt_e <= 4'd0;if(cnt_o == div_o - 1'b1)cnt_o <= 4'd0;elsecnt_o <= cnt_o + 1'b1;end
endalways @(posedge clk_in or negedge rst) beginif(!rst)clk_MN <= 1'b0;else beginif(cnt<c89) beginif(cnt_e == 4'd0 || cnt_e == div_e/2)clk_MN <= ~clk_MN;endif(cnt>=c89) beginif(cnt_o == 4'd0 || cnt_o == (div_o - 1'b1)/2)clk_MN <= ~clk_MN;endend
endendmodule