题解 | #占空比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