zoukankan      html  css  js  c++  java
  • 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/

    多多指教。点头致谢!

      

         

  • 相关阅读:
    饮冰三年-人工智能-Python-35权限管理(万能的权限通用模块)
    饮冰三年-人工智能-Python-34CRM项目实战
    饮冰三年-人工智能-Python-33权限管理(通过配置快速生成列表)
    集腋成裘-15-MongoDB系列-02Find详细
    集腋成裘-14-MongoDB系列-01初识MongoDB
    饮冰三年-人工智能-Python-33博客园山寨版之报障管理
    饮冰三年-人工智能-Python-32博客园山寨版之后台管理
    JVM内存管理
    连接池实现原理
    定时器
  • 原文地址:https://www.cnblogs.com/lgy-gdeu/p/12925675.html
Copyright © 2011-2022 走看看