题解 | #任意小数分频#

任意小数分频

http://www.nowcoder.com/practice/24c56c17ebb0472caf2693d5d965eabb

简析

分频器

小数分频器是分频器中最难的一种,而且不能像整数分频那样得到均匀且占空比为50%的分频输出。

小数分频

假设输出clk_out是输入clk_inNN分频。首先要将分频系数NN化为分数形式,比如4.751944.75\rightarrow \frac{19}{4}3.434103.4\rightarrow \frac{34}{10}。本题中,8.78.7可以化为8710\frac{87}{10}。这意味着在87个clk_in周期内输出10个clk_out周期就可以实现分频。

然后采用若干种(一般是两种)整数分频在87个原周期clk_in内产生10个新时钟周期clk_out。整数分频的分频系数有很多种选择,但要尽可能接近,提高clk_out的均匀度。一般推荐在小数分频系数NN的附近选取。因为8<N<98<N<9,所以两个整数分频系数是8和9。接着要计算87个clk_out周期分别有多少个是8分频和9分频的。设每10个clk_out中有xx个8分频输出和yy个9分频输出,则可列出如下方程:

{x+y=10,8x+9y=87\left\{ \begin{array}{l} x+y=10, \\ 8x+9y=87 \end{array} \right.

可得x=3x=3y=7y=7。也就是3个8分频和7个9分频一组,循环输出,就等效于8.7分频。 最后安排组内8分频和9分频的位置。这里的方法也不固定,不过本题要求3个8分频先输出,再输出7个9分频,如下图。

参数介绍

题目提供的

  • M_N=87。一组clk_out输出需要的clk_in时钟数量。
  • c89=24。切换分频系数的时间点。从这里可以看出,本题要求先输出3个8分频。
  • div_e=8。分频系数1。
  • div_o=9。分频系数2。

自定义的

  • cyc_cnt。对clk_in进行计数,达到M_N后清零。
  • div_flag。8/9分频标志。当div_flag==0时是8分频;当div_flag==1时是9分频。cyc_cnt==M_N-1或者cyc_cnt==c89-1时该标志位翻转。
  • clk_cnt。用于产生分频输出。当div_flag==0时,计数最大值是div_e-1;当div_flag==1时,计数最大值是div_o-1
  • clk_out_r。根据clk_cntdiv_flag产生分频输出。

代码

`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 [3:0] clk_cnt;
    reg [6:0] cyc_cnt;
    reg div_flag;
    reg clk_out_r;
    
    always@(posedge clk_in or negedge rst) begin
        if(~rst)
            clk_cnt <= 0;
        else if(~div_flag)
            clk_cnt <= clk_cnt==(div_e-1)? 0: clk_cnt+1;
        else
            clk_cnt <= clk_cnt==(div_o-1)? 0: clk_cnt+1;
    end
    
    always@(posedge clk_in or negedge rst) begin
        if(~rst)
            cyc_cnt <= 0;
        else
            cyc_cnt <= cyc_cnt==(M_N-1)? 0: cyc_cnt+1;
    end
    
    always@(posedge clk_in or negedge rst) begin
        if(~rst)
            div_flag <= 0;
        else
            div_flag <= cyc_cnt==(M_N-1)||cyc_cnt==(c89-1)? ~div_flag: div_flag;
    end
    
    always@(posedge clk_in or negedge rst) begin
        if(~rst)
            clk_out_r <= 0;
        else if(~div_flag)
            clk_out_r <= clk_cnt<=((div_e>>2)+1);
        else
            clk_out_r <= clk_cnt<=((div_o>>2)+1);
    end
    
    assign clk_out = clk_out_r;
//*************code***********//
endmodule
Verilog篇题解 文章被收录于专栏

本人对牛客网verilog篇题目一些理解

全部评论
第一个<=为非阻塞赋值,第二个<= 为关系操作符小于等于。故上式即为当clk_cnt小于等于(div_e>>2)+1时,clk_out_r=1;又div_e=5'd8=4'b1000,(div_e>>2)+1=0010+1=0011=3
9 回复 分享
发布于 2022-08-12 11:04
clk_out_r <= clk_cnt<=((div_e>>2)+1);这个怎么理解的呢?
2 回复 分享
发布于 2022-05-29 15:48
clk_out_r 也可以这样写 always @(posedge clk_in or negedge rst) begin if(~rst) begin clk_out_r <= 0; end else if(clk_cnt==0||clk_cnt==4) clk_out_r <= ~clk_out_r; end end
2 回复 分享
发布于 2022-10-12 21:44 广东
想问问最后的结果,clk_out_r 里面4‘d8>>2和4’d9>>2结果不是一样吗
1 回复 分享
发布于 2022-12-04 21:45 广东
为啥九分频的时候占空比设为5/9通过不了测试呢
1 回复 分享
发布于 2023-07-07 17:33 湖北
最后一个判断条件写成 clk_out_r <= (clk_cnt < (div_e>>1)); 会更好吧,除以4再+1,占空比会很差
1 回复 分享
发布于 2023-09-30 10:56 陕西
同问
点赞 回复 分享
发布于 2022-07-03 16:21
9分频的占空比是不是没有要求
点赞 回复 分享
发布于 2022-08-13 16:03
兄弟,你和我想到一起了,我第一反应,9分频时占空比为5/9,但没通过..
点赞 回复 分享
发布于 2023-07-10 11:19 上海
跑不通哇,可以有两个<=吗?
点赞 回复 分享
发布于 2023-08-28 11:14 四川

相关推荐

和蔼:在竞争中脱颖而出,厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
点赞 评论 收藏
分享
10-30 21:47
已编辑
广东财经大学 web前端
小红书 实习 9-10k
哇咔咔嘞:先签小厂,然后去实习,春招找到好的再违约
点赞 评论 收藏
分享
103 16 评论
分享
牛客网
牛客企业服务