Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Path
  • CDC/RDC Glossary
  • CDC/RDC Metrics Reference
  • CDC/RDC Interview Prep
  • CDC/RDC Signoff Cheatsheet
  • Clock Domains and Failure Modes8
  • Metastability and Synchronizers16
  • CDC Protocols and Handshakes16
  • Reconvergence and Gray Coding16
  • Reset Domain Crossing16
  • Architecture and Design Rules16
    • CDC-Aware Partitioning
    • Clock Gating and Muxing
      • Glitch-Free Clock Mux
      • Gating as a Domain Boundary
      • Crossing with Gated Clocks
      • Clock Switching and Reset
    • Interface and IP Rules
    • Quasi-Static Signals and Configuration
  • CDC Signoff Methodology24
  • RDC Signoff16
  • Debug and Case Studies11
  • CDC and RDC Interview Prep30
  • Capstone: Sign Off a Multi-clock Peripheral4
Loading lesson

‹Clock Gating and Muxing
  1. Topics
  2. CDC & RDC
  3. Architecture and Design Rules
  4. Clock Gating and Muxing
  5. Glitch-Free Clock Mux

Part 6 · Architecture and Design Rules · Intermediate

Glitch-Free Clock Mux

Switching between two clocks safely; the hazard of a naive mux; the standard synchronised-select structure with a runnable example.

On this page

    A design that switches its clock source, for example between a fast and a slow oscillator, needs a mux on the clock net. A logic mux on a clock is one of the few places where an ordinary-looking gate can destroy a whole chip: a runt pulse clocks some flops and not others, leaving the state permanently inconsistent.

    The hazard of a naive mux

    design.sv
    // bad-example
    assign clk_o = sel ? clk_b : clk_a;   // if sel changes near a clock edge, clk_o gets a runt pulse

    If sel changes while the selected clock is high, the output follows it at once: a shortened pulse, or an extra edge when the other clock happens to be high. Either violates the minimum pulse width every flop was characterised with.

    The standard approach, in words

    1. Synchronise the select into each clock domain. The request to use clock A is captured by two flops on clock A; the request to use clock B by two flops on clock B. Neither side ever acts on a select that is still settling.

    2. One enable latch per side, transparent while its clock is low. The latch can only change the enable while its clock is safely low, so a pulse that has started always completes at full width.

    3. Mutual exclusion through feedback. Each latch's input includes the other side's enable: side A may turn on only while side B is off, and vice versa. The switch therefore sequences itself: the old clock stops first, then the new clock starts.

    Switching takes a few cycles of the slower clock, during which the output sits still. That dead time is the price of safety; downstream logic must tolerate a paused clock (see clock switching and reset).

    Complete example and testbench

    The mux below follows the structure above, with an asynchronous reset standing in for power-on reset. The testbench switches in both directions and checks two things: every phase of clk_o is full width (no runt pulses), and the two enables never overlap.

    glitch_free_clk_mux.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    `timescale 1ns/1ps
    
    module glitch_free_clk_mux (
      input  logic clk_a, clk_b, rst_n, sel,
      output logic en_a, en_b, output logic clk_o
    );
      logic q_a1, q_a2, q_b1, q_b2, ga, gb;
      always_ff @(posedge clk_a or negedge rst_n)
        if (!rst_n) {q_a1, q_a2} <= 2'b00;
        else {q_a1, q_a2} <= {~sel, q_a1};      // select-A request into A
      always_ff @(posedge clk_b or negedge rst_n)
        if (!rst_n) {q_b1, q_b2} <= 2'b00;
        else {q_b1, q_b2} <= {sel, q_b1};       // select-B request into B
      always_latch
        if (!rst_n) en_a = 1'b0;
        else if (!clk_a) en_a = q_a2 & ~en_b;   // A starts only after B stopped
      assign ga = clk_a & en_a;
      always_latch
        if (!rst_n) en_b = 1'b0;
        else if (!clk_b) en_b = q_b2 & ~en_a;   // B starts only after A stopped
      assign gb = clk_b & en_b;
      assign clk_o = ga | gb;
    endmodule
    

    Simulation output

    How to read it: the lanes are sampled every half cycle of clk_a, so odd slots show clk_a high. sel rises between slots 20 and 21. en_a falls at slot 24 and clk_o sits at 0 through slots 24 to 29, the dead time while the switch completes. en_b rises at slot 28 and clk_o follows clk_b again from slot 30. After sel falls back around slot 32, the enables swap back around slot 40. No lane ever shows a narrow pulse: every clk_o phase is a full half period of whichever clock is selected.

    What the tools and the review look for

    Check

    What it means

    Select synchronisation

    The select reaches each side through destination-clock flops, never directly.

    Latch structure preserved

    The enable latches keep their hold behaviour through synthesis; the mux is a recognised cell or a do-not-touch block.

    No combinational select

    Nothing decodes the select combinationally into the enables.

    Dead time tolerated

    Downstream logic is specified to ride through a paused clock.

    Common pitfall

    Driving the select from an asynchronous source, such as a register bit that software can change at any moment, without synchronising it first. The synchroniser flops inside the mux handle one asynchronous input; feeding them a second unsynchronised select doubles the risk. Drive the select from a settled register that meets the mux's stability assumption, and do not bypass the mux's own per-domain synchronisers.

    Interview

    “Why can't I switch clocks with a mux?” Because the select can change mid-pulse and produce a runt. The expected answer names the three ingredients: per-domain synchronised select, low-transparent enable latches, and mutual-exclusion feedback so the old clock stops before the new one starts.

    Check yourself The output pauses for several cycles every time the mux switches. Is that a bug?

    No. The pause is the mutual-exclusion sequencing: the old side must be observably off before the new side starts. Budget for it and make sure downstream state machines tolerate a still clock.

    Check yourself A reviewer proposes removing one synchroniser stage on the select to switch faster. What breaks?

    The select may then violate the enable latch timing and the switch can produce exactly the runt pulse the structure exists to prevent. The synchroniser delay is part of the safety, not overhead.

    Related topics

    • Gating as a Domain Boundary

    • RTL: Clock Gating

    Previous

    83 / 179

    Next: Gating as a Domain Boundary

    Up next

    Up nextGating as a Domain Boundary

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Crossing with Gated Clocks
    • Clock Switching and Reset
    clk_aclk_bselen_aen_bclk_o
    Simulation output: switching the glitch-free mux from a 10 ns clock to a 20 ns clock and back