Module 10: Capstone Projects ยท Project 2: UART Sequential Flow

Project 2, Part 3: Physical Verification and Retrospective

In the previous article we added a hold buffer after CTS. That buffer is a real physical change to the design, and it is the reason LVS on this project deserves more attention than on Project 1. In this article we run the checks and write the report.

DRC

Run the Magic DRC script from Module 8.1 on runs/uart_run1/final/gds/uart_top.gds:

COUNT: 0

Clean, as expected for a design at 45% utilisation with no congestion.

LVS

Extract and compare with the final powered netlist, as in Module 8.2:

netgen -batch lvs \
  "uart_top_extracted.spice uart_top" \
  "runs/uart_run1/final/pnl/uart_top.pnl.v uart_top" \
  "$PDK_ROOT/sky130A/libs.tech/netgen/sky130A_setup.tcl" \
  lvs_uart.report
Final result: Circuits match uniquely.

The hold buffer is in both the layout and the netlist, and it matches like any other cell. It does so because the fix was made by the resizer inside OpenROAD’s database: the same database that routing then used and from which OpenLane wrote the final netlist. The layout and the netlist were never allowed to disagree. Keep that in mind; Project 5 is about what happens when an edit is made outside the flow and they do disagree.

The mistake to avoid is applying a change, a buffer, a resize, a hand-drawn wire, directly to the layout and going straight to signoff without the netlist being rewritten from the same change. The layout is then ahead of the netlist, and LVS reports an extra instance even though the layout may be exactly what you intended.

Antenna and timing

Antenna: 0 violating nets
Worst setup slack, all corners: +1.02 ns (ss)
Worst hold slack, all corners:  +0.05 ns (ff)

These are the numbers from the multi-corner table in the previous article. Nothing changed during verification.

The signoff report

Check Result
Synthesis 431 cells, 62 flops
CTS 62 sinks, 9 clock buffers, 142 ps skew
Hold violations after CTS 1 found, fixed with one hold buffer
Routing 0 violations
DRC (Magic, KLayout) 0
LVS (final netlist, including the hold buffer) Match
Antenna 0
Worst setup slack, all corners +1.02 ns
Worst hold slack, all corners +0.05 ns
GDS runs/uart_run1/final/gds/uart_top.gds

Every row is clean, but unlike Project 1’s report this one has a story in it: one row records a real problem that had to be found and fixed before the rest of the table could be true.

What Project 1 could never have shown

It is worth naming the lesson precisely, because “sequential designs are harder” is too vague to be useful. A hold violation is a problem of data arriving too early relative to the capturing clock, the opposite of a setup violation’s data arriving too late. It needs three things at once: flops placed close together, clock delays to them that are not equal, which only a real clock tree creates, and a data path short enough for the two effects to meet. A design without a clock tree cannot produce it, however large it is, because the failure lives in the gap between the ideal clock synthesis assumes and the real tree CTS builds. Project 1 had no tree. This project did, and the very first post-CTS check found a violation. That was not staged for the lesson; nearly every real sequential design shows at least one.

Practice Exercise

Project 1’s report has a CTS row that says “not applicable”. If someone wanted a “hold violations after CTS” row in Project 1’s report as well, what is the accurate entry, and why is “0” the wrong one?

Solution

The accurate entry is “not applicable: no clock tree”. Writing “0” says the check was run and found nothing, which suggests CTS ran and passed on that design, when in fact the stage was skipped. The distinction matters in real signoff reports: a “0 violations” entry for a check that was never performed gives false confidence to anyone reading it later. A careful report always separates “checked, nothing found” from “not applicable, not checked”, which is the precision the signoff checklist of Module 9.3 asks for.

Project 2 closes with a real hold violation found, understood and fixed, the first real problem of this module and one no combinational design could have produced. Project 3 changes the challenge: a small controller around a hardened SRAM macro, where the difficulty is not timing but floorplanning, placing and verifying around a block you did not build.

โ† Project 2, Part 2: CTS and Timing Closure Project 3, Part 1: Integrating a Hardened Macro โ†’