Skip to main content

Verilog Simulation Basics & Testbench Design

· loading · loading · ·
Hardware Design Verilog Simulation Testbench Timescale Simulation Regions Hardware Verification
Hardware Design
Axolot Logic
Author
Axolot Logic
Digital Design Engineer
Table of Contents
Verilog HDL Series - This article is part of a series.
Part 14: This Article

🧪 Verilog Simulation Basics
#

Simulation in Verilog is the process of executing your design over time to observe behavior and verify correctness.

💡 Key Concepts:
#

  • Simulation time progresses in discrete steps (e.g., #10).
  • Testbenches apply inputs and observe outputs.
  • No synthesis — purely virtual execution.

🧰 What is a Testbench?
#

A testbench is a Verilog module that instantiates the DUT (Design Under Test), generates input stimuli, and optionally monitors outputs.

✅ Example:
#

module tb;
  reg clk, rst;
  wire out;

  my_design dut (.clk(clk), .rst(rst), .out(out));

  initial begin
    rst = 1; #5; rst = 0;
    #100 $finish;
  end
endmodule

Testbenches are not synthesizable and often use $display, $monitor, $dumpvars.


⏱️ timescale Directive
#

The timescale directive defines simulation time units and precision.

✅ Syntax:
#

`timescale 1ns / 1ps
ValueMeaning
1ns1 simulation time unit = 1 nanosecond
/1psTime precision = 1 picosecond

Always place timescale at the top of each .v file, especially testbenches.


🧭 Verilog Simulation Scheduling Regions
#

In Verilog, each simulation time step is divided into multiple simulation regions that determine the order in which different processes and assignments are executed.

Understanding these regions is crucial for writing reliable testbenches and debugging race conditions.


1. Preponed Region
#

  • Event triggers such as @(posedge clk) are evaluated here.
  • This region captures signal changes before any assignments are made.
  • Used for edge-sensitive behavior and sampling inputs.

2. Active Region
#

  • Blocking assignments (=) are executed here.
  • Continuous assignments (assign), gate and primitive evaluations occur here.
  • $display, $write, $finish, and similar tasks also run in this region.
  • This is the main execution region for procedural code.

3. Inactive Region
#

  • This region executes any #0 delay statements.
  • It has lower priority than the active region.
  • Useful when multiple events are scheduled for the same simulation time.

4. Nonblocking Assign Update Region
#

  • The right-hand side (RHS) of nonblocking assignments (<=) is evaluated in the active region.
  • The left-hand side (LHS) updates are scheduled here and applied later.
  • This delay helps avoid race conditions and allows parallel process scheduling.

5. Postponed Region
#

  • This is the last region of the time step.
  • $monitor, $strobe, and waveform dumping ($dumpvars) occur here.
  • All values are settled, making this region ideal for observation and logging.

🧠 Key Notes:
#

  • Blocking (=): Executed immediately in active region
  • Nonblocking (<=): RHS evaluated first, LHS updated later
  • $display vs $monitor: $display runs in active, $monitor in postponed
  • Race conditions may occur when initial or always blocks interact across regions without proper control

⏰ Clock Generation in Testbench
#

A clock signal can be generated using initial + forever or always.

✅ Example 1: Using always
#

reg clk = 0;
always #5 clk = ~clk;  // 10ns clock period

✅ Example 2: Using initial
#

initial begin
  clk = 0;
  forever #5 clk = ~clk;
end

Avoid using forever inside synthesizable code — this is testbench only.

  • Initial value: Always initialize clk = 0 (or 1) before toggling to avoid undefined (x) behavior at time 0.
  • Period definition: The delay #5 defines the half-period. So #5 results in a 10ns full clock cycle.
  • Duty cycle: A 50% duty cycle is achieved by symmetric high/low times. Use #3/#7 for 30%–70% duty if needed.
  • Multiple clocks: For multi-domain designs, define separate blocks with different periods.

🔄 Typical Simulation Flow
#

  1. initial blocks start at time 0.
  2. assign/always logic responds to changes.
  3. Time advances using # delays or event triggers.
  4. $monitor, $dumpvars record output.

🧪 Behavioral vs Gate-Level Simulation in Verilog
#

🔹 Behavioral Simulation
#

  • Operates at the RTL (Register Transfer Level).
  • Describes the intended functionality using always, assign, initial, etc.
  • Fast and ideal for early functional testing.
  • Does not include actual gate-level structure or delays.

🔹 Gate-Level Simulation
#

  • Simulates the synthesized netlist — logic gates, flip-flops, muxes, etc.
  • Reflects real hardware behavior, including timing delays and fan-out effects.
  • Slower, but essential for final verification.
  • Includes Standard Delay Format (SDF) files in ASIC flows.

Verilog HDL Series - This article is part of a series.
Part 14: This Article

Related

Verilog Command-Line Input: $plusargs for Testbench Control
· loading · loading
Hardware Design Verilog Command Line Plusargs Testbench Simulation Control Hardware Verification
Hardware Design
Verilog Hierarchical Reference: Accessing Internal Signals
· loading · loading
Hardware Design Verilog Hierarchical Reference Force Release Testbench Simulation Debugging Hardware Verification
Hardware Design
Verilog Delay Controls: #Delay, @Event, Wait
· loading · loading
Hardware Design Verilog Delay Event Control Wait Statement Simulation Testbench
Hardware Design
Verilog System Functions & Tasks for Simulation
· loading · loading
Hardware Design Verilog System Functions Verilog Tasks Simulation Testbench Randomization
Hardware Design
Verilog VCD: Waveform Dumping for Simulation Analysis
· loading · loading
Hardware Design Verilog VCD Waveform Viewing Simulation Analysis Testbench GTKWave
Hardware Design
Verilog initial Block: Testbench & Simulation Essentials
· loading · loading
Hardware Design Verilog Initial Verilog Testbench Simulation Hardware Verification Digital Design
Hardware Design