← RTL Design Interviews

Interview Question · Concept

Why ASICs Avoid Clocks Made in Logic

L2 Mid-LevelL3 Seniorclocksclock switchingsta

The Question

The interviewer asks

A designer makes a slow clock with a counter and picks between two clocks with a mux. Why do ASIC teams push back?

Reveal the Model Answer

A clock made by logic is a new clock domain with its own skew and delay. STA must be told about it, and clock-tree tools must balance it. A plain mux between clocks can cut a pulse short when the select changes, and a short pulse can break flops. Prefer one clock with an enable. If a switch is truly needed, use a glitch-free switch or the library cell.

div2: The Clock Stops at the DividerArrows are signals. clk reaches dv and ra; the divided net clkd clocks rb and rc.
div2: the clock stops at the dividerArrows are signals. `clk` reaches `dv` and `ra`; the divided net `clkd` clocks `rb` and `rc`. component clk port create_clock, 1 ns component dv (dfxtp_1) toggles every edge component ra (dfxtp_1) on clk generated clkd net create_generated_clock component rb, rc (dfxtp_1) on clkd clockclockQclockdata
  1. The clock stops at dv

    The tool follows clk to the CLK pins of dv and ra. It does not cross dv.

  2. Declare the divided clock

    create_generated_clock -divide_by 2 -source [get_ports clk] on dv/Q names a 2 ns clock tied to clk.

  3. Crossings are timed

    Now ra → rb is a path from clk to clkd, checked with edges of both clocks.

Read the diagram as text
  • clk port: create_clock, 1 ns
  • dv (dfxtp_1): toggles every edge
  • ra (dfxtp_1): on clk
  • clkd net: create_generated_clock
  • rb, rc (dfxtp_1): on clkd
  • clk port → dv (dfxtp_1): clock
  • clk port → ra (dfxtp_1): clock
  • dv (dfxtp_1) → clkd net: Q
  • clkd net → rb, rc (dfxtp_1): clock
  • ra (dfxtp_1) → rb, rc (dfxtp_1): data

A generated clock keeps its master, so the tool knows where its edges fall relative to clk.

A glitch-free switch from a 10 ns clock to a 16 ns clock at t = 17 ns.

RUNIcarus Verilog · in your browser
Edit the code, then run it
Expected: shortest high pulse 5.0 ns, shortest low pulse 5.0 ns PASS: no pulse shorter than the faster clock's 5 ns half period

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Mid-Level)

A good mid-level answer names the new clock domain, the STA declaration it needs, and the glitch a clock mux can make. It offers an enable as the first fix.

Cross-Questions

Where the interviewer goes next. Open a node to practise that follow-up.

WhyBreak ItCompareScale It

  1. Why ASICs Avoid Clocks Made in Logic
  2. WhyWhy STA Must Be Told About a Generated ClockL2 Mid-Level

    Why can't STA simply time the flops behind a divider without a new constraint?

    Reveal the Model Answer

    STA times paths from clocks it knows. A divider's output is a flop output, so STA does not treat it as a clock unless told. create_generated_clock names it, gives its ratio to the master and lets the tool add the divider delay to the clock latency.

    Self-Check

    Tick each key point you covered in your answer.

    Tool as Truth

    Puts a second create_clock directly on the divider output.

    That makes an unrelated clock that starts at the divider, so the divider's own delay is lost. L2.6 measured a clock latency of 0 that way.

    Source Lesson L2.6, measured with OpenROAD (OpenSTA 3.1.0) on sky130hd, 2026-11-03

  3. CompareA Clock Enable Instead of a Divided ClockL1 JuniorL2 Mid-Level

    Compare running slow logic on a divided clock with running it on the main clock and an enable.

    Reveal the Model Answer

    With an enable, the logic keeps the main clock and updates only when a one-cycle tick is high. There is one clock tree, no crossing, and STA times it normally. The cost is the enable logic and some clock power. Clock gating with a library cell can remove most of that power.

    Inside a Clock-Gating CellArrows show signals. The latch passes en only while clk is low.
    Inside a clock-gating cellArrows show signals. The latch passes en only while clk is low. manager en from a flop manager clk free-running bridge Latch open while clk is low bridge AND gate clk & held en completer gclk whole pulses only enheld enclk
    1. clk low

      The latch is open: a new en passes to the AND gate. The AND output is 0, because clk is 0.

      Follow the calls, values and waits
      1. data en: en → Latch
      2. data en: Latch → AND gate
    2. clk high

      The latch is closed. A change on en stops at the latch, so gclk is either a whole clock pulse or nothing.

    Read the diagram as text
    • en: from a flop
    • clk: free-running
    • Latch: open while clk is low
    • AND gate: clk & held en
    • gclk: whole pulses only
    • en → Latch: en
    • Latch → AND gate: held en
    • clk → AND gate: clk
    • AND gate → gclk

    A latch-and-AND model of this cell, run on the lab bench, writes 11 22 33 44: no extra entries.

    Self-Check

    Tick each key point you covered in your answer.

    Missed Corner

    "An enable makes the slow logic's paths run at the slow rate in STA."

    STA still times them for one fast period unless you add a multicycle path. That is safe only when the enable really guarantees it.

    Source OpenSTA 3.1.0 command reference, set_multicycle_path (as cited in lesson L2.8)

  4. Scale ItWho Makes the Clocks on an SoCL3 SeniorL4 Staff

    Scale it: on an SoC with many blocks, who should make the clocks, and what should block RTL contain?

    Reveal the Model Answer

    A clock controller makes the clocks: PLLs, dividers, glitch-free switches and gating cells taken from the library. It ships with its constraints. Block RTL receives clocks and uses enables or library gating cells. It never builds clocks from its own logic. Then STA, clock-tree synthesis and CDC checks all start from one list of clocks.

    Self-Check

    Tick each key point you covered in your answer.

    Wrong Altitude

    Each block team writes its own divider "to save a request to the clock team".

    Each one is an undeclared domain with its own skew and its own crossings. The chip-level constraints and CDC analysis then miss them.

    Half-Truth

    Writes the clock-gating latch and AND in RTL.

    The library ICG cell carries the timing checks on its enable pin that STA needs. A hand-made latch and AND does not carry them.

    Source SkyWater sky130_fd_sc_hd Liberty, cells dlclkp_1 and sdlclkp_1 (as read for lesson L5.6)

  5. Break ItSwitching to a Clock That Is Not RunningL2 Mid-LevelL3 Senior

    Asked if they offer the glitch-free switch

    Break it: what happens if the glitch-free switch selects a clock that is stopped?

    Reveal the Model Answer

    The old side turns off on its own falling edge. The new side turns on only at a falling edge of the new clock. If that clock is stopped, it never turns on, so the output stays low. The system must start the new clock first, or use a switch with a fallback.

    Self-Check

    Tick each key point you covered in your answer.

    Missed Corner

    "A glitch-free switch always completes."

    Its handover needs edges from both clocks. The twin switches to a stopped clock and counts no output edges after the switch.

    Run It

    The glitch-free switch with clk_b held at 0.

    RUNIcarus Verilog · in your browser
    Edit the code, then run it
    Expected: rising edges on clk_out after the switch: 0 FAIL: switching to a stopped clock leaves no clock at all; the handover needs edges from both clocks
    See the Fix
    `timescale 1ns/1ps
    module tb;
      logic clk_a = 0, clk_b = 0, sel = 0, clk_out;
      always #5 clk_a = ~clk_a;                    // 10 ns clock
      always #8 clk_b = ~clk_b;                    // 16 ns clock
      // Glitch-free switch (simplified: real designs add synchronizer flops on sel in each domain).
      // Each side turns off on its own falling edge, and the other side waits until it is off.
      logic qa = 1, qb = 0;
      always @(negedge clk_a) qa <= ~sel & ~qb;
      always @(negedge clk_b) qb <=  sel & ~qa;
      assign clk_out = (clk_a & qa) | (clk_b & qb);
      realtime t_last = 0, min_hi = 1000, min_lo = 1000;
      int edges_after = 0;
      always @(clk_out) begin
        if ($realtime > 0 && clk_out === 0 && $realtime - t_last < min_hi) min_hi = $realtime - t_last;
        if ($realtime > 0 && clk_out === 1 && $realtime - t_last < min_lo) min_lo = $realtime - t_last;
        t_last = $realtime;
        if ($realtime > 60 && clk_out === 1) edges_after++;
      end
      initial begin
        #17 sel = 1;                               // switch while clk_a is high and clk_b is low
        #180;
        $display("rising edges on clk_out after the switch: %0d", edges_after);
        if (edges_after > 0) $display("PASS: with both clocks running the switch completes");
        $finish;
      end
    endmodule
    

    Prints: PASS: with both clocks running the switch completes

What People Get Wrong

Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.

Misconception

"A clock mux is just a mux; the tools handle it."

If the select changes while the outputs differ, the output can switch twice in a few nanoseconds. The twin measures a 2 ns high pulse from 10 ns and 16 ns clocks.

Run It

A plain mux switched at t = 17 ns, while clk_a is high and clk_b is low.

RUNIcarus Verilog · in your browser
Edit the code, then run it
Expected: shortest high pulse 2.0 ns, shortest low pulse 5.0 ns FAIL: the plain mux cut a high pulse shorter than either clock's half period
See the Fix
`timescale 1ns/1ps
module tb;
  logic clk_a = 0, clk_b = 0, sel = 0, clk_out;
  always #5 clk_a = ~clk_a;                    // 10 ns clock
  always #8 clk_b = ~clk_b;                    // 16 ns clock
  // Glitch-free switch (simplified: real designs add synchronizer flops on sel in each domain).
  // Each side turns off on its own falling edge, and the other side waits until it is off.
  logic qa = 1, qb = 0;
  always @(negedge clk_a) qa <= ~sel & ~qb;
  always @(negedge clk_b) qb <=  sel & ~qa;
  assign clk_out = (clk_a & qa) | (clk_b & qb);
  realtime t_last = 0, min_hi = 1000, min_lo = 1000;
  int edges_after = 0;
  always @(clk_out) begin
    if ($realtime > 0 && clk_out === 0 && $realtime - t_last < min_hi) min_hi = $realtime - t_last;
    if ($realtime > 0 && clk_out === 1 && $realtime - t_last < min_lo) min_lo = $realtime - t_last;
    t_last = $realtime;
    if ($realtime > 60 && clk_out === 1) edges_after++;
  end
  initial begin
    #17 sel = 1;                               // switch while clk_a is high and clk_b is low
    #180;
    $display("shortest high pulse %0.1f ns, shortest low pulse %0.1f ns", min_hi, min_lo);
    if (min_hi >= 5 && min_lo >= 5) $display("PASS: no pulse shorter than the faster clock's 5 ns half period");
    $finish;
  end
endmodule

Prints: PASS: no pulse shorter than the faster clock's 5 ns half period

Half-Truth

"A divided clock saves power, so it is always better than an enable."

It does stop toggling in the slow logic. But it adds a domain, crossings and STA work. Clock gating with a library cell saves the same power on one clock.

Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 8.1.5.4 Chip-enable flip-flops

Delivery

Proposes a fix before asking whether the two clocks are related.

Related clocks can be timed by STA. Unrelated ones need a crossing on every path between them. The answer depends on it.

Learn It, Then Prove It