waljj

时钟分频-偶数分频和奇数分频

0
阅读(2590)

分频电路在项目中经常要用到,这里介绍两种分频电路。偶数分频和奇数分频。

偶数分频:

偶数分频相对来说简单点。只要做一个计数器,计数值为需要分频的偶数值,输出时钟在计数值的前半部分和后半部分进行取反就可得到。如对时钟进行4分频的代码如下:

`timescale 1ns/100ps

 

module even_div_fre

(

  input clk_i,reset_i,

  output reg clk_o

);

 

  reg [2:0]cnt;

  

  always @ (posedge clk_i or negedge reset_i) begin

      if (!reset_i)begin

             clk_o <= 1'b0;

                 cnt <= 3'd0;

               end

        else if (cnt < 3'd1 ) begin

             cnt <= cnt + 1'b1;

               end

            else  begin

                 cnt <= 3'd0;

                     clk_o <= ~clk_o;

                   end

     end

endmodule

其中cnt < 3'd1中的3'd1值是4分频的一半减一得到的。其仿真结果如下图:

奇数分频:

奇数分频则比较繁琐点。方式应该有很多种,这里介绍项目中经常用到的一种。分4个步骤:

  1. 建立一个计数器cnt。计数值为分频值减一,如进行N次分频,那么计数值为N-1。N为奇数。
  2. 设定两个寄存器,如rt1,rt2。当cnt = 0时,rt1为1,否则rt1为0,。当cnt 等于2(对于3分频为2,对应5分频为3,对应7分频为4,以此类推)时,rt2为1,否则rt2为0。
  3. 设定两个寄存器div1,div2。当rt1为1时,在时钟的上升沿对div1进行取反。当rt2为1时,在时钟的下降沿对div2进行取反。
  4. 时钟的输出为div1和div2的异或。

如对时钟进行3分频的代码如下:

module odd_div_fre

(

  input clk_i,reset_i,

  output reg rt1,rt2,div1,div2,

  output clk_o

);

 

  reg [1:0]cnt;

 

  always @ (posedge clk_i or negedge reset_i) begin

      if (!reset_i)begin

             cnt <= 2'd0 ;

               end

            else if (cnt < 2'd2)begin

                 cnt <= cnt + 1'b1 ;

                   end

            else cnt <= 2'd0 ;

      end

 

  always @ (posedge clk_i or negedge reset_i) begin

      if (!reset_i)begin

             rt1 <= 1'b0 ;

               end

            else if (cnt == 2'd0) begin

                 rt1 <= 1'b1 ;

                   end

            else  rt1 <= 1'b0 ;

      end

 

  always @ (posedge clk_i or negedge reset_i) begin

      if (!reset_i)begin

             rt2 <= 1'b0 ;

               end

            else if (cnt == 2'd2) begin

                 rt2 <= 1'b1 ;

                   end

            else  rt2 <= 1'b0 ;

      end

 

  always @ (posedge clk_i or negedge reset_i) begin

      if (!reset_i)begin

             div1 <= 1'b0 ;

               end

            else if (rt1 == 1'b1) begin

                 div1 <= ~div1 ;

                   end

      end

 

  always @ (negedge clk_i or negedge reset_i) begin

      if (!reset_i)begin

             div2 <= 1'b0 ;

               end

            else if (rt2 == 1'b1) begin

                 div2 <= ~div2 ;

                   end

      end

 

  assign clk_o = div1 ^ div2;

 

endmodule

把rt1,rt2,div1,div2放在output中,是为了进行仿真时,看到输出波形,便于调试。其仿真结果如下图: