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
Xescapes.
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.
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):
// 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));// 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# 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):
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 cycles6. Debugging Session — a clock-gated UART that corrupts on enable
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 CROSSINGA 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.
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.
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
- Build a clock-gated UART/timer with a combinational ICG enable and clock-gate it on/off.
- Observe: the gated clock glitches and the datapath corrupts (8.6).
- Change: register the enable (stable across the ICG window).
- 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.