Imagine you are given the job of building a house. Do you start by picking out paint colors or choosing bathroom fixtures? Of course not! You first need to consider how the owners will use the space and what their budget is so you can decide what type of house to build.
The same logic applies to hardware verification. Before you dive into the details of the SystemVerilog language, you need to understand how you plan to verify your design and how that will influence your testbench structure. As you begin this journey, remember the most important principle of a verification engineer: “Bugs are good”. Your goal is to be as devious as possible to extract all possible bugs early in the process while they are still easy to fix.
The Verification Process
What is the true goal of verification? It isn’t just about finding bugs; it is about ensuring that the design is an accurate representation of the hardware specification.
The verification process parallels the design process, adding a crucial layer of redundancy. The verification engineer independently reads the hardware specification, interprets it, and builds tests to prove the RTL code matches that interpretation.
During the verification process, you will hunt for bugs in several key areas:
- The Block Level: Testing individual modules to ensure basic operations (like bus transactions or ALU additions) complete successfully.
- Boundaries Between Blocks: Problems often arise when different designers interpret the same specification differently. You must find these disputed areas of logic to ensure signals change precisely when they are supposed to.
- The System Level: At the highest level, you must test the entire system executing multiple operations concurrently. This helps uncover subtle data alignment and timing bugs.
- Error Injection: Once the design performs its designated functions, you must test how it recovers from errors, such as partial transactions or corrupted data.
The Verification Plan
To navigate the verification process successfully, you need a map. The verification plan is closely tied to the hardware specification and contains a description of what features need to be exercised and the specific techniques to be used. These techniques might include directed testing, random testing, assertions, formal proofs, or the use of verification IP.
Basic Testbench Functionality
A testbench wraps around the Design Under Test (DUT) to determine its correctness. At its core, every testbench accomplishes this through a few fundamental steps:
- Generate stimulus
- Apply stimulus to the DUT
- Capture the response
- Check for correctness
- Measure progress against the overall verification goals
Methodology Basics
Traditionally, engineers used “directed tests” to incrementally cover features in a verification plan. While directed tests are good for finding the bugs you expect to be there, they are incredibly time-consuming and struggle to keep up with doubling design complexity.
To reach 100% coverage faster and find the bugs you never anticipated, you must adopt a modern methodology. The fundamental principles of this methodology include:
- Constrained-random stimulus: Relying on the simulator to automatically generate valid but randomized inputs.
- Functional coverage: Using automated metrics to measure your verification progress and identify untested design holes.
- Layered testbench using transactors: Breaking the testbench into manageable, separated pieces (such as signal, command, functional, and scenario layers).
- A common testbench for all tests: Building a shared infrastructure so you don’t have to start from scratch for every test.
- Keeping test-specific code separate: Leaving “hooks” in your common testbench so individual tests can inject disturbances or shape stimulus without complicating the shared infrastructure.
By adopting these guidelines, you trade the tedious manual labor of writing hundreds of directed tests for a robust, reusable environment that finds bugs automatically.
