基於FPGA的任意分頻實現


一、引言

  在數字邏輯電路設計中,分頻器是一種基本的電路單元。通常用來對某個給定頻率進行分頻,以得到我們想要的頻率。在FPGA中,我們一般都是通過計數器來實現分頻,分頻得到的時鍾質量沒有通過PLL得到的時鍾質量好,用於對時鍾信號要求較高的邏輯設計中,還是用PLL分頻比較好。下面將詳細介紹任意偶數分頻,奇數分頻,小數分頻。

 

二、偶數分頻

  以四分頻為例,假設系統時鍾頻率為 50MHz,那么周期為 20ns,四分頻之后得到的時鍾頻率為 12.5MHz,時鍾周期為 80ns。在50MHz的系統時鍾的驅動下,計數器要在計數到  40 ns ,輸出時鍾翻轉,計數到40 ns時,計數器的值為1,剛好計數兩下。

  代碼如下:

 1 // *********************************************************************************
 2 // Project Name : even_divclk
 3 // Email            : 
 4 // Create Time   : 2020/07/07 9:59
 5 // Module Name  : even_divclk
 6 // editor        : qing
 7 // Version        : Rev1.0.0
 8 // Description  : 任意占空比為50%的偶數分頻
 9 // *********************************************************************************
10 
11 module even_divclk(
12     input                sclk                ,  // System clk 50MHz
13     input                s_rst_n        ,
14 
15     output    reg         div_clk        
16     );
17 
18 //========================================================================\
19 // =========== Define Parameter and Internal signals =========== 
20 //========================================================================/
21 
22 // parameter         n    =                 ;
23 parameter         n    =    4             ; // just for test
24 
25 reg            [19:0]        cnt         ;
26 
27 always @ (posedge sclk or negedge s_rst_n) begin  // cnt
28         if(s_rst_n == 1'b0)
29             cnt <= 0;
30         else if(cnt == n/2 - 1)
31             cnt <= 0;
32         else
33             cnt <= cnt + 1'b1; 
34     end    
35 
36 always @ (posedge sclk or negedge s_rst_n) begin
37     if(s_rst_n == 1'b0)
38         div_clk <= 1'b0;
39     else if(cnt == n/2 - 1)
40         div_clk <= ~div_clk;
41     else
42         div_clk <= div_clk;    
43 end
44 
45 endmodule
View Code

  testbench:

 1 // *********************************************************************************
 2 // Project Name : even_divclk
 3 // Email        : 
 4 // Create Time  : 2020/07/07 10:10
 5 // Module Name  : even_divclk_tb
 6 // editor        : qing
 7 // Version        : Rev1.0.0
 8 // *********************************************************************************
 9 `timescale 1ns/1ps
10 module even_divclk_tb;
11     reg            sclk        ;
12     reg         s_rst_n        ;
13     wire        div_clk        ;
14 
15 even_divclk even_divclk_inst(
16     .sclk    (sclk        ),
17     .s_rst_n(s_rst_n    ),
18     .div_clk(div_clk    )
19     );
20 
21 initial
22     sclk = 1'b0;
23     always #10 sclk = ~sclk;
24 
25 initial
26     begin
27         #1;
28         s_rst_n = 1'b0;
29         #21;
30         s_rst_n = 1'b1;
31     end
32 
33 endmodule
View Code

  Modelsim仿真結果:

   由圖可見,達到預期目的。

 

三、奇數分頻

 

  奇數分頻需要通過兩個輔助時鍾來生成,如上圖所示,以占空比為 50% 的 5 分頻為例,分頻得到的信號 div_clk = clk_p | clk_n。

  假設分頻系數為 n,那么 clk_p 在 在時鍾信號的上升沿的驅動下第 (n - 1)/2 - 1 個時鍾的上升沿翻轉一次,在(n - 1)個時鍾的上升沿的時候再翻轉一次;clk_n 則是在時鍾信號的下降沿的驅動下,在第(n - 1)/2 - 1個時鍾的下降沿翻轉一次,在( n - 1)個時鍾的時候再翻轉一次,將 clk_p 與 clk_n 做或運算得到 div_clk。

  下面是一個占空比為 50% 的5分頻的例程。

 1 // *********************************************************************************
 2 // Project Name : odd_divclk
 3 // Email            : 
 4 // Create Time  : 2020/07/07 11:12
 5 // Module Name  : odd_divclk
 6 // editor        : qing
 7 // Version        : Rev1.0.0
 8 // Description    : 任意占空比為 50% 的奇數分頻 
 9 // *********************************************************************************
10 
11 module odd_divclk(
12     input                sclk        ,  // System clk 50MHz
13     input                s_rst_n        ,
14 
15     output                div_clk        
16     );
17 //========================================================================\
18 // =========== Define Parameter and Internal signals =========== 
19 //========================================================================/
20 
21 parameter         n =    5                ;
22 
23 reg            [19:0]        cnt1         ;
24 reg            [19:0]        cnt2        ;
25 reg                        clk_p        ;
26 reg                         clk_n        ;        
27 
28 //=============================================================================
29 //****************************     Main Code    *******************************
30 //=============================================================================
31 
32 always @ (posedge sclk or negedge s_rst_n) begin  // cnt1
33     if(s_rst_n == 1'b0)
34         cnt1 <= 0;
35     else if(cnt1 == n - 1)
36         cnt1 <= 0;
37     else
38         cnt1 <= cnt1 + 1'b1;        
39 end
40 
41 always @ (posedge sclk or negedge s_rst_n) begin  // cnt2
42     if(s_rst_n == 1'b0)
43         clk_p <= 1'b1;
44     else if(cnt1 == (n-1)/2-1)    
45         clk_p <= ~clk_p;
46     else if(cnt1 == (n-1))
47         clk_p <= ~clk_p;
48 end
49 
50 always @ (negedge sclk or negedge s_rst_n) begin  // cnt2
51     if(s_rst_n == 1'b0)
52         cnt2 <= 0;
53     else if(cnt2 == n - 1)
54         cnt2 <= 0;
55     else
56         cnt2 <= cnt2 + 1'b1;        
57 end
58 
59 always @ (negedge sclk or negedge s_rst_n) begin  // cnt2
60     if(s_rst_n == 1'b0)
61         clk_n <= 1'b1;
62     else if(cnt2 == (n-1)/2-1)    
63         clk_n <= ~clk_n;
64     else if(cnt2 == n - 1)
65         clk_n <= ~clk_n;
66 end
67 
68 assign div_clk = clk_p | clk_n;
69 
70 endmodule    
View Code

  testbench

 1 // *********************************************************************************
 2 // Project Name : even_divclk
 3 // Email        : 
 4 // Create Time  : 2020/07/07 10:10
 5 // Module Name  : even_divclk_tb
 6 // editor        : qing
 7 // Version        : Rev1.0.0
 8 // *********************************************************************************
 9 `timescale 1ns/1ps
10 module even_divclk_tb;
11     reg            sclk        ;
12     reg         s_rst_n        ;
13     wire        div_clk        ;
14 
15 odd_divclk odd_divclk_inst(
16     .sclk    (sclk        ),
17     .s_rst_n(s_rst_n    ),
18     .div_clk(div_clk    )
19     );
20 
21 initial
22     sclk = 1'b0;
23     always #10 sclk = ~sclk;
24 
25 initial
26     begin
27         #1;
28         s_rst_n = 1'b0;
29         #21;
30         s_rst_n = 1'b1;
31     end
32 
33 endmodule
View Code

  Modelsim仿真結果

 

 

四、小數分頻

  未完待續······


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM