As low-power design becomes more important, Dynamic Frequency Scaling (DFS) technique, which uses a high-speed clock (PLL) when the chip is busy and switches to a low-speed clock (Oscillator) when in standby mode, has become essential.
The most common mistake beginner RTL engineers make at this point is treating the clock as data.
// Code you should never do
assign clk_out = select ? clk_fast : clk_slow;Using a MUX this way causes glitches. When switching occurs while the clock is high, the clock pulse is truncated, creating a very short "runt pulse." This short pulse violates the minimum pulse width requirement of the D-FlipFlop, causing the entire chip to enter a metastability state and malfunction.
In this article, we will learn about the principles and implementation code of a Glitch-free Clock Mux that safely switches clocks whenever a switching signal is sent.
1. Basic principle: “Turn on after the current clock is off.”
The core principle of preventing glitches is simple: Break-before-make.
- When the select signal changes, we should not immediately switch to the new clock.
- Wait until the currently used clock (clk_current) goes Low (0) and then disconnect.
- After verifying that the output is perfectly 0, connect a new clock (clk_next).
This process prevents the High section of the clock from being cut off.
2. Circuit Structure: Secure Handshake Between Asynchronous Clocks
To switch two clocks (Asynchronous Clocks) with completely different frequencies and phases, a synchronizer and a feedback loop are required.
Core Components
- Falling-Edge Flip-Flop: When turning the clock on or off, we use a F/F that operates on the negative edge to avoid touching the high clock period. This ensures that the Enable signal changes only when the clock is low.
- Feedback Path: To check if the other party's clock is completely off, I get the other party's state value as my Enable condition (Mutual Exclusion).
- 2-DFF Synchronizer: Since the select signal does not know which clock it will come in on, it must be synchronized to each clock domain.
3. Verilog Implementation
module glitch_free_clk_mux (
input wire clk0, // Clock Source A
input wire clk1, // Clock Source B
input wire select, // 0: clk0, 1: clk1
input wire rst_n, // Asynchronous Reset
output wire clk_out // Glitch-free Output
);
reg [1:0] q0, q1; // Synchronizers (Rising Edge)
reg g0, g1; // Gating FFs (Falling Edge)
// --- Path for CLK 0 ---
// Request activation when the opponent (g1) is off (!g1) and the selection is 0 (!select)
always @(posedge clk0 or negedge rst_n) begin
if (!rst_n) q0 <= 2'b00; // Safely reset to 0
else q0 <= {q0[0], ~select & ~g1}; // Sync & Logic
end
// Actual gating is performed at the falling edge (high pulse protection)
always @(negedge clk0 or negedge rst_n) begin
if (!rst_n) g0 <= 1'b0;
else g0 <= q0[1];
end
// --- Path for CLK 1 ---
// Request activation when the opponent (g0) is off (!g0) & selection is 1 (select)
always @(posedge clk1 or negedge rst_n) begin
if (!rst_n) q1 <= 2'b00; // Safely reset to 0
else q1 <= {q1[0], select & ~g0}; // Sync & Logic
end
// Actual gating is performed at the falling edge
always @(negedge clk1 or negedge rst_n) begin
if (!rst_n) g1 <= 1'b0;
else g1 <= q1[1];
end
// --- Output Logic ---
// Only the active clock passes (AND-OR structure)
wire clk0_gated = clk0 & g0;
wire clk1_gated = clk1 & g1;
assign clk_out = clk0_gated | clk1_gated;
endmodule4. Motion Scenario Analysis
What happens if the user changes select from 0 to 1?
- Request: select=1.
- CLK0 Blocked: The input to the CLK0 logic is ~select, so it becomes 0. On the falling edge of CLK0, g0 drops to 0. The CLK0 path is now blocked.
- Dead Zone: The g0=0 signal passes to CLK1. At this time, both clocks are blocked, and the output remains at 0. (Safe Zone)
- CLK1 Activation: The CLK1 logic checks that select=1 and is named g0=0. On the Falling Edge of CLK1, g1 transitions to 1.
- Output: clk_out now follows CLK1.
This process ensures that switching never occurs while either clock is high.
5. Conclusion: Clock is uncompromising.
Glitch-free muxes have higher latency than regular muxes. It takes several clock cycles (synchronization process) after the select signal is given for the actual clock to change.
But this delay comes at the cost of safety. A single glitch on the clock line can trigger a time bomb that could trigger an error anywhere among billions of transistors.
- If you use clocks of different frequencies: Be sure to use the asynchronous handshake circuit introduced above.
- If it is a synchronous clock (multiplier relationship) coming from the same PLL: A slightly simpler circuit is possible, but if you are confused, it is safest to just use the circuit above.
References: VLSI tutorials