0
0
VerilogHow-ToBeginner · 4 min read

How to Write Testbench in Verilog: Syntax and Example

To write a testbench in Verilog, create a separate module without ports that instantiates the design under test (DUT), applies stimulus signals, and monitors outputs. Use initial blocks to set inputs and $monitor or $display to observe results during simulation.
📐

Syntax

A Verilog testbench is a module without input or output ports. It includes:

  • Instantiation of the design under test (DUT).
  • Signal declarations to connect to DUT inputs and outputs.
  • Initial blocks to apply stimulus and control simulation time.
  • Monitoring statements like $monitor or $display to print output values.
verilog
module testbench();
  // Declare signals to connect to DUT
  reg clk, reset;
  wire out_signal;

  // Instantiate DUT
  design_module dut(.clk(clk), .reset(reset), .out(out_signal));

  // Apply stimulus
  initial begin
    clk = 0;
    reset = 1;
    #10 reset = 0;
    // further stimulus
  end

  // Clock generation
  always #5 clk = ~clk;

  // Monitor outputs
  initial begin
    $monitor("At time %t, out = %b", $time, out_signal);
  end
endmodule
💻

Example

This example shows a simple testbench for a 1-bit D flip-flop module. It applies clock and data signals and prints the output Q.

verilog
module dff(input clk, input d, output reg q);
  always @(posedge clk) begin
    q <= d;
  end
endmodule

module testbench();
  reg clk = 0;
  reg d = 0;
  wire q;

  // Instantiate the D flip-flop
  dff dut(.clk(clk), .d(d), .q(q));

  // Clock generation: toggle every 5 time units
  always #5 clk = ~clk;

  initial begin
    // Apply stimulus
    $display("Time\tclk\td\tq");
    $monitor("%0t\t%b\t%b\t%b", $time, clk, d, q);

    d = 0; #10;
    d = 1; #10;
    d = 0; #10;
    d = 1; #10;
    $finish;
  end
endmodule
Output
Time clk d q 5 1 0 0 10 0 0 0 15 1 1 0 20 0 1 1 25 1 0 1 30 0 0 0 35 1 1 0 40 0 1 1
⚠️

Common Pitfalls

Common mistakes when writing Verilog testbenches include:

  • Not toggling the clock signal, so the DUT never sees clock edges.
  • Forgetting to initialize inputs, causing unknown (X) states.
  • Not using $finish to end simulation, which can run forever.
  • Using blocking assignments (=) incorrectly inside always blocks for sequential logic.
verilog
/* Wrong: Clock not toggled, simulation never ends */
module testbench_wrong();
  reg clk = 0;
  initial begin
    // No clock toggling
    #100 $finish;
  end
endmodule

/* Right: Clock toggled and simulation ends */
module testbench_right();
  reg clk = 0;
  always #5 clk = ~clk;
  initial begin
    #100 $finish;
  end
endmodule
📊

Quick Reference

Tips for writing effective Verilog testbenches:

  • Use initial blocks to set inputs and control simulation flow.
  • Generate clocks with always blocks toggling signals.
  • Instantiate the DUT inside the testbench module.
  • Use $monitor or $display to observe signals.
  • End simulation with $finish to avoid infinite runs.

Key Takeaways

Write a testbench as a separate module without ports that instantiates your design.
Use initial blocks to apply input signals and always blocks to generate clocks.
Monitor outputs with $monitor or $display to see simulation results.
Always initialize inputs and toggle clocks to avoid unknown states.
End simulation explicitly with $finish to stop the run.