Due to various application scenario constraints, chips often need to switch between different clock sources under different applications during operation. For example, low-power and high-performance modes require low-frequency and high-frequency clocks, respectively. The two clock sources may be from the same source and synchronous, or they may be unrelated. Directly using selection logic for clock switching will likely cause glitches in the divided clock signal, so clock switching logic also requires special handling.

Clock Switching Problem

The circuit diagram of directly using selection logic to switch clocks is shown below.

If the clock select signal sel_clk1 is asynchronous to both clocks, then the clock switching moment is arbitrary. If the clock switches from clk1 to clk2, and the switching moment is when the clk1 output level is high, switching the clock immediately at this time will cause glitches on the output clock. The waveform diagram is as follows:

Clock Switching Scheme

Switching clocks when the two levels are opposite will definitely produce glitches; when the levels are the same, even if no glitch is produced, the period or duty cycle of the first clock after switching is not ideal. Therefore, to avoid glitches, the clock switching should be performed when both clocks are at low level.

A typical clock switching circuit is shown below.

This circuit uses the falling edge of the clock to buffer the clock select signal sel_clk1. Meanwhile, one clock select signal provides feedback control for the other clock, ensuring that only one clock is active at any time. Finally, an OR operation combines the two clock paths to complete the clock switching process.

The waveform diagram of using the above circuit to complete clock switching (clk1->clk2) is shown below.

As can be seen from the figure, when switching from clk1 to clk2, clk1 is turned off first, then clk2 is turned on. Since the clock select signal is synchronized to the falling edge of the clock, no glitches will occur during the switching process.

The waveform diagram of switching from clk2 to clk1 is shown below.

Considering that the select signal may be an asynchronous signal, two stages of flip-flops need to be added before the buffer flip-flop of the clock select signal for synchronization to reduce the propagation of metastability. The structure diagram is as follows. This clock switching circuit is more universal.

Clock Switching Design

A universal and safe clock switching logic description is as follows.

Example

module clk_switch(
    input               rstn ,
    input               clk1,
    input               clk2,
    input               sel_clk1 , // 1 clk1, 0 clk2
    output              clk_out
    );

   reg [2:0]            sel_clk1_r ;
   reg [1:0]            sel_clk1_neg_r ;
   reg [2:0]            sel_clk2_r ;
   reg [1:0]            sel_clk2_neg_r ;

   //Use 3-cycle buffering to synchronize the AND operation between the other clock control signal and this clock control signal
   always @(posedge clk1 or negedge rstn) begin
      if (!rstn) begin
         sel_clk1_r     <= 3'b111 ; //Note the default value
      end
      else begin
         //sel clk1, and not sel clk2
         sel_clk1_r     <= {sel_clk1_r[1:0], sel_clk1 & (!sel_clk2_neg_r[1])} ;
      end
   end

   //On the falling edge, use 2-cycle buffering for the clock select signal
   always @(negedge clk1 or negedge rstn) begin
      if (!rstn) begin
         sel_clk1_neg_r <= 2'b11 ; //Note the default value
      end
      else begin
         sel_clk1_neg_r <= {sel_clk1_neg_r[0], sel_clk1_r[2]} ;
      end
   end

   //Use 3-cycle buffering to synchronize the AND operation between the other clock control signal and this clock control signal
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn) begin
         sel_clk2_r     <= 3'b0 ; //Note the default value
      end
      else begin
         //sel clk2, and not sel clk1
         sel_clk2_r     <= {sel_clk2_r[1:0], !sel_clk1 & (!sel_clk1_neg_r[1])} ;
      end
   end

   //On the falling edge, use 2-cycle buffering for the clock select signal
   always @(negedge clk2 or negedge rstn) begin
      if (!rstn) begin
         sel_clk2_neg_r <= 2'b0 ; //Note the default value
      end
      else begin
         sel_clk2_neg_r <= {sel_clk2_neg_r[0], sel_clk2_r[2]} ;
      end
   end

   //When performing clock logic operations, a specific process cell library is generally used.
   //Here, Verilog's built-in logic gate cells are used instead
   wire clk1_gate, clk2_gate ;
   and (clk1_gate, clk1, sel_clk1_neg_r[1]) ;
   and (clk2_gate, clk2, sel_clk2_neg_r[1]) ;
   or  (clk_out, clk1_gate, clk2_gate) ;

endmodule

The testbench description is as follows, mainly generating the select signal for asynchronous clocks.

Example

`timescale 1ns/1ps
module test ;
   reg          clk_100mhz, clk_200mhz ;
   reg          rstn ;
   reg          sel ;
   wire         clk_out ;

   always #(2.5)    clk_200mhz  = ~clk_200mhz ;
   always @(posedge clk_200mhz)
                    clk_100mhz  = #1 ~clk_100mhz ;

   initial begin
      clk_100mhz  = 0 ;
      clk_200mhz  = 0 ;
      rstn        = 0 ;
      sel         = 1 ;
      #11 rstn    = 1 ;
      #36.2 sel   = ~sel ;
      #119.7 sel   = ~sel ;
   end

   clk_switch u_clk_switch(
     .rstn      (rstn),
     .clk1      (clk_100mhz),
     .clk2      (clk_200mhz),
     .sel_clk1  (sel),
     .clk_out   (clk_out));

   initial begin
      forever begin
         #100;
         if ($time >= 10000)  $finish ;
      end
   end

endmodule

The simulation results are as follows. It can be seen that no glitches are generated when clocks switch to each other, but there is a delay.

Source Code Download for This Chapter

Download