VLSIChaps Academy · Track 01

Your First Testbench, Display and Finish

~12 min Hands-on lab 1 exercise Verilator
Page 07 of 20
01

What Is a Testbench?

Every module you build in SystemVerilog needs something to drive its inputs and check its outputs. That something is a testbench. A testbench is itself a SystemVerilog module, but it has no ports. It exists only in simulation and is never synthesised into hardware. Its entire job is to create the environment that your design under test, the DUT, would normally operate in.

On previous pages you wrote modules that describe hardware. This page flips the perspective. You are now the engineer sitting outside the chip, deciding what inputs to apply and what outputs to observe. That mental shift is one of the most important in verification.

02

Driving Inputs and Instantiating the DUT

To test a module, you first declare signals in the testbench to connect to the DUT ports, then instantiate the DUT by name. Named port connections, written as .port_name(signal_name), are the professional style because they survive port order changes without silent bugs.

Inside an initial block you drive inputs by assignment. Stimulus is procedural: assignments happen one after another in time order. This is different from the continuous assignment you used in your design modules. The initial block runs exactly once from simulation time zero and is the place to set up your scenario, wait for responses, and observe results.

One caution: a combinational gate like the and_gate you will test does not update its output at time zero. You assign inputs at time zero, but the gate event is scheduled and settles a moment later. Adding a small time delay with #1; advances the simulator by one time unit so propagation completes before you read the output. Skip that delay and you will see an unknown value on the output even though your inputs look correct.

03

$display and $finish

SystemVerilog provides a family of system tasks for observing simulation. $display is the workhorse: it prints a formatted string to the simulation log, much like printf in C. The format string uses %b for binary, %d for decimal, and %h for hexadecimal. A call like $display("y = %b", y); prints the current binary value of y with a label, which is exactly the output the grader is looking for.

$finish tells the simulator the test is done and it should exit cleanly. Without it, an event driven simulator keeps running, waiting for something that never arrives. In a professional environment a runaway simulation wastes compute hours. The habit of finishing explicitly is one worth building from your very first testbench.

04

The Verilator Reality Check

Verilator, the engine behind this lab, compiles SystemVerilog to C++ and runs it natively. That means it enforces strict two-file conventions: it expects the DUT module and the testbench module to both be present in the compilation. The grader handles that automatically here, concatenating the provided design with your testbench before compiling.

What matters to you as the learner is that Verilator output is exactly what appears in the engine panel. The line y = 1 must be present in stdout for the grader to mark you as passing. No label, no pass. Wrong label, no pass. This precision mirrors a real CI regression: the check script looks for an exact string, and everything else is a failure. Write the display statement to produce that exact string.

Lab: Write a Testbench for and_gate

The and_gate module is provided below and is already included in the grader compilation. Your job is to complete the testbench: instantiate and_gate, drive a=1 and b=1, wait one time unit so the gate propagates, print y using $display("y = %b", y), then call $finish. The grader matches stdout against the string "y = 1".

Five steps in order: declare logic signals, instantiate and_gate with named ports, open an initial block, assign a=1 and b=1 then write #1; to advance time, then call $display("y = %b", y) and $finish. The grader checks that the output line reads exactly y = 1.
Compiling and simulating...
Correct. Your testbench instantiated the DUT, drove both inputs, waited for propagation, and printed the output. That is the complete anatomy of a working testbench.
Not quite. The simulation ran but the output did not match the expected string "y = 1". Check your input assignments, the delay, and the exact format of your $display call.
Compile error.
Something went wrong reaching the engine. Try again in a moment.
AI Mentor
Thinking...
📲 Join 20K+ Engineers