题解 | 进阶版16#占空比50%的奇数分频#
占空比50%的奇数分频
http://www.nowcoder.com/practice/ccfba5e5785f4b3f9d7ac19ab13d6b31
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半个周期。
以7分频为例,代码如下:
/******************************************** 计数器实现 7 分频 作者:FPGA探索者 *********************************************/ module Odd_Divider( inputclk, inputrst_n, outputclk_divider ); reg [2:0] count_p; //上升沿计数 reg [2:0] count_n; //下降沿计数 reg clk_p; //上升沿分频 reg clk_n; //下降沿分频 //上升沿计数 作者:FPGA探索者 always @ ( posedge clk&nbs***bsp;negedge rst_n ) begin if(!rst_n ) count_p<= 3'b0; elseif( count_p == 3'd6 ) count_p<= 3'b0; else count_p<= count_p + 1'b1; end //上升沿分频 作者:FPGA探索者 always @ ( posedge clk&nbs***bsp;negedge rst_n ) begin if(!rst_n ) begin clk_p<= 1'b0; end elsebegin if(count_p == 3'd3 || count_p == 3'd6 ) begin clk_p<= ~clk_p; end end end //下降沿计数 作者:FPGA探索者 always @ ( negedge clk&nbs***bsp;negedge rst_n ) begin if(!rst_n ) count_n<= 3'b0; elseif( count_n == 3'd6 ) count_n<= 3'b0; else count_n<= count_n + 1'b1; end //下降沿分频 作者:FPGA探索者 always @ ( negedge clk&nbs***bsp;negedge rst_n ) begin if(!rst_n ) begin clk_n<= 1'b0; end elsebegin if(count_n == 3'd3 || count_n == 3'd6 ) begin clk_n<= ~clk_n; end end end assign clk_divider = clk_p | clk_n; endmodule仿真如下: