FPGA開發基礎-------------Glitch Free時鍾切換技術(1)


   在通信領域當中,經常會在芯片運行過程當中進行時鍾切換,特別是當芯片內部中有兩個時鍾源時,往往通過內部邏輯控制多路復用器來實現時鍾源的切換。

時鍾切換的分類

   第一種:第一種時兩個時鍾源的頻率呈倍數關系;

   第二種:兩個時鍾源完全沒有關系,異步時鍾。

解決方法

   當兩個時鍾可能完全無關,也可能成倍數關系。當聽到要進行時鍾切換時,第一個想到的語法就是三目運算。完全合乎邏輯。但是在網上查閱資料的時候,發現原來是最爛的一種設計。

     1 assign outclk = sel? clk0: clk1; 

  寫法不入眼……而且這樣寫的話,考慮的實際工程的問題太少了。肯定會產生毛刺,對搭建的整個系統是非常危險的,因為有些寄存器可能會捕獲到時鍾沿其他沒捕獲到,造成系統的不穩定。在此寫法上繼續升級。使用AND-OR型多路復用器邏輯進行簡單的時鍾切換。如下圖所示:

    1 assign outclk = (clk1 & select) | (~select & clk0); 

 

 

 

 

 

從圖中可以看出,如果當Select信號發生改變時,信號源正好處於高電平的時刻,那么就會產生毛刺。從而影響后續的電路。仿真一下電路可以看出來效果。實現的代碼:

 

  

 1 // *********************************************************************************
 2 // Project Name : 
 3 // weixin       : li15226499835
 4 // Website      : https://www.cnblogs.com/lgy-gdeu/
 5 // Create Time  : 2020// 
 6 // File Name    : .v
 7 // Module Name  : 
 8 // Abstract     :
 9 // editor        : sublime text 3
10 // *********************************************************************************
11 // Modification History:
12 // Date         By              Version                 Change Description
13 // -----------------------------------------------------------------------
14 // 2020//          Liguoyong           1.0                     Original
15 //  
16 // *********************************************************************************
17 `timescale      1ns/1ns
18 module  first_glitch_free(
19     //system signals
20     input               wire            sclk    ,
21     input                wire            rst_n    ,
22     //others
23     input                wire             clk_1    , 
24     input                wire             clk_2    ,
25     input               wire            select  , 
26     output              wire            out_clk
27     
28 
29 );
30 
31 //=============================================================================
32 //****************************     Main Code    *******************************
33 //=============================================================================
34 
35 assign     out_clk  =  (select & sclk)|(~select & clk_2);
36 
37     
38 endmodule

 

tb測試的激勵文件:

 1 // *********************************************************************************
 2 // Project Name : 
 3 // weixin       : li15226499835
 4 // Website      : https://www.cnblogs.com/lgy-gdeu/
 5 // Create Time  : 2020// 
 6 // File Name    : .v
 7 // Module Name  : 
 8 // Abstract     :
 9 // editor        : sublime text 3
10 // *********************************************************************************
11 // Modification History:
12 // Date         By              Version                 Change Description
13 // -----------------------------------------------------------------------
14 // 2020//          Liguoyong           1.0                     Original
15 //  
16 // *********************************************************************************
17 `timescale      1ns/1ns
18 
19 module first_glitch_free_tb;
20 
21 reg             sclk        ;
22 reg             tb_clk_1    ;
23 reg             tb_clk_2    ;
24 reg             tb_rst_n    ;
25 reg             tb_select   ;
26 wire            tb_out_clk  ;
27 
28 initial begin
29     tb_rst_n   =    0;
30     sclk       =    1;
31     #100
32     tb_rst_n   =    1;
33     tb_select  =    0;
34     #487
35     tb_select  =    1;
36     #2000
37     $finish;
38 end    
39 
40 always   #10  sclk   =  ~sclk ;
41 
42 
43 //=============================================================================
44 //****************************     Main Code    *******************************
45 //=============================================================================
46 
47 
48 always  @(posedge sclk or negedge tb_rst_n )begin
49     if(!tb_rst_n)
50         tb_clk_1 <= 0;
51     else 
52         tb_clk_1 <= ~tb_clk_1 ;
53 end
54 
55 always @(posedge tb_clk_1 or negedge tb_rst_n)begin
56     if(!tb_rst_n)
57         tb_clk_2 <=  0;
58     else 
59         tb_clk_2 <= ~tb_clk_2;        
60 end
61 wire        tb_clk_3 ;
62 assign     tb_clk_3 = ~tb_clk_2;
63 //例化
64 first_glitch_free first_glitch_free_inst(
65     //system signals
66     .sclk                   (sclk    )    ,
67     .clk_1                  (tb_clk_1)    , 
68     .clk_2                  (tb_clk_3)    ,
69     .rst_n                  (tb_rst_n)    ,
70     //output
71     .select                  (tb_select), 
72     .out_clk                 (tb_out_clk)
73     
74 
75 );
76 
77 endmodule

 仿真圖:

 

 

 

 

 

   避免毛刺的方法繼續往下看,下圖針對的是兩個時鍾源頻率成倍數關系。在每個時鍾源的選擇路徑中插入一個下降沿觸發的D觸發器,這樣可以保證上面的情況被避免,確保在切換時鍾源時,即使任意時鍾處於高電平,也不會引起輸出的變換,時鍾源切換時,這個反饋能保證一個時鍾被完全取消選擇后,輸出傳播另一個時鍾,從而避免產生任何毛刺。

 

 

 

 

 

 

   這個電路有三個時序路徑需要考慮,SELECT到兩個觸發器的任何一個,DFF0到DFF1,DFF1到DFF0,這三條路徑上的輸入信號與時鍾邊沿同時發生變化,都可能會引起亞穩態,所以需要將觸發器的觸發邊沿和SELECT信號的變換邊沿分開,這可以通過時序約束來實現,因為這兩個時鍾是呈倍數的關系。芯片在啟動的時候,兩個觸發器都應該處於0狀態。

代碼:

  

 1 // *********************************************************************************
 2 // Project Name : 
 3 // weixin       : li15226499835
 4 // Website      : https://www.cnblogs.com/lgy-gdeu/
 5 // Create Time  : 2020// 
 6 // File Name    : .v
 7 // Module Name  : 
 8 // Abstract     :
 9 // editor        : sublime text 3
10 // *********************************************************************************
11 // Modification History:
12 // Date         By              Version                 Change Description
13 // -----------------------------------------------------------------------
14 // 2020//          Liguoyong           1.0                     Original
15 //  
16 // *********************************************************************************
17 `timescale      1ns/1ns
18 module  first_glitch_free(
19     //system signals
20     input               wire            sclk    ,
21     input                wire            rst_n    ,
22     //others
23     input                wire             clk_1    , 
24     input                wire             clk_2    ,
25     input               wire            select  , 
26     output              wire            out_clk
27     
28 
29 );
30 //=============================================================================
31 //****************************     Main Code    *******************************
32 //=============================================================================
33 reg                    out_clk1;
34 reg                 out_clk2;
35 
36 //=============================================================================
37 //****************************     Main Code    *******************************
38 //=============================================================================
39 
40 //assign     out_clk  =  (select & sclk)|(~select & clk_2);
41 //out_clk1
42 always  @(posedge sclk or negedge rst_n)begin
43     if(!rst_n)
44         out_clk1    <=   0;
45     else 
46         out_clk1    <=  ~out_clk2 & ~select;        
47 end
48  //out_clk2
49  always @(posedge sclk or negedge rst_n)begin
50      if(!rst_n)
51          out_clk2    <=   0;
52      else 
53          out_clk2    <=  select&~out_clk1    ;    
54  end
55 
56 //out_clk
57 assign     out_clk  =  (clk_2&out_clk2)|(clk_1&out_clk1);
58 
59 
60 endmodule
View Code

tb測試文件

 1 // *********************************************************************************
 2 // Project Name : 
 3 // weixin       : li15226499835
 4 // Website      : https://www.cnblogs.com/lgy-gdeu/
 5 // Create Time  : 2020// 
 6 // File Name    : .v
 7 // Module Name  : 
 8 // Abstract     :
 9 // editor        : sublime text 3
10 // *********************************************************************************
11 // Modification History:
12 // Date         By              Version                 Change Description
13 // -----------------------------------------------------------------------
14 // 2020//          Liguoyong           1.0                     Original
15 //  
16 // *********************************************************************************
17 `timescale      1ns/1ns
18 
19 module first_glitch_free_tb;
20 
21 reg             sclk        ;
22 reg             tb_clk_1    ;
23 reg             tb_clk_2    ;
24 reg             tb_rst_n    ;
25 reg             tb_select   ;
26 wire            tb_out_clk  ;
27 wire            tb_clk_3    ;
28 initial begin
29     tb_rst_n   =    0;
30     sclk       =    1;
31     #100
32     tb_rst_n   =    1;
33     tb_select  =    0;
34     #487
35     tb_select  =    1;
36     #2000
37     $finish;
38 end    
39 
40 always   #10  sclk   =  ~sclk ;
41 
42 //=============================================================================
43 //****************************     Main Code    *******************************
44 //=============================================================================
45 
46 
47 always  @(posedge sclk or negedge tb_rst_n )begin
48     if(!tb_rst_n)
49         tb_clk_1 <= 0;
50     else 
51         tb_clk_1 <= ~tb_clk_1 ;
52 end
53 
54 always @(posedge tb_clk_1 or negedge tb_rst_n)begin
55     if(!tb_rst_n)
56         tb_clk_2 <=  0;
57     else 
58         tb_clk_2 <= ~tb_clk_2;        
59 end
60 
61 
62 assign     tb_clk_3 = ~tb_clk_2;
63 //例化
64 first_glitch_free first_glitch_free_inst(
65     //system signals
66     .sclk                   (sclk    )    ,
67     .clk_1                  (tb_clk_1)    , 
68     .clk_2                  (tb_clk_2)    ,
69     .rst_n                  (tb_rst_n)    ,
70     //output
71     .select                  (tb_select) , 
72     .out_clk                 (tb_out_clk)
73     
74 
75 );
76 
77 endmodule
View Code

仿真圖形:

 

   第二種方法是針對兩個異步時鍾源的切換,這個方法是在第一種方法的基礎上,在選擇路徑上再插入一個上升沿觸發D觸發器,這是為了針對對兩個異步時鍾源產生的反饋信號以及異步信號SELECT,對選擇信號進行同步處理,這樣即使是兩個異步的時鍾源進行切換,也可以避免亞穩態的產生。

 

 

 

仿真代碼:

 1 // *********************************************************************************
 2 // Project Name : 
 3 // weixin       : li15226499835
 4 // Website      : https://www.cnblogs.com/lgy-gdeu/
 5 // Create Time  : 2020// 
 6 // File Name    : .v
 7 // Module Name  : 
 8 // Abstract     :
 9 // editor        : sublime text 3
10 // *********************************************************************************
11 // Modification History:
12 // Date         By              Version                 Change Description
13 // -----------------------------------------------------------------------
14 // 2020//          Liguoyong           1.0                     Original
15 //  
16 // *********************************************************************************
17 `timescale      1ns/1ns
18 module  first_glitch_free(
19     //system signals
20     input               wire            sclk    ,
21     input                wire            rst_n    ,
22     //others
23     input                wire             clk_1    , 
24     input                wire             clk_2    ,
25     input               wire            select  , 
26     output              wire            out_clk
27     
28 
29 );
30 //=============================================================================
31 //****************************     Main Code    *******************************
32 //=============================================================================
33 reg                    out_clk1;
34 reg                 out_clk1_r;
35 reg                 out_clk2;
36 reg                 out_clk2_r;
37 
38 //=============================================================================
39 //****************************     Main Code    *******************************
40 //=============================================================================
41 
42 //assign     out_clk  =  (select & sclk)|(~select & clk_2);
43 //out_clk1
44 always  @(posedge sclk or negedge rst_n)begin
45     if(!rst_n)
46         out_clk1    <=   0;
47     else 
48         out_clk1    <=  ~out_clk2 & ~select;        
49 end
50 
51 //out_clk1_r
52 always @(posedge sclk or negedge rst_n)begin
53     if(!rst_n)
54         out_clk1_r  <=   0;
55     else 
56         out_clk1_r  <= out_clk1;    
57 end
58 
59  //out_clk2
60  always @(posedge sclk or negedge rst_n)begin
61      if(!rst_n)
62          out_clk2    <=   0;
63      else 
64          out_clk2    <=  select&~out_clk1    ;    
65  end
66 
67 //out_clk2_r
68 always @(posedge sclk or negedge rst_n)begin
69     if(!rst_n)
70         out_clk2_r   <=   0;
71     else 
72         out_clk2_r   <=  out_clk2;    
73 end 
74 
75 //out_clk
76 assign     out_clk  =  (clk_2&out_clk2_r)|(clk_1&out_clk1_r);
77 
78 
79 endmodule
View Code

tb激勵代碼

 1 // *********************************************************************************
 2 // Project Name : 
 3 // weixin       : li15226499835
 4 // Website      : https://www.cnblogs.com/lgy-gdeu/
 5 // Create Time  : 2020// 
 6 // File Name    : .v
 7 // Module Name  : 
 8 // Abstract     :
 9 // editor        : sublime text 3
10 // *********************************************************************************
11 // Modification History:
12 // Date         By              Version                 Change Description
13 // -----------------------------------------------------------------------
14 // 2020//          Liguoyong           1.0                     Original
15 //  
16 // *********************************************************************************
17 `timescale      1ns/1ns
18 
19 module first_glitch_free_tb;
20 
21 reg             sclk        ;
22 reg             tb_clk_1    ;
23 reg             tb_clk_2    ;
24 reg             tb_rst_n    ;
25 reg             tb_select   ;
26 wire            tb_out_clk  ;
27 wire            tb_clk_3    ;
28 initial begin
29     tb_rst_n   =    0;
30     sclk       =    1;
31     #100
32     tb_rst_n   =    1;
33     tb_select  =    0;
34     #487
35     tb_select  =    1;
36     #2000
37     $finish;
38 end    
39 
40 always   #10  sclk   =  ~sclk ;
41 
42 //=============================================================================
43 //****************************     Main Code    *******************************
44 //=============================================================================
45 
46 
47 always  @(posedge sclk or negedge tb_rst_n )begin
48     if(!tb_rst_n)
49         tb_clk_1 <= 0;
50     else 
51         tb_clk_1 <= ~tb_clk_1 ;
52 end
53 
54 always @(posedge tb_clk_1 or negedge tb_rst_n)begin
55     if(!tb_rst_n)
56         tb_clk_2 <=  0;
57     else 
58         tb_clk_2 <= ~tb_clk_2;        
59 end
60 
61 
62 assign     tb_clk_3 = ~tb_clk_2;
63 //例化
64 first_glitch_free first_glitch_free_inst(
65     //system signals
66     .sclk                   (sclk    )    ,
67     .clk_1                  (tb_clk_1)    , 
68     .clk_2                  (tb_clk_2)    ,
69     .rst_n                  (tb_rst_n)    ,
70     //output
71     .select                  (tb_select) , 
72     .out_clk                 (tb_out_clk)
73     
74 
75 );
76 
77 endmodule
View Code

仿真波形

 

 

參考文獻:https://www.eetimes.com/techniques-to-make-clock-switching-glitch-free/

多多指教。點頭致謝!

 

 

 

  

 

 

     

 


免責聲明!

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



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