题解 | #任意小数分频#

任意小数分频

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

`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; //奇数周期

// ==================================================================================================
    // 关于Verilog编写小数分频电路,最开始确实没有头绪。牛客上本题的解析还是很到位的,第一个题解教会了我如何思考,
    // 第二个题解教会了我这题如何编码:

    //1 https://blog.nowcoder.net/n/a4d81838e9d24ceca35797c4754b7fe8
    //2 https://blog.nowcoder.net/n/7d57a3086a6448f69637cf284b492f3b

    // Verilog不可能精确地实现小数的分频,只能通过多个周期,以及不同的整数分频数来模拟小数分频的效果。
    // 这里需要实现8.7分频,即频率上 clk_in:clk_out=8.7:1=87:10,也就是说,8.7分频相当于87个clk_in内输出10个clk_out。
    // 然后对于小数分频,采用小数的上下限整数来设置分频,因为8<8.7<9,所以8.7分频需要通过clk_in的8分频和9分频共同来模拟。
    // 设10个clk_out周期中,有x个是clk_in的8分频时钟,有y个是clk_in的9分频时钟。
    // 由方程
    // x+y = 10 ①
    // 和
    // 8x+9y = 87 ②
    // 解得:
    // x=3, y=7
    // 即,对clk_in进行三次8分频和7次9分频,可以得到8.7分频的效果。
    // 根据题目中已有的要求,c98=24=3×8 知,本题需要先进行8分频。
// ==================================================================================================

//*************code***********//

    wire        rst_n   ;
    assign  rst_n = rst ;

    reg [6:0]   cnt_total;
    always @(posedge clk_in or negedge rst_n) 
    begin
        if(~rst_n)
            cnt_total <= 'd0;
        else
            cnt_total <= (cnt_total==M_N-1'd1)? 'd0 : cnt_total+1'd1;
    end

    reg [3:0] cnt_div_8; // 8分频的计数器
    reg [3:0] cnt_div_9; // 9分频的计数器
    // 8,9分频的计数器逻辑
    always @(posedge clk_in or negedge rst_n) 
    begin
        if(~rst_n) begin
            cnt_div_8 <= 'd0;
            cnt_div_9 <= 'd0;
        end
        else begin
            if(cnt_total <= c89-1) begin
                cnt_div_8 <= (cnt_div_8==DIV_E-1)? 'd0 : cnt_div_8+1'd1;
                cnt_div_9 <= 'd0;
            end
            else if(cnt_total > c89-1) begin
                cnt_div_9 <= (cnt_div_9==DIV_O-1)? 'd0 : cnt_div_9+1'd1;
                cnt_div_8 <= 'd0;
            end
            else begin
                cnt_div_8 <= 'd0;
                cnt_div_9 <= 'd0;
            end
        end
    end

    reg     clk_out_r;
    assign  clk_out = clk_out_r;
    // 输出逻辑
    always @(posedge clk_in or negedge rst_n) 
    begin
        if(~rst_n)
            clk_out_r <= 1'b0;
        else begin
            if(cnt_total <= c89-1)
            // 执行 8 分频输出
                clk_out_r <= (cnt_div_8==((DIV_E>>1)) || cnt_div_8=='d0)? ~clk_out_r : clk_out_r;
            else if(cnt_total > c89-1)
            // 执行 9 分频输出
                clk_out_r <= (cnt_div_9==((DIV_O>>1)) || cnt_div_9=='d0)? ~clk_out_r : clk_out_r;
            else
                clk_out_r <= clk_out_r;
        end
    end

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

全部评论

相关推荐

07-18 18:45
已编辑
中山职业技术学院 Java
投递TP-LINK等公司10个岗位
点赞 评论 收藏
分享
今天 13:42
门头沟学院 Java
点赞 评论 收藏
分享
点赞 评论 收藏
分享
来个厂收我吧:首先,市场侧求职我不是很懂。 但是,如果hr把这份简历给我,我会觉得求职人不适合做产品经理。 问题点: 1,简历的字体格式不统一,排版不尽如人意 2,重点不突出,建议参考star法则写个人经历 3,印尼官方货币名称为印度尼西亚卢比(IDR),且GMV690000印尼盾换算为305人民币,总成交额不高。 4,右上角的意向职位在发给其他公司时记得删除。 5,你所有的经历都是新媒体运营,但是你要投市场营销岗位,jd和简历不匹配,建议用AI+提示词,参照多个jd改一下经历内容。 修改建议: 1,统一字体(中文:思源黑体或微软雅黑,英文数字:time new romans),在word中通过表格进行排版(b站学) 2,校招个人经历权重:实习经历=创业经历(大创另算)>项目经历>实训经历>校园经历 3,请将项目经历时间顺序改为倒序,最新的放最上方。 4,求职方向不同,简历文字描述侧重点也需要不同。
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务