时钟分频

来自:https://www.runoob.com/w3cnote/verilog2-clock-division.html
目前在大部分设计中还广泛使用集成锁相环(如altera的PLL,Xilinx的DLL)来进行时钟的分频、倍频以及相移设计,但是,对于时钟要求不太严格的设计,通过自主设计进行时钟分频的实现方法仍然非常流行。首先这种方法可以节省锁相环资源,再者,这种方式只消耗不多的逻辑单元就可以达到对时钟操作的目的。

1. 偶数分频:

采用模N/2计数器,计数器在 (N/2-1)时,输出波形实现翻转。

module clk_div_odd(clk, rstn, clk_div10); 
    input wire clk ;   
    input wire rstn ;
    output wire clk_div10 ;
    parameter N = 10 ;
    reg clk_div10_r ;
    reg [3:0] cnt ;
    always @(posedge clk or negedge rstn) begin
        if(!rstn) cnt <= 'd0;
        else if(cnt==(N/2)-1) cnt <= 'd0;
        else cnt <= cnt + 1;
    end

    assign clk_div10 = clk_div10_r;
    always @(posedge clk or negedge rstn) begin
        if(!rstn) clk_div10_r <= 1'b0;
        else if(cnt == (N/2)-1) clk_div10_r <= ~clk_div10_r;
        else clk_div10_r <= clk_div10_r;
    end
endmodule        

2. 奇数分频

如果不要求占空比为 50%,可用模N计数器。然后根据计数值选择一定的占空比输出分频时钟。对于实现占空比为50%的奇数分频,可以利用源时钟双边沿特性并采用"与操作"或"或操作"的方式将分频时钟占空比调整到 50%。

或操作:

module clk_div_even(clk, rstn, clk_div9);
input wire clk ;
input wire rstn ;
output wire clk_div9 ;
parameter N = 9 ;
reg clk_div9_r ;
reg [3:0] cnt ;
always @(posedge clk or negedge rstn) begin
    if(!rstn) cnt <= 'd0;
    else if(cnt==N-1) cnt <= 'd0;
    else cnt <= cnt + 1;
end

//count when posedge
reg clkp_div9_r;
always @(posedge clk or negedge rstn) begin
    if(!rstn) clkp_div9_r <= 1'b0;
    else if(cnt == (N/2)-1) clkp_div9_r <= 1'b0; //4-8 low
    else if(cnt == N-1) clkp_div9_r <= 1'b1; //0-3 high
end

//count when negedge
reg clkn_div9_r;
always @(negedge clk or negedge rstn) begin
    if(!rstn) clkn_div9_r <= 1'b0;
    else if(cnt == (N/2)-1) clkn_div9_r <= 1'b0;
    else if(cnt == N-1) clkn_div9_r <= 1'b1;
end

assign clk_div9 = clkp_div9_r | clkn_div9_r ;

endmodule

与操作:

原理:假设实现N=2K+1分频,则计数器通过下降沿采样产生K个高电平;K+1个低电平的信号,通过下降沿采样将该信号平移0.5T相位,然后将这两个信号一或,则原来的高电平多出半个周期,原来的低电平减少半个周期。

3. 半整数分频:

在实际工程中,我们还经常会遇到半分频器。比如要得到2MHz的时钟信号,而系统晶振频率为25MHz,这时候就需要对系统时钟作12.5分频。那么这种半分频器又该如何实现呢?最直接的办法当然还是用计数器了,由于半整数分频无法实现50%的占空比(因为50%占空比就要求一个周期内高低电平都是6.25个系统时钟周期,这个0.25是不可能实现的),我们只能让占空比尽可能接近50%。

以4.5分频为例:

采用一个模9计数器分前5(3低2高)后4(2低2高),然后采用一个模5计数器在时钟下降沿采样产生一个调整信号,当计数到5/2-1=2的时候翻转,然后将这两个信号相或:

4. 小数分频

小数分频不能做到分频后的每个时钟周期都是源时钟周期的小数分频倍,更不能做到分频后的时钟占空比均为 50%,因为 Verilog 不能对时钟进行小数计数。和半整数分频中第一次分频时引入的"平均频率"概念类似,小数分频也是基于可变分频和多次平均的方法实现的。例如进行 7.6 倍分频,则保证源时钟 76 个周期的时间等于分频时钟 10 个周期的时间即可。

实现方法如下:

以7.6分频为例,其分频计算公式为:7M+8N=76;M+N=10,则

7 分频和 8 分频的实现顺序有以下 4 种:

(1) 先进行 4 次 7 分频,再进行 6 次 8 分频;

(2) 先进行 6 次 8 分频,再进行 4 次 7 分频;

(3) 将 4 次 7 分频平均地插入到 6 次 8 分频中;

(4) 将 6 次 8 分频平均地插入到 4 次 7 分频中。

前两种方法时钟频率不均匀,相位抖动较大,所以一般会采用后两种平均插入的方法进行小数分频操作。平均插入可以通过分频次数差累计的方法实现。

7.6 分频的实现过程如下:

(1) 第一次分频次数差值为 76-10*7 = 6 < 10,第一次进行 7 分频。

(2) 第二次差值累加结果为 6+6=12 > 10,第二次使用 8 分频,同时差值修改为 12-10=2。

(3) 第三次差值累加结果为 2+6=8 < 10,第三次使用 7 分频。

(4) 第四次差值累加结果为 8+6=14 > 10,第四次使用 8 分频,差值修改为 14-10=4。

以此类推,完成将 6 次 8 分频平均插入到 4 次 7 分频的过程。

posted @ 2023-01-14 15:25  Kazu-ki  阅读(378)  评论(0编辑  收藏  举报