`timescale 1ns / 1ps module Clk_Divider# ( parameter DEBUG_ENABLE = 1'b1, parameter REF_CLK = 32'd50_000_000 ) ( input I_clk, input I_rst_n, output O_div2, output O_div3, output O_div4, output O_div8, output O_div2hz );
//2分频代码:只要基于源时钟每个时钟的上升沿对O_div2_r寄存器取反 reg O_div2_r; always@(posedge I_clk)begin if(!I_rst_n) O_div2_r <= 1'b0; else O_div2_r <= ~O_div2_r; end
//4分频和8分频代码:共同使用了div_cnt1计数器 //4分频就是对计数器在div_cnt1==2'b00或者div_cnt1==2'b10的时候对O_div4_r寄存器取反; //而8分频是对div_cnt1==2'b00的时候对O_div8_r取反 reg [1:0] div_cnt1; always@(posedge I_clk)begin if(!I_rst_n) div_cnt1 <= 2'b00; else div_cnt1 <= div_cnt1+1'b1; end
reg O_div4_r; reg O_div8_r; always@(posedge I_clk)begin if(!I_rst_n) O_div4_r <= 1'b0; else if(div_cnt1==2'b00 || div_cnt1==2'b10) O_div4_r <= ~O_div4_r; else O_div4_r <= O_div4_r; end
always@(posedge I_clk)begin if(!I_rst_n) O_div8_r <= 1'b0; else if(div_cnt1==2'b00) O_div8_r <= ~O_div8_r; else O_div8_r <= O_div8_r; end /* 3分频的本质是我们需要在每次1.5倍的时钟周期的时候实现3分频寄存器的翻转,但是我们无法直接实现1.5倍的分频。 因此采取分别采取2个计数器pos_cnt和neg_cnt,分别对上升沿和下降沿计数。计数周期是0-1-2,共计3个时钟周期。 我们取pos_cnt == 2'd1的时候O_div3_r0输出高电平,neg_cnt == 2'd1的时候O_div3_r1输出高电平。 由于O_div3_r0和O_div3_r1输出1个时钟的高电平,但是相位相差180°,因此只要执行O_div3 = O_div3_r0 | O_div3_r1运算, 就能实现1.5倍周期的输出高电平,那么剩余的1.5倍源时钟周期就是输出低电平了。 */ reg [1:0] pos_cnt; reg [1:0] neg_cnt; always@(posedge I_clk)begin if(!I_rst_n) pos_cnt <= 2'b00; else if(pos_cnt == 2'd2) pos_cnt <= 2'b00; else pos_cnt <= pos_cnt + 1'b1; end
always@(negedge I_clk)begin if(!I_rst_n) neg_cnt <= 2'b00; else if(neg_cnt == 2'd2) neg_cnt <= 2'b00; else neg_cnt <= neg_cnt + 1'b1; end
reg O_div3_r0; reg O_div3_r1; always@(posedge I_clk)begin if(!I_rst_n) O_div3_r0 <= 1'b0; else if(pos_cnt < 2'd1) O_div3_r0 <= 1'b1; else O_div3_r0 <= 1'b0; end
always@(negedge I_clk)begin if(!I_rst_n) O_div3_r1 <= 1'b0; else if(neg_cnt < 2'd1) O_div3_r1 <= 1'b1; else O_div3_r1 <= 1'b0; end
reg O_div2hz_r; reg [25:0] div2hz_cnt;
wire ms250_en = (div2hz_cnt == REF_CLK/4 - 1'b1); always@(posedge I_clk) begin if(!I_rst_n) div2hz_cnt <= 0; else if(div2hz_cnt < REF_CLK/4 - 1'b1) div2hz_cnt <= div2hz_cnt + 1'b1; else div2hz_cnt <= 0; end
always@(posedge I_clk) begin if(!I_rst_n) O_div2hz_r <= 0; else if(ms250_en) O_div2hz_r <= ~O_div2hz_r; else O_div2hz_r <= O_div2hz_r; end
assign O_div2 = O_div2_r; assign O_div3 = O_div3_r0 | O_div3_r1; assign O_div4 = O_div4_r; assign O_div8 = O_div8_r; assign O_div2hz = O_div2hz_r;
generate if(DEBUG_ENABLE == 1'b1) begin : debugcore //添加ila IP ,Chipscope观察信号 ila_0 ila_0 ( .clk(I_clk), // input wire clk .probe0(O_div2hz), // input wire [0:0] probe0 .probe1({O_div2,O_div3,O_div4,O_div8}) // input wire [3:0] probe1 ); end Endgenerate
endmodule
|