分频
分频
当分频为2的整数次幂时 8分频:将一个3位的计数器最高位输出,也就是计数长度为8 module divider #(parameterN=3) ( input clk, input rstn, output clk_div, ); reg [N-1] div_reg; always@(posedge clk or negedge rst_n) begin if (!rstn) begin div_reg<=1'b0; end else begin div_reg<=div_reg+1'b1; end end assign clk_div=div_reg[N-1]; endmodule 不考虑占空比 任意数 一个最大计数长度为N(从0计数到N-1)的计数器,其最高位的输出,是输入频率的N分频。 module divide #(paremeter N=3)( input clk, input rstn, output clk_div ); reg [N-1:0] div_reg; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin div_reg<=1'b0; end else if (div_reg==3'b4) begin #5分频 div_reg<=1'b0; end else begin div_reg<=div_reg+1'b1; end end assign clk_div=div_reg[N-1]; endmodule 偶数倍分频(占空比50%) module divider #(parameterN=6) ( input clk, input rstn, output clk_div, ); reg [N-1] div_cnt; reg div_reg; always@(posedge clk or negedge rst_n) begin if (!rstn) begin div_reg<=1'b0; div_cnt<=1'b0; end else if (div_cnt==(N>>1)-1) begin div_cnt<=1'b0; div_reg<=~div_reg; end else begin div_reg<=div_reg+1'b1; end end assign clk_div=div_reg; endmodule 奇数倍分频 占空比50% module divide #(parameterN=5) ( input clk, input rstn, output clk_div, ); reg sig_r ; //定义一个上升沿翻转的信号 reg sig_f ; //定义一个下降沿翻转的信号 reg [N-1] cnt_r ; reg [N-1:0] cnt_f;//下降沿计数器 wire clk_f; assign clk_f =~clk; always@(posedge clk_r negedge rst_n) begin //上升沿计数 if (!rstn) begin sig_r<=1'b0; sig_r<=1'b0; end else if (cnt_r==(N>>1)-1) begin sig_r<= ~sig_r; cnt_r<= cnt_r+1'b1; end else if (cnt_r==(N-1) )begin sig_r<= ~sig_r; cnt_r<= 1'b0; end else begin div_reg<=cnt_r+1'b1; end always@(posedge clk_f negedge rst_n) begin //下降沿计数 if (!rstn) begin sig_f<=1'b0; sig_f<=1'b0; end else if (cnt_f==(N>>1)-1) begin sig_f<= ~sig_f; cnt_f<= cnt_f+1'b1; end else if (cnt_f==(N-1) )begin sig_f<= ~sig_f; cnt_f<= 1'b0; end else begin div_reg<=cnt_f+1'b1; end assign clk_div = sig_f || sig_r ; endmodule assign clk_out = (fre_div == 1'b1)? clk_in : (fre_div[0]? clk_odd : clk_even) 占空比50%的任意整数分频 module test#(parameter N=1)(//N分频 input clk, input rst_n, output clk_div ); //奇数分频 reg sig_r ;//定义一个上升沿翻转的信号 reg sig_f ;//定义一个下降沿翻转的信号 reg [N-1:0] cnt_r;//上升沿计数器 reg [N-1:0] cnt_f;//下降沿计数器 wire clk_f ; assign clk_f = ~clk ;//用来触发下降沿计数器的时钟 //由于同时使用上升沿和下降沿触发器不好,因此我们为同一边沿,都使用上升沿触发 //只不过是将时钟进行反向 always @(posedge clk or negedge rst_n)begin//上升沿计数 if(rst_n == 1'b0)begin sig_r <= 0 ; cnt_r <= 0 ; end else begin cnt_r <= cnt_r + 1 ; if( cnt_r == (N-1)/2 )begin sig_r <= ~sig_r ; end else if ( cnt_r == (N-1) )begin sig_r <= ~sig_r ; cnt_r <= 0 ; end end end always @(posedge clk_f or negedge rst_n)begin//下降沿计数 if(rst_n == 1'b0)begin sig_f <= 0 ; cnt_f <= 0 ; end else begin cnt_f <= cnt_f + 1 ; if( cnt_f == (N-1)/2 )begin sig_f <= ~sig_f ; end else if ( cnt_f == (N-1) )begin sig_f <= ~sig_f ; cnt_f <= 0 ; end end end //偶数分频 reg div_reg ; reg [N-1:0] div_cnt ;//分频计数器 always @(posedge clk or negedge rst_n)begin if (rst_n == 1'b0 )begin div_cnt <= 0 ; div_reg <= 0 ; end else begin div_cnt <= div_cnt + 1'b1 ; if(div_cnt == (N/2 - 1))begin div_cnt <= 0; div_reg <= ~div_reg ; end end end assign clk_div = (N == 1)?clk : ( N%2 == 1)?(sig_f || sig_r ): div_reg; //这里用来输出分频值。对2的取余操作是综合的 endmodule
module sim_test; reg clk; reg rst_n; wire clk_out; test sim_test( .clk(clk), .rst_n(rst_n), .clk_div(clk_div) ); initial begin clk_in = 1'b0; rst_n = 1'b1; #20 rst_n = 1'b0; #20 rst_n = 1'b1; end always #10 clk = ~clk; endmodule