Topic hub

Verification

How to prove an FPGA design does what you meant before it reaches silicon, from self-checking testbenches and cocotb through UVM, formal with SymbiYosys and Verilator in CI.

Updated 13 Nov 2026 · testbench, cocotb, UVM, formal verification, SymbiYosys, Verilator, coverage, continuous integration

Overview

Verification is the work of showing that a design meets its specification before it is built. On an FPGA the cost of a mistake is lower than on an ASIC, because you can reprogram the part, but it is far from zero: a bug found on the board can take days to isolate with an on-chip logic analyser, and a bug found in the field can take a product recall. This hub is for engineers who want a verification approach that scales from a single module to a system, and for anyone who has only ever “looked at the waveform” and suspects that is not enough.

The spectrum runs from a directed testbench that drives a few vectors, through constrained-random simulation with coverage, to formal proofs that cover every possible input. Most projects need a mix. The choice depends on how much the design costs if it is wrong.

Key ideas

Self-checking testbenches

A testbench is non-synthesisable HDL (or Python, or C++) that instantiates the design under test (DUT), drives its inputs and watches its outputs. The first improvement over watching waveforms is making it self-checking: the testbench computes what the output should be, compares, and prints pass or fail. The second is separating the roles. A driver converts transactions into pin wiggles, a monitor converts pin wiggles back into transactions, a scoreboard compares them against a reference model, and the test itself only chooses what transactions to send. That structure is what UVM formalises, but it is useful at any scale, and you can build it in plain VHDL, SystemVerilog or Python.

TestbenchTestsequences, seedsDrivertxn to pinsDUTsynthesisable RTLMonitorpins to txnReference modelPython or C, untimedScoreboardcompare, count, coverageexpectedactualResult: pass or fail printed, and a coverage report of which cases were exercised
A layered testbench. The test chooses transactions, the driver and monitor handle pins, and the scoreboard compares the DUT with a reference model.

cocotb, UVM and constrained random

cocotb lets you write the testbench in Python and run it against any mainstream simulator, including the free Icarus Verilog, GHDL and Verilator. Coroutines await clock edges, the full Python ecosystem is available for reference models, and the DUT stays in HDL. It has become the default for open-source cores and for small teams.

UVM (Universal Verification Methodology) is a SystemVerilog class library standardised by Accellera and the IEEE. It defines the agent, sequence, scoreboard and factory structure that large ASIC teams use. Its strengths are reuse and constrained-random generation: you describe the legal input space with constraints and let the simulator pick thousands of random cases, then use functional coverage to see which parts of the space were hit. Its cost is a steep learning curve and a need for a commercial simulator, because free tools do not fully support the SystemVerilog class features UVM requires. On FPGA projects it is common in the IP-vendor world and rare in small teams. For VHDL users, OSVVM and UVVM offer similar ideas without SystemVerilog.

Formal verification

Formal tools do not simulate. They treat the design as a set of equations and ask a solver whether a property can ever be violated. Bounded model checking proves that no counterexample exists within N cycles. Induction proves it for all cycles. The properties are written as SystemVerilog assertions or PSL, and the same assertions can run in simulation. SymbiYosys (SBY) from YosysHQ drives open-source solvers and is free to use with Verilog. AMD Vivado, Siemens Questa and Cadence JasperGold offer vendor formal. Formal is unmatched for FIFOs, arbiters, bus protocol compliance and anything where the bug is a rare ordering of events that random simulation would take years to hit. It struggles with large arithmetic and deep pipelines.

Verilator, coverage and CI

Verilator compiles synthesisable SystemVerilog into a C++ model that runs ten to a hundred times faster than an event-driven simulator. It is the right tool for long software-driven tests, such as booting Linux on a soft core, and it reports line and toggle coverage. Putting simulation in continuous integration means every commit runs the test suite in a container with Verilator, Icarus, GHDL or a licensed simulator, and failures block the merge. A hardware project without CI is relying on someone remembering to re-run the tests.

Where to start

Intermediate lessons on cocotb, SystemVerilog assertions and a first formal proof with SymbiYosys are coming.

Tools and vendors

Tool Kind Languages Cost Typical use
Icarus Verilog Event simulator Verilog, some SV Free Small Verilog designs, cocotb
GHDL Event simulator VHDL Free VHDL designs, cocotb, formal via Yosys
Verilator Compiled simulator SystemVerilog Free Fast system-level tests, CI
cocotb Testbench framework Python Free Any simulator above or below
SymbiYosys Formal Verilog, SVA Free Proofs on modules
Vivado Simulator Event simulator VHDL, Verilog, SV Free with Vivado AMD IP simulation
Questa, Xcelium, VCS Event simulator All, full UVM Commercial UVM, large mixed-language projects
OSVVM, UVVM VHDL libraries VHDL Free Constrained random and coverage in VHDL

Vendor simulators are described under /vendors/amd/, /vendors/altera/ and /vendors/opensource/.

Common mistakes

  • Checking results by eye in a waveform viewer and calling it tested.
  • Using the design itself as the reference model, which proves only that the code equals the code.
  • Writing tests that pass regardless of the DUT because a comparison is never reached.
  • Driving inputs on the same edge the DUT samples them, creating race conditions that hide or invent bugs.
  • Reporting 100 % line coverage as if it meant 100 % of behaviour was exercised.
  • Leaving simulation out of CI, so the test suite rots as the design changes.

Going deeper