题解 | #占空比50%的奇数分频#

占空比50%的奇数分频

https://www.nowcoder.com/practice/ccfba5e5785f4b3f9d7ac19ab13d6b31

`timescale 1ns/1ns

module odo_div_or
   (
    input    wire  rst ,
    input    wire  clk_in,
    output   wire  clk_out7
    );

    wire          rst_n;
    assign rst_n = rst;

//=========================================================================
// 这里,实现占空比 50%的奇数分频,可以在输入时钟的基础上,对其上升沿和下降沿分别计数,
// 从而得到两个时钟。
// 在本题中,奇数为7,且因为最开始时钟输出为低电平,因此在非50%占空比的7分频电路下,应当将输出时钟拉高的周期数目设置得短一些。
// 则设置翻转计数值为 [7/2]+1=4,效果也就是如:
// 周期0,1,2,3低电平;周期4,5,6为高电平。这样不是50%占空比。实现50%占空比,需要对时钟的
// 上升沿进行计数,按照如上翻转规律,得到时钟clk_p;再对时钟的下降沿进行计数,同样得到clk_n。
// 这样clk_p和clk_n的相位差为半个时钟周期。

// 根据clk_p,clk_n和clk_in的时序对比,对(clk_p|clk_n)进行逻辑判断即可得到占空比50%的7分频电路。
// 即其翻转位置在第三个周期的中间。(3.5个周期)
//=========================================================================

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

    // ======================================================================================
    // 方式(二):通过对clk_in上下沿分别进行计数,得到两个7分频3:4占比时钟
    // ======================================================================================
    reg [2:0] cnt_pos;
    always @(posedge clk_in, negedge rst_n) 
    begin
        if(~rst_n)
            cnt_pos <= 3'd0;
        else
            cnt_pos <= (cnt_pos==3'd6)? 3'd0 : (cnt_pos+1'd1);
    end
    reg clk_p;
    always @(posedge clk_in or negedge rst_n) 
    begin
        if(~rst_n)
            clk_p <= 1'b0;
        else 
            clk_p <= (cnt_pos==3'd3 || cnt_pos==3'd6)? ~clk_p : clk_p;
    end

    reg [2:0] cnt_neg;
    always @(negedge clk_in or negedge rst_n) 
    begin
        if(~rst_n)
            cnt_neg <= 3'd0;
        else begin
            cnt_neg <= (cnt_neg==3'd6)? 3'd0 : (cnt_neg+1'd1);
        end
    end
    reg clk_n;
    always @(negedge clk_in or negedge rst_n) 
    begin
        if(~rst_n)
            clk_n <= 1'b0;
        else
            clk_n <= (cnt_neg==3'd3 || cnt_neg==3'd6)? ~clk_n : clk_n;
    end

    assign clk_out7 = clk_p | clk_n;

    // ======================================================================================
    // 方式(一)- 未能通过:如下的判断方式,同时判断了上升沿和下降沿计数,得到的输出时钟总是在 clk_in 的上升沿同步拉高
    // ======================================================================================
    /*
    reg [2:0] cnt_neg;
    always @(negedge clk_in or negedge rst_n) 
    begin
        if(~rst_n)
            cnt_neg <= 3'd1;
        else
            cnt_neg <= (cnt_neg==3'd7)? 3'd1 : cnt_neg+1'd1;
    end

    reg [2:0] cnt_pos;
    always @(posedge clk_in or negedge rst_n) 
    begin
        if(~rst_n)
            cnt_pos <= 3'd1;
        else
            cnt_pos <= (cnt_pos==3'd7)? 3'd1 : cnt_pos+1'd1;
    end

    
   assign clk_out7 =cnt_neg[2] && ~(cnt_neg==3'd3 && clk_in);
   */

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

全部评论

相关推荐

不愿透露姓名的神秘牛友
今天 14:10
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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