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

占空比50%的奇数分频

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

注意:

不能同时判断上升沿和下降沿,虽然能通过提交。看大佬解释才知道“这是经典的错误示范,一个always里不能同时写posedge和negedge,这是不可以综合的。

经典错误解法:

`timescale 1ns/1ns

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

//*************code***********//
    reg [2:0] cnt;
    reg clk_out;
    always@(posedge clk_in or negedge clk_in or negedge rst)
        if(~rst)
            cnt <= 0;
        else 
            cnt <= cnt==6? 0:cnt+1;
        
    always@(posedge clk_in or negedge clk_in or negedge rst)
        if(~rst)
            clk_out <= 0;
        else if(cnt==6)
            clk_out <= ~clk_out7;
 
    assign clk_out7 = clk_out;

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

参考大佬的解析:https://blog.nowcoder.net/n/add8496f99154788834702f455c7f2f6?f=comment

1. 偶数分频

 简单,只是注意时钟翻转的条件是(N/2)还是(N/2)-1,非阻塞赋值在下一个时钟才会更新值。

2. 奇数分频

奇数分频比偶数分频复杂一些,当不要求分频的占空比时,对输入时钟clk上升沿计数,可以设置两个计数的翻转点,一个是(N-1)/2,一个是(N-1),计数到(N-1)时输出时钟翻转且将计数器清零,假设计数器计数0~(N-1)/2区间输出低电平,则输出时钟的低电平有(N-1)/2 + 1个clk周期,高电平的计数是(N-1)/2+1 ~ (N-1),共(N-1)/2个clk周期,可见不是50%占空比。

当要求占空比为50%时,对输入时钟clk的上升沿和下降沿分别计数,根据两个计数器得到两个错位输出的时钟,将两个时钟做“或”运算,可以弥补相差的时钟,达到50%占空比。

图中的clk实际上应该是clk_half半个周期。

下面是正确解法:

`timescale 1ns/1ns

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

//*************code***********//
    parameter N=7;
    reg [2:0] cnt_p, cnt_n;
    reg clk_out_p, clk_out_n;
    always@(posedge clk_in or negedge rst)
        if(~rst)
            cnt_p <= 0;
        else 
            cnt_p <= cnt_p==N-1? 0:cnt_p+1;
  
        
    always@(posedge clk_in or negedge clk_in or negedge rst)
        if(~rst)
            clk_out_p <= 0;
        else
            clk_out_p <= cnt_p==N-1||cnt_p==N>>1? ~clk_out_p:clk_out_p;
    
    always@(negedge clk_in or negedge rst)
        if(~rst)
            cnt_n <= 0;
        else 
            cnt_n <= cnt_n==N-1? 0:cnt_n+1;

    always@(negedge clk_in or negedge rst)
        if(~rst)
            clk_out_n <= 0;
        else
            clk_out_n <= cnt_n==N-1||cnt_n==N>>1? ~clk_out_n:clk_out_n;

    assign clk_out7 = clk_out_p||clk_out_n;

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

全部评论

相关推荐

shtdbb_:还不错,没有让你做了笔试再挂你
点赞 评论 收藏
分享
评论
1
1
分享
牛客网
牛客企业服务