Every DV team running a constrained-random testbench on a modern SoC has access to both simulation and formal verification tools. In practice, most teams default to simulation for 95% of the design and use formal only for specific block-level properties, usually after someone has tried and failed to close coverage on a particular area with simulation alone.
That pattern is partly rational and partly habit. Simulation is what most DV engineers learned first, the testbench infrastructure already exists, and the EDA license is already in use. But there are classes of properties where formal is strictly better — not marginally better, strictly — and using simulation for those properties wastes weeks of effort that could be spent elsewhere.
This is a practical guide to that boundary: which properties belong to formal, which belong to simulation, and which are genuinely in the grey zone where tool choice depends on design-specific factors.
What Formal Verification Actually Does
Formal verification — specifically property checking or model checking — proves or disproves a property about a design by exhaustive state space exploration rather than by executing specific stimulus sequences. Instead of running a set of test vectors and observing whether the output is correct, formal tools construct a mathematical model of the design and check whether the specified property holds for all possible inputs, across all reachable states.
The implication: for a property that formal successfully proves, the guarantee is not "this property held for all the tests I ran." It is "this property holds for every possible input sequence, with no exceptions." That is a categorically different kind of confidence than simulation coverage provides.
The cost of that guarantee: formal scales poorly with state space size. For designs with large register files, deep FIFOs, and complex FSM encodings, the state space grows exponentially and the formal tool either runs for a prohibitively long time or hits a resource limit and produces an "inconclusive" result rather than a proof. This is the fundamental scaling constraint that makes formal a tool for specific properties on bounded designs rather than a full-design verification strategy.
Properties Where Formal Is the Right Tool
The best use cases for formal property checking share a common characteristic: the property needs to hold for all possible inputs or all possible sequences, and simulation cannot exhaust the relevant space in a reasonable amount of time.
Deadlock freedom. Does this arbitration logic, handshake protocol, or request-grant FSM contain any state sequence that leads to a deadlock — a situation where no progress is possible regardless of future inputs? Finding a deadlock via simulation requires constructing exactly the right sequence of inputs to reach the deadlock state. Proving absence of deadlock via simulation requires arguing that you've tested all relevant sequences, which is never fully possible for a multi-agent protocol. Formal tools can often prove deadlock freedom for bounded state machines where the cycle depth is tractable.
Protocol invariants. "No two agents are simultaneously granted exclusive access to the bus." "The data output is stable within N cycles of the request being asserted." "The FIFO never asserts both empty and full simultaneously." These are safety properties — conditions that must never be violated — and they're expressible in SVA as assert property statements. Formal can check whether the property holds under all reachable states and all input combinations. Simulation checks whether it holds for the stimulus sequences you happened to run.
Equivalence checking. RTL-to-RTL equivalence (verifying that a refactored or optimized version of a block is functionally identical to the original) is a formal application where the technique has no simulation equivalent. You cannot simulate a design against itself to prove equivalence — you need to prove that both implementations have the same output for all possible inputs, which is exactly what combinational and sequential equivalence checking does.
Bounded reachability for deep FSM paths. If you have an FSM where a specific error recovery state requires 50 cycles of specific inputs to reach, simulation might hit it or might not. Bounded model checking with a depth bound of 60 can prove either that the state is reachable within that bound or that it isn't. This is more precise than "we ran 10,000 random seeds and didn't hit it, so we wrote a directed test."
Properties Where Simulation Is the Right Tool
Simulation's strength is in scenarios where the property you want to verify involves complex, realistic stimulus patterns at scale — where the question isn't "does any sequence violate this?" but "does the design behave correctly given this specific class of inputs?"
Full-system stimulus response. "The design processes a packet stream at line rate with no drops under these traffic patterns." This is not a property that formal handles well — it requires meaningful stimulus (real or realistic packet data), a complex environment model (PHY, memory, clock domains), and a time-scale that makes exhaustive state space exploration impractical. Constrained-random simulation with well-structured monitors and scoreboards is the right tool here.
Performance and timing properties in context. Latency, throughput, and QoS properties under specific workloads are simulation territory. Formal can prove that a property holds for all sequences; it cannot efficiently prove that a system achieves a certain throughput goal under a realistic load distribution, because the realistic load distribution is precisely what needs to be modeled.
Coverage-driven verification of complex protocol interactions. When you have a complex bus protocol (PCIe, AXI, DDR) and you want to ensure your implementation handles all valid transaction combinations correctly, constrained-random simulation with VIP-generated stimulus is typically more productive than formal property checking. The state space of a full-protocol interaction is too large for formal, but structured constrained-random generation can achieve high functional coverage efficiently.
Post-silicon correlation and emulation workloads. Once you're validating against actual software or hardware workloads — running a real-world application on an FPGA prototype or emulator — you're in simulation territory by definition.
The Grey Zone: When Tool Choice Depends on Specifics
Several common DV scenarios genuinely sit in between, and the right tool depends on design-specific factors.
FSM completeness. Verifying that every state in an FSM has at least one reachable path from the reset state can be done with formal (reachability checking) or with constrained-random simulation (FSM state coverage). Formal gives you a complete answer faster for small FSMs (under 20-30 states); simulation is often more practical for larger FSMs where the formal state space is borderline tractable. The coverage database you get from simulation is also more useful for downstream analysis — formal's output is "proved" or "failed," not a graded coverage map.
Checking specific counter or accumulator properties. "This counter never overflows under these constraints" is a formal property if you can fully specify the constraint space and the counter is small. If the counter is 32 bits and driven by complex datapath logic, formal may time out. Simulation with coverage on the counter value range is the practical alternative, though it's not a proof.
FIFO pointer wrap-around and empty/full conditions. The classic verification case where formal shines for small FIFOs (4-16 deep) — you can write a property that proves the full/empty flags are always correct and let formal exhaustively check it. For FIFOs with hundreds of entries, the state space blows up and simulation with functional coverage on the boundary conditions is the practical approach.
The Integration Pattern: Formal First, Then Simulation
The most productive teams we've seen use formal and simulation in a specific integration pattern: formal at block level early, simulation at integration level throughout.
Before a block goes into the SoC integration testbench, run formal property checks on the block-level assertions: protocol invariants, deadlock freedom for internal FSMs, any safety properties that need to hold regardless of the integration context. Prove them at block level while the block state space is small enough for formal to be tractable. Those formal-verified properties then become assumptions that the integration-level simulation can rely on — you've reduced the simulation burden by proving the block-level invariants once rather than testing for them implicitly in every integration test.
At integration level, constrained-random simulation with functional coverage is the primary tool. The block-level formal results give you confidence in the building blocks; the integration simulation is where you verify that the building blocks interact correctly under realistic stimulus.
This isn't a novel insight — the split between block-level formal and integration-level simulation has been the recommended approach in the DV literature for over a decade. What still surprises us is how many teams skip the block-level formal step entirely, usually because the testbench infrastructure for integration simulation is already in place and running formal on a new block requires setting up constraints and writing SVA properties. That setup cost is real; the payoff in reduced integration-level debugging is also real, and in our estimation the payoff usually exceeds the setup cost for FSM-heavy blocks and protocol interface blocks.
Coverage Closure and the Formal/Simulation Choice
When you're at 85-90% coverage with a simulation campaign and the remaining holes are concentrated in FSM transitions and deep sequential bins, the question of whether to switch to formal deserves explicit consideration — not just "let's write more directed tests."
For a specific uncovered FSM transition with a bounded predecessor path (reachable within, say, 30 cycles), a formal reachability check can tell you in minutes whether the transition is structurally reachable at all. If it is, formal can give you a counterexample — a specific input sequence that reaches it — which you can convert to a directed test. If it isn't (because your constraint environment inadvertently precludes it), formal tells you that too, which means the coverage hole is a testbench issue, not a simulation duration issue.
We use this pattern in Photoniq's analysis: when the model identifies a high-priority uncovered FSM transition, part of the output is whether the transition appears to be structurally reachable within the constraint environment. For cases where formal analysis would be more efficient than empirical test generation, the recommendation says so explicitly, with enough information about the transition's predecessor requirements to set up the formal check.
Formal and simulation are not competitors. They have different strength profiles against different problem classes, and using them together — deliberately, with clear reasoning about which tool fits each problem — is what separates efficient verification campaigns from ones where the DV team is still writing directed tests in the final week before tape-out.