top of page
Search

System Verilog Program Structure — module, program, initial

  • Feb 6
  • 4 min read

1. Introduction

Once you move beyond basic syntax in System Verilog, the first real confusion beginners face is:

  • Why does my simulation sometimes behave differently?

  • Why does System Verilog have both module and program?

  • What exactly does initial control?

This topic appears very frequently in interviews, but more importantly, it directly affects whether your simulation code is safe or unsafe.

A key point to understand early is this:

Code can compile, simulate, and still be logically unsafe.

This article explains why that happens and how System Verilog prevents it.

A key point to understand early is this:

Code can compile, simulate, and still be logically unsafe.

This article explains why that happens and how System Verilog prevents it.


2. Before Anything Else: Design vs Testbench (No Assumptions)

Before discussing keywords, we must clearly separate two ideas.

What is Design (DUT)?

Design (DUT – Design Under Test):

  • Represents real hardware

  • Meant to be synthesized

  • Describes how a circuit behaves

In System Verilog, design is written using module.

Example designs:

  • Flip-flop

  • Counter

ALU

What is a Testbench?

A testbench:

  • Is not hardware

  • Exists only in simulation

  • Drives inputs to the design

  • Observes outputs from the design

You can think of a testbench as a test program for hardware.

Even in simple testbenches, two roles exist:

  • Driver → applies inputs

  • Checker → checks outputs

System Verilog introduces the program block specifically for testbench code.

3. What Is the Difference Between module and program? (Snippet Target)

In System Verilog, a module models hardware and executes in the active simulation region, while a program models testbench behavior and executes after all modules to prevent race conditions.

In short:

  • module → hardware

program → testbench


Quick Comparison

Feature

module

program

Purpose

Hardware modeling

Testbench modeling

Synthesizable

Yes

No

Simulation region

Active

Reactive

Can race with DUT

Yes

No

Intended use

Design

Verification

4. Why This Distinction Matters (The Core Problem)

In simulation:

  • The design samples inputs on clock edges

  • The testbench drives those inputs

If both execute at the same simulation time, then:

  • Sometimes the design sees the old value

  • Sometimes the new value

  • The language gives no guarantee

This situation is called a race condition.

A race condition means behavior depends on execution order, not logic.


5. Where initial Fits (Important Clarification)

initial:

  • Runs once when simulation starts

  • Does not control priority

  • Executes according to where it is declared

Key rule:

initial defines what runs, module vs program defines when it runs.


6. Unsafe Code Example — Works but Is NOT Safe

This code may appear to work, but it is not guaranteed by the language.

❌ NOT SAFE — Testbench as module

module dut(input logic clk, input logic a, output logic y);

  always_ff @(posedge clk)

    y <= a;

endmodule


module testbench;

  logic clk, a, y;


  dut d1(.clk(clk), .a(a), .y(y));


  initial clk = 0;

  always #5 clk = ~clk;


  initial begin

    a = 0;

    #10 a = 1;   // changes exactly at posedge

    #1  if (y !== 0) $error("RACE: y sampled new value");

    #10 $finish;

  end

endmodule


Why This Is Unsafe

  • DUT and testbench are both module

  • Both execute in the same simulation region

  • Order is not guaranteed

  • Behavior depends on simulator scheduling

No syntax error. No compile error. But language-level unsafe.


7. Safe Code Example — Deterministic and Correct

Now we fix only one thing: Move the testbench into a program.

✅ SAFE — Testbench as program

module dut(input logic clk, input logic a, output logic y);

  always_ff @(posedge clk)

    y <= a;

endmodule


program testbench;

  logic clk, a, y;


  dut d1(.clk(clk), .a(a), .y(y));


  initial clk = 0;

  always #5 clk = ~clk;


  initial begin

    a = 0;

    #10 a = 1;   // same timing as before

    #1  if (y !== 0) $error("THIS SHOULD NEVER HAPPEN");

    #10 $finish;

  end

endprogram


Why This Is Safe

  • DUT (module) executes first

  • Testbench (program) executes after

  • Sampling happens before driving

  • Execution order is guaranteed by System Verilog

Same logic. Different scheduling. Only one is correct.


8.Key Takeaway (This Is the Core Insight)

  • Code can work and still be unsafe

  • Race conditions do not always show visible errors

  • System Verilog program exists to remove undefined behavior

This is why verification engineers care about this distinction.


9. Common Beginner Mistakes

  1. Writing entire testbench using module

  2. Assuming delays (#) fix race conditions

  3. Believing initial controls execution order

Mixing synthesizable logic inside program


10. Interview Perspective

Interviewers are not asking:

“Does the code run?”

They are asking:

“Is the behavior guaranteed by the language?”

Strong one-line answer:

Program prevents race conditions between testbench and RTL.


11. Knowledge Check

  1. Why can two modules race in simulation?

  2. What guarantee does program provide?

  3. Does initial decide execution order?

If you can answer these clearly, you understand the topic.


12. What’s Next

Now that execution order and structure are clear, the next confusion beginners face is:

“Which data types should I use, and why?”

👉 Next Article: SystemVerilog Data Types — logic, bit, reg, wire

This topic is both:

  • Highly interview-relevant

  • Critical for writing correct code

 
 
 

Recent Posts

See All
APB Protocol Using UVM: A Beginner's Guide

Learn how to implement the AMBA APB (Advanced Peripheral Bus) protocol using UVM (Universal Verification Methodology). This beginner-friendly guide includes complete, copy-paste ready UVM code example

 
 
 
UVM Sequences

let's break down the UVM sequence code in that format: ### UVM Sequence Tutorial for Beginners: ```systemverilog class my_sequence...

 
 
 

Comments


bottom of page