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