Reset sequencing races are a specific RTL bug class that hand-written directed testbenches routinely miss. Such benches find the cases their authors predicted. For a FIFO, a verification engineer usually tests write, read, simultaneous write and read, full, and empty. Those scenarios follow the expected usage model. The untested space consists of conditions no one anticipated, which is where several important RTL bug families hide.
This reflects the structure of directed testing, not a lack of engineering ability. A test exercises only behavior represented in its model, and that model is limited by what was understood when the test was written. Identifying bug classes outside that boundary helps focus supplemental verification effort.
Reset Races
Directed benches most often miss reset sequencing under concurrent activity. The usual reset test asserts reset at simulation time zero, while every interface is idle. The design remains quiescent, reset deasserts cleanly, and initialization completes correctly. Once that test passes, the verification plan labels the reset requirement tested.
The silicon-relevant case is reset during live activity. An AXI write may be underway, a DMA controller may be mid-transfer, and the interrupt FIFO may contain pending entries. The power management controller can issue reset because of thermal throttling. These operations were not necessarily built to survive reset. The key question is whether their partial state damages post-reset initialization.
This class can produce registers retaining pre-reset values because the reset tree failed to reach them synchronously, FSM states entering an illegal state when reset races with a combinatorial output, and DMA buffer pointers becoming misaligned because reset arrived during an increment.
Reaching these bugs needs concurrent stimulus: an active transaction from the bus master agent, reset asserted by the reset controller model, and coverage for the FSM state at reset combined with the post-reset initialization state. Directed benches seldom include that combination. Reset and transaction tests are normally separate, so their intersection never entered the original list.
Multi-Cycle Paths in FSM Transitions
FSMs with multi-cycle transitions expose another gap in directed testing. When an FSM remains in one state for several clock cycles, the usual test exercises the transition once under nominal conditions. It does not vary the arrival of the trigger across cycle 1, cycle 2, and cycle N of that multi-cycle state.
This is especially important in FSM-based handshakes. In a request-acknowledge handshake, the FSM waits in PENDING_ACK for acknowledge. A directed test may assert acknowledge on cycle 2 of PENDING_ACK. A corner bug may appear on cycle 1, before combinatorial output evaluation is complete, or after cycle 8, when a timeout counter overflows. Neither timing is included because it is not the normal acknowledgment case.
Constrained random reaches this space more effectively, provided coverage records the cycle count within each multi-cycle state. Without that point, the solver has no target for those cycle counts and may never exercise them.
Protocol Error Injection
Protocol error injection is where directed testbench coverage is usually thinnest. AXI4 permits the error responses SLVERR, DECERR, and OKAY. After detecting an illegal access, an AXI slave can return SLVERR, which the master must handle correctly. Most directed benches exercise OKAY. Few inject SLVERR into a read transaction within a burst. Almost none inject it mid-burst, with OKAY on the first three beats and SLVERR on the fourth.
The engineer who built the AXI master testbench was primarily checking correct protocol generation. Error handling existed in the specification and was marked tested after basic SLVERR handling passed. The mid-burst case was omitted because it needs a precise sequence: begin a four-beat read burst, complete three beats with OKAY, inject SLVERR on beat four, then verify that the master's internal state machine handles the partial error and returns beat data with the correct error flags.
This stimulus needs a slave model able to inject errors at selected beat positions. Most UVM slave models lack that control because they were built for compliance, not adversarial behavior. Adding targeted error injection to an existing slave model is a high-value testbench investment during a verification campaign.
CDC Violations
CDC bugs are difficult to find in simulation because the model does not reproduce physical metastability. CDC verification is generally assigned to static CDC analysis tools. Yet static analysis misses some CDC-related functional bugs, including behavior across domains with unusual clock ratios and behavior when crossing logic is gated.
Gated CDC crossings are a clear directed-test weakness. If a clock-domain gate is controlled by a configuration register, and crossing logic should reset when the gate deasserts, behavior depends on the order of gate-off assertion, crossing-signal capture, and gate-on reassertion. CDC tests usually leave the gate enabled. Gate cycling during an active crossing is absent from the list.
Static CDC tools identify structural issues such as unsynchronized signals, synchronizer fan-out, and reconvergence paths. They do not evaluate functional interactions between gating sequences and in-flight crossing signals. That case needs simulation combining gate cycling with transaction injection, a constrained random scenario rather than a directed one.
Arbiter Corner Cases
An arbiter that behaves under light contention can expose priority inversion under sustained heavy contention. A typical round-robin test sends one request from each master and checks ordered cycling. It does not examine one master holding its request continuously while another waits for a grant, with a third issuing a high-priority request during the interval in which the first has waited longest.
RTL priority-arbitration bugs are often small and consequential. A starvation counter may overflow silently and return to zero, making prevention logic grant incorrectly. A pipeline register added for timing closure may delay sampling of a priority bit by one cycle without a corresponding change to the arbiter's state machine.
These failures need sustained contention among multiple masters. Creating it with three UVM agents that assert together for enough cycles to trip a starvation counter requires a specialized directed test or constrained random guided by suitable coverage goals. Most directed arbiter tests exercise only one grant at a time.
Coverage Models Beyond Directed Tests
The pattern is consistent: each bug depends on several conditions across concurrent operations, while directed tests do not naturally produce that combination. A coverage model exposes those conditions and shows whether they were exercised.
For reset sequencing, record the FSM state when reset is asserted. For error injection, record the burst beat index receiving the error. For arbitration, record how many cycles each master has waited at every grant decision. Once these points are present in the coverage database, the gap is visible. Without them, it remains hidden.
For these categories, begin with the coverage model rather than writing more directed tests. Run constrained random against it and use the coverage database to identify conditions the existing testbench cannot reach. Those gaps indicate where to add testbench capability or automated stimulus generation.
At BigEndian, we have found that five categories, reset racing, multi-cycle FSM transitions, error injection, CDC gating, and priority arbitration under contention, account for a disproportionate share of coverage arcs that constrained random does not close and directed tests leave open. Knowing why hand-written tests struggle with them helps determine where additional stimulus is required.