module, initial and $display.It's always best to get started using a very simple example, and none serves the purpose better than "Hello World !". The program below does not describe any hardware. It is a tiny testbench, a piece of Verilog that only runs in a simulator, and it prints one line of text to the console.
4 min read | Beginner Level
What You'll Learn
- How a minimal Verilog program is structured with
module,initialand$display - How to compile and run a Verilog file in a simulator
- Common mistakes that stop a first program from compiling or printing
Hello World Example
Save the code below in a file, for example tb.v. Lines starting with // are comments and are ignored by the simulator.
// Single line comments start with double forward slash "//"
// Verilog code is always written inside modules, and each module represents a digital block with some functionality
module tb;
// Initial block is another construct typically used to initialize signal nets and variables for simulation
initial
// Verilog supports displaying signal values to the screen so that designers can debug whats wrong with their circuit
// For our purposes, we'll simply display "Hello World"
$display ("Hello World !");
endmodule
Running this file in a simulator prints the message once:
$ /usr/bin/vvp simulation Hello World !
How the Code Works
Even this short program uses the three constructs that appear in almost every testbench.
module ... endmodule
A module called tb with no input-output ports acts as the top module for the simulation. All Verilog code lives between module <name> and endmodule. In a real project, a design module (for example an adder) has ports for its inputs and outputs, while the testbench module that drives it usually has none, because nothing outside the simulation connects to it. Because no other module instantiates tb, the simulator picks it as the top of the design hierarchy.
initial
The initial block starts and executes its first statement at time 0 units, and it runs only once. Here it contains a single statement, so no begin and end are needed. When an initial block contains more than one statement, the statements must be grouped with begin ... end, as shown in the mistakes section below.
$display
$display is a Verilog system task that prints a formatted string to the console and adds a newline at the end. All system tasks start with a $ and are built into the simulator. $display is the main tool for debugging: you can print the values of signals to see what your circuit is doing at a given time.
Synthesis result: Nothing. $display cannot be synthesized into hardware, and synthesis tools ignore initial blocks that only print messages. A module like tb with no ports and no logic produces an empty netlist. This is expected: a testbench is never meant to become hardware. Some FPGA tools do read simple initial assignments to set the power-up value of registers, but that is the only hardware meaning an initial block can have.
Quick Check
How many times is "Hello World !" printed if the simulation runs for 1000 time units?
Show Answer
Once. An initial block executes only one time, starting at time 0. To print a message repeatedly, you would need a loop or an always block with a delay.
Compiling and Running the Simulation
A simulation usually takes two steps: the source files are first compiled (checked for errors and converted to an internal format), and the result is then run. With the open-source simulator Icarus Verilog, the log above comes from these two commands:
$ iverilog -o simulation tb.v # Compile tb.v into a file called "simulation" $ vvp simulation # Run the compiled simulation Hello World !
Commercial simulators follow the same idea, although many of them combine compiling and running into a single command. If the compiler reports an error, the run step never happens, so always read the first error message carefully: later errors are often caused by the first one.
Checking a New Tool Installation
When a team sets up a new compute server, a new simulator version or a continuous integration job, the first thing they run is a tiny program like this one. If "Hello World !" appears, the license, the paths and the compile and run scripts all work. If it does not, the problem is in the setup, not in the design, which saves hours of debugging a large testbench that could never have run.
Common Beginner Mistakes
Mistake #1: Several statements in an initial block without begin and end
Wrong:
initial
$display ("Hello");
$display ("World"); // Not inside the initial block: compile error
Right:
initial begin
$display ("Hello");
$display ("World");
end
Why? Without begin ... end, an initial block contains only the next statement. The second $display then sits directly inside the module, where procedural statements are not allowed.
Mistake #2: Using single quotes for strings
Wrong: $display ('Hello World !');
Right: $display ("Hello World !");
Why? Verilog strings always use double quotes. The single quote has a different meaning in Verilog: it is part of sized numbers such as 4'b1010.
Mistake #3: Forgetting the semicolon or endmodule
Wrong: $display ("Hello World !") with no semicolon, or a file that ends without endmodule
Right: End every statement with ; and close every module with endmodule
Why? The compiler often reports the error on the line after the missing semicolon, or at the end of the file for a missing endmodule. If an error line looks correct, check the line above it.
Mistake #4: Wrong capitalization of keywords and system tasks
Wrong: Module tb;, Initial or $Display
Right: module tb;, initial and $display
Why? Verilog is case sensitive. All keywords and system tasks are lowercase, and names such as count and Count are two different variables.
Mistake #5: Expecting $display to print from real hardware
Wrong: Adding $display to a design and expecting to see messages from the FPGA or chip
Right: Use $display only to debug in simulation; in hardware, observe signals with LEDs, a logic analyzer or a UART
Why? $display is a simulation-only system task. Synthesis ignores it, so the hardware contains nothing that could print text.
Practice Exercise
Challenge: Your Own Greeting
Modify the Hello World example so that the simulation prints these two lines, in this order:
Hello Verilog ! My first simulation works
Hint
You need two $display statements in the same initial block. Remember what a block with more than one statement needs.
Solution
module tb;
initial begin
$display ("Hello Verilog !");
$display ("My first simulation works");
end
endmodule
Statements inside a begin ... end block execute one after another, so the two lines are printed in the order they are written. Without begin ... end, only the first $display would belong to the initial block, and the compiler would report an error for the second one.
Summary
In this tutorial, you learned:
- All Verilog code is written inside a
module ... endmodule, and a testbench is a module with no ports that acts as the top of the simulation - An
initialblock runs once, starting at time 0, and needsbegin ... endfor more than one statement $displayis a system task that prints a message to the console, followed by a newline- A simulation is compiled first and then run, and the first error message is the one to fix first
$displayand print-onlyinitialblocks are simulation features that synthesis ignores