Debugging
Static checks
The sim-versus-silicon divergences a passing testbench will never catch.
A design can pass every test it has and still be wrong on real hardware. Simulation and silicon disagree in a small number of well-known ways, and those ways can be looked for directly, without a testbench and without running anything.
Three layers of checking
| Check | What it looks at |
|---|---|
| Lint | Verilator over your sources: width mismatches, unused and undriven signals, latches, unreachable code, and the rest of the standard catalogue. |
| Synthesis check | Yosys elaborates the design and reports what it inferred, which is where a latch you did not intend or an undriven net tends to surface. |
| Hardware scan | A focused set of rules for the places simulation and hardware are known to part company. This is the layer that a passing testbench cannot substitute for. |
A debug run reaches for these itself, particularly when the testbench passes and you are telling it the design is wrong anyway. If a tool is not available on the deployment, the check reports itself as unavailable rather than quietly reporting nothing found.
What the hardware scan looks for
| Pattern | Why it matters |
|---|---|
| Registers with no reset | They start at a defined value in simulation and at whatever the fabric feels like in hardware. |
| initial used as a reset | Works in a simulator, is ignored or unsupported on much real silicon. |
| A clock-domain crossing with no synchroniser | Metastability does not exist in a zero-delay simulation, so this passes cleanly and fails intermittently on a board. |
| A clock generated by combinational logic | Glitches on it are invisible in simulation and very much not invisible in a real clock tree. |
| Blocking assignment inside a clocked block | Changes evaluation order in a way that can differ between simulation and synthesis. |
| One register driven from two clocks | Simulatable, not implementable. |
| Delays in synthesisable code | Honoured by the simulator, ignored in silicon; a design that relies on one behaves differently in each. |
| Four-state comparisons | Comparing against X or Z is a simulation construct with no hardware meaning. |
These are heuristics, and they say so
The scan reads your source text; it does not elaborate the design the way a synthesiser does. So every finding carries a confidence level, and a finding is meant to be confirmed against the source before it gets reported as a root cause. A high-confidence finding is usually worth acting on directly. A low-confidence one is a place to look.
Note
Testbenches are excluded from the scan by default. Delays and four-state comparisons are correct in a testbench and wrong in RTL, so including them would bury the findings that matter under findings that do not.
Reading the findings
warning hw_scan rtl/uart_rx.v:38 high
`baud_cnt` is never reset. It starts as X in simulation and at an
arbitrary value on the device.
warning hw_scan rtl/uart_rx.v:71 medium
`rx_sync` crosses from the rx clock domain with no synchroniser.
warning verilator rtl/fifo.v:22
Bit-width mismatch: assignment of 9 bits to an 8-bit target.Findings are grouped by severity. An error from lint or synthesis is usually something that will not build. A warning is usually something that will build and may not do what you meant.
Where the checks stop
There is no timing analysis and no power analysis here, and neither can be inferred from these results. If a design passes everything on this page and still fails on the board, the next step is your own vendor toolchain with your own constraints. What this layer is good at is the class of bug that survives a green testbench, which is a large enough class to be worth a few seconds of every debug run.