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