分频:简单来说,二分频后的方波一个周期为标准方波高低电平循环两个周期,四分频为4个周期。分频后的时钟周期为原来的n倍,即为n分频。
频率和周期的关系:f=1/T
(1)简单的计数器
计数器实质是对输入的驱动时钟进行计数,在某种意义上讲,等同于对时钟进行分频。
下面举例来说明:假设寄存器位数为n,最大计数长度为2n(从0计数到N-1)的计数器。假设位数为3,从0开始依次计数为:000、001、010、011、100、101、110、111。一共计8个数,计满后下一次计数为000,开始循环计数。观察这几个数的最高位,00001111,每一个周期计数一次,共计8次,8个周期,8分频。次高位为00,4个周期完成循环,为4分频。最低位为0,2个周期完成循环,为2分频。最高位的输出为N=2^n分频,次高位为N/2分频。
module test#(parameter N=3)( input clk, input rst_n, output clk_div ); reg [N-1:0] div_reg ;//分频计数器 always @(posedge clk or negedge rst_n) if (rst_n == 1'b0 ) div_reg <= 0 ; else div_reg <= div_reg + 1'b1 ; assign clk_div = div_reg[N-1] ; endmodule
讯享网
当n不是2的整数次幂时,如n为5,从0计数到n-1,其最高位作为时钟输出(占空比不一定为 50%),即从0计数到4后又返回0,那么需要定义一个三位的寄存器。寄存器的计数过程为:
000-001-010-011-100-000-001-010-011-100-000-001-010-011-100-000-001-010-011-100···
最高位为0-0-0-0-1-0-0-0-0-1,计数5次,5个周期,为5分频。但占空比不是50%。
可以看出:一个最大计数长度为N(从0计数到N-1)的计数器,其最高位的输出,是输入频率的N分频。
(2)偶数分频(50%占空比)
当进行2、4、8(2的n次)分频时,输出2的n次最高位即为相应分频,并且占空比为50%,但6、10这样的分频,占空比就不是50%了,该怎么办呢?
解决办法很简单,以6分频举例,当计数到3时,将时钟翻转,计数清零并重新计数。当n=6时,6/2=3,计算机计数从0开始,0、1、2、3共计数4次。
讯享网module test#(parameter N=6)( input clk, input rst_n, output clk_div ); reg div_reg ; reg [N-1:0] div_cnt ;//分频计数器 always @(posedge clk or negedge rst_n) if (rst_n == 1'b0 )begin div_cnt <= 0 ; div_reg <= 0 ; end else if(div_cnt == (N/2 - 1))begin div_cnt <= 0; div_reg <= ~div_reg ; end else div_cnt <= div_cnt + 1'b1 ; assign clk_div = div_reg ; endmodule
(3)奇数倍分频
①占空比接近50%
第一种方法与上面的类似,先将奇数变成偶数,再除以2,计数完成进行时钟翻转。此时得出的分频接近50%,N越大越趋近于50%。
②占空比50%
一个周期的系统时钟可以分为一个高电平和低电平。假设目标为3分频,循环三次的话高低高低高低;假如我是说假如在高低高这三个阶段输出1,在地高低这三个阶段输出0,组成的新时钟刚好是占空比为50%的3分频时钟。
那我们该怎样实现呢?
从上升沿开始计数到1(也就是上面系统时钟的高低),计数时输出1,完成后输出0,一直到计数到2时翻转。
从下降沿开始计数,计一个周期(也就是上面的低高),计数时输出1,完成后输出0,一直到计数为2时翻转。两个时钟相或,就可以得到想要的结果。如下图所示:

第一个上升沿来临后,计数器从0开始自加1,同时输出1,第二个上升沿来临后,计数器值自加1,输出变为0,第三个上升沿来临计数为2,下一个上升沿来临时,计数器满足要求,开始翻转输出,这样循环。
下降沿采用同样思路编写代码。
module test#(parameter N=5)(//N分频 input clk, input rst_n, output clk_div ); reg sig_r ;//定义一个上升沿翻转的信号 reg sig_f ;//定义一个下降沿翻转的信号 reg [N-1:0] cnt_r;//上升沿计数器 reg [N-1:0] cnt_f;//下降沿计数器 wire clk_f ; assign clk_f = ~clk ;//用来触发下降沿计数器的时钟 //由于同时使用上升沿和下降沿触发器不好,因此我们为同一边沿,都使用上升沿触发 //只不过是将时钟进行反向 always @(posedge clk or negedge rst_n)begin//上升沿计数 if(rst_n == 1'b0)begin sig_r <= 0 ; cnt_r <= 0 ; end else if( cnt_r == (N-1)/2 )begin sig_r <= ~sig_r ; cnt_r <= cnt_r + 1 ; end else if ( cnt_r == (N-1) )begin sig_r <= ~sig_r ; cnt_r <= 0 ; end else cnt_r <= cnt_r + 1 ; end always @(posedge clk_f or negedge rst_n)begin//下降沿计数 if(rst_n == 1'b0)begin sig_f <= 0 ; cnt_f <= 0 ; end else if( cnt_f == (N-1)/2 )begin sig_f <= ~sig_f ; cnt_f <= cnt_f + 1 ; end else if ( cnt_f == (N-1) )begin sig_f <= ~sig_f ; cnt_f <= 0 ; end else cnt_f <= cnt_f + 1 ; end assign clk_div = sig_f || sig_r ; endmodule
讯享网module test #( parameter cfactor= 5)( input clk, input rst_n, output clk_div ); reg clk_loc; //reg [15:0] cnt;//allowed maximum clock division factor is 65536 reg [7:0] cnt;//allowed maximum clock division factor is 256 assign clk_div = (cfactor==1)? clk : clk_loc; //assign clk_div = ((rst==1) || (cfactor==1))? clk : clk_loc; always@(posedge clk or negedge rst_n) if(!rst_n)begin cnt <= 'd0; clk_loc = 1; end else begin cnt <= cnt + 1'b1; if(cnt==cfactor/2-1) clk_loc = 0; else if(cnt==cfactor-1) begin cnt <= 'd0; clk_loc = 1; end end endmodule

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/129087.html