A Beginner’s Guide to Verilog

Prerna Mittal
8 min readOct 29, 2023

--

What is Verilog?

Verilog is a Hardware Description Language intended for verification through simulation, timing analysis, test analysis and logic synthesis.

I’m a Computer Science student. Why should I know Verilog?

This is one of the most commonly asked questions! Proficiency in Verilog enhances communication with hardware and embedded teams, ensuring seamless integration of software and hardware components. It sharpens problem-solving skills and accelerates debugging processes. Additionally, knowing software and hardware concepts opens doors for innovation, allowing CSE students to explore creative solutions that effectively merge software and hardware technologies.

What you should know

•Verilog is case-sensitive. “a” and “A” differ!
•Most of the syntax and concept is similar to C language.
•A Verilog file is saved with a “.v” extension.

Identifiers

•Identifiers are names given to objects that can be referred to in a design.
•An identifier can contain alphabets (a-z, A-Z), digits (0–1) and special characters(_, $).
•An identifier must begin with an alphabet or underscore(__).
•Identifiers are case-sensitive.
•Some identifiers allow the use of any printable ASCII character. They are called as escaped identifiers. An escaped identifier starts with a \ and ends with a white space.
•An identifier can not be a reserved keyword of the Verilog library.

Numbers

Syntax: <size>’ <base> <number>
Size: decimal value specifying the number of bits to represent a number.
Base: base represents the format of the number. It can be decimal (d or D), hexadecimal (h or H), octal (o or O), binary (b or B)
Number: specifying number is chosen base format.

4'b1011; // 4-bit binary number indicates value 11 in binary
4'd11; // 4-bit number specified in decimal with value 11.
4'hB; //4-bit number specified in hexadecimal, value=11 in decimal.

Data Types

Nets (wire)
Registers (reg)
Arrays (Eg: wire temp[0:5][0:2])
Integers (integer)
Strings (Eg: reg 8*[3:1]str = “Verilog”)
Time (time)
Vectors (group of bits, can be reg or wire)
Value Set: 0, 1, X (unknown/don’t care value), Z (high impedance value)

Parameters

•Parameters are used to declare constants in Verilog.
•These constants can be overridden during compilation time.
•”defparam” keyword is used to override a parameter.

Module

It is the basic building block of a Verilog.

module module_name(port definition);
//body of module containing logic
endmodule

Note: there’s no space between “end” and “module” in “endmodule”. That’s a common mistake students usually make!

Port Definition

The three types of ports are Input (module can only receive), Output (module can only send) and Inout (module can both send and receive).

Operators

Operators in Verilog are the same as in C language. The additional ones that are different and important are:
Concatenation: {A, B, C} will result in concatenation of values of A, B and C
Replication: {2{A}} will result in the concatenation of values of A twice ie. replication of the value of A.

Initial Block

•Initial block is used for one-time execution during the whole simulation.
•There may be any number of initial blocks inside a module.
•If there is more than one initial block, every block executes at 0 simulation time.
•If there are multiple statements within an initial block, they must be grouped using begin and end keywords.
•Initial blocks are typically used for initialization, monitoring, providing test inputs and other operations, which must be executed only once during the entire simulation.
•Timing control is used to provide delay
•‘#’ followed by time value provides a delay.
•Initial block is not synthesizable, hence used for Testbench or simulation, not for Designs.

Initial begin
//procedural assignments;
//delay statements;
end

Always Block

•Always block executes continuously during simulation, just like a looping fashion.
•If there are multiple always blocks, then all blocks start at O time and execute simultaneously.
•always block can be controlled with the help of a sensitivity list. If a sensitivity list is not provided, then always block runs continuously.
•always block is executed whenever an event occurs on any of the variables present in the sensitivity list.
•@ is event control directive that halts the execution of the statement until the event occurs on any of the variables listed in the sensitivity list.
• Statements inside the always block are executed in a sequential manner.
• Timing control is used to provide a delay in the execution of an assignment by a specified time.
•always block is synthesizable, provided the coding guidelines for synthesis are applied.
•always block can be used for both combinational and sequential logic design.

always [@ (senstivity_list)]
begin
//[timing control]
//procedural assignments;
end
Initial Vs Always Block (An Important Concept!)

Note: if the module has both initial and always block, then execution of the initial block will start before always block.

Fork-Join

A Verilog fork-join block always causes the process executing the fork statement to block until the termination of all forked processes.
•It is a concurrent block.
•Fork-Join is a non-synthesizable statement.
•Delay statements and nesting are allowed.

initial begin //or you can use "always"
fork
statement 1;
statement 2;
join
end

Note: in begin-end , statements are executed in the order they are listed (i.e. sequentially), whereas in fork-join, statements are executed parallelly.

Blocking Assignment

•Preferred for combinational design.
•During simulation, it blocks the execution of statements until the assignment occurs.
•Are executed one after the other in the procedural block.
• In blocking statements, the assignment occurs at the very same time
•“=”sign is used to perform blocking procedural assignment.

module block_test;
reg [1:0] a=2'b01, b=2'b10, c=2'b11;
initial begin
a=2'b00; b=a; c=b; // Blocking Assignments
Sdisplay(" a=%b\n, b=%b\n, c=%b\n", a,b,c);
end
endmodule
OUTPUT:
a=00
b=00
c=00

Non-Blocking Assignment

Non-blocking statements do not block the execution of other statements.
• In case of non-blocking, the assignment is scheduled to occur at the end of the current simulation time or at the end of the procedure block.
• Verilog recommends using non-blocking statements to model sequential circuits.
•”<=” sign is used for assignment.

module block_test;
reg [1:0] a=2'b01, b=2'b10, c=2'b11;
initial begin
a<=2b00; b<=a; c<=b; // Non- Blocking Assignments
Sdisplay(" a=%b\n, b=%b\n, c=%b\n", a,b,c);
end
endmodule
OUTPUT:
a=01
b=10
c=11

Race Condition

•In Verilog, sometimes more than one assignments are scheduled for execution at the same time.
•In these situations, a non-deterministic condition occurs, which is known as the race-around condition.
•In race-around conditions, the order of execution dependent upon the simulator.
• To avoid these situations, one can use zero delay modelling.

Key System Tasks

Key Compiler Directives

Note:
•The time precision value should be equal to or smaller than the time unit value.
•Both time precision and time unit should be made up of an integer number and a character string that represents a unit of time.
•The valid numbers are 1, 10, and 100. The valid characters are s, ms, us, ns, ps, and fs.

The compiler directives are written with a back-tick (`) and not a single-quote(‘). That’s another commonly made mistake!

Functions

•Declaration of functions started with keyword function and ended with endfunction.
•Functions always return a single value.
•They cannot have output and inout ports.
•A function must have at least one input argument. It may contain more than one input.
• Functions do not support delay, Event and Timing Control statements.
•Functions always execute in zero simulation time.
•When a function is declared, a register with the same name is declared by default
•Return type and all inputs are 1-bit reg by default.
•Only Blocking sequential statements are allowed.

function [return_type] function_name;
input declarations;
//local registers declaration;
begin
sequential statements;
end
endfunction

How do you call a function?

assign net_name = function_name (input_list); 
reg_name1 = function_name (input_list);
reg_name2 <= function_name (input_list);

Tasks

•Tasks are declared with keyword task and endtask.
•Tasks can pass multiple values through output and inout ports. Atask may have zero or more arguments of type input, output or inout.
•Delay, Event and Timing Control statements are allowed inside tasks.
•Tasks may execute in non-zero simulation time.
•A task can be called from a task and procedural assignment.
•A task can invoke other tasks and functions.
•A task is invoked by specifying the task name followed by input, output or inout arguments.
•The argument should be specified in the same order they are declared. •Tasks can be disabled by “disable” keyword.
•By default, the size of ports and local registers is 1-bit reg.

task task_name;
input, output or inout declarations;
local registers declaration;
begin
//begin-end if multiple statements
[timing_control]
sequential statements;
end endtask

How do you call a task?

task_name (input, output or inout list);
Another important difference to remember!

These are the most important concepts one must know if they’re studying Verilog and are often asked in interviews!

But how do I run a Verilog code?

I use Ubuntu on a Virtual Machine to perform Hardware Design and Modelling. This is probably the simplest method to compile and simulate your Verilog codes!
Text Editor: gedit
Compiler: Icarus Verilog (iverilog)
Waveform Simulator: gtkwave

The verilog codes are writen with gedit on Ubuntu using the following commands in the terminal:
open gedit for editing your Verilog file

gedit module.v

Compilation

1. For separate module and testbench files, use the command:

iverilog -o testbench_tb.vvp testbench_tb.v

2. For a single file, use the command:

iverilog -Wall module.v
unbuffer vvp a.out

Simulating

A .vvp file can be generated for simulation using the command:

vvp testbench_tb.vvp

Waveform Generation

gtkwave dumpfile.vcd
Sample Waveform generated by gtkwave for a 3-bit up counter

Alternatively, GTKWave can be opened by simply clicking on the “dumpfile.vcd” file created in your workspace folder after the previous command.

Reference Material

For referring examples and general codes: https://github.com/prernamittal/HardwareDesignAndModelling/tree/main

Detailed Verilog tutorial:
https://www.chipverify.com/tutorials/verilog

Give yourself a pat if you have reached the end of this guide!
In a nutshell, this guide teaches you the basics of Verilog in an easy way. It shows common mistakes and how to run your code. It’s like a friendly coach, helping you avoid confusion and giving you tools to learn more. Now, you’re all set to dive into Verilog with confidence!

--

--

Prerna Mittal

Upcoming SWE @Microsoft | Ex-Intern @Microsoft, Cadence | Samsung PRISM Intern | NXP WIT Scholar'22 | UIUC+ Research Intern | Beta MLSA | GATE CS qualified