Skip to content

GLS · Chapter 14 · Industry Case Studies

Case Study — UART / Timer Peripheral GLS

The fourth case study scales up to a peripheral, a UART or timer block, the project thread's next step after the FSM. A peripheral brings several gate-level concerns together: clock gating for power, a clock-domain crossing between the baud or sample domain and the system clock, real timing, and functional sanity. It ships the full artifact set: RTL, netlist, SDF, an adapted testbench, an expected log, and a debug walkthrough. Peripheral-level GLS combines the earlier bars, functional sanity, full-timing clean, and X and reset clean, with two new concerns: the clock-gate enable timing that must be stable across the gating cell's window, and the synchronizer on a status bit crossing clock domains. The debug centers on a clock-gated UART whose enable glitches the gated clock. This is where the book's threads converge on one real block.

Foundation13 min readGLSCase StudyUARTClock GatingCDC

Chapter 14 · Section 14.4 · Industry Case Studies

Project thread — the FSM (14.3) becomes a UART/timer peripheral here, combining clock gating and CDC. 14.5 does an AXI-Lite peripheral; 14.6 integrates everything into the mini-SoC.

1. Why Should I Learn This?

A peripheral is where the individual GLS concerns converge — this case combines them on one block.

  • Prior bars: functional sanity + full-timing clean (14.2) + X/reset clean (14.3).
  • New concerns: clock-gate enable timing (8.6) and a CDC synchronizer (9.3).
  • The debug: a clock-gated UART whose enable glitches the gated clock.

This is the first multi-concern case — the pattern for real blocks.

2. Real Silicon Story — the UART that corrupted when clock-gated

A clock-gated UART worked when always-on but corrupted its shift register whenever it was clock-gated on/off to save power.

The ICG enable was derived combinationally and changed too close to the clock edge, violating the ICG latch's window and glitching the gated clock (8.6) — so the UART's gated flops captured on a bad clock and corrupted. GLS surfaced the glitch; registering the enable (stable across the ICG window) fixed it. (A separate check confirmed the UART's status-bit crossing into the system domain used a proper synchronizer, 9.3.)

Lesson: a peripheral's clock gating and CDC are gate-level-specific concerns GLS catches — a glitchy ICG enable corrupts the block; verify enable timing (8.6) and the crossing synchronizer (9.3), on top of the timing and X/reset bars.

3. Concept — the peripheral GLS case

The design: a UART/timer peripheral — a shift/count datapath, clock-gated for power, with a status bit crossing to the system domain.

Peripheral GLS combines the bars:

  • Functional sanity — the block still works on key vectors (equivalence sanity, 13.3) — not full functional coverage (RTL/UVM's job).
  • Full-timing clean (14.2) — verified SDF + no real violations + no unexplained X.
  • X/reset clean (14.3) — every state flop reset, no power-up X escapes.

Two new gate-level-specific concerns:

  • Clock-gate enable timing (8.6): the ICG enable must be stable across the cell's window — a combinational/late enable glitches the gated clock, corrupting the gated flops. Register the enable.
  • CDC synchronizer (9.3): a status bit crossing from the baud/sample domain to the system clock needs a two-flop synchronizer (checks disabled on its first flop, 8.4/9.3). GLS shows the crossing under real delays; static CDC + MTBF verify it structurally/statistically (9.1).

Peripheral-clean (the combined bar):

  • Functional sanity passes, full-timing clean, X/reset clean, clock-gate enable stable (no gated-clock glitch), crossing synchronized.

Scope (accuracy):

  • GLS combines these dynamic checks; CDC also needs static CDC/MTBF (9.1), timing signoff is STA (0.3). GLS stays dynamic.
UART/timer peripheral: functional sanity, full-timing, X/reset, clock-gate enable timing, CDC synchronizerFunctional sanityblock works (equivalencesanity, 13.3)Full-timing cleanverified SDF (14.2)X/reset cleanevery state flop reset(14.3)Clock-gate enable(8.6)ICG enable stable acrosswindow → register itCDC synchronizer(9.3)status bit baud→systemclock (+ static CDC/MTBF,9.1)Peripheral-cleanall bars pass (dynamic;STA/CDC complement)12
Figure 1 - the UART/timer peripheral GLS case (representative). A peripheral combines: FUNCTIONAL SANITY (equivalence sanity), FULL-TIMING clean (verified SDF, 14.2), X/RESET clean (every state flop reset, 14.3), plus two new gate-level-specific concerns -- CLOCK-GATE enable timing (ICG enable must be stable across its window or the gated clock glitches, 8.6) and a CDC SYNCHRONIZER on a status bit crossing the baud/sample domain to the system clock (9.3, + static CDC/MTBF, 9.1). Peripheral-clean = all bars pass. GLS is dynamic; STA/static-CDC/MTBF complement it.

4. Mental Model — the first real building, wired for power and two clocks

The peripheral is the first real building on the SoC block — not a single brick (DFF) or a small structure (counter/FSM), but a wired building with power management and two clocks.

  • It needs the foundations of the earlier cases: it works (functional sanity), it's timed (full-timing), it comes up cleanly (X/reset).
  • Plus new systems: a power switch on the lights (clock gating) that must be flipped cleanly (stable enable, or the lights flicker — gated-clock glitch), and a doorway between two rooms on different schedules (the CDC crossing) that needs an airlock (synchronizer).
  • Get any system wrong — flickering lights (glitch), a bad airlock (unsynchronized crossing) — and the building misbehaves, even if the foundations are fine.

A real building: foundations (function/timing/reset) plus power and dual-clock systems, all verified.

5. Working Example — the peripheral artifact set

The clock-gated UART/timer (representative RTL sketch + the bug):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// UART/timer peripheral — clock-gated datapath + a status-bit CDC crossing — REPRESENTATIVE
icg u_icg (.clk(clk), .en(uart_en_q), .gclk(gclk));      // ICG: enable must be STABLE (8.6)
always_ff @(posedge gclk) shift_reg <= {rx, shift_reg[7:1]};  // gated UART datapath
// status bit crossing baud/sample domain -> system clock: 2-flop synchronizer (9.3)
sync2 u_sync (.clk(sys_clk), .d(uart_busy), .q(uart_busy_sys));
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// THE BUG (this case): the ICG enable is combinational -> glitches the gated clock (8.6)
assign uart_en = rx_active & ~idle;                       // late/glitchy -> gclk glitch -> corrupt
// THE FIX: register the enable (stable across the ICG window)
always_ff @(posedge clk) uart_en_q <= rx_active & ~idle;  // stable enable -> clean gclk
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# Expected log — REPRESENTATIVE (peripheral-clean bars):
#   [X/reset]      power-up X -> reset -> clean (14.3)
#   [full-timing]  SDF verified 0 unmatched (14.2); real clk-to-Q; checks triaged (8.4)
#   [clock-gate]   BUG: enable glitch -> gclk glitch -> shift_reg X ; FIX: registered enable -> clean (8.6)
#   [CDC]          uart_busy crosses via 2-flop synchronizer (checks disabled on 1st flop, 9.3)
#   [function]     sanity vectors pass (RX/TX frame / timer tick)
#   result: PERIPHERAL-CLEAN = all bars pass. (CDC also needs static CDC/MTBF, 9.1; timing signoff = STA)

Practical context (representative, tool-neutral):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
gls/case_uart/
  rtl/uart.v   netlist/uart.vg   lib/cells.v (ICG + sync)   sdf/uart.sdf   tb/tb_uart.v   expected/uart.log
# Flow: synth -> GLS combining bars: function sanity + full-timing (verify SDF) + X/reset + clock-gate + CDC
# Peripheral-clean: all bars pass. Complement with static CDC/MTBF (9.1) and STA (timing signoff).

The clock-gated UART: enable glitch (bug) vs registered enable (fixed), as a real waveform:

Clock-gated UART: a combinational enable glitches the gated clock (bug); a registered enable is clean (fix)

9 cycles
A combinational ICG enable glitches the gated clock and corrupts the shift register; a registered enable keeps the gated clock cleancombinational enable → gclk glitch → corruptcombinational enable →…registered enable → cleanregistered enable → cl…clken_bad (combinational)gclk_bad (glitches)XXshift_reg (bad)XXXXXXXgclk_good (registered en)t0t1t2t3t4t5t6t7t8
Representative. en_bad (combinational) changes near the clock edge, glitching gclk_bad and corrupting shift_reg (X, 8.6). en_good is registered and stable across the ICG window, so gclk_good is clean and the UART datapath captures correctly. Peripheral-clean also requires the status-bit CDC crossing to use a synchronizer (9.3). Fix: register the ICG enable.

6. Debugging Session — a clock-gated UART that corrupts on enable

1

A clock-gated UART corrupts its datapath whenever it is clock-gated because the ICG enable is combinational and glitches the gated clock; registering the enable (stable across the ICG window) fixes it, and the status-bit crossing is confirmed synchronized

PERIPHERAL: REGISTER THE ICG ENABLE; SYNCHRONIZE THE CROSSING
Symptom

A clock-gated UART works always-on but corrupts its shift register whenever it's clock-gated on/off — the datapath goes X/wrong on enable.

Root Cause

A glitchy ICG enable (8.6). The UART's ICG enable is derived combinationally (rx_active & ~idle) and changes too close to the clock edge, violating the ICG latch's timing window and glitching the gated clock — so the UART's gated flops capture on a bad clock and corrupt. GLS surfaces the gated-clock glitch (the 8.6 bug, now on a real peripheral). Meanwhile the peripheral's status-bit crossing (uart_busy → system clock) must be checked separately: it needs a two-flop synchronizer (9.3), with its first flop's timing checks disabled (8.4). The corruption isn't the datapath logic — it's the clock-gate enable timing, a gate-level-specific concern on top of the timing/X-reset bars.

Fix

Register the ICG enable so it's stable across the cell's window (uart_en_q <= rx_active & ~idle; feeding the ICG) — the gated clock stops glitching and the datapath captures cleanly (8.6). Confirm the status-bit crossing uses a proper two-flop synchronizer (9.3), complemented by static CDC + MTBF (9.1). Then verify peripheral-clean = functional sanity + full-timing clean (14.2) + X/reset clean (14.3) + clock-gate enable stable + crossing synchronized. The lesson: a peripheral combines the earlier bars (function/full-timing/X-reset) with two new gate-level-specific concerns — clock-gate enable timing (register the ICG enable, stable across its window, 8.6) and a CDC synchronizer on domain-crossing status bits (9.3, + static CDC/MTBF, 9.1); peripheral-clean = all bars pass. This is where the book's threads converge on one real block. (GLS is dynamic; STA/static-CDC/MTBF complement it, 0.3/9.1.)

7. Common Mistakes

  • Combinational ICG enable — glitches the gated clock (8.6); register it.
  • Unsynchronized status-bit crossing — needs a two-flop synchronizer (9.3).
  • Dropping the earlier bars — function/full-timing/X-reset still apply.
  • Treating CDC GLS as CDC signoff — needs static CDC/MTBF too (9.1).
  • Not verifying SDF annotation on the timed peripheral run (4.5/14.2).

8. Industry Best Practices

  • Register the ICG enable (stable across the cell window, 8.6).
  • Synchronize domain-crossing status bits (two-flop, 9.3); disable checks on the first flop only (8.4).
  • Verify the combined peripheral-clean bar (function/timing/X-reset/clock-gate/CDC).
  • Complement CDC GLS with static CDC/MTBF (9.1) and timing with STA (0.3).
  • Verify SDF annotation on the timed run (4.5).

Senior Engineer Thinking

  • Beginner: "The UART corrupts when clock-gated — the datapath logic is buggy."
  • Senior: "Is the ICG enable combinational? That glitches the gated clock (8.6) — register it. And does the status-bit crossing use a synchronizer (9.3)? A peripheral is all the bars at once — function, timing, X/reset, clock-gate, CDC."

The senior checks the clock-gate enable and the CDC crossing on top of the earlier bars.

Silicon Impact

A peripheral is the first block where multiple gate-level failure modes coexist — and each is a real silicon risk: a glitchy ICG enable corrupts the datapath whenever power management engages (an intermittent, clock-gating-triggered failure, 8.6/0.3), and an unsynchronized domain crossing produces metastability-driven corruption (9.x). GLS is where these converge and are caught together, on top of the timing and X/reset bars from the earlier cases. Peripheral-clean — function + full-timing + X/reset + clock-gate enable + CDC synchronizer — is the bar that says a real block is gate-level-sound, complemented by static CDC/MTBF (9.1) and STA (timing). Mastering the peripheral case is the step from single-concern designs (DFF/counter/FSM) to the multi-concern reality of the SoC (14.6).

Engineering Checklist

  • Registered the ICG enable (stable across the cell window, 8.6).
  • Synchronized domain-crossing status bits (two-flop, first-flop checks off, 9.3/8.4).
  • Verified full-timing clean (SDF verified, 14.2) and X/reset clean (14.3).
  • Confirmed functional sanity (equivalence sanity, not full coverage, 13.3).
  • Complemented CDC with static CDC/MTBF (9.1) and timing with STA (0.3).

Try Yourself

  1. Build a clock-gated UART/timer with a combinational ICG enable and clock-gate it on/off.
  2. Observe: the gated clock glitches and the datapath corrupts (8.6).
  3. Change: register the enable (stable across the ICG window).
  4. Expect: the gated clock is clean and the datapath captures correctly. Then add a status-bit crossing and confirm it uses a two-flop synchronizer (9.3). Verify the combined peripheral-clean bar.

Any free Verilog simulator with ICG and synchronizer cells runs the peripheral case. No paid tool required for the concept.

Interview Perspective

  • Weak: "The UART corrupts when gated — fix the datapath."
  • Good: "The ICG enable glitches the gated clock; register it. And synchronize any domain-crossing status bits."
  • Senior: "A peripheral is all the bars at once: functional sanity, full-timing clean (verified SDF), X/reset clean, plus clock-gate enable timing (register the ICG enable, stable across its window) and a CDC synchronizer on crossing status bits (with static CDC/MTBF). GLS catches the glitchy enable and the crossing under real delays; STA signs off timing and static CDC/MTBF sign off the crossing. Peripheral-clean = all bars pass."

9. Interview / Review Questions

10. Key Takeaways

  • A peripheral (UART/timer) is the first multi-concern case — it combines the earlier bars (functional sanity, full-timing clean 14.2, X/reset clean 14.3) with two new gate-level-specific concerns.
  • Clock-gate enable timing (8.6): the ICG enable must be stable across the cell's window — a combinational/late enable glitches the gated clock and corrupts the gated datapath; register the enable.
  • CDC synchronizer (9.3): a status bit crossing the baud/sample domain to the system clock needs a two-flop synchronizer (first-flop checks disabled, 8.4), complemented by static CDC/MTBF (9.1).
  • Peripheral-clean = all bars pass — function + full-timing + X/reset + clock-gate enable + CDC synchronizer.
  • GLS combines these dynamic checks; CDC also needs static CDC/MTBF (9.1) and timing signoff is STA (0.3) — this is where the book's threads converge on one real block. Next: 14.5 — AXI-Lite peripheral GLS.

Quick Revision

Peripheral (UART/timer) = first multi-concern case. Combines earlier bars — functional sanity + full-timing clean (14.2) + X/reset clean (14.3) — with two new concerns: clock-gate enable timing (register the ICG enable, stable across its window, 8.6 — else gated-clock glitch corrupts) and a CDC synchronizer on status-bit crossings (9.3 + static CDC/MTBF, 9.1). Peripheral-clean = all bars pass. GLS dynamic; STA/static-CDC/MTBF complement. Next: 14.5 — AXI-Lite peripheral GLS.