Modern testbench architecture

The aim of this article is to explain the what and why of modern testbench architecture. With the knowledge in this article, you should be able to understand how most of all modern verification frameworks are structured and how similar they really are. There are many hardware verification frameworks in this world, but the concepts have almost stayed the same for decades. If you squint hard enough, they all look the same.

Interface

The DUT and the Interface

We have a design that we want to test. We call this the “design under test” (DUT). The design has input and output pins. We group related pins on a design under test into interfaces. Interfaces are our primary means of accessing the functionality of our design, but interfaces is not our primary means of understanding. We would like some abstraction that only considers the functionality of our DUT, not the cycle by cycle nature of the interface.

Transaction

The DUT and the transaction

At the core of modern testbench architecture is the transaction. A transaction is a data structure that encapsulates the information that is needed to perform some functionality. Our transactions is our primary means of understanding when designing testbenches. It is also our primary means of abstraction from the cycle by cycle nature of the underlying hardware.

We think in sequences of transactions in order to stimulate our design into interesting scenarios.

The flow of transactions: Drivers and Monitors

Drivers and Monitors connect the transaction to the interface

We need to have a mechanism for connecting transactions and interfaces. We have one mechanism for each direction. A driver converts a transaction to cycle by cycle pin wiggles. A monitor samples cycle by cycle pin wiggles and convert these into transactions for us to understand and reason about. We some times call drivers and monitors bus functional models.

The flow of transactions: Sequencer

A generator or sequencer creates transactions that the driver converts into pin wiggles. The sequencer orchestrates one or more sequences of transactions. The sequencer is often simple. The complexity is often embedded inside sequences. Sequences can contain other sequences, so they can be composed into arbitrarily complex scenarios.

Transaction generation and sequencing is often where most frameworks differ.

Agent

The Agent wraps the driver, monitor and sequencer

For ease of use and understanding, we group the driver, monitor and sequencer into an agent. An agent handles all instantiation and connection of the components inside the agent. This makes reuse much easier

Checkers and Scoreboards

Checkers and Scoreboards verify the design

Checkers and scoreboards are our primary means of verifying our design. A checker observes an interface or the output of a single agent and looks for inconsistencies. A scoreboard connects two or more agents and compares their outputs. Depending on methodology, the scoreboard may be connected directly to monitors instead of their agents.

Checkers are placed in multiple places, depending on the needs of the testbench. Checks can be placed inside a monitor or in a subscriber to the monitor. It is possible that a generic instance of an interface does not guarantee a certain property, but the DUT does, so the check must go into a subscriber to the monitor insider the environment instead of placing the check directly in the monitor. Placement of checks is often based on the taste of the individual verification engineer.

Coverage

Coverage collection gives you a sanity check on whether all interesting use cases were hit

Coverage collectors are placed in multiple places just like checkers. While they often exist together with checkers, they are separated from checkers both conceptually and for ease of reuse. Coverage collection may appear inside monitors just like checkers, but they are often placed inside a subscriber as a generic interface may be able to perform some transaction that the DUT will never perform. Keeping the generic coverage collection inside the monitor would make it impossible to close coverage.

Environments

An environment is a collection of agents for a design under test. The environment also hooks up agents, scoreboards and subscribers. An environment can contain other environments enabling the ability to reuse an environment as a subsystem in a larger verification environment. This mean of combination allows for more complex testbenches to be built out of smaller, simpler testbenches. The goal is to put as much as possible into the environment in order to maximize reuse.

Ideally there is only one environment per DUT in order to maximize reuse.

Harness (top)

The harness is the top level module that instantiates the DUT and connects it to the environment. It is the starting point for the simulator to begin execution. The top level is ideally a relatively small module, but connectivity and corner cases often makes it much larger than anticipated.

Tests

The complete system architecture of a modern testbench

Tests control the environment and the DUT inside the harness to push the DUT into interesting behavior. The goal is to have many tests for each environment. The environment should only have to be compiled once and then have all the tests simulated in parallel.

Conclusion

This overview shows how most of the many verification methodologies are structured and how similar they are. If you see a new verification methodology, then the learning curve should not be too steep if you already understand the general structure.

References

Never miss an article