Verilog 每日一题 —经典时钟分频(VL17 任意小数分频)

题目描述

请设计一个可以实现任意小数分频的时钟分频器,比如说8.7分频的时钟信号

注意rst为低电平复位

提示:

其实本质上是一个简单的数学问题,即如何使用最小公倍数得到时钟周期的分别频比。

设小数为nn,此处以8.7倍分频的时钟周期为例。

首先,由于不能在硬件上进行小数的运算(比如2.1个时钟这种是不现实的,也不存在3.3个寄存器),小数分频不能做到分频后每个时钟周期都是源时钟的nn倍,也无法实现占空比为1/2,因此,考虑小数分频,其实现方式应当为53个clkout时钟周期是10个clkin时钟周期的8.7倍。



题目解析:

8.7倍分频,即周期变为原来的8.7倍,周期计数不存在0.几个周期,所以需要将87个clk,转换为输出的10个周期,这就实现了8.7倍分频。类似的,小数倍都可以用这种方法。

进一步的,为了使得周期更加接近,且尽量靠近50%的占空比,在这一题里用了拆分输出周期长度的方法,分别以离8.7最近的两个整数8和9,以8个clk和9个clk为周期进行拆分。

所以,由于需要满足总周期为10,且和为87,则有,易得,8clk为周期的有三个,9clk为周期的有7个。可以得出他们分别的计数周期为8和9.

而对于偶数周期8,4clk跳变一次,对于奇数周期9, 4clk和5clk跳变一次。

此方法针对所有的小数都适用,总结流程为:

1、确定周期数之比;如8.7——87比10, 4.2——21比5。

2、确定奇数和偶数周期的长度;如8.7——87比10——8和9;4.2——21比5——2和3。

3、计算奇数和偶数周期个数;如8.7—87比10—8和9—3个/7个;4.2—21比5—4和5—4个/1个。

4、分别设置一个奇数偶数的计数器,偶数周期num/2时跳变,奇数周期(num-1/2)时跳变。

注意:若奇数周期也一定要求50%的占空比,则可以结合原输入clk的所有边沿进行考虑。

具体代码详解如下:

`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***********//
    
    //需要一个clk_in的计数器 cnt1,计数87个clk周期
    reg [6:0] cnt1;
    always @(posedge clk_in or negedge rst) begin
        if(!rst) 
            cnt1 <= 0 ;
        else
            cnt1 <=(cnt1==M_N-1)? 0 : cnt1 + 1;
    end

 
    //需要对奇数周期和偶数周期进行计数 cnt_e cnt_o
    reg [3:0] cnt_e,cnt_o;    //位宽一开始写成3bits了,要注意3bits只能计到7           
    always @(posedge clk_in or negedge rst) begin
        if(!rst) begin
            cnt_e <= 0;
            cnt_o <= 0;
        end
        else if(cnt1 <= c89-1) 
            cnt_e <= ( cnt_e  == div_e-1 )? 0 : cnt_e +1; //偶数周期
     
        else if(cnt1 > c89-1) 
            cnt_o <= ( cnt_o == div_o-1 )? 0 : cnt_o + 1; //奇数周期
           
    end
    
    //输出out1
    reg out;
    always @(posedge clk_in or negedge rst) begin
        if(!rst) 
            out <= 0 ;
        else if( ((cnt_e == 4 | cnt_e == 0)&&(cnt1 <c89 )) | ( (cnt_o == 0 |  cnt_o == 4)&&(cnt1 >= c89 )) ) 
//条件判断,偶数周期,4clk翻转一次;期数周期,在4clk和5clk翻转
            out <= ~out ; 
    end
    
    assign clk_out = out;

//*************code***********//
endmodule

 



结束啦!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值