0% found this document useful (0 votes)
7 views

Introduction to Verilog

The Verilog Programming Guide introduces Verilog as a hardware description language (HDL) used for designing digital systems at various abstraction levels, including behavioral, register-transfer, and gate levels. It provides a step-by-step tutorial on setting up the ModelSim environment, simulating a D flip-flop, and organizing project files for effective design management. The guide emphasizes the importance of understanding Verilog syntax and structure for successful hardware design and simulation.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Introduction to Verilog

The Verilog Programming Guide introduces Verilog as a hardware description language (HDL) used for designing digital systems at various abstraction levels, including behavioral, register-transfer, and gate levels. It provides a step-by-step tutorial on setting up the ModelSim environment, simulating a D flip-flop, and organizing project files for effective design management. The guide emphasizes the importance of understanding Verilog syntax and structure for successful hardware design and simulation.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 197

Verilog Programming Guide

INTRODUCTION

Verilog is a HARDWARE DESCRIPTION LANGUAGE (HDL). A hardware description


language is a language used to describe a digital system: for example, a network switch,
a microprocessor or a memory or a simple flip-flop. This just means that, by using a HDL,
one can describe any (digital) hardware at any level.

1 // D flip-flop Code
2 module d_ff ( d, clk, q, q_bar);
3 input d ,clk;
4 output q, q_bar;
5 wire d ,clk;
6 reg q, q_bar;
7
8 always @ (posedge clk)
9 begin
10 q <= d;
11 q_bar <= ! d;

1
Verilog Programming Guide

12 end
13
14 endmodule
You could download file d_ff.v here

One can describe a simple Flip flop as that in the above figure, as well as a complicated
design having 1 million gates. Verilog is one of the HDL languages available in the
industry for hardware designing. It allows us to design a Digital design at Behavior Level,
Register Transfer Level (RTL), Gate level and at switch level. Verilog allows hardware
designers to express their designs with behavioral constructs, deferring the details of
implementation to a later stage in the final design.

This Verilog Guide is designed to get the user familiar with simulating user code,
testbenches, and test modules. We will use ModelSim software. It is free to download and
provides an extensive set of tools for simulating designs. So, lets get started…

////////////////////////////////Lesson #1/////////////////////////////////////

In this first lesson, let’s set up the ModelSim environment and simulate a simple
flip flop.

First, set up your file system to allow easy access to updating and modifying
your files. There are many ways to set up your file system, the following is the
one that works best for me.

Go to the xx_Project_xx_DVD-> Verilog Getting Started->Tutorials_HDL. Copy


the Lesson 1 Folder over to our local drive from the DVD. In this folder you will
notice a top level project folder.

2
Verilog Programming Guide

The project level folder is called “Lesson_1_Flip_Flop”. Under this project level
folder are various revisions of the project (The DVD will only include one
revision, the user is expected to save further revisions of the project files).
Multiple revisions allow you to keep copies of previously working projects and
refer to them later when the currently edited source code no longer compiles.

Under the this top level folder, the project is organized with the following
folders:

3
Verilog Programming Guide

• EPT_10M04_AF_S2_Top – This folder contains all the Altera project level files such
as pin, sdc, configuration, programming object files etc.
• ModelSim – This folder contains all the compiled object files for ModelSims use. It
also includes the *.do files. These ‘do’ files are the make files for ModelSim. They
tell the compiler which source files to compile and allow compile time options.
• Sim – This folder contains special source files that have non-synthesizeable
constructs in them.
• Src – This folder contains all your source files. Only synthesizeable code should go
into this folder.
• Test – This folder contains source code for the models which are used to model
behavior of devices that are not part of the FPGA. These source files can contain
non-synthesizable code.
• Testbench -- This folder contains the main testbench source code. The testbench
controls the operation of the user source code, test models and simulation code. It
provides the main stimulus such as the clock and reset.

In the src folder, create a file named “EPT_10M04_AF_S2_Top.v”. Then open


this file in an editor, I prefer to use NotePad++. Add in the D flip-flop code and
add comments to describe the file and the parts of the file.

4
Verilog Programming Guide

Next, setup the Testbench file to provide a stimulus for our user code. The
Testbench file provides all the hardware external devices that the FPGA needs
to operate the user code. These include the oscillator, reset, push buttons,
communications, etc… Open the Testbench folder and notice the two files in it.

5
Verilog Programming Guide

• tb_define.v contains pre-defined parameters for the testbench execution


• tb_ept_10m04_top.v contains declarations, stimulus, tasks and leif modules to
exercise the user code.

Inside the tb_ept_10m04_top.v file, we see ‘module’ declaration along with the
name of test bench. The parameter declarations are listed to allow certain
registers to have constant values. We will discuss parameters and the details of
the Verilog files later in the tutorial. For now, we will focus on getting started
and performing our first simulation. Scroll down the testbench file and locate
the “Instantiate DUT” section.

6
Verilog Programming Guide

7
Verilog Programming Guide

You can see that the testbench uses the name of the module declared in
‘EPT_10M04_AF_S2_Top.v’. This is called the leif instantiation. When ModelSim
starts the compilation process, it will search the directory path for the module
‘EPT_10M04_AF_S2_Top’. This instantiation must include the inputs and
outputs declared in the module. In this case:

• ‘d’ – Input into the D flip flop


• ‘clk’ – Input into the D flip flop
• ‘q’ – Output from the D flip flop
• ‘q_bar’ – Output from the D flip flop

Using the leif instantiation module, we have now connected the testbench with
the user code. When ModelSim starts the simulation process, testbench will
control the stimulus to the inputs and accept the outputs from the user code.

To add stimulus, we use Verilog code. To add a clock, we use the ‘forever’ key
word.

The parameter ‘CYCLE_50’ is defined in the tb_define.v file. We add the ‘#’
character at the beginning of the line to inform the compiler to “add the
following” as a delay in simulator steps. During simulation, the simulator will
start a timer that halts this signal (and only this signal) and waits for the timer
to expire. After the delay has expired, the signal is set equal to its complement
state. Then, because of the ‘forever’ keyword, the process starts over, delay,
then set signal to its complement. The result is a clock at 50MHz. We will go
through the details of all these details later in the tutorial.

8
Verilog Programming Guide

Next, add the stimulus for ‘d’ input. We do this using the ‘initial’ block.
Everything between the ‘begin’ ‘end’ keywords is executed once per simulation.

9
Verilog Programming Guide

You can see here that the stimulus ‘d’ is set to 1’b1 after a delay of of 100 *
CYCLE. Where ‘CYCLE’ is defined in the tb_define.v file. Then, after another
delay, the ‘d’ is set to 1’b0. Finally, a delay of 50*CYCLE is added then the ‘d’ is
set to 1’b1. The result is a toggle from high to low to high on the ‘d’ signal.

Next, get the ModelSim loaded up on your laptop/PC. Follow the install guide on
how to install the ModelSim application.

10
Verilog Programming Guide

Then, open the


application and Go to File->Change Directory

11
Verilog Programming Guide

At the dialog box, locate the ModelSim folder under the


EPT_10M04_AF_S2_TOP project.

Select the ModelSim folder. Next, we will compile each module individually.
Click on the ‘Compile’ menu item. Select the ‘Compile’ tab.

12
Verilog Programming Guide

In the ‘Compile Source Files’ window, select the ‘src’ folder.

13
Verilog Programming Guide

Select the ‘EPT_10M04)AF_S2_Top.v’ file.

14
Verilog Programming Guide

Click the ‘Compile’ button.

15
Verilog Programming Guide

You will receive the ‘Create Library’ message box. Select Yes.

After the file is compiled, the log will indicate the status of compilation.

16
Verilog Programming Guide

Next, repeat the compile steps for the

• tb_define.v
• tb_ept_10m04_top.v

17
Verilog Programming Guide

Note, you will not get receive the message box asking to create the
‘work’ folder this time. After the compilation has completed, we are ready to run
the Simulation. The simulation enviroment is controlled by the *.do files. The
*.do files act as makefiles to control which files get simulated and add compile
options. There are two *.do files needed for our simulation. They are found in
the ModelSim folder.

• Sim_ept10m04_top.do – Contains the files and compile options.


• Wave_ept_10m04_top.do – Contains the display flags for the ‘Waveforms’ window.

When we look inside the sim_ept_10m04_top.do file we see the two files to
simulate.

There are also simulate options that use the ‘+define’ keyword. At the endof the
file we see the ‘do wave_ept_10m04_top.do’ instruction. This will add the
display flags to the ‘Waveforms’ window.

18
Verilog Programming Guide

Start the simulation by typing do sim_ept_10m04_top.do into the command


window.

When the simulator completes its run, the Wave window appears.

Zoom into the first 10 microseconds of the simulation usin the Zoom buttons.

19
Verilog Programming Guide

Now we see the ‘d’ stimulus toggling and the ‘q’ output following the input.
Zoom in even farther.

20
Verilog Programming Guide

21
Verilog Programming Guide

We can see after first delay that ‘d’ signal is asserted high. Before this assertion
the signal is not defined in the simulation, so technically it is a Don’t Care
(indicated by the red ‘floating’ line). Once the ‘d’ is asserted, the delay is added
by the simulator. After this delay the ‘d’ signal is de-asserted. Then, another
dealy and the ‘d’ is asserted high.

Now that we know what the simulator is doing, we can exam the user code, the
D Flip Flop.

The D Flip Flop provides a registered output. This means that the input ‘d’ will
be applied to the output ‘q’ but only after one rising edge of the clock. Because
the output ‘q’ is synchronous to the clock, it is called a synchronous register.
We can really see what this means when we zoom in even closer in the
simulation.

22
Verilog Programming Guide

23
Verilog Programming Guide

Examining the user code, we can see this synchronous behavior occuring
because of the always statement.

The always keyword is used to cause a process to occur when an event


happens. The event is what is in the paranthesis. In this case, the event is the
rising edge of the ‘clk’ signal). Verilog uses the ‘posedge’ keyword to describe
rising edge and ‘clk’ is our input clock from the testbench. So, what the Verilog
code is telling us is that whenever we get a rising edge on the clock, the output
‘q’ is equal to ‘d’. Also the ‘q_bar’ output is set to the complement of ‘d’. This is
exactly what the simluation is showing us.

We will cover the details of the Verilog keywords, description of synchronous


code and combinatorial code later in this tutorial. This first lesson was
designed to get you started with using ModelSim.

VERILOG ABSTRACTION LEVELS

Verilog Abstraction Levels

Verilog supports designing at many different levels of abstraction. Three of them are very
important:

• Behavioral level
• Register-Transfer Level
• Gate Level

24
Verilog Programming Guide

Behavioral level

Behavioral verilog deals with the logic or behavior of a system. It handles complex logic
implementation and which is why in industry all implement the behavioral models of the
system called as RTL.

This level describes a system by concurrent algorithms (Behavioral). Each algorithm itself
is sequential, that means it consists of a set of instructions that are executed one after the
other. Functions, Tasks and Always blocks are the main elements. There is no regard to
the structural realization of the design.

Register-Transfer Level

Designs using the Register-Transfer Level specify the characteristics of a circuit by


operations and the transfer of data between the registers. An explicit clock is used. RTL
design contains exact timing bounds: operations are scheduled to occur at certain times.
Modern RTL code definition is "Any code that is synthesizable is called RTL code".

RTL is an acronym for register transfer level. This implies that your Verilog code describes how
data is transformed as it is passed from register to register. The transforming of the data is
performed by the combinational logic that exists between the registers. Don't worry! RTL code
also applies to pure combinational logic - you don't have to use registers. To show you what we
mean by RTL code, let's consider a simple example.

module AOI (input A, B, C, D, output F);


assign F = ~((A & B) | (C & D));
endmodule

The AOI gate that we have used as an example so far has actually been written in RTL form.
This means that continuous assignments are a valid way of describing designs for input to RTL
synthesis tools. What other code techniques can we use? How about:

1 module MUX2 (input SEL, A, B, output F);

25
Verilog Programming Guide
2 input SEL, A, B;
3 output F;
4
5 INV G1 (SEL, SELB);
6 AOI G2 (SELB, A, SEL, B, FB);
7 INV G3 (.A(FB), .F(F));
8 endmodule

Gate Level

Modeling done at this level is usually called gate level modeling as it involves gates and
has a one to one relation between a hardware schematic and the Verilog code. Verilog
supports a few basic logic gates known as primitives as they can be instantiated like
modules since they are already predefined.

Within the logic level the characteristics of a system are described by logical links and
their timing properties. All signals are discrete signals. They can only have definite logical
values (`0', `1', `X', `Z`). The usable operations are predefined logic primitives (AND, OR,
NOT etc gates).

1 module gates (
2 input a, b,
3 output c, d, e);
4
5 and(c, a, b); // c is the output, a and b are inputs
6 or(d, a, b); // d is the output, a and b are inputs
7 xor( e, a, b) // e is the output, a and b are inputs
8 endmodule

26
Verilog Programming Guide

MODULES, PORTS, DATA TYPES AND


OPERATORS
Modules

Since Verilog is a HDL (hardware description language - one used for the conceptual
design of integrated circuits), it also needs to have these things. In Verilog, we call our
"black boxes" module. This is a reserved word within the program used to refer to things
with inputs, outputs, and internal logic workings; they're the rough equivalents of functions
with returns in other programming languages.

Module instances are also examples of synthesizable RTL statements. However, one of
the reasons to use synthesis technology is to be able to describe the design at a higher
level of abstraction than using a collection of module instances or low-level binary
operators in a continuous assignment. We would like to be able to describe what the
design does and leave the consideration of how the design is implemented up to the
synthesis tool. This is a first step (and a pretty big conceptual one) on the road to high-
level design. We are going to use a feature of the Verilog language that allows us to
specify the functionality of a design (the ‘what') that can be interpreted by a synthesis
tool.

In Verilog, after we have declared the module name and port names, we can define the
direction of each port. The code for this is shown below.

1 module arbiter (
2 // Two slashes make a comment line.
3 clock , // clock
4 reset , // Active high, syn reset
5 req_0 , // Request 0
6 req_1 , // Request 1
7 gnt_0 , // Grant 0
8 gnt_1 // Grant 1

27
Verilog Programming Guide
9 );
10 //-------------Input Ports-----------------------------
11 // Note : all commands are semicolon-delimited
12 input clock ;
13 input reset ;
14 input req_0 ;
15 input req_1 ;
16 //-------------Output Ports----------------------------
17 output gnt_0 ;
18 output gnt_1 ;
19 //-------------Internal Signals----------------------------
20 reg count_1 ;
21 reg stop_1 ;
22
23 //-------------Add User Code----------------------------
24 …
25 endmodule

You could download file one_day1.v here

Types of Ports

Port Description

Input The design module can only receive values from outside using its input ports

Output The design module can only send values to the outside using its output ports

Inout The design module can either send or receive values using its inout ports

Ports are by default considered as nets of type wire .

Syntax
input [net_type] [range] list_of_names; // Input port

28
Verilog Programming Guide

inout [net_type] [range] list_of_names; // Input & Output port


output [net_type] [range] list_of_names; // Output port driven by a
wire

output [var_type] [range] list_of_names; // Output port driven by a


variable

Example

In the code shown below, there are three input ports, one output port and one inout port.

1 module my_design (
2
3 input wire clk,
4 input en,
5 input rw,
6 inout [15:0] data,
7 output int_1 );
8
9 // Design behavior as Verilog code
10
11

12 endmodule

It is illegal to use the same name for multiple ports.

input aport; // First declaration - valid


input aport; // Error - already declared

output aport; // Error - already declared

29
Verilog Programming Guide

Bi-Directional Ports Example -

inout read_enable; // port named read_enable is bi-directional

How to define vector signals (signals composed of sequences of more than one bit)?
Verilog provides a simple way to define these as well.

Vector Signals Example -

inout [7:0] address; //port "address" is bidirectional

Note the [7:0] means we're using the little-endian convention - you start with 0 at the
rightmost bit to begin the vector, then move to the left. If we had done [0:7], we would be
using the big-endian convention and moving from left to right. Endianness is a purely
arbitrary way of deciding which way your data will "read," but does differ between
systems, so using the right endianness consistently is important. As an analogy, think of
some languages (English) that are written left-to-right (big-endian) versus others (Arabic)
written right-to-left (little-endian). Knowing which way the language flows is crucial to
being able to read it, but the direction of flow itself was arbitrarily set years back.

Summary

30
Verilog Programming Guide

• We learnt how a block/module is defined in Verilog.


• We learnt how to define ports and port directions.
• We learnt how to declare vector/scalar ports.

Data Types

Verilog Language has two primary data types:

• Nets - represent structural connections between components.


• Registers - represent variables used to store data.

Every signal has a data type associated with it:

• Explicitly declared with a declaration in your Verilog code.


• Implicitly declared with no declaration when used to connect structural building
blocks in your code. Implicit declaration is always a net type "wire" and is one bit
with

Types of Nets

Each net type has a functionality that is used to model different types of hardware (such as
PMOS, NMOS, CMOS, etc)

31
Verilog Programming Guide

Net Data Type Functionality

wire, tri Interconnecting wire - no special resolution function

wor, trior Wired outputs OR together (models ECL)

wand, triand Wired outputs AND together (models open-collector)

tri0, tri1 Net pulls-down or pulls-up when not driven

supply0, supply1 Net has a constant logic 0 or logic 1 (supply strength)

trireg Retains last value, when driven by z (tristate).

Summary

• Wire data type is used for connecting two points.


• Reg data type is used for storing values.

Register Data Types

• Registers store the last value assigned to them until another assignment
statement changes their value.
• Registers represent data storage constructs.
• You can create regs arrays called memories.
• register data types are used as variables in procedural blocks.
• A register data type is required if a signal is assigned a value within a procedural
block
• Procedural blocks begin with keyword initial and always.

Data Types Functionality

32
Verilog Programming Guide

reg Unsigned variable

integer Signed variable - 32 bits

time Unsigned integer - 64 bits

real Double precision floating point variable

Note : Of all register types, reg is the one which is most widely used

Operators

Operators are the same things here as they are in other programming languages. They
take two values and compare (or otherwise operate on) them to yield a third result -
common examples are addition, equals, logical-and... To make life easier for us, nearly all
operators (at least the ones in the list below) are exactly the same as their counterparts in
the C programming language.

Arithmetic Operators

• Binary: +, -, *, /, % (the modulus operator)


• Unary: +, - (This is used to specify the sign)
• Integer division truncates any fractional part
• The result of a modulus operation takes the sign of the first operand
• If any operand bit value is the unknown value x, then the entire result value is x
• Register data types are used as unsigned values (Negative numbers are stored in two's
complement form)

33
Verilog Programming Guide

Example

1 module arithmetic_operators();
2
3 initial begin
4 $display (" 5 + 10 = %d", 5 + 10);
5 $display (" 5 - 10 = %d", 5 - 10);
6 $display (" 10 - 5 = %d", 10 - 5);
7 $display (" 10 * 5 = %d", 10 * 5);
8 $display (" 10 / 5 = %d", 10 / 5);
9 $display (" 10 / -5 = %d", 10 / -5);
10 $display (" 10 %s 3 = %d","%", 10 % 3);
11 $display (" +5 = %d", +5);
12 $display (" -5 = %d", -5);
13 #10 $finish;
14 end
15
16 endmodule
You could download file arithmetic_operators.v here

5 + 10 = 15
5 - 10 = -5
10 - 5 = 5
10 * 5 = 50
10 / 5 = 2
10 / -5 = -2
10 % 3 = 1
+5 = 5
-5 = -5

34
Verilog Programming Guide

Relational Operators

Operator Description

a < b a less than b

a > b a greater than b

a <= b a less than or equal to b

a >= b a greater than or equal to b

• The result is a scalar value (example a < b)


• 0 if the relation is false (a is bigger then b)
• 1 if the relation is true ( a is smaller then b)
• x if any of the operands has unknown x bits (if a or b contains X)

Note: If any operand is x or z, then the result of that test is treated as false (0)

Example

35
Verilog Programming Guide

1 module relational_operators();
2
3 initial begin
4 $display (" 5 <= 10 = %b", (5 <= 10));
5 $display (" 5 >= 10 = %b", (5 >= 10));
6 $display (" 1'bx <= 10 = %b", (1'bx <= 10));
7 $display (" 1'bz <= 10 = %b", (1'bz <= 10));
8 #10 $finish;
9 end
10
11 endmodule
You could download file relational_operators.v here

5 <= 10 = 1
5 >= 10 = 0
1'bx <= 10 = x
1'bz <= 10 = x

Equality Operators

There are two types of Equality operators. Case Equality and Logical Equality.

Operator Description

a === b a equal to b, including x and z (Case equality)

a !== b a not equal to b, including x and z (Case inequality)

a == b a equal to b, result may be unknown (logical equality)

36
Verilog Programming Guide

a != b a not equal to b, result may be unknown (logical equality)

• Operands are compared bit by bit, with zero filling if the two operands do not
have the same length
• Result is 0 (false) or 1 (true)
• For the == and != operators, the result is x, if either operand contains an x or a z
• For the === and !== operators, bits with x and z are included in the comparison
and must match for the result to be true

Note : The result is always 0 or 1.

Example

1 module equality_operators();
2
3 initial begin
4 // Case Equality
5 $display (" 4'bx001 === 4'bx001 = %b", (4'bx001 === 4'bx001));
6 $display (" 4'bx0x1 === 4'bx001 = %b", (4'bx0x1 === 4'bx001));
7 $display (" 4'bz0x1 === 4'bz0x1 = %b", (4'bz0x1 === 4'bz0x1));
8 $display (" 4'bz0x1 === 4'bz001 = %b", (4'bz0x1 === 4'bz001));
9 // Case Inequality
10 $display (" 4'bx0x1 !== 4'bx001 = %b", (4'bx0x1 ! == 4'bx001));
11 $display (" 4'bz0x1 !== 4'bz001 = %b", (4'bz0x1 ! == 4'bz001));
12 // Logical Equality
13 $display (" 5 == 10 = %b", (5 == 10));
14 $display (" 5 == 5 = %b", (5 == 5));
15 // Logical Inequality
16 $display (" 5 != 5 = %b", (5 != 5));
17 $display (" 5 != 6 = %b", (5 != 6));
18 #10 $finish;
19 end

37
Verilog Programming Guide
20
21 endmodule
You could download file equality_operators.v here

4'bx001 === 4'bx001 = 1


4'bx0x1 === 4'bx001 = 0
4'bz0x1 === 4'bz0x1 = 1
4'bz0x1 === 4'bz001 = 0
4'bx0x1 !== 4'bx001 = 1
4'bz0x1 !== 4'bz001 = 1
5 == 10 =0
5 == 5 =1
5 != 5 =0
5 != 6 =1

Logical Operators

Operator Description

!logic negation

&& logical and

|| logical or

• Expressions connected by && and || are evaluated from left to right


• Evaluation stops as soon as the result is known
• The result is a scalar value:
o 0 if the relation is false
o 1 if the relation is true
o x if any of the operands has x (unknown) bits

38
Verilog Programming Guide

Example

1 module logical_operators();
2
3 initial begin
4 // Logical AND
5 $display ("1'b1 && 1'b1 = %b", (1'b1 && 1'b1));
6 $display ("1'b1 && 1'b0 = %b", (1'b1 && 1'b0));
7 $display ("1'b1 && 1'bx = %b", (1'b1 && 1'bx));
8 // Logical OR
9 $display ("1'b1 || 1'b0 = %b", (1'b1 || 1'b0));
10 $display ("1'b0 || 1'b0 = %b", (1'b0 || 1'b0));
11 $display ("1'b0 || 1'bx = %b", (1'b0 || 1'bx));
12 // Logical Negation
13 $display ("! 1'b1 = %b", ( ! 1'b1));
14 $display ("! 1'b0 = %b", ( ! 1'b0));
15 #10 $finish;
16 end
17
18 endmodule
You could download file logical_operators.v here

1'b1 && 1'b1 = 1


1'b1 && 1'b0 = 0
1'b1 && 1'bx = x
1'b1 || 1'b0 = 1
1'b0 || 1'b0 = 0
1'b0 || 1'bx = x
! 1'b1 =0
! 1'b0 =1

39
Verilog Programming Guide

Bit-wise Operators

Bitwise operators perform a bit wise operation on two operands. They take each bit in one
operand and perform the operation with the corresponding bit in the other operand. If one
operand is shorter than the other, it will be extended on the left side with zeroes to match
the length of the longer operand.

Operator Description

~ negation

& and

| inclusive or

^ exclusive or

^~ or ~^ exclusive nor (equivalence)

• Computations include unknown bits, in the following way:


o ~x = x
o 0&x = 0
o 1&x = x&x = x
o 1|x = 1
o 0|x = x|x = x
o 0^x = 1^x = x^x = x
o 0^~x = 1^~x = x^~x = x
• When operands are of unequal bit length, the shorter operand is zero-filled in the
most significant bit positions.

40
Verilog Programming Guide

Example

1 module bitwise_operators();
2
3 initial begin
4 // Bit Wise Negation
5 $display (" ~4'b0001 = %b", (~4'b0001));
6 $display (" ~4'bx001 = %b", (~4'bx001));
7 $display (" ~4'bz001 = %b", (~4'bz001));
8 // Bit Wise AND
9 $display (" 4'b0001 & 4'b1001 = %b", (4'b0001 & 4'b1001));
10 $display (" 4'b1001 & 4'bx001 = %b", (4'b1001 & 4'bx001));
11 $display (" 4'b1001 & 4'bz001 = %b", (4'b1001 & 4'bz001));
12 // Bit Wise OR
13 $display (" 4'b0001 | 4'b1001 = %b", (4'b0001 | 4'b1001));
14 $display (" 4'b0001 | 4'bx001 = %b", (4'b0001 | 4'bx001));
15 $display (" 4'b0001 | 4'bz001 = %b", (4'b0001 | 4'bz001));
16 // Bit Wise XOR
17 $display (" 4'b0001 ^ 4'b1001 = %b", (4'b0001 ^ 4'b1001));
18 $display (" 4'b0001 ^ 4'bx001 = %b", (4'b0001 ^ 4'bx001));
19 $display (" 4'b0001 ^ 4'bz001 = %b", (4'b0001 ^ 4'bz001));
20 // Bit Wise XNOR
21 $display (" 4'b0001 ~^ 4'b1001 = %b", (4'b0001 ~^ 4'b1001));
22 $display (" 4'b0001 ~^ 4'bx001 = %b", (4'b0001 ~^ 4'bx001));
23 $display (" 4'b0001 ~^ 4'bz001 = %b", (4'b0001 ~^ 4'bz001));
24 #10 $finish;
25 end
26
27 endmodule
You could download file bitwise_operators.v here

~4'b0001 = 1110
~4'bx001 = x110

41
Verilog Programming Guide

~4'bz001 = x110
4'b0001 & 4'b1001 = 0001
4'b1001 & 4'bx001 = x001
4'b1001 & 4'bz001 = x001
4'b0001 | 4'b1001 = 1001
4'b0001 | 4'bx001 = x001
4'b0001 | 4'bz001 = x001
4'b0001 ^ 4'b1001 = 1000
4'b0001 ^ 4'bx001 = x000
4'b0001 ^ 4'bz001 = x000
4'b0001 ~^ 4'b1001 = 0111
4'b0001 ~^ 4'bx001 = x111
4'b0001 ~^ 4'bz001 = x111

Reduction Operators

Operator Description

& and

~& nand

| or

~| nor

^ xor

^~ or ~^ xnor

• Reduction operators are unary.

42
Verilog Programming Guide

• They perform a bit-wise operation on a single operand to produce a single bit


result.
• Reduction unary NAND and NOR operators operate as AND and OR
respectively, but with their outputs negated.
o Unknown bits are treated as described before.

Example

1 module reduction_operators();
2
3 initial begin
4 // Bit Wise AND reduction
5 $display (" & 4'b1001 = %b", (& 4'b1001));
6 $display (" & 4'bx111 = %b", (& 4'bx111));
7 $display (" & 4'bz111 = %b", (& 4'bz111));
8 // Bit Wise NAND reduction
9 $display (" ~& 4'b1001 = %b", (~& 4'b1001));
10 $display (" ~& 4'bx001 = %b", (~& 4'bx001));
11 $display (" ~& 4'bz001 = %b", (~& 4'bz001));
12 // Bit Wise OR reduction
13 $display (" | 4'b1001 = %b", (| 4'b1001));
14 $display (" | 4'bx000 = %b", (| 4'bx000));
15 $display (" | 4'bz000 = %b", (| 4'bz000));
16 // Bit Wise NOR reduction
17 $display (" ~| 4'b1001 = %b", (~| 4'b1001));
18 $display (" ~| 4'bx001 = %b", (~| 4'bx001));
19 $display (" ~| 4'bz001 = %b", (~| 4'bz001));
20 // Bit Wise XOR reduction
21 $display (" ^ 4'b1001 = %b", (^ 4'b1001));
22 $display (" ^ 4'bx001 = %b", (^ 4'bx001));
23 $display (" ^ 4'bz001 = %b", (^ 4'bz001));
24 // Bit Wise XNOR
25 $display (" ~^ 4'b1001 = %b", (~^ 4'b1001));
26 $display (" ~^ 4'bx001 = %b", (~^ 4'bx001));
27 $display (" ~^ 4'bz001 = %b", (~^ 4'bz001));
28 #10 $finish;

43
Verilog Programming Guide

29 end
30
31 endmodule
You could download file reduction_operators.v here

& 4'b1001 = 0
& 4'bx111 = x
& 4'bz111 = x
~& 4'b1001 = 1
~& 4'bx001 = 1
~& 4'bz001 = 1
| 4'b1001 = 1
| 4'bx000 = x
| 4'bz000 = x
~| 4'b1001 = 0
~| 4'bx001 = 0
~| 4'bz001 = 0
^ 4'b1001 = 0
^ 4'bx001 = x
^ 4'bz001 = x
~^ 4'b1001 = 1
~^ 4'bx001 = x
~^ 4'bz001 = x

Shift Operators

Operator Description

<< left shift

>> right shift

44
Verilog Programming Guide

• The left operand is shifted by the number of bit positions given by the right
operand.
• The vacated bit positions are filled with zeroes.

Example

1 module shift_operators();
2
3 initial begin
4 // Left Shift
5 $display (" 4'b1001 << 1 = %b", (4'b1001 << 1));
6 $display (" 4'b10x1 << 1 = %b", (4'b10x1 << 1));
7 $display (" 4'b10z1 << 1 = %b", (4'b10z1 << 1));
8 // Right Shift
9 $display (" 4'b1001 >> 1 = %b", (4'b1001 >> 1));
10 $display (" 4'b10x1 >> 1 = %b", (4'b10x1 >> 1));
11 $display (" 4'b10z1 >> 1 = %b", (4'b10z1 >> 1));
12 #10 $finish;
13 end
14
15 endmodule
You could download file shift_operators.v here

4'b1001 << 1 = 0010


4'b10x1 << 1 = 0x10
4'b10z1 << 1 = 0z10
4'b1001 >> 1 = 0100
4'b10x1 >> 1 = 010x
4'b10z1 >> 1 = 010z

Concatenation Operator

45
Verilog Programming Guide

• Concatenations are expressed using the brace characters { and }, with commas
separating the expressions within.
o Example: + {a, b[3:0], c, 4'b1001} // if a and c are 8-bit numbers, the
results has 24 bits
• Unsized constant numbers are not allowed in concatenations.

Example

1 module concatenation_operator();
2
3 initial begin
4 // concatenation
5 $display (" {4'b1001,4'b10x1} = %b", {4'b1001,4'b10x1});
6 #10 $finish;
7 end
8
9 endmodule
You could download file concatenation_operator.v here

{4'b1001,4'b10x1} = 100110x1

Replication Operator

46
Verilog Programming Guide

Replication operator is used to replicate a group of bits n times. Say you have a 4 bit
variable and you want to replicate it 4 times to get a 16 bit variable: then we can use the
replication operator.

Operator Description

{n{m}} Replicate value m, n times

• Repetition multipliers (must be constants) can be used:


o {3{a}} // this is equivalent to {a, a, a}
• Nested concatenations and replication operator are possible:
o {b, {3{c, d}}} // this is equivalent to {b, c, d, c, d, c, d}

Example

1 module replication_operator();
2
3 initial begin
4 // replication
5 $display (" {4{4'b1001}} = %b", {4{4'b1001}});
6 // replication and concatenation
7 $display (" {4{4'b1001,1'bz}} = %b", {4{4'b1001,1'bz}});
8 #10 $finish;
9 end
10
11 endmodule
You could download file replication_operator.v here

{4{4'b1001} = 1001100110011001

47
Verilog Programming Guide

{4{4'b1001,1'bz} = 1001z1001z1001z1001z

Conditional Operators

• The conditional operator has the following C-like format:


o cond_expr ? true_expr : false_expr
• The true_expr or the false_expr is evaluated and used as a result depending on
what cond_expr evaluates to (true or false).

Example

1 module conditional_operator();
2
3 wire out;
4 reg enable,data;
5 // Tri state buffer
6 assign out = (enable) ? data : 1'bz;
7
8 initial begin
9 $display ("time\t enable data out");
10 $monitor ("%g\t %b %b %b",$time,enable,data,out);
11 enable = 0;
12 data = 0;
13 #1 data = 1;
14 #1 data = 0;
15 #1 enable = 1;
16 #1 data = 1;
17 #1 data = 0;
18 #1 enable = 0;
19 #10 $finish;
20 end

48
Verilog Programming Guide
21
22 endmodule
You could download file conditional_operator.v here

time enable data out


0 0 0 z
1 0 1 z
2 0 0 z
3 1 0 0
4 1 1 1
5 1 0 0
6 0 0 z

Operator Precedence

Operator Symbols

Unary, Multiply, Divide, Modulus !, ~, *, /, %

Add, Subtract, Shift +, - , <<, >>

Relation, Equality <,>,<=,>=,==,!=,===,!==

Reduction &, !&,^,^~,|,~|

Logic &&, ||

Conditional ?:

49
Verilog Programming Guide

Operator Type Operator Symbol Operation Performed

Arithmetic * Multiply

/ Division

+ Add

- Subtract

% Modulus

+ Unary plus

- Unary minus

Logical ! Logical negation

&& Logical and

|| Logical or

Relational > Greater than

< Less than

>= Greater than or equal

<= Less than or equal

Equality == Equality

!= inequality

Reduction ~ Bitwise negation

~& nand

50
Verilog Programming Guide

| or

~| nor

^ xor

^~ xnor

~^ xnor

Shift >> Right shift

<< Left shift

Concatenation {} Concatenation

Conditional ? conditional

//////////////////////////////////////Lesson #2///////////////////////////////////

In this lesson, we will use the operators in Verilog code.


First, let’s open the Lesson 2 and explore the operators code. Go to the
xx_Project_xx_DVD-> Verilog Getting Started->Tutorials_HDL. Locate the
Lesson_2_Operators folder in the DVD.

51
Verilog Programming Guide

Go through the initial steps as outlined in Lesson 1. Those initial steps open
ModelSim, Change Directory to the ModelSim Folder, Compile the source file,
then start the simulation using the “do sim_ept_10m04_top.do”

Open the Top Level file in the “src’ folder. Examine the standalone module that
will perform the selected operation.

Next, open and view the test bench to exercise each operator and display the
results.

52
Verilog Programming Guide

The top level module is created following the syntax rules of Verilog. Use the
keyword “module” followed by the name of the module. Then, add an opening
parenthesis and define the inputs and outputs. This tutorial will cover in greater
detail the keywords “module”, “input”, and “output”, signals, registers and
assignment statements later on. For now, just follow the coding. This module
simply takes in two operands, performs an operation then outputs the results.
This lesson is designed to get you familiar with how operators work and how to
use them. This lesson specifically takes in two operands of eight bits each and
the output is eight bits. The reason for this is in the future you will write code
that manipulates both multi-bit registers and single bit signals. The operators
will act differently on registers and signals. So, you will need to understand this
and how to use operators.

53
Verilog Programming Guide

Lets look at the code,

The first four operators “+, -, *, /” work on the entire eight registers in total. If we
look at the test bench, we will see that we can access the inputs by placing an
eight value on the inputs at the start of the simulation. Then, use the “$display”
keyword to display the outputs on the log window.

54
Verilog Programming Guide

You can see the testbench “$display” manipulates the operands by simply
using the “%h” syntax. This similar to the C language. When you want to
display a number to the log screen add the “%h” inside a string. Then close the
string and place the name of the register inside the paranthesis. Run the

55
Verilog Programming Guide

ModelSim simulation using the *.do file by following the steps in Lesson #1.
The output on the log screen looks like the following:

You can see the result of the operation in the log window after running the
simulation. Note that the first four operators work on the entire eight bits of the
input registers.
The “Logical Operators” only operate on single bit signals. When we use an
eight bit register, the operator has to be assigned to each individual bit in
separate assignments.

56
Verilog Programming Guide

The result of the logical operator on an eight bit register show the number as a
complete eight bit number:

57
Verilog Programming Guide

The rest of the operators operate on the entire eight registers. This is an
important distinction that you must handle appropriately when writing your
code. The results of the other operators:

58
Verilog Programming Guide

Feel free to explore the operators by changing the initial values of these
numbers and seeing the results after running the simulation.

59
Verilog Programming Guide

CONTROL STATEMENTS
Control statements in Verilog include: if, else, repeat, while, for, case - it's Verilog that
looks exactly like C. Even though the functionality appears to be the same as in C, Verilog
is an HDL, so the descriptions should translate to hardware. This means you've got to be
careful when using control statements (otherwise your designs might not be
implementable in hardware).

If-else

If-else statements check a condition to decide whether or not to execute a portion of


code. If a condition is satisfied, the code is executed. Else, it runs this other portion of
code.

1 // begin and end act like curly braces in C/C++.


2 if (enable == 1'b1) begin
3 data = 10; // Decimal assigned
4 address = 16'hDEAD; // Hexadecimal
5 wr_enable = 1'b1; // Binary

60
Verilog Programming Guide

6 end else begin


7 data = 32'b0;
8 wr_enable = 1'b0;
9 address = address + 1;
10 end
You could download file one_day2.v here

One could use any operator in the condition checking, as in the case of C language. If
needed we can have nested if else statements; statements without else are also ok, but
they have their own problem, when modeling combinational logic, in case they result in a
Latch (this is not always true).

Case

Case statements are used where we have one variable which needs to be checked for
multiple values. like an address decoder, where the input is an address and it needs to be
checked for all the values that it can take. Instead of using multiple nested if-else
statements, one for each value we're looking for, we use a single case statement: this is
similar to switch statements in languages like C++.

Case statements begin with the reserved word case and end with the reserved
word endcase (Verilog does not use brackets to delimit blocks of code). The cases,
followed with a colon and the statements you wish executed, are listed within these two
delimiters. It's also a good idea to have a default case. Just like with a finite state
machine (FSM), if the Verilog machine enters into a non-covered statement, the machine
hangs. Defaulting the statement with a return to idle keeps us safe.

1 case(address)
2 0 : memory_cell_0 = 16’hffe0;
3 1 : memory_cell_1 = 16’hac81;

61
Verilog Programming Guide

4 2 : memory_cell_2 = 16’h3f76;
5 default : memory_cell_1 = 16’h0000;
6 endcase
You could download file one_day3.v here

Note: One thing that is common to if-else and case statement is that, if you don't cover all
the cases (don't have 'else' in If-else or 'default' in Case), and you are trying to write a
combinational statement, the synthesis tool will infer Latch.

While

A while statement executes the code within it repeatedly if the condition it is assigned to
check returns true. While loops are not synthesizable in hardware and not normally used
for models in real life, but they are used in test benches. As with other statement blocks,
they are delimited by begin and end.

1 while (free_time) begin


2 $display ("Continue with webpage development");
3 end
You could download file one_day4.v here

As long as free_time variable is set, code within the begin and end will be executed. i.e
print "Continue with web development". Let's looks at a stranger example, which uses
most of Verilog constructs. Well, you heard it right. Verilog has fewer reserved words than
VHDL, and in this few, we use even lesser for actual coding. So good of Verilog... so
right.

62
Verilog Programming Guide

1 module counter (clk,rst,enable,count);


2 input clk, rst, enable;
3 output [3:0] count;
4 reg [3:0] count;
5
6 always @ (posedge clk or posedge rst)
7 if (rst) begin
8 count <= 0;
9 end else begin : COUNT
10 while (enable) begin
11 count <= count + 1;
12 disable COUNT;
13 end
14 end
15
16 endmodule
You could download file one_day5.v here

The example above uses most of the constructs of Verilog. You'll notice a new block
called always - this illustrates one of the key features of Verilog. Most software
languages, as we mentioned before, execute sequentially - that is, statement by
statement. Verilog programs, on the other hand, often have many statements executing in
parallel. All blocks marked always will run - simultaneously - when one or more of the
conditions listed within it is fulfilled.

In the example above, the always block will run when either rst or clk reaches a positive
edge - that is, when their value has risen from 0 to 1. You can have two or
more always blocks in a program going at the same time (not shown here, but commonly
used).

63
Verilog Programming Guide

We can disable a block of code, by using the reserve word disable. In the above example,
after each counter increment, the COUNT block of code (not shown here) is disabled.

For loop

For loops in Verilog are almost exactly like for loops in C or C++. The only difference is
that the ++ and -- operators are not supported in Verilog. Instead of writing i++ as you
would in C, you need to write out its full operational equivalent, i = i + 1.

1 for (i = 0; i < 16; i = i +1) begin


2 $display ("Current value of i is %d", i);
3 end
You could download file one_day6.v here

This code will print the numbers from 0 to 15 in order. Be careful when using for loops for
register transfer logic (RTL) and make sure your code is actually sanely implementable in
hardware... and that your loop is not infinite. The for keyword is synthesizable in
hardware.

Repeat

Repeat is similar to the for loop we just covered. Instead of explicitly specifying a
variable and incrementing it when we declare the for loop, we tell the program how
many times to run through the code, and no variables are incremented (unless we want
them to be, like in this example).

1 repeat (16) begin

64
Verilog Programming Guide

2 $display ("Current value of i is %d", i);


3 i = i + 1;
4 end
You could download file one_day7.v here

The output is exactly the same as in the previous for-loop program example. It is relatively
rare to use a repeat (or for-loop) in actual hardware implementation. However, the repeat
keyword is synthesizable in hardware.

Summary

• While, if-else, case(switch) statements are the same as in C language.


• If-else and case statements require all the cases to be covered for combinational
logic.
• For-loop is the same as in C, but no ++ and -- operators.
• Repeat is the same as the for-loop but without the incrementing variable.

////////////////////////////////Lesson #3/////////////////////////////////////////

In this lesson, let’s explore the Verilog control statements. The control
statements are a big contributor to a lot of Verilog code out there in the world.
The control statements encompass both synthesizable and non-synthesizable
Verilog code.

Go to the xx_Project_xx_DVD-> Verilog Getting Started->Tutorials_HDL. Copy


the top level Lesson 3 folder to the users local drive. Go through the initial
steps as outlined in Lesson 1. Those initial steps open ModelSim, Change

65
Verilog Programming Guide

Directory to the ModelSim Folder, Compile the source file, then start the
simulation using the “do sim_ept_10m04_top.do”

This lesson will introduce the user to Verilog Control Statements. It provides a
Testbench and user code. The Testbench will exercise each control and display
the results to the log window of ModelSim. The user code is organized as a
module with only synthesizable code that mimics the project that will go into an
FPGA. The user code includes non-synthesizable code that can only be used in
a testbench. There are three files used in Lesson 3.

• EPT_10M04_AF_S2_Top.v
• tb_ept_10m04_top.v
• tb_define.v

The user code:

66
Verilog Programming Guide

The Testbench code contains the stimulus for the user code:

67
Verilog Programming Guide

The If – Else control statement user code takes in an eight bit count value from
the Testbench and compares it to a maximum count value. If the incoming value
is lesser than the max count, it returns a value of zero. If the incoming value is
greater than max count, it returns the incoming value. This shows how the “if” a
value is equal to zero, “then” execute a statement, “else” execute a different
statement.

68
Verilog Programming Guide

The Testbench produces a count by using the “+” operator and adding a ‘1’ to
the current count value. The resulting incremented count is transmitted to the
IF ELSE Block in the user code.

69
Verilog Programming Guide

Here, the Testbench uses the ‘while’ statement to cause the Testbench to
compare the control and if it is true, execute the statements in the loop. When
the statements have completed, the control is again compared to a value. If
true, the loop continues. This cycle continues until the while control is false.
The user code is comparing the each incremented count to the max value.
When the count is greater than the max count, the result is transmitted to the
Testbench and compared to the while control. At this point the while control will
be false and the loop is exited. The next statement to execute is the
“$display(“If Else Statement reached……”). The result on the log window of the
ModelSim is:

70
Verilog Programming Guide

The Case Control Statement uses the case->select statement->execute


statement.
case(‘control’)
1: ‘statement’;
2: ‘statement’:
.
.
Endcase

71
Verilog Programming Guide

The Testbench transmits an eight bit count value to the user code. This count
value determines which statement is selected. Then the statement is executed.

72
Verilog Programming Guide

The Testbench uses the ‘repeat’ control statement to cause the statements
between begin/end to execute ten times. Each iteration through the repeat cycle
causes the ‘case_input_register’ to increment by one. This value is transmitted
to the user code and selects a statement to execute based on the case control.
The result on the log window of ModelSim is:

73
Verilog Programming Guide

74
Verilog Programming Guide

The while statement is not synthesizable. So, it will be implemented in the


Testbench while the user code will perform an incremented count and produce
a non-zero result when the count reaches maximum count.

The while loop takes the value it receives from result of the user code while
block and compares it to the control of the while statement. If it is zero, the
statements in the Testbench while loop execute. This continues as the user
code increments the counter based on the clock supplied by the Test bench. In
this case it is 50 MHz. When the counter reaches the max value, the user code
transmits this value. The Testbech while loop compares this to zero and
determines the while control is false and exits the loop. The result in the log
window of ModelSIm:

75
Verilog Programming Guide

The For Loop is used to execute statements within a pre-set range. Usually the
for loop repeats the same statement with a slight modification based on the
index counter of the for loop.

76
Verilog Programming Guide

VARIABLE ASSIGNMENT

In digital there are two types of elements, combinational and sequential. Of course we
know this. But the question is "How do we model this in Verilog ?". Well Verilog provides
two ways to model the combinational logic and only one way to model sequential logic.

• Combinational elements can be modeled using assign and always statements.


• Sequential elements can be modeled using only always statement.
• There is a third block, which is used in test benches only: it is called Initial
statement.

Initial Blocks

An initial block, as the name suggests, is executed only once when simulation starts. This
is useful in writing test benches. If we have multiple initial blocks, then all of them are
executed at the beginning of simulation.

Example

1 initial begin
2 clk = 0;
3 reset = 0;
4 req_0 = 0;
5 req_1 = 0;
6 end
You could download file one_day8.v here

77
Verilog Programming Guide

In the above example, at the beginning of simulation, (i.e. when time = 0), all the variables
inside the begin and end block are driven zero.

Always Blocks

As the name suggests, an always block executes always, unlike initial blocks which
execute only once (at the beginning of simulation). A second difference is that an
always block should have a sensitive list or a delay associated with it.

The sensitive list is the one which tells the always block when to execute the block of
code, as shown in the figure below. The @ symbol after reserved word ' always',
indicates that the block will be triggered "at" the condition in parenthesis after symbol
@.

An always block indicates a set of procedural instructions that happen in the order they
are written. The reg data type can hold on to its value while the rest of the always block
is completed, while the 'wire' data type (the default one) does not. Reg is what has to be
used in every always block, even though that particular block is short and ends
immediately. Assign is used for wire types and can be thought of as connecting physical
wires between pieces of hardware, or a path for a signal to travel.

One important note about always block: it can not drive wire data type, but can drive reg
and integer data types.

1 always @ (a or b or sel)
2 begin
3 y = 0;
4 if (sel == 0) begin
5 y = a;

78
Verilog Programming Guide

6 end else begin


7 y = b;
8 end
9 end
You could download file one_day9.v here

The above example is a 2:1 mux, with input a and b; sel is the select input and y is the
mux output. In any combinational logic, output changes whenever input changes. This
theory when applied to always blocks means that the code inside always blocks needs
to be executed whenever the input variables (or output controlling variables) change.
These variables are the ones included in the sensitive list, namely a, b and sel.

There are two types of sensitive list: level sensitive (for combinational circuits) and edge
sensitive (for flip-flops). The code below is the same 2:1 Mux but the output y is now a
flip-flop output.

1 always @ (posedge clk )


2 if (reset == 0) begin
3 y <= 0;
4 end else if (sel == 0) begin
5 y <= a;
6 end else begin
7 y <= b;
8 end
You could download file one_day10.v here

We normally have to reset flip-flops, thus every time the clock makes the transition from
0 to 1 (posedge), we check if reset is asserted (synchronous reset), then we go on with
normal logic. If we look closely we see that in the case of combinational logic we had "="
for assignment, and for the sequential block we had the "<=" operator. Well, "=" is

79
Verilog Programming Guide

blocking assignment and "<=" is nonblocking assignment. "=" executes code


sequentially inside a begin / end, whereas nonblocking "<=" executes in parallel.

We can have an always block without sensitive list, in this case we need to have a delay
as shown in the code below.

1 always begin
2 #5 clk = ~clk;
3 end
You could download file one_day11.v here

#5 in front of the statement delays its execution by 5 time units.

Assign Statement

An assign statement is used for modeling only combinational logic and it is executed
continuously. So the assign statement is called 'continuous assignment statement' as
there is no sensitive list.

1 assign out = (enable) ? data : 1'bz;


You could download file one_day12.v here

80
Verilog Programming Guide

The above example is a tri-state buffer. When enable is 1, data is driven to out, else out
is pulled to high-impedance. We can have nested conditional operators to construct
mux, decoders and encoders.

1 assign out = data;


You could download file one_day13.v here

The assignment statement starts with the keyword assign followed by the signal name
which can be either a single signal or a concatenation of different signal nets. The driver
strength and delay are optional and are mostly used for dataflow modeling than
synthesizing into real hardware. The expression or signal on the right hand side is
evaluated and assigned to the net or expression of nets on the left hand side.

assign <net_expression> = [drive_strength] [delay] <expression of


different signals or constant value>

Rules:

• LHS should always be a scalar or vector net or a concatenation of scalar or


vector nets and never a scalar or vector register.
• RHS can contain scalar or vector registers and function calls.
• Whenever any operand on the RHS changes in value, LHS will be updated
with the new value.
• Assign statements are also called continuous assignments and are always
active.

Task and Function

Often times we find certain pieces of code to be repetitive and called multiple times
within the RTL. They mostly do not consume time and might involve complex
calculations that need to be done with different values. In such cases, we can declare a

81
Verilog Programming Guide

‘function’ and place the repetitive code inside the function and allow it to return the
result. This will reduce the amount of lines in the RTL drastically since all you need to
do now is to do a function call and pass data on which the computation needs to be
performed. In fact, this is very similar to the functions in C.

The purpose of a function is to return the value that is to be used in an expression. A


function definition always start with the keyword ‘function’ followed by the return type,
name and a port list enclosed in parantheses. Verilog knows that a function definition is
over when it finds the ‘endfunction’ keyword. Note that a function shall have at least
one input declared and the return type will be void if the function does not return
anything.

Syntax

function [automatic] [return_type] name ([port_list]);


[statements]
endfunction

The keyword ‘automatic’ will make the function reentrant and items declared within the
task are dynamically allocated rather than shared between different invocations of the
task. This will be useful for recursive functions and when the same function is exectued
concurrently by N processes when forked.

Code below is used for calculating even parity.

1 function parity;
2 input [31:0] data;
3 integer i;
4 begin
5 parity = 0;
6 for (i= 0; i < 32; i = i + 1) begin

82
Verilog Programming Guide

7 parity = parity ^ data[i];


8 end
9 end
10 endfunction
You could download file one_day14.v here

Functions and tasks have the same syntax; one difference is that tasks can have
delays, whereas functions can not have any delay. This means that function can be
used for modeling combinational logic.

Function rules

• A function cannot contain any time-controlled statements like #, @, wait, posedge, negedge
• A function cannot start a task because it may consume simulation time, but can call other
functions
• A function should have atleast one input
• A function cannot have non-blocking assignments or force-release or assign-deassign
• A function cannot have any triggers
• A function cannot have an output or inout

A second difference is that functions can return a value, whereas tasks can not.

////////////////////////////////Lesson #4/////////////////////////////////////////

In this lesson, let’s explore the Verilog Blocks, Tasks and Functions. These
items are fundamental when writing test benches. Blocks, Tasks and Functions
encompass both synthesizable and non-synthesizable Verilog code.

Go to the xx_Project_xx_DVD-> Verilog Getting Started->Tutorials_HDL and


copy the Lesson 4 HDL folder to the users local drive. Go through the initial

83
Verilog Programming Guide

steps as outlined in Lesson 1. Those initial steps open ModelSim, Change


Directory to the ModelSim Folder, Compile the source file, then start the
simulation using the “do sim_ept_10m04_top.do”

This lesson will introduce the user to Verilog Blocks, Tasks and Functions. It
provides a Testbench and user code. The Testbench will exercise each item and
display the results to the log window of ModelSim. The user code is organized
as a module it includes non-synthesizable code that can only be used in a
testbench. There are three files used in Lesson 4.

• EPT_10M04_AF_S2_Top.v
• tb_ept_10m04_top.v
• tb_define.v

The user code:

84
Verilog Programming Guide

85
Verilog Programming Guide

The Testbench code contains the stimulus for the user code:

86
Verilog Programming Guide

Initial Block

The Initial statement starts at line 180 in the tb_ept_10m04_top.

The Initial block is started at the beginning of a simulation at time 0 unit. This
block will be executed only once during the entire simulation. Execution of an
initial block finishes once all the statements within the block are executed. In
the case of Lesson 4, the initial block is used to give a value to registers, in_a
and in_b at the beginning of simulation. The registers are set to:

• in_a = 1
• in_b = 0

There are other Initial blocks in the Lesson 4 testbench. However, these are
needed to provide registers and signals with valid settings. We will cover these
other testbench Initial Blocks in future Lessons.

87
Verilog Programming Guide

Always Combinational Block


The Always Block are used to describe events that should happen under certain
conditions. The Lesson 4 Always Block is explored using the various
instantiations on line 92 of the EPT_10M04_AF_S2_Top.v file.

88
Verilog Programming Guide

The first Always Block is a Combinational method. This block uses a Sensitivity
List immediately following the statement “always”. The sensitive list is the one
which tells the always block when to execute the block of code.

Here, the Project Top uses the ‘while’ statement to cause the Always
Combinational Block to compare the signals in the Sensitivity List and if true,
execute the statements in the loop. When the statements have completed, the
control is again compared to a value. If true, the statements are executed again.

89
Verilog Programming Guide

This cycle continues until the while control is false. This comparison
continually happens until the end of simulation. The output looks like the
following:

Run the simulation as per the instructions outlined in Lesson 1. In the


command window of the ModelSim, type ‘do sim_ept_10m04_top.do’

90
Verilog Programming Guide

The Combinational Block uses Always->Sensitivity List True->execute


statement.
if(SELECT == 1)
Y_COMB = IN_A
else
Y_COMB = IN_B

From the Simulation, we can see that Y_COMB oscillates from low to high with
the input SELECT. The user can experiment with this simulation and change the
polarity of IN_A and IN_B. Run the simulation again and check the results for
the change.

Always Synchronous Block


The Synchronous Always Block starts on line 103 of the
EPT_10M04_AF_S2_Top.v file.

91
Verilog Programming Guide

The Synchronous Always Block is different from the Combinational Always


Block in that the Synchronous executes the statements only when the clock
signal asserts. In hardware, the FPGA will have a clock signal from a separate
oscillator. This clock signal is added to an FPGA pin. This clock pin will be
used internal in the FPGA to provide the clock for synchronous code. The
Always Block will add the clock signal to the Sensitivity List.

always@(posedge CLK)
begin


end

The Always Synchronous block above execute the statements in the begin/end
frame only when the signal, CLK, is rising. Run the simulation to see what the
synchronous always block does.

Starting at the leftmost part of the simulation, the RST_N is asserted low. So,
Y_SYNC is set low. Once the RST_N asserts high, the always statements
execute when the CLK signal goes high.

92
Verilog Programming Guide

In this case, SELECT = 0 so, Y_SYNC = IN_A= 1. Notice that Y_SYNC changes to
to equal IN_A only after the clock has completed the rising edge. You can see
from the simulation that SELECT goes from 1 to 0, but the Y_SYNC does not
change value until after CLK = 1. This is fundamental of synchronous operation.
After five CLK cycles, the SELECT = 1.

When SELECT = 1, Y_SYNC = IN_B=0. Again, notice that Y_SYNC does not
change immediately. It only changes after the rising edge of CLK.

Next the user is encouraged to experiment with the Always Blocks. Change the
polarity of the SELECT and re-run the simulation. Notice how the results
change.

Always Block No Sensitivity List


The Always Block with no Sensitivity List starts on line 119 of the
EPT_10M04_AF_S2_Top.v file.

93
Verilog Programming Guide

The Sensitivity List of the Always Block has several variations. One such
variation is the Always block without Sensitivity List. This block will execute the
statements on each simulation time cycle. Remember, this is in deference to the
Always Block with Sensitivity List in that the statements are only executed once
the events in the Sensitivity List occur. In this exercise, we add a delay of ‘#100’
which means delay the next statement for 100 simulations cycles. The results of
y_nosense = !y_nonsense is alternating high and low. The delay causes the
oscillation to run slower. Run the simulation to see what the no sensitivity
always block does.

Earlier, we set up CLK to equal 50MHz. The 50MHz clock uses a delay of #10
simulation cycles to produce the 50MHz period. The period of our delay #100 is
equal to 10 cycles of the 50MHz clock. You can see the Always Block with no
Sensitivity List is executing at each simulation cycle. The user is encouraged to
experiment with this simulation by changing the value of the delay and re-
running the simulation. Notice what the changes are.

Assignment Statements

94
Verilog Programming Guide

The Always Block with no Sensitivity List starts on line 119 of the
EPT_10M04_AF_S2_Top.v file.

The Assignment Statements are used for combinatorial and register logic. So
the assign statement is called 'continuous assignment statement' as there is no
sensitive list. The value can either be a constant or an expression comprising a
group of signals. Please note the signal on the LHS must be declared as a wire.
It can never be declared as a register.

Because the assignment is continuous, OUT_1 above will simply follow any
signal applied to the IN_1. Run the simulation to verify this.

For OUT_2, this syntax is legal and produces a reliable output. This is called an
inline if-then-else statement.

• If ENABLE = 1, then OUT_2 = data_2 (assign OUT_2 = ENABLE ? data_2 : 1’bz)


• Else if ENABLE =0, then OUT_2 = 1’bz (assign OUT_2 = ENABLE ? data_2 : 1’bz)

The 1’bz output indicates the tri-state condition. Remember that signals can
have one of four states, high, low, don’t care and tri-state. Run the simulation to
see the results.

95
Verilog Programming Guide

Notice that the blue line in ModelSim indicates the tri-state condition of 1’bz.
From the inline if-then-else, when ENABLE = 0, OUT_2 = 1’bz. When ENABLE =
1, the first part of the inline if-then-else executes and the OUT_2 = data_2 = 1.
The user is encouraged to experiment with the simulation and change the
polarity of the signals and re-run the simulation to examine the results.

96
Verilog Programming Guide

Functions
The Functions starts on line 139 of the EPT_10M04_AF_S2_Top.v file. Functions
are declared with the “function” keyword. This keyword starts the function, and
it ends with the keyword “endfunction”. The function can return only one signal
or vector, but can have multiple inputs. The function in Lesson 4 calculates the
parity of a 32 bit word. This is useful for ensuring digital communications
between two devices was successful. It is also a perfect example of the use of
functions. This calculation would be repeated for each 32 bit word transferred.
This might be performed thousands of times per transaction. The function is
listed and called inside the top level project. The testbench provides a signal to
start the calculation. For the parity function notice the signal inputs.

97
Verilog Programming Guide

The OUT_3 signal is assigned the value of parity. Parity is declared as a ‘reg’.

In the function call, the return value of the function is assigned to parity. This
return must be of type ‘reg’. During the assignment above of OUT_3 to partiy,
OUT_3 must be declared as ‘wire’. The function call on line 165 takes in one
input signal. In this function, the input is a 32 bit vector. The function performs
the action, then returns a signal and assigns it to parity. For this function, the
return is a single bit. In the function call above for parity_3(), the output
assigned signal, parity, is set to zero when RST_N asserts. This is not

98
Verilog Programming Guide

necessary but the signal, parity, will show up as ‘Don’t Care’ in the simulation.
This reset assertion will ensure that parity and anything using this signal will
have a value during all simulation.

The listing is shown on line 139. This is the real meat of the function, where is
does its action.

The function is declared with the ‘function’ keyword. Then the input is declared,
which is a 32 bit vector. An internal ‘integer’ is declared to allow a counter to be
used. The for loop always the ability to step through each bit of the 32 bit vector
and perform the calculation. And of course ‘parity_3’ provides the output of the
function. So, run the simulation using the do sim_ept_10m04_top.do and
examine the results.

The parity_3() function is called when SELECT_3 goes high. SELECT_3 is


manipulated by the testbench. The parity_3() function uses a for loop to
calculate the result of parity for the IN_3 32 bit word. It happens instantly in the
simulation. So, the result, OUT_3 is available immediately. The user is
encouraged to experiment with the parity_3() function. Go into the file,

99
Verilog Programming Guide

tb_define.v and change the base number, FUNCTIONS_PARITY_DATA. Then,


re-run the simulation and examine the results.

Tasks
The Tasks guide starts on line 170 of the EPT_10M04_AF_S2_Top.v file. Tasks
are declared with the “task” keyword. This keyword starts the function, and it
ends with the keyword “endtask”.

100
Verilog Programming Guide

The task can have as many inputs and outputs as needed. The inputs and
outputs can be signals or vectors or a mixture of both. The task will only
execute when it is called. When all its statements have completed the task
returns control back to the testbench.

The task in Lesson 4 will compare two vectors and return the results. The
Testbench provides the stimulus for this compare. And it uses the results
returned from the task to display to the command window.

101
Verilog Programming Guide

The testbench provides IN_A_4 and IN_B_4 which are 32 bit vectors to the
compare_4() task.

The numbers are provided in tb_define.v

102
Verilog Programming Guide

Run the simulation using the do sim_ept_10m04_top.do in the command


window. The top level code performs the compare every cycle of CLK. The
compare_4() task uses a for loop to count and index, i, from 0 to 31 and
compares each bit of the two 32 bit vectors. If the two bits are equal, the
resulting 32 bit vector places a 1 in the indexed bit. If they are not equal a 0 is
placed in the indexed bit. Using the two numbers provided in tb_define.v the
results:

The testbench reads the result vector and performs another compare to
determine what should be displayed in the command window.

103
Verilog Programming Guide

The user is encouraged to experiment with the compare_4() task. Change the
numbers in the tb_define so that the numbers are equal. Re-run the simulation
and notice how the results change.

This is the end of Lesson 4

TEST BENCHES

The goal of this Verilog guide is to introduce the user to producing FPGA designs by
simulating the design before committing to hardware. So, we can create a simple design
such as the d flip flop and add it to the simulator and add the stimulus such as clocks
and inputs. Run the simulation and examine the outputs. This is all fairly manageable
with hand coding the stimulus. Let's look at a more complex design and the need to
provide more complex stimulus and a method to examine the output. This is were Test

104
Verilog Programming Guide

Bench comes in. Verilog was designed as a modeling language first. So, it has some
very useful tools to make it easy to provide a complex stimulus and methods to easily
examine outputs.

Lexical Conventions

The basic lexical conventions used by Verilog HDL are similar to those in the C
programming language. Verilog HDL is a case-sensitive language. All keywords are in
lowercase.

White Space

White space can contain the characters for blanks, tabs, newlines, and form feeds.
These characters are ignored except when they serve to separate other tokens.
However, blanks and tabs are significant in strings.

White space characters are :

• Blank spaces
• Tabs
• Carriage returns
• New-line
• Form-feeds

Bad Code : Never write code like this.

1 module addbit(a,b,ci,sum,co);
2 input a,b,ci;output sum co;
3 wire a,b,ci,sum,co;endmodule

105
Verilog Programming Guide

You could download file bad_code.v here

Good Code : Nice way to write code.

1 module addbit (
2 a,
3 b,
4 ci,
5 sum,
6 co);
7 input a;
8 input b;
9 input ci;
10 output sum;
11 output co;
12 wire a;
13 wire b;
14 wire ci;
15 wire sum;
16 wire co;
17
18 endmodule
You could download file good_code.v here

Comments

There are two forms to introduce comments.

• Single line comments begin with the token // and end with a carriage return
• Multi line comments begin with the token /* and end with the token */

Examples of Comments

106
Verilog Programming Guide

1 /* This is a
2 Multi line comment
3 example */
4 module addbit (
5 a,
6 b,
7 ci,
8 sum,
9 co);
10
11 // Input Ports Single line comment
12 input a;
13 input b;
14 input ci;
15 // Output ports
16 output sum;
17 output co;
18 // Data Types
19 wire a;
20 wire b;
21 wire ci;
22 wire sum;
23 wire co;
24
25 endmodule
You could download file comment.v here

Case Sensitivity

Verilog HDL is case sensitive

• Lower case letters are unique from upper case letters


• All Verilog keywords are lower case

107
Verilog Programming Guide

Examples of Unique names

1 input // a Verilog Keyword


2 wire // a Verilog Keyword
3 WIRE // a unique name ( not a keyword)
4 Wire // a unique name (not a keyword)
You could download file unique_names.v here

NOTE : Never use Verilog keywords as unique names, even if the case is different.

Identifiers

Identifiers are names used to give an object, such as a register or a function or a


module, a name so that it can be referenced from other places in a description.

• Identifiers must begin with an alphabetic character or the underscore character


(a-z A-Z _ )
• Identifiers may contain alphabetic characters, numeric characters, the
underscore, and the dollar sign (a-z A-Z 0-9 _ $ )
• Identifiers can be up to 1024 characters long.

Examples of legal identifiers

data_input mu

clk_input my$clk

i386 A

108
Verilog Programming Guide

Escaped Identifiers

Verilog HDL allows any character to be used in an identifier by escaping the identifier.
Escaped identifiers provide a means of including any of the printable ASCII characters
in an identifier (the decimal values 33 through 126, or 21 through 7E in hexadecimal).

• Escaped identifiers begin with the back slash ( \ )


• Entire identifier is escaped by the back slash.
• Escaped identifier is terminated by white space (Characters such as commas,
parentheses, and semicolons become part of the escaped identifier unless
preceded by a white space)
• Terminate escaped identifiers with white space, otherwise characters that should
follow the identifier are considered as part of it.

Examples of escape identifiers

Verilog does not allow to identifier to start with a numeric character. So if you really want
to use a identifier to start with a numeric value then use a escape character as shown
below.

1 // There must be white space after the


2 // string which uses escape character
3 module \1dff (
4 q, // Q output
5 \q~ , // Q_out output
6 d, // D input
7 cl$k, // CLOCK input
8 \reset* // Reset input
9 );
10

109
Verilog Programming Guide

11 input d, cl$k, \reset* ;


12 output q, \q~ ;
13
14 endmodule
You could download file escape_id.v here

Numbers in Verilog

You can specify constant numbers in decimal, hexadecimal, octal, or binary format.
Negative numbers are represented in 2's complement form. When used in a number,
the question mark (?) character is the Verilog alternative for the z character. The
underscore character (_) is legal anywhere in a number except as the first character,
where it is ignored.

Integer Numbers

Verilog HDL allows integer numbers to be specified as

• Sized or unsized numbers (Unsized size is 32 bits)


• In a radix of binary, octal, decimal, or hexadecimal
• Radix and hex digits (a,b,c,d,e,f) are case insensitive
• Spaces are allowed between the size, radix and value

Syntax: <size>'<radix><value>;

Example of Integer Numbers

Integer Stored as

110
Verilog Programming Guide

1 00000000000000000000000000000001

8'hAA 10101010

6'b10_0011 100011

'hF 00000000000000000000000000001111

Verilog expands <value> filling the specified <size> by working from right-to-left

• When <size> is smaller than <value>, then leftmost bits of <value> are truncated
• When <size> is larger than <value>, then leftmost bits are filled, based on the
value of the leftmost bit in <value>.
o Leftmost '0' or '1' are filled with '0'
o Leftmost 'Z' are filled with 'Z'
o Leftmost 'X' are filled with 'X'

Note : X Stands for unknown and Z stands for high impedance, 1 for logic high or 1 and
0 for logic low or 0.

Example of Integer Numbers

Integer Stored as

6'hCA 001010

6'hA 001010

111
Verilog Programming Guide

16'bZ ZZZZZZZZZZZZZZZZ

8'bx xxxxxxxx

Real Numbers

• Verilog supports real constants and variables


• Verilog converts real numbers to integers by rounding
• Real Numbers can not contain 'Z' and 'X'
• Real numbers may be specified in either decimal or scientific notation
• < value >.< value >
• < mantissa >E< exponent >
• Real numbers are rounded off to the nearest integer when assigning to an
integer.

Example of Real Numbers

Real Number Decimal notation

1.2 1.2

0.6 0.6

3.5E6 3,500000.0

112
Verilog Programming Guide

Signed and Unsigned Numbers

Verilog Supports both types of numbers, but with certain restrictions. Like in C language
we don't have int and unint types to say if a number is signed integer or unsigned
integer.

Any number that does not have negative sign prefix is a positive number. Or indirect
way would be "Unsigned".

Negative numbers can be specified by putting a minus sign before the size for a
constant number, thus they become signed numbers. Verilog internally represents
negative numbers in 2's complement format. An optional signed specifier can be added
for signed arithmetic.

Examples

Number Description

32'hDEAD_BEEF Unsigned or signed positive number

-14'h1234 Signed negative number

The example file below shows how Verilog treats signed and unsigned numbers.

1 module signed_number;

113
Verilog Programming Guide
2
3 reg [31:0] a;
4
5 initial begin
6 a = 14'h1234;
7 $display ("Current Value of a = %h", a);
8 a = -14'h1234;
9 $display ("Current Value of a = %h", a);
10 a = 32'hDEAD_BEEF;
11 $display ("Current Value of a = %h", a);
12 a = -32'hDEAD_BEEF;
13 $display ("Current Value of a = %h", a);
14 #10 $finish;
15 end
16
17 endmodule
You could download file signed_number.v here

Current Value of a = 00001234


Current Value of a = ffffedcc
Current Value of a = deadbeef
Current Value of a = 21524111

Strings

A string is a sequence of characters enclosed by double quotes and all contained on a


single line. Strings used as operands in expressions and assignments are treated as a
sequence of eight-bit ASCII values, with one eight-bit ASCII value representing one
character. To declare a variable to store a string, declare a register large enough to hold
the maximum number of characters the variable will hold. Note that no extra bits are
required to hold a termination character; Verilog does not store a string termination
character. Strings can be manipulated using the standard operators.

114
Verilog Programming Guide

When a variable is larger than required to hold a value being assigned, Verilog pads the
contents on the left with zeros after the assignment. This is consistent with the padding
that occurs during assignment of non-string values.

Certain characters can be used in strings only when preceded by an introductory character
called an escape character. The following table lists these characters in the right-hand
column together with the escape sequence that represents the character in the left-hand
column.

Special Characters in Strings

Character Description

\n New line character

\t Tab character

\\ Backslash (\) character

\" Double quote (") character

\ddd A character specified in 1-3 octal digits (0 <= d <= 7)

%% Percent (%) character

Example

115
Verilog Programming Guide

1 //-----------------------------------------------------
2 // Design Name : strings
3 // File Name : strings.v
4 // Function : This program shows how string
5 // can be stored in reg
6 // Coder� : Deepak Kumar Tala
7 //-----------------------------------------------------
8 module strings();
9 // Declare a register variable that is 21 bytes
10 reg [8*21:0] string ;
11
12 initial begin
13 string = "This is sample string";
14 $display ("%s \n", string);
15 end
16
17 endmodule
You could download file strings.v here

Logic Values and signal Strengths

The Verilog HDL has got four logic values

Logic Value Description

0 zero, low, false

1 one, high, true

z or Z high impedance, floating

x or X unknown, uninitialized, contention

116
Verilog Programming Guide

Gate and Switch delays

In real circuits, logic gates have delays associated with them. Verilog provides the
mechanism to associate delays with gates.

• Rise, Fall and Turn-off delays.


• Minimal, Typical, and Maximum delays.

In Verilog delays can be introduced with #'num' as in the examples below, where # is a
special character to introduce delay, and 'num' is the number of ticks simulator should
delay current statement execution.

• #1 a = b : Delay by 1, i.e. execute after 1 tick


• #2 not (a,b) : Delay by 2 all assignments made to a.

Real transistors have resolution delays between the input and output. This is modeled in
Verilog by specifying one or more delays for the rise, fall, turn-on and turn off time
seperated by commas.

Syntax: keyword #(delay{s}) unique_name (node specifications);

Switch element Number Of Delays Specified delays

117
Verilog Programming Guide

Switch 1 Rise, fall and turn-off times of equal length

2 Rise and fall times

3 Rise, fall and turn off

(r)tranif0, (r)tranif1 1 both turn on and turn off

2 turn on, turn off

(r)tran 0 None allowed

Rise Delay

The rise delay is associated with a gate output transition to 1 from another value (0, x, z).

Fall Delay

The fall delay is associated with a gate output transition to 0 from another value (1, x, z).

118
Verilog Programming Guide

Turn-off Delay

The Turn-off delay is associated with a gate output transition to z from another value (0, 1,
x).

Min Value

The min value is the minimum delay value that the gate is expected to have.

Typ Value

The typ value is the typical delay value that the gate is expected to have.

Max Value

119
Verilog Programming Guide

The max value is the maximum delay value that the gate is expected to have.

Example

Below are some examples to show the usage of delays.

Example - Single Delay

1 module buf_gate ();


2 reg in;
3 wire out;
4
5 buf #(5) (out,in);
6
7 initial begin
8 $monitor ("Time = %g in = %b out=%b", $time, in, out);
9 in = 0;
10 #10 in = 1;
11 #10 in = 0;
12 #10 $finish;
13 end
14
15 endmodule
You could download file buf_gate.v here

Time = 0 in = 0 out=x
Time = 5 in = 0 out=0

120
Verilog Programming Guide

Time = 10 in = 1 out=0
Time = 15 in = 1 out=1
Time = 20 in = 0 out=1
Time = 25 in = 0 out=0

Example - Two Delays

1 module buf_gate1 ();


2 reg in;
3 wire out;
4
5 buf #(2,3) (out,in);
6
7 initial begin
8 $monitor ("Time = %g in = %b out=%b", $time, in, out);
9 in = 0;
10 #10 in = 1;
11 #10 in = 0;
12 #10 $finish;
13 end
14

121
Verilog Programming Guide

15 endmodule
You could download file buf_gate1.v here

Time = 0 in = 0 out=x
Time = 3 in = 0 out=0
Time = 10 in = 1 out=0
Time = 12 in = 1 out=1
Time = 20 in = 0 out=1
Time = 23 in = 0 out=0

Example - All Delays

1 module delay();
2 reg in;
3 wire rise_delay, fall_delay, all_delay;
4
5 initial begin
6 $monitor (

122
Verilog Programming Guide

7 "Time=%g in=%b rise_delay=%b fall_delay=%b all_delay=%b",


8 $time, in, rise_delay, fall_delay, all_delay);
9 in = 0;
10 #10 in = 1;
11 #10 in = 0;
12 #20 $finish;
13 end
14
15 buf #(1,0)U_rise (rise_delay,in);
16 buf #(0,1)U_fall (fall_delay,in);
17 buf #1 U_all (all_delay,in);
18
19 endmodule
You could download file delay.v here

Time = 0 in = 0 rise_delay = 0 fall_delay = x all_delay = x


Time = 1 in = 0 rise_delay = 0 fall_delay = 0 all_delay = 0
Time = 10 in = 1 rise_delay = 0 fall_delay = 1 all_delay = 0
Time = 11 in = 1 rise_delay = 1 fall_delay = 1 all_delay = 1
Time = 20 in = 0 rise_delay = 0 fall_delay = 1 all_delay = 1
Time = 21 in = 0 rise_delay = 0 fall_delay = 0 all_delay = 0

Example - Complex Example

123
Verilog Programming Guide

1 module delay_example();
2
3 wire out1,out2,out3,out4,out5,out6;
4 reg b,c;
5
6 // Delay for all transitions
7 or #5 u_or (out1,b,c);
8 // Rise and fall delay
9 and #(1,2) u_and (out2,b,c);
10 // Rise, fall and turn off delay
11 nor #(1,2,3) u_nor (out3,b,c);
12 //One Delay, min, typ and max
13 nand #(1:2:3) u_nand (out4,b,c);
14 //Two delays, min,typ and max
15 buf #(1:4:8,4:5:6) u_buf (out5,b);
16 //Three delays, min, typ, and max
17 notif1 #(1:2:3,4:5:6,7:8:9) u_notif1 (out6,b,c);
18
19 //Testbench code
20 initial begin
21 $monitor (
22 "Time=%g b=%b c=%b out1=%b out2=%b out3=%b out4=%b out5=%b out6=%b",
23 $time, b, c , out1, out2, out3, out4, out5, out6);
24 b = 0;
25 c = 0;
26 #10 b = 1;
27 #10 c = 1;
28 #10 b = 0;
29 #10 $finish;
30 end
31
32 endmodule
You could download file delay_example.v here

Time = 0 b = 0 c=0 out1=x out2=x out3=x out4=x out5=x out6=x


Time = 1 b = 0 c=0 out1=x out2=x out3=1 out4=x out5=x out6=x
Time = 2 b = 0 c=0 out1=x out2=0 out3=1 out4=1 out5=x out6=z
Time = 5 b = 0 c=0 out1=0 out2=0 out3=1 out4=1 out5=0 out6=z
Time = 8 b = 0 c=0 out1=0 out2=0 out3=1 out4=1 out5=0 out6=z
Time = 10 b = 1 c=0 out1=0 out2=0 out3=1 out4=1 out5=0 out6=z

124
Verilog Programming Guide

Time = 12 b = 1 c=0 out1=0 out2=0 out3=0 out4=1 out5=0 out6=z


Time = 14 b = 1 c=0 out1=0 out2=0 out3=0 out4=1 out5=1 out6=z
Time = 15 b = 1 c=0 out1=1 out2=0 out3=0 out4=1 out5=1 out6=z
Time = 20 b = 1 c=1 out1=1 out2=0 out3=0 out4=1 out5=1 out6=z
Time = 21 b = 1 c=1 out1=1 out2=1 out3=0 out4=1 out5=1 out6=z
Time = 22 b = 1 c=1 out1=1 out2=1 out3=0 out4=0 out5=1 out6=z
Time = 25 b = 1 c=1 out1=1 out2=1 out3=0 out4=0 out5=1 out6=0
Time = 30 b = 0 c=1 out1=1 out2=1 out3=0 out4=0 out5=1 out6=0
Time = 32 b = 0 c=1 out1=1 out2=0 out3=0 out4=1 out5=1 out6=1
Time = 35 b = 0 c=1 out1=1 out2=0 out3=0 out4=1 out5=0 out6=1

Blocking and Nonblocking assignment

Blocking assignments are executed in the order they are coded, hence they are
sequential. Since they block the execution of next statement, till the current statement is
executed, they are called blocking assignments. Assignment are made with "=" symbol.
Example a = b;

Nonblocking assignments are executed in parallel. Since the execution of next statement
is not blocked due to execution of current statement, they are called nonblocking
statement. Assignments are made with "<=" symbol. Example a <= b;

Note : Correct way to spell 'nonblocking' is 'nonblocking' and not 'non-blocking'.

Example - blocking and nonblocking

125
Verilog Programming Guide

1 module blocking_nonblocking();
2
3 reg a,b,c,d;
4 // Blocking Assignment
5 initial begin
6 #10 a = 0;
7 #11 a = 1;
8 #12 a = 0;
9 #13 a = 1;
10 end
11
12 initial begin
13 #10 b <= 0;
14 #11 b <= 1;
15 #12 b <= 0;
16 #13 b <= 1;
17 end
18
19 initial begin
20 c = #10 0;
21 c = #11 1;
22 c = #12 0;
23 c = #13 1;
24 end
25
26 initial begin
27 d <= #10 0;
28 d <= #11 1;
29 d <= #12 0;
30 d <= #13 1;
31 end
32
33 initial begin
34 $monitor("TIME = %g A = %b B = %b C = %b D = %b",$time, a, b, c, d);
35 #50 $finish;
36 end
37
38 endmodule
You could download file blocking_nonblocking.v here

Simulator Output

126
Verilog Programming Guide

TIME = 0 A = x B = x C = x D = x
TIME = 10 A = 0 B = 0 C = 0 D = 0
TIME = 11 A = 0 B = 0 C = 0 D = 1
TIME = 12 A = 0 B = 0 C = 0 D = 0
TIME = 13 A = 0 B = 0 C = 0 D = 1
TIME = 21 A = 1 B = 1 C = 1 D = 1
TIME = 33 A = 0 B = 0 C = 0 D = 1
TIME = 46 A = 1 B = 1 C = 1 D = 1

Waveform

The Conditional Statement if-else

It's known fact that priority implementation takes more logic to implement than parallel
implementation. So if you know the inputs are mutually exclusive, then you can code the
logic in parallel if.

127
Verilog Programming Guide

1 module parallel_if();
2
3 reg [3:0] counter;
4 wire clk,reset,enable, up_en, down_en;
5
6 always @ (posedge clk)
7 // If reset is asserted
8 if (reset == 1'b0) begin
9 counter <= 4'b0000;
10 end else begin
11 // If counter is enable and up count is mode
12 if (enable == 1'b1 && up_en == 1'b1) begin
13 counter <= counter + 1'b1;
14 end
15 // If counter is enable and down count is mode
16 if (enable == 1'b1 && down_en == 1'b1) begin
17 counter <= counter - 1'b1;
18 end
19 end
20
21 endmodule
You could download file parallel_if.v here

The Case Statement

The case statement compares an expression to a series of cases and executes the
statement or statement group associated with the first matching case:

• case statement supports single or multiple statements.


• Group multiple statements using begin and end keywords.

128
Verilog Programming Guide

Syntax of a case statement look as shown below.

case ()

< case1 > : < statement >

< case2 > : < statement >

.....

default : < statement >

endcase

Normal Case

Example- case

1 module mux (a,b,c,d,sel,y);


2 input a, b, c, d;
3 input [1:0] sel;
4 output y;
5

129
Verilog Programming Guide

6 reg y;
7
8 always @ (a or b or c or d or sel)
9 case (sel)
10 0 : y = a;
11 1 : y = b;
12 2 : y = c;
13 3 : y = d;
14 default : $display("Error in SEL");
15 endcase
16
17 endmodule
You could download file mux.v here

Example- case without default

1 module mux_without_default (a,b,c,d,sel,y);


2 input a, b, c, d;
3 input [1:0] sel;
4 output y;
5
6 reg y;
7
8 always @ (a or b or c or d or sel)
9 case (sel)
10 0 : y = a;
11 1 : y = b;
12 2 : y = c;
13 3 : y = d;
14 2'bxx,2'bx0,2'bx1,2'b0x,2'b1x,
15 2'bzz,2'bz0,2'bz1,2'b0z,2'b1z : $display("Error in SEL");
16 endcase
17
18 endmodule
You could download file mux_without_default.v here

130
Verilog Programming Guide

The example above shows how to specify multiple case items as a single case item.

The Verilog case statement does an identity comparison (like the === operator); one can
use the case statement to check for logic x and z values as shown in the example below.

Example- case with x and z

1 module case_xz(enable);
2 input enable;
3
4 always @ (enable)
5 case(enable)
6 1'bz : $display ("enable is floating");
7 1'bx : $display ("enable is unknown");
8 default : $display ("enable is %b",enable);
9 endcase
10
11 endmodule
You could download file case_xz.v here

The casez and casex statement

Special versions of the case statement allow the x ad z logic values to be used as "don't
care":

131
Verilog Programming Guide

• casez : Treats z as don't care.


• casex : Treats x and z as don't care.

Example- casez

1 module casez_example();
2 reg [3:0] opcode;
3 reg [1:0] a,b,c;
4 reg [1:0] out;
5
6 always @ (opcode or a or b or c)
7 casez(opcode)
8 4'b1zzx : begin // Don't care about lower 2:1 bit, bit 0 match with x
9 out = a;
10 $display("@%0dns 4'b1zzx is selected, opcode %b",$time,opcode);
11 end
12 4'b01?? : begin
13 out = b; // bit 1:0 is don't care
14 $display("@%0dns 4'b01?? is selected, opcode %b",$time,opcode);
15 end
16 4'b001? : begin // bit 0 is don't care
17 out = c;
18 $display("@%0dns 4'b001? is selected, opcode %b",$time,opcode);
19 end
20 default : begin
21 $display("@%0dns default is selected, opcode %b",$time,opcode);
22 end
23 endcase
24
25 // Testbench code goes here
26 always #2 a = $random;

132
Verilog Programming Guide

27 always #2 b = $random;
28 always #2 c = $random;
29
30 initial begin
31 opcode = 0;
32 #2 opcode = 4'b101x;
33 #2 opcode = 4'b0101;
34 #2 opcode = 4'b0010;
35 #2 opcode = 4'b0000;
36 #2 $finish;
37 end
38
39 endmodule
You could download file casez_example.v here

Simulation Output - casez

@0ns default is selected, opcode 0000


@2ns 4'b1zzx is selected, opcode 101x
@4ns 4'b01?? is selected, opcode 0101
@6ns 4'b001? is selected, opcode 0010
@8ns default is selected, opcode 0000

Example- casex

1 module casex_example();
2 reg [3:0] opcode;
3 reg [1:0] a,b,c;
4 reg [1:0] out;
5
6 always @ (opcode or a or b or c)

133
Verilog Programming Guide

7 casex(opcode)
8 4'b1zzx : begin // Don't care 2:0 bits
9 out = a;
10 $display("@%0dns 4'b1zzx is selected, opcode %b",$time,opcode);
11 end
12 4'b01?? : begin // bit 1:0 is don't care
13 out = b;
14 $display("@%0dns 4'b01?? is selected, opcode %b",$time,opcode);
15 end
16 4'b001? : begin // bit 0 is don't care
17 out = c;
18 $display("@%0dns 4'b001? is selected, opcode %b",$time,opcode);
19 end
20 default : begin
21 $display("@%0dns default is selected, opcode %b",$time,opcode);
22 end
23 endcase
24
25 // Testbench code goes here
26 always #2 a = $random;
27 always #2 b = $random;
28 always #2 c = $random;
29
30 initial begin
31 opcode = 0;
32 #2 opcode = 4'b101x;
33 #2 opcode = 4'b0101;
34 #2 opcode = 4'b0010;
35 #2 opcode = 4'b0000;
36 #2 $finish;
37 end
38
39 endmodule
You could download file casex_example.v here

Simulation Output - casex

134
Verilog Programming Guide

@0ns default is selected, opcode 0000


@2ns 4'b1zzx is selected, opcode 101x
@4ns 4'b01?? is selected, opcode 0101
@6ns 4'b001? is selected, opcode 0010
@8ns default is selected, opcode 0000

Example- Comparing case, casex, casez

1 module case_compare;
2
3 reg sel;
4
5 initial begin
6 #1 $display ("\n Driving 0");
7 sel = 0;
8 #1 $display ("\n Driving 1");
9 sel = 1;
10 #1 $display ("\n Driving x");
11 sel = 1'bx;
12 #1 $display ("\n Driving z");
13 sel = 1'bz;
14 #1 $finish;
15 end
16
17 always @ (sel)
18 case (sel)
19 1'b0 : $display("Normal : Logic 0 on sel");
20 1'b1 : $display("Normal : Logic 1 on sel");
21 1'bx : $display("Normal : Logic x on sel");
22 1'bz : $display("Normal : Logic z on sel");
23 endcase
24
25 always @ (sel)
26 casex (sel)

135
Verilog Programming Guide

27 1'b0 : $display("CASEX : Logic 0 on sel");


28 1'b1 : $display("CASEX : Logic 1 on sel");
29 1'bx : $display("CASEX : Logic x on sel");
30 1'bz : $display("CASEX : Logic z on sel");
31 endcase
32
33 always @ (sel)
34 casez (sel)
35 1'b0 : $display("CASEZ : Logic 0 on sel");
36 1'b1 : $display("CASEZ : Logic 1 on sel");
37 1'bx : $display("CASEZ : Logic x on sel");
38 1'bz : $display("CASEZ : Logic z on sel");
39 endcase
40
41 endmodule
You could download file case_compare.v here

Simulation Output

Driving 0
Normal : Logic 0 on sel
CASEX : Logic 0 on sel
CASEZ : Logic 0 on sel

Driving 1
Normal : Logic 1 on sel
CASEX : Logic 1 on sel
CASEZ : Logic 1 on sel

Driving x
Normal : Logic x on sel
CASEX : Logic 0 on sel
CASEZ : Logic x on sel

Driving z
Normal : Logic z on sel
CASEX : Logic 0 on sel

136
Verilog Programming Guide

CASEZ : Logic 0 on sel

Looping Statements

Looping statements appear inside procedural blocks only; Verilog has four looping
statements like any other programming language.

• forever
• repeat
• while
• for

The forever statement

The forever loop executes continually, the loop never ends. Normally we use forever
statements in initial blocks.

syntax : forever < statement >

One should be very careful in using a forever statement: if no timing construct is present in
the forever statement, simulation could hang. The code below is one such application,
where a timing construct is included inside a forever statement.

137
Verilog Programming Guide

Example - Free running clock generator

1 module forever_example ();


2
3 reg clk;
4
5 initial begin
6 #1 clk = 0;
7 forever begin
8 #5 clk = ! clk;
9 end
10 end
11
12 initial begin
13 $monitor ("Time = %d clk = %b",$time, clk);
14 #100 $finish;
15 end
16
17 endmodule
You could download file forever_example.v here

The repeat statement

The repeat loop executes < statement > a fixed < number > of times.

syntax : repeat (< number >) < statement >

138
Verilog Programming Guide

Example- repeat

1 module repeat_example();
2 reg [3:0] opcode;
3 reg [15:0] data;
4 reg temp;
5
6 always @ (opcode or data)
7 begin
8 if (opcode == 10) begin
9 // Perform rotate
10 repeat (8) begin
11 #1 temp = data[15];
12 data = data << 1;
13 data[0] = temp;
14 end
15 end
16 end
17 // Simple test code
18 initial begin
19 $display (" TEMP DATA");
20 $monitor (" %b %b ",temp, data);
21 #1 data = 18'hF0;
22 #1 opcode = 10;
23 #10 opcode = 0;
24 #1 $finish;
25 end
26
27 endmodule
You could download file repeat_example.v here

139
Verilog Programming Guide

The while loop statement

The while loop executes as long as an < expression > evaluates as true. This is the same
as in any other programming language.

syntax : while (< expression >) < statement >

Example- while

1 module while_example();
2
3 reg [5:0] loc;
4 reg [7:0] data;
5
6 always @ (data or loc)
7 begin
8 loc = 0;
9 // If Data is 0, then loc is 32 (invalid value)
10 if (data == 0) begin
11 loc = 32;
12 end else begin
13 while (data[0] == 0) begin
14 loc = loc + 1;
15 data = data >> 1;

140
Verilog Programming Guide

16 end
17 end
18 $display ("DATA = %b LOCATION = %d",data,loc);
19 end
20
21 initial begin
22 #1 data = 8'b11;
23 #1 data = 8'b100;
24 #1 data = 8'b1000;
25 #1 data = 8'b1000_0000;
26 #1 data = 8'b0;
27 #1 $finish;
28 end
29
30 endmodule
You could download file while_example.v here

The for loop statement

The for loop is the same as the for loop used in any other programming language.

• Executes an < initial assignment > once at the start of the loop.
• Executes the loop as long as an < expression > evaluates as true.
• Executes a < step assignment > at the end of each pass through the loop.

syntax : for (< initial assignment >; < expression >, < step assignment >) < statement >

Note : verilog does not have ++ operator as in the case of C language.

141
Verilog Programming Guide

Example - For

1 module for_example();
2
3 integer i;
4 reg [7:0] ram [0:255];
5
6 initial begin
7 for (i = 0; i < 256; i = i + 1) begin
8 #1 $display(" Address = %g Data = %h",i,ram[i]);
9 ram[i] <= 0; // Initialize the RAM with 0
10 #1 $display(" Address = %g Data = %h",i,ram[i]);
11 end
12 #1 $finish;
13 end
14
15 endmodule
You could download file for_example.v here

////////////////////////////////Lesson #5/////////////////////////////////////////

In this lesson, let’s explore the Test Benches.

Go to the xx_Project_xx_DVD-> Verilog Getting Started->Tutorials_HDL and


copy the Lesson 5 HDL folder to the users local drive. Go through the initial
steps as outlined in Lesson 1. Those initial steps open ModelSim, Change
Directory to the ModelSim Folder, Compile the source file, then start the
simulation using the “do sim_ept_10m04_top.do”

142
Verilog Programming Guide

This lesson will to into depth on Test Benches. It provides a Testbench and
user code. The Testbench will exercise each item and display the results to the
log window of ModelSim. The user code is organized as a module it includes
non-synthesizable code that can only be used in a testbench. There are three
files used in Lesson 5.

• EPT_10M04_AF_S2_Top.v
• tb_ept_10m04_top.v
• tb_define.v

The user code:

The Testbench code contains the stimulus for the user code:

The Always Block are used to describe events that should happen under certain
conditions. The Lesson 4 Always Block is explored using the various
instantiations on line 92 of the EPT_10M04_AF_S2_Top.v file.

143
Verilog Programming Guide

Sequential Logic using Procedural Coding

To model sequential logic, a procedure block must be sensitive to positive edge or


negative edge of clock. To model asynchronous reset, procedure block must be
sensitive to both clock and reset. All the assignments to sequential logic should be
made through nonblocking assignments.

Sometimes it's tempting to have multiple edge triggering variables in the sensitive list:
this is fine for simulation. But for synthesis this does not make sense, as in real life, flip-
flop can have only one clock, one reset and one preset (i.e. posedge clk or posedge
reset or posedge preset).

One common mistake the new beginner makes is using clock as the enable input to flip-
flop. This is fine for simulation, but for synthesis, this is not right.

Example - Bad coding - Using two clocks

1 module wrong_seq();

144
Verilog Programming Guide
2
3 reg q;
4 reg clk1, clk2, d1, d2;
5
6 always @ (posedge clk1 or posedge clk2)
7 if (clk1) begin
8 q <= d1;
9 end else if (clk2) begin
10 q <= d2;
11 end
12
13 initial begin
14 $monitor ("CLK1 = %b CLK2 = %b D1 = %b D2 %b Q = %b",
15 clk1, clk2, d1, d2, q);
16 clk1 = 0;
17 clk2 = 0;
18 d1 = 0;
19 d2 = 1;
20 #10 $finish;
21 end
22
23 always
24 #1 clk1 = ~clk1;
25
26 always
27 #1.9 clk2 = ~clk2;
28
29 endmodule
You could download file wrong_seq.v here

Example - D Flip-flop with async reset and async preset

1 module dff_async_reset_async_preset();
2
3 reg clk,reset,preset,d;
4 reg q;
5
6 always @ (posedge clk or posedge reset or posedge preset)

145
Verilog Programming Guide

7 if (reset) begin
8 q <= 0;
9 end else if (preset) begin
10 q <= 1;
11 end else begin
12 q <= d;
13 end
14
15 // Testbench code here
16 initial begin
17 $monitor("CLK = %b RESET = %b PRESET = %b D = %b Q = %b",
18 clk,reset,preset,d,q);
19 clk = 0;
20 #1 reset = 0;
21 preset = 0;
22 d = 0;
23 #1 reset = 1;
24 #2 reset = 0;
25 #2 preset = 1;
26 #2 preset = 0;
27 repeat (4) begin
28 #2 d = ~d;
29 end
30 #2 $finish;
31 end
32
33 always
34 #1 clk = ~clk;
35
36 endmodule
You could download file dff_async_reset_async_preset.v here

Example - D Flip-flop with sync reset and sync preset

1 module dff_sync_reset_sync_preset();
2
3 reg clk,reset,preset,d;

146
Verilog Programming Guide

4 reg q;
5
6 always @ (posedge clk)
7 if (reset) begin
8 q <= 0;
9 end else if (preset) begin
10 q <= 1;
11 end else begin
12 q <= d;
13 end
14
15 // Testbench code here
16 initial begin
17 $monitor("CLK = %b RESET = %b PRESET = %b D = %b Q = %b",
18 clk,reset,preset,d,q);
19 clk = 0;
20 #1 reset = 0;
21 preset = 0;
22 d = 0;
23 #1 reset = 1;
24 #2 reset = 0;
25 #2 preset = 1;
26 #2 preset = 0;
27 repeat (4) begin
28 #2 d = ~d;
29 end
30 #2 $finish;
31 end
32
33 always
34 #1 clk = ~clk;
35
36 endmodule
You could download file dff_sync_reset_sync_preset.v here

A procedure can't trigger itself

One cannot trigger the block with a variable that block assigns value
or drives.

147
Verilog Programming Guide

1 module trigger_itself();
2
3 reg clk;
4
5 always @ (clk)
6 #5 clk = ! clk;
7
8 // Testbench code here
9 initial begin
10 $monitor("TIME = %d CLK = %b",$time,clk);
11 clk = 0;
12 #500 $display("TIME = %d CLK = %b",$time,clk);
13 $finish;
14 end
15
16 endmodule
You could download file trigger_itself.v here

Procedural Block Concurrency

If we have multiple always blocks inside one module, then all the
blocks (i.e. all the always blocks and initial blocks) will start executing at time 0 and will
continue to execute concurrently. Sometimes this leads to race conditions, if coding is
not done properly.

1 module multiple_blocks ();


2 reg a,b;
3 reg c,d;
4 reg clk,reset;
5 // Combo Logic
6 always @ ( c)
7 begin
8 a = c;

148
Verilog Programming Guide

9 end
10 // Seq Logic
11 always @ (posedge clk)
12 if (reset) begin
13 b <= 0;
14 end else begin
15 b <= a & d;
16 end
17
18 // Testbench code here
19 initial begin
20 $monitor("TIME = %d CLK = %b C = %b D = %b A = %b B = %b",
21 $time, clk,c,d,a,b);
22 clk = 0;
23 reset = 0;
24 c = 0;
25 d = 0;
26 #2 reset = 1;
27 #2 reset = 0;
28 #2 c = 1;
29 #2 d = 1;
30 #2 c = 0;
31 #5 $finish;
32 end
33 // Clock generator
34 always
35 #1 clk = ~clk;
36
37 endmodule
You could download file multiple_blocks.v here

Race condition

1 module race_condition();
2 reg b;
3
4 initial begin

149
Verilog Programming Guide

5 b = 0;
6 end
7
8 initial begin
9 b = 1;
10 end
11
12 endmodule
You could download file race_condition.v here

In the code above it is difficult to say the value of b, as both blocks are supposed to
execute at same time. In Verilog, if care is not taken, a race condition is something that
occurs very often.

Named Blocks

Blockscan be named by adding : block_name after the keyword begin. Named blocks
can be disabled using the 'disable' statement.

Example - Named Blocks

1 // This code find the lowest bit set


2 module named_block_disable();
3
4 reg [31:0] bit_detect;
5 reg [5:0] bit_position;
6 integer i;
7
8 always @ (bit_detect)

150
Verilog Programming Guide

9 begin : BIT_DETECT
10 for (i = 0; i < 32 ; i = i + 1) begin
11 // If bit is set, latch the bit position
12 // Disable the execution of the block
13 if (bit_detect[i] == 1) begin
14 bit_position = i;
15 disable BIT_DETECT;
16 end else begin
17 bit_position = 32;
18 end
19 end
20 end
21
22 // Testbench code here
23 initial begin
24 $monitor(" INPUT = %b MIN_POSITION = %d", bit_detect, bit_position);
25 #1 bit_detect = 32'h1000_1000;
26 #1 bit_detect = 32'h1100_0000;
27 #1 bit_detect = 32'h1000_1010;
28 #10 $finish;
29 end
30
31 endmodule
You could download file named_block_disable.v here

In the example above, BIT_DETECT is the named block and it is


disabled whenever the bit position is detected.

Procedural blocks and timing controls.

• Delay controls.
• Edge-Sensitive Event controls.
• Level-Sensitive Event controls-Wait statements.
• Named Events.

151
Verilog Programming Guide

Delay Controls

Delays the execution of a procedural statement by specific simulation time.

#< time > < statement >;

Example - clk_gen

1 module clk_gen ();


2
3 reg clk, reset;
4
5 initial begin
6 $monitor ("TIME = %g RESET = %b CLOCK = %b", $time, reset, clk);
7 clk = 0;
8 reset = 0;
9 #2 reset = 1;
10 #5 reset = 0;
11 #10 $finish;
12 end
13
14 always
15 #1 clk = ! clk;
16
17 endmodule
You could download file clk_gen.v here

Simulation Output

TIME = 0 RESET = 0 CLOCK = 0

152
Verilog Programming Guide

TIME = 1 RESET = 0 CLOCK = 1


TIME = 2 RESET = 1 CLOCK = 0
TIME = 3 RESET = 1 CLOCK = 1
TIME = 4 RESET = 1 CLOCK = 0
TIME = 5 RESET = 1 CLOCK = 1
TIME = 6 RESET = 1 CLOCK = 0
TIME = 7 RESET = 0 CLOCK = 1
TIME = 8 RESET = 0 CLOCK = 0
TIME = 9 RESET = 0 CLOCK = 1
TIME = 10 RESET = 0 CLOCK = 0
TIME = 11 RESET = 0 CLOCK = 1
TIME = 12 RESET = 0 CLOCK = 0
TIME = 13 RESET = 0 CLOCK = 1
TIME = 14 RESET = 0 CLOCK = 0
TIME = 15 RESET = 0 CLOCK = 1
TIME = 16 RESET = 0 CLOCK = 0

Waveform

Edge sensitive Event Controls

Delays execution of the next statement until the specified transition


on a signal.

syntax : @ (< posedge >|< negedge > signal) < statement >;

153
Verilog Programming Guide

Example - Edge Wait

1 module edge_wait_example();
2
3 reg enable, clk, trigger;
4
5 always @ (posedge enable)
6 begin
7 trigger = 0;
8 // Wait for 5 clock cycles
9 repeat (5) begin
10 @ (posedge clk) ;
11 end
12 trigger = 1;
13 end
14
15 //Testbench code here
16 initial begin
17 $monitor ("TIME : %g CLK : %b ENABLE : %b TRIGGER : %b",
18 $time, clk,enable,trigger);
19 clk = 0;
20 enable = 0;
21 #5 enable = 1;
22 #1 enable = 0;
23 #10 enable = 1;
24 #1 enable = 0;

154
Verilog Programming Guide

25 #10 $finish;
26 end
27
28 always
29 #1 clk = ~clk;
30
31 endmodule
You could download file edge_wait_example.v here

Simulator Output

TIME : 0 CLK : 0 ENABLE : 0 TRIGGER : x


TIME : 1 CLK : 1 ENABLE : 0 TRIGGER : x
TIME : 2 CLK : 0 ENABLE : 0 TRIGGER : x
TIME : 3 CLK : 1 ENABLE : 0 TRIGGER : x
TIME : 4 CLK : 0 ENABLE : 0 TRIGGER : x
TIME : 5 CLK : 1 ENABLE : 1 TRIGGER : 0
TIME : 6 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 7 CLK : 1 ENABLE : 0 TRIGGER : 0
TIME : 8 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 9 CLK : 1 ENABLE : 0 TRIGGER : 0
TIME : 10 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 11 CLK : 1 ENABLE : 0 TRIGGER : 0
TIME : 12 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 13 CLK : 1 ENABLE : 0 TRIGGER : 0
TIME : 14 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 15 CLK : 1 ENABLE : 0 TRIGGER : 1
TIME : 16 CLK : 0 ENABLE : 1 TRIGGER : 0
TIME : 17 CLK : 1 ENABLE : 0 TRIGGER : 0
TIME : 18 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 19 CLK : 1 ENABLE : 0 TRIGGER : 0
TIME : 20 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 21 CLK : 1 ENABLE : 0 TRIGGER : 0
TIME : 22 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 23 CLK : 1 ENABLE : 0 TRIGGER : 0
TIME : 24 CLK : 0 ENABLE : 0 TRIGGER : 0
TIME : 25 CLK : 1 ENABLE : 0 TRIGGER : 1
TIME : 26 CLK : 0 ENABLE : 0 TRIGGER : 1

155
Verilog Programming Guide

Level-Sensitive Even Controls ( Wait statements )

Delays execution of the next statement until < expression > evaluates to true

syntax : wait (< expression >) < statement >;

Example - Level Wait

1 module wait_example();
2
3 reg mem_read, data_ready;
4 reg [7:0] data_bus, data;
5
6 always @ (mem_read or data_bus or data_ready)
7 begin
8 data = 0;
9 while (mem_read == 1'b1) begin
10 // #1 is very important to avoid infinite loop
11 wait (data_ready == 1) #1 data = data_bus;
12 end
13 end
14
15 // Testbench Code here
16 initial begin
17 $monitor ("TIME = %g READ = %b READY = %b DATA = %b",
18 $time, mem_read, data_ready, data);
19 data_bus = 0;
20 mem_read = 0;
21 data_ready = 0;

156
Verilog Programming Guide

22 #10 data_bus = 8'hDE;


23 #10 mem_read = 1;
24 #20 data_ready = 1;
25 #1 mem_read = 1;
26 #1 data_ready = 0;
27 #10 data_bus = 8'hAD;
28 #10 mem_read = 1;
29 #20 data_ready = 1;
30 #1 mem_read = 1;
31 #1 data_ready = 0;
32 #10 $finish;
33 end
34
35 endmodule
You could download file wait_example.v here

Simulator Output

TIME = 0 READ = 0 READY = 0 DATA = 00000000


TIME = 20 READ = 1 READY = 0 DATA = 00000000
TIME = 40 READ = 1 READY = 1 DATA = 00000000
TIME = 41 READ = 1 READY = 1 DATA = 11011110
TIME = 42 READ = 1 READY = 0 DATA = 11011110
TIME = 82 READ = 1 READY = 1 DATA = 11011110
TIME = 83 READ = 1 READY = 1 DATA = 10101101
TIME = 84 READ = 1 READY = 0 DATA = 10101101

Intra-Assignment Timing Controls

Intra-assignment controls always evaluate the right side expression immediately and
assign the result after the delay or event control.

157
Verilog Programming Guide

In non-intra-assignment controls (delay or event control on the left side), the right side
expression is evaluated after the delay or event control.

Example - Intra-Assignment

1 module intra_assign();
2
3 reg a, b;
4
5 initial begin
6 $monitor("TIME = %g A = %b B = %b",$time, a , b);
7 a = 1;
8 b = 0;
9 a = #10 0;
10 b = a;
11 #20 $display("TIME = %g A = %b B = %b",$time, a , b);
12 $finish;
13 end
14
15 endmodule
You could download file intra_assign.v here

Simulation Output

TIME = 0 A = 1 B = 0
TIME = 10 A = 0 B = 0
TIME = 30 A = 0 B = 0

Waveform

158
Verilog Programming Guide

Modeling Combo Logic with Continuous Assignments

Whenever any signal changes on the right hand side, the entire right-hand side is re-
evaluated and the result is assigned to the left hand side.

Example - Tri-state Buffer

1 module tri_buf_using_assign();
2 reg data_in, enable;
3 wire pad;
4
5 assign pad = (enable) ? data_in : 1'bz;
6
7 initial begin
8 $monitor ("TIME = %g ENABLE = %b DATA : %b PAD %b",
9 $time, enable, data_in, pad);
10 #1 enable = 0;
11 #1 data_in = 1;
12 #1 enable = 1;
13 #1 data_in = 0;
14 #1 enable = 0;
15 #1 $finish;
16 end

159
Verilog Programming Guide
17
18 endmodule
You could download file tri_buf_using_assign.v here

Simulation Output

TIME = 0 ENABLE = x DATA : x PAD x


TIME = 1 ENABLE = 0 DATA : x PAD z
TIME = 2 ENABLE = 0 DATA : 1 PAD z
TIME = 3 ENABLE = 1 DATA : 1 PAD 1
TIME = 4 ENABLE = 1 DATA : 0 PAD 0
TIME = 5 ENABLE = 0 DATA : 0 PAD z

Waveform

Example - Mux

1 module mux_using_assign();
2 reg data_in_0, data_in_1;

160
Verilog Programming Guide

3 wire data_out;
4 reg sel;
5
6 assign data_out = (sel) ? data_in_1 : data_in_0;
7
8 // Testbench code here
9 initial begin
10 $monitor("TIME = %g SEL = %b DATA0 = %b DATA1 = %b OUT = %b",
11 $time,sel,data_in_0,data_in_1,data_out);
12 data_in_0 = 0;
13 data_in_1 = 0;
14 sel = 0;
15 #10 sel = 1;
16 #10 $finish;
17 end
18
19 // Toggel data_in_0 at #1
20 always
21 #1 data_in_0 = ~data_in_0;
22
23 // Toggel data_in_1 at #2
24 always
25 #2 data_in_1 = ~data_in_1;
26
27 endmodule
You could download file mux_using_assign.v here

Simulation Output

TIME = 0 SEL = 0 DATA0 = 0 DATA1 = 0 OUT = 0


TIME = 1 SEL = 0 DATA0 = 1 DATA1 = 0 OUT = 1
TIME = 2 SEL = 0 DATA0 = 0 DATA1 = 1 OUT = 0
TIME = 3 SEL = 0 DATA0 = 1 DATA1 = 1 OUT = 1
TIME = 4 SEL = 0 DATA0 = 0 DATA1 = 0 OUT = 0
TIME = 5 SEL = 0 DATA0 = 1 DATA1 = 0 OUT = 1
TIME = 6 SEL = 0 DATA0 = 0 DATA1 = 1 OUT = 0
TIME = 7 SEL = 0 DATA0 = 1 DATA1 = 1 OUT = 1
TIME = 8 SEL = 0 DATA0 = 0 DATA1 = 0 OUT = 0
TIME = 9 SEL = 0 DATA0 = 1 DATA1 = 0 OUT = 1

161
Verilog Programming Guide

TIME = 10 SEL = 1 DATA0 = 0 DATA1 = 1 OUT = 1


TIME = 11 SEL = 1 DATA0 = 1 DATA1 = 1 OUT = 1
TIME = 12 SEL = 1 DATA0 = 0 DATA1 = 0 OUT = 0
TIME = 13 SEL = 1 DATA0 = 1 DATA1 = 0 OUT = 0
TIME = 14 SEL = 1 DATA0 = 0 DATA1 = 1 OUT = 1
TIME = 15 SEL = 1 DATA0 = 1 DATA1 = 1 OUT = 1
TIME = 16 SEL = 1 DATA0 = 0 DATA1 = 0 OUT = 0
TIME = 17 SEL = 1 DATA0 = 1 DATA1 = 0 OUT = 0
TIME = 18 SEL = 1 DATA0 = 0 DATA1 = 1 OUT = 1
TIME = 19 SEL = 1 DATA0 = 1 DATA1 = 1 OUT = 1

Waveform

$display, $strobe, $monitor

These commands have the same syntax, and display text on the screen during
simulation. They are much less convenient than waveform display tools like GTKWave.
or Undertow or Debussy. $display and $strobe display once every time they are
executed, whereas $monitor displays every time one of its parameters changes. The
difference between $display and $strobe is that $strobe displays the parameters at the
very end of the current simulation time unit rather than exactly when it is executed. The
format string is like that in C/C++, and may contain format characters. Format
characters include %d (decimal), %h (hexadecimal), %b (binary), %c (character), %s

162
Verilog Programming Guide

(string) and %t (time), %m (hierarchy level). %5d, %5b etc. would give exactly 5 spaces
for the number instead of the space needed. Append b, h, o to the task name to change
default format to binary, octal or hexadecimal.

Syntax

• $display ("format_string", par_1, par_2, ... );


• $strobe ("format_string", par_1, par_2, ... );
• $monitor ("format_string", par_1, par_2, ... );
• $displayb (as above but defaults to binary..);
• $strobeh (as above but defaults to hex..);
• $monitoro (as above but defaults to octal..);

$time, $stime, $realtime

These return the current simulation time as a 64-bit integer, a 32-bit integer, and a real
number, respectively.

$reset, $stop, $finish

$reset resets the simulation back to time 0; $stop halts the simulator and puts it in
interactive mode where the user can enter commands; $finish exits the simulator back
to the operating system.

163
Verilog Programming Guide

$scope, $showscope

$scope(hierarchy_name) sets the current hierarchical scope to hierarchy_name.


$showscopes(n) lists all modules, tasks and block names in (and below, if n is set to 1)
the current scope.

$random

$random generates a random integer every time it is called. If the sequence is to be


repeatable, the first time one invokes random giving it a numerical argument (a seed).
Otherwise the seed is derived from the computer clock.

$dumpfile, $dumpvar, $dumpon, $dumpoff, $dumpall

These can dump variable changes to a simulation viewer like Debussy. The dump files
are capable of dumping all the variables in a simulation. This is convenient for
debugging, but can be very slow.

Syntax

• $dumpfile("filename.vcd")
• $dumpvar dumps all variables in the design.
• $dumpvar(1, top) dumps all the variables in module top and below, but not
modules instantiated in top.
• $dumpvar(2, top) dumps all the variables in module top and 1 level below.
• $dumpvar(n, top) dumps all the variables in module top and n-1 levels below.
• $dumpvar(0, top) dumps all the variables in module top and all level below.
• $dumpon initiates the dump.
• $dumpoff stop dumping.

164
Verilog Programming Guide

$fopen, $fdisplay, $fstrobe $fmonitor and $fwrite

These commands write more selectively to files.

• $fopen opens an output file and gives the open file a handle for use by the other
commands.
• $fclose closes the file and lets other programs access it.
• $fdisplay and $fwrite write formatted data to a file whenever they are executed.
They are the same except $fdisplay inserts a new line after every execution and
$write does not.
• $strobe also writes to a file when executed, but it waits until all other operations
in the time step are complete before writing. Thus initial #1 a=1; b=0;
$fstrobe(hand1, a,b); b=1; will write write 1 1 for a and b.
• $monitor writes to a file whenever any of its arguments changes.

Syntax

• handle1=$fopen("filenam1.suffix")
• handle2=$fopen("filenam2.suffix")
• $fstrobe(handle1, format, variable list) //strobe data into filenam1.suffix
• $fdisplay(handle2, format, variable list) //write data into filenam2.suffix
• $fwrite(handle2, format, variable list) //write data into filenam2.suffix all on one
line. Put in the format string where a new line is desired.

Writing a testbench is as complex as writing the RTL code itself. These days ASICs are
getting more and more complex and thus verifying these complex ASIC has become a
challenge. Typically 60-70% of time needed for any ASIC is spent on

165
Verilog Programming Guide

verification/validation/testing. Even though the above facts are well known to most ASIC
engineers, still engineers think that there is no glory in verification.

Memory Modeling

To help modeling of memory, Verilog provides support for two dimensions arrays.
Behavioral models of memories are modeled by declaring an array of register variables;
any word in the array may be accessed using an index into the array. A temporary
variable is required to access a discrete bit within the array.

Syntax

reg [wordsize:0] array_name [0:arraysize]

Examples

Declaration

reg [7:0] my_memory [0:255];

Here [7:0] is the memory width and [0:255] is the memory depth with the following
parameters:

• Width : 8 bits, little endian

166
Verilog Programming Guide

• Depth : 256, address 0 corresponds to location 0 in the array.

Storing Values

my_memory[address] = data_in;

Reading Values

data_out = my_memory[address];

Bit Read

Sometimes there may be need to read just one bit. Unfortunately Verilog does not allow
to read or write only one bit: the workaround for such a problem is as shown below.

data_out = my_memory[address];

data_out_it_0 = data_out[0];

Initializing Memories

167
Verilog Programming Guide

A memory array may be initialized by reading memory pattern file from disk and storing
it on the memory array. To do this, we use system tasks $readmemb and $readmemh.
$readmemb is used for binary representation of memory content and $readmemh for
hex representation.

Syntax

$readmemh("file_name",mem_array,start_addr,stop_addr);

Note : start_addr and stop_addr are optional.

Example - Simple memory

1 module memory();
2 reg [7:0] my_memory [0:255];
3
4 initial begin
5 $readmemh("memory.list", my_memory);
6 end
7 endmodule
You could download file memory.v here

Example - Memory.list file

1 //Comments are allowed


2 1100_1100 // This is first address i.e 8'h00
3 1010_1010 // This is second address i.e 8'h01
4 @ 55 // Jump to new address 8'h55

168
Verilog Programming Guide

5 0101_1010 // This is address 8'h55


6 0110_1001 // This is address 8'h56
You could download file memory.list here

$readmemh system task can also be used for reading testbench vectors. I will cover this
in detail in the test bench section ... when I find time.

Introduction to FSM

State machines or FSM are the heart of any digital design; of course a counter is a
simple form of FSM. When I was learning Verilog, I used to wonder "How do I code
FSM in Verilog" and "What is the best way to code it". I will try to answer the first part of
the question below and second part of the question can be found in the tidbits section.

State machine Types

There are two types of state machines as classified by the types of outputs generated
from each. The first is the Moore State Machine where the outputs are only a function of
the present state, the second is the Mealy State Machine where one or more of the
outputs are a function of the present state and one or more of the inputs.

Mealy Model

169
Verilog Programming Guide

Moore Model

State machines can also be classified according to the state encoding


used. Encoding style is also a critical factor which decides speed and gate complexity of
the FSM. Binary, gray, one hot, one cold, and almost one hot are the different types of
encoding styles used in coding FSM states.

Modeling State machines.

One thing that need to be kept in mind when coding FSM is that
combinational logic and sequence logic should be in two different always blocks. In the

170
Verilog Programming Guide

above two figures, next state logic is always the combinational logic. State Registers
and Output logic are sequential logic. It is very important that any asynchronous signal
to the next state logic be synchronized before being fed to the FSM. Always try to keep
FSM in a separate Verilog file.

Using constants declaration like parameter or `define to define states


of the FSM makes code more readable and easy to manage.

Example - Arbiter

We will be using the arbiter FSM to study FSM coding styles in


Verilog.

171
Verilog Programming Guide

Verilog Code

FSM code should have three sections:

• Encoding style.
• Combinational part.
• Sequential part.

Encoding Style

There are many encoding styles around, some of which are:

• Binary Encoding
• One Hot Encoding
• One Cold Encoding
• Almost One Hot Encoding
• Almost One Cold Encoding
• Gray Encoding

Of all the above types we normally use one hot and binary encoding.

One Hot Encoding

1 parameter [4:0] IDLE = 5'b0_0001;


2 parameter [4:0] GNT0 = 5'b0_0010;

172
Verilog Programming Guide

3 parameter [4:0] GNT1 = 5'b0_0100;


4 parameter [4:0] GNT2 = 5'b0_1000;
5 parameter [4:0] GNT3 = 5'b1_0000;
You could download file fsm_one_hot_params.v here

Binary Encoding

1 parameter [2:0] IDLE = 3'b000;


2 parameter [2:0] GNT0 = 3'b001;
3 parameter [2:0] GNT1 = 3'b010;
4 parameter [2:0] GNT2 = 3'b011;
5 parameter [2:0] GNT3 = 3'b100;
You could download file fsm_binary_params.v here

Gray Encoding

1 parameter [2:0] IDLE = 3'b000;


2 parameter [2:0] GNT0 = 3'b001;
3 parameter [2:0] GNT1 = 3'b011;
4 parameter [2:0] GNT2 = 3'b010;
5 parameter [2:0] GNT3 = 3'b110;
You could download file fsm_gray_params.v here

Combinational Section
This section can be modeled using functions, assign statements or using always blocks
with a case statement. For the time being let's see the always block version

173
Verilog Programming Guide

1 always @ (state or req_0 or req_1 or req_2 or req_3)


2 begin
3 next_state = 0;
4 case(state)
5 IDLE : if (req_0 == 1'b1) begin
6 next_state = GNT0;
7 end else if (req_1 == 1'b1) begin
8 next_state= GNT1;
9 end else if (req_2 == 1'b1) begin
10 next_state= GNT2;
11 end else if (req_3 == 1'b1) begin
12 next_state= GNT3;
13 end else begin
14 next_state = IDLE;
15 end
16 GNT0 : if (req_0 == 1'b0) begin
17 next_state = IDLE;
18 end else begin
19 next_state = GNT0;
20 end
21 GNT1 : if (req_1 == 1'b0) begin
22 next_state = IDLE;
23 end else begin
24 next_state = GNT1;
25 end
26 GNT2 : if (req_2 == 1'b0) begin
27 next_state = IDLE;
28 end else begin
29 next_state = GNT2;
30 end
31 GNT3 : if (req_3 == 1'b0) begin
32 next_state = IDLE;
33 end else begin
34 next_state = GNT3;
35 end
36 default : next_state = IDLE;
37 endcase
38 end
You could download file fsm_combo.v here

174
Verilog Programming Guide

Sequential Section

This section has to be modeled using only edge sensitive logic such as always block
with posedge or negedge of clock.

1 always @ (posedge clock)


2 begin : OUTPUT_LOGIC
3 if (reset == 1'b1) begin
4 gnt_0 <= #1 1'b0;
5 gnt_1 <= #1 1'b0;
6 gnt_2 <= #1 1'b0;
7 gnt_3 <= #1 1'b0;
8 state <= #1 IDLE;
9 end else begin
10 state <= #1 next_state;
11 case(state)
12 IDLE : begin
13 gnt_0 <= #1 1'b0;
14 gnt_1 <= #1 1'b0;
15 gnt_2 <= #1 1'b0;
16 gnt_3 <= #1 1'b0;
17 end
18 GNT0 : begin
19 gnt_0 <= #1 1'b1;
20 end
21 GNT1 : begin
22 gnt_1 <= #1 1'b1;
23 end
24 GNT2 : begin
25 gnt_2 <= #1 1'b1;
26 end
27 GNT3 : begin

175
Verilog Programming Guide

28 gnt_3 <= #1 1'b1;


29 end
30 default : begin
31 state <= #1 IDLE;
32 end
33 endcase
34 end
35 end
You could download file fsm_seq.v here

Full Code using binary encoding

1 module fsm_full(
2 clock , // Clock
3 reset , // Active high reset
4 req_0 , // Active high request from agent 0
5 req_1 , // Active high request from agent 1
6 req_2 , // Active high request from agent 2
7 req_3 , // Active high request from agent 3
8 gnt_0 , // Active high grant to agent 0
9 gnt_1 , // Active high grant to agent 1
10 gnt_2 , // Active high grant to agent 2
11 gnt_3 // Active high grant to agent 3
12 );
13 // Port declaration here
14 input clock ; // Clock
15 input reset ; // Active high reset
16 input req_0 ; // Active high request from agent 0
17 input req_1 ; // Active high request from agent 1
18 input req_2 ; // Active high request from agent 2
19 input req_3 ; // Active high request from agent 3
20 output gnt_0 ; // Active high grant to agent 0
21 output gnt_1 ; // Active high grant to agent 1
22 output gnt_2 ; // Active high grant to agent 2
23 output gnt_3 ; // Active high grant to agent
24
25 // Internal Variables

176
Verilog Programming Guide

26 reg gnt_0 ; // Active high grant to agent 0


27 reg gnt_1 ; // Active high grant to agent 1
28 reg gnt_2 ; // Active high grant to agent 2
29 reg gnt_3 ; // Active high grant to agent
30
31 parameter [2:0] IDLE = 3'b000;
32 parameter [2:0] GNT0 = 3'b001;
33 parameter [2:0] GNT1 = 3'b010;
34 parameter [2:0] GNT2 = 3'b011;
35 parameter [2:0] GNT3 = 3'b100;
36
37 reg [2:0] state, next_state;
38
39 always @ (state or req_0 or req_1 or req_2 or req_3)
40 begin
41 next_state = 0;
42 case(state)
43 IDLE : if (req_0 == 1'b1) begin
44 next_state = GNT0;
45 end else if (req_1 == 1'b1) begin
46 next_state= GNT1;
47 end else if (req_2 == 1'b1) begin
48 next_state= GNT2;
49 end else if (req_3 == 1'b1) begin
50 next_state= GNT3;
51 end else begin
52 next_state = IDLE;
53 end
54 GNT0 : if (req_0 == 1'b0) begin
55 next_state = IDLE;
56 end else begin
57 next_state = GNT0;
58 end
59 GNT1 : if (req_1 == 1'b0) begin
60 next_state = IDLE;
61 end else begin
62 next_state = GNT1;
63 end
64 GNT2 : if (req_2 == 1'b0) begin
65 next_state = IDLE;
66 end else begin
67 next_state = GNT2;
68 end

177
Verilog Programming Guide

69 GNT3 : if (req_3 == 1'b0) begin


70 next_state = IDLE;
71 end else begin
72 next_state = GNT3;
73 end
74 default : next_state = IDLE;
75 endcase
76 end
77
78 always @ (posedge clock)
79 begin : OUTPUT_LOGIC
80 if (reset) begin
81 gnt_0 <= #1 1'b0;
82 gnt_1 <= #1 1'b0;
83 gnt_2 <= #1 1'b0;
84 gnt_3 <= #1 1'b0;
85 state <= #1 IDLE;
86 end else begin
87 state <= #1 next_state;
88 case(state)
89 IDLE : begin
90 gnt_0 <= #1 1'b0;
91 gnt_1 <= #1 1'b0;
92 gnt_2 <= #1 1'b0;
93 gnt_3 <= #1 1'b0;
94 end
95 GNT0 : begin
96 gnt_0 <= #1 1'b1;
97 end
98 GNT1 : begin
99 gnt_1 <= #1 1'b1;
100 end
101 GNT2 : begin
102 gnt_2 <= #1 1'b1;
103 end
104 GNT3 : begin
105 gnt_3 <= #1 1'b1;
106 end
107 default : begin
108 state <= #1 IDLE;
109 end
110 endcase
111 end

178
Verilog Programming Guide

112 end
113
114 endmodule
You could download file fsm_full.v here

Testbench

1 `include "fsm_full.v"
2
3 module fsm_full_tb();
4 reg clock , reset ;
5 reg req_0 , req_1 , req_2 , req_3;
6 wire gnt_0 , gnt_1 , gnt_2 , gnt_3 ;
7
8 initial begin
9 $display("Time\t R0 R1 R2 R3 G0 G1 G2 G3");
10 $monitor("%g\t %b %b %b %b %b %b %b %b",
11 $time, req_0, req_1, req_2, req_3, gnt_0, gnt_1, gnt_2, gnt_3);
12 clock = 0;
13 reset = 0;
14 req_0 = 0;
15 req_1 = 0;
16 req_2 = 0;
17 req_3 = 0;
18 #10 reset = 1;
19 #10 reset = 0;
20 #10 req_0 = 1;
21 #20 req_0 = 0;
22 #10 req_1 = 1;
23 #20 req_1 = 0;
24 #10 req_2 = 1;
25 #20 req_2 = 0;
26 #10 req_3 = 1;
27 #20 req_3 = 0;
28 #10 $finish;
29 end
30
31 always
32 #2 clock = ~clock;
33

179
Verilog Programming Guide
34
35 fsm_full U_fsm_full(
36 clock , // Clock
37 reset , // Active high reset
38 req_0 , // Active high request from agent 0
39 req_1 , // Active high request from agent 1
40 req_2 , // Active high request from agent 2
41 req_3 , // Active high request from agent 3
42 gnt_0 , // Active high grant to agent 0
43 gnt_1 , // Active high grant to agent 1
44 gnt_2 , // Active high grant to agent 2
45 gnt_3 // Active high grant to agent 3
46 );
47
48
49
50 endmodule
You could download file fsm_full_tb.v here

Simulator Output

Time R0 R1 R2 R3 G0 G1 G2 G3
0 0 0 0 0 x x x x
7 0 0 0 0 0 0 0 0
30 1 0 0 0 0 0 0 0
35 1 0 0 0 1 0 0 0
50 0 0 0 0 1 0 0 0
55 0 0 0 0 0 0 0 0
60 0 1 0 0 0 0 0 0
67 0 1 0 0 0 1 0 0
80 0 0 0 0 0 1 0 0
87 0 0 0 0 0 0 0 0
90 0 0 1 0 0 0 0 0
95 0 0 1 0 0 0 1 0
110 0 0 0 0 0 0 1 0
115 0 0 0 0 0 0 0 0
120 0 0 0 1 0 0 0 0
127 0 0 0 1 0 0 0 1
140 0 0 0 0 0 0 0 1
147 0 0 0 0 0 0 0 0

assign and deassign

180
Verilog Programming Guide

The assign and deassign procedural assignment statements allow continuous


assignments to be placed onto registers for controlled periods of time. The assign
procedural statement overrides procedural assignments to a register. The deassign
procedural statement ends a continuous assignment to a register.

Example - assign and deassign

1 module assign_deassign ();


2
3 reg clk,rst,d,preset;
4 wire q;
5
6 initial begin
7 $monitor("@%g clk %b rst %b preset %b d %b q %b",
8 $time, clk, rst, preset, d, q);
9 clk = 0;
10 rst = 0;
11 d = 0;
12 preset = 0;
13 #10 rst = 1;
14 #10 rst = 0;
15 repeat (10) begin
16 @ (posedge clk);
17 d <= $random;
18 @ (negedge clk) ;
19 preset <= ~preset;
20 end
21 #1 $finish;
22 end
23 // Clock generator
24 always #1 clk = ~clk;
25
26 // assign and deassign q of flip flop module
27 always @(preset)
28 if (preset) begin
29 assign U.q = 1; // assign procedural statement
30 end else begin

181
Verilog Programming Guide

31 deassign U.q; // deassign procedural statement


32 end
33
34 d_ff U (clk,rst,d,q);
35
36 endmodule
37
38 // D Flip-Flop model
39 module d_ff (clk,rst,d,q);
40 input clk,rst,d;
41 output q;
42 reg q;
43
44 always @ (posedge clk)
45 if (rst) begin
46 q <= 0;
47 end else begin
48 q <= d;
49 end
50
51 endmodule
You could download file assign_deassign.v here

Simulator Output

@0 clk 0 rst 0 preset 0 d 0 q x


@1 clk 1 rst 0 preset 0 d 0 q 0
@2 clk 0 rst 0 preset 0 d 0 q 0
@3 clk 1 rst 0 preset 0 d 0 q 0
@4 clk 0 rst 0 preset 0 d 0 q 0
@5 clk 1 rst 0 preset 0 d 0 q 0
@6 clk 0 rst 0 preset 0 d 0 q 0
@7 clk 1 rst 0 preset 0 d 0 q 0
@8 clk 0 rst 0 preset 0 d 0 q 0
@9 clk 1 rst 0 preset 0 d 0 q 0
@10 clk 0 rst 1 preset 0 d 0 q 0
@11 clk 1 rst 1 preset 0 d 0 q 0
@12 clk 0 rst 1 preset 0 d 0 q 0
@13 clk 1 rst 1 preset 0 d 0 q 0

182
Verilog Programming Guide

@14 clk 0 rst 1 preset 0 d 0 q 0


@15 clk 1 rst 1 preset 0 d 0 q 0
@16 clk 0 rst 1 preset 0 d 0 q 0
@17 clk 1 rst 1 preset 0 d 0 q 0
@18 clk 0 rst 1 preset 0 d 0 q 0
@19 clk 1 rst 1 preset 0 d 0 q 0
@20 clk 0 rst 0 preset 0 d 0 q 0
@21 clk 1 rst 0 preset 0 d 0 q 0
@22 clk 0 rst 0 preset 1 d 0 q 1
@23 clk 1 rst 0 preset 1 d 1 q 1
@24 clk 0 rst 0 preset 0 d 1 q 1
@25 clk 1 rst 0 preset 0 d 1 q 1
@26 clk 0 rst 0 preset 1 d 1 q 1
@27 clk 1 rst 0 preset 1 d 1 q 1
@28 clk 0 rst 0 preset 0 d 1 q 1
@29 clk 1 rst 0 preset 0 d 1 q 1
@30 clk 0 rst 0 preset 1 d 1 q 1
@31 clk 1 rst 0 preset 1 d 1 q 1
@32 clk 0 rst 0 preset 0 d 1 q 1
@33 clk 1 rst 0 preset 0 d 1 q 1
@34 clk 0 rst 0 preset 1 d 1 q 1
@35 clk 1 rst 0 preset 1 d 0 q 1
@36 clk 0 rst 0 preset 0 d 0 q 1
@37 clk 1 rst 0 preset 0 d 1 q 0
@38 clk 0 rst 0 preset 1 d 1 q 1
@39 clk 1 rst 0 preset 1 d 1 q 1
@40 clk 0 rst 0 preset 0 d 1 q 1

force and release

Another form of procedural continuous assignment is provided by the force and release
procedural statements. These statements have a similar effect on the assign-deassign
pair, but a force can be applied to nets as well as to registers.

One can use force and release while doing gate level simulation to work around reset
connectivity problems. Also can be used insert single and double bit errors on data read
from memory.

183
Verilog Programming Guide

Example - force and release

1 module force_release ();


2
3 reg clk,rst,d,preset;
4 wire q;
5
6 initial begin
7 $monitor("@%g clk %b rst %b preset %b d %b q %b",
8 $time, clk, rst, preset, d, q);
9 clk = 0;
10 rst = 0;
11 d = 0;
12 preset = 0;
13 #10 rst = 1;
14 #10 rst = 0;
15 repeat (10) begin
16 @ (posedge clk);
17 d <= $random;
18 @ (negedge clk) ;
19 preset <= ~preset;
20 end
21 #1 $finish;
22 end
23 // Clock generator
24 always #1 clk = ~clk;
25
26 // force and release of flip flop module
27 always @(preset)
28 if (preset) begin
29 force U.q = preset; // force procedural statement
30 end else begin
31 release U.q; // release procedural statement
32 end
33
34 d_ff U (clk,rst,d,q);
35

184
Verilog Programming Guide

36 endmodule
37
38 // D Flip-Flop model
39 module d_ff (clk,rst,d,q);
40 input clk,rst,d;
41 output q;
42 wire q;
43 reg q_reg;
44
45 assign q = q_reg;
46
47 always @ (posedge clk)
48 if (rst) begin
49 q_reg <= 0;
50 end else begin
51 q_reg <= d;
52 end
53
54 endmodule
You could download file force_release.v here

Simulator Output

@0 clk 0 rst 0 preset 0 d 0 q x


@1 clk 1 rst 0 preset 0 d 0 q 0
@2 clk 0 rst 0 preset 0 d 0 q 0
@3 clk 1 rst 0 preset 0 d 0 q 0
@4 clk 0 rst 0 preset 0 d 0 q 0
@5 clk 1 rst 0 preset 0 d 0 q 0
@6 clk 0 rst 0 preset 0 d 0 q 0
@7 clk 1 rst 0 preset 0 d 0 q 0
@8 clk 0 rst 0 preset 0 d 0 q 0
@9 clk 1 rst 0 preset 0 d 0 q 0
@10 clk 0 rst 1 preset 0 d 0 q 0
@11 clk 1 rst 1 preset 0 d 0 q 0
@12 clk 0 rst 1 preset 0 d 0 q 0
@13 clk 1 rst 1 preset 0 d 0 q 0
@14 clk 0 rst 1 preset 0 d 0 q 0
@15 clk 1 rst 1 preset 0 d 0 q 0

185
Verilog Programming Guide

@16 clk 0 rst 1 preset 0 d 0 q 0


@17 clk 1 rst 1 preset 0 d 0 q 0
@18 clk 0 rst 1 preset 0 d 0 q 0
@19 clk 1 rst 1 preset 0 d 0 q 0
@20 clk 0 rst 0 preset 0 d 0 q 0
@21 clk 1 rst 0 preset 0 d 0 q 0
@22 clk 0 rst 0 preset 1 d 0 q 1
@23 clk 1 rst 0 preset 1 d 1 q 1
@24 clk 0 rst 0 preset 0 d 1 q 0
@25 clk 1 rst 0 preset 0 d 1 q 1
@26 clk 0 rst 0 preset 1 d 1 q 1
@27 clk 1 rst 0 preset 1 d 1 q 1
@28 clk 0 rst 0 preset 0 d 1 q 1
@29 clk 1 rst 0 preset 0 d 1 q 1
@30 clk 0 rst 0 preset 1 d 1 q 1
@31 clk 1 rst 0 preset 1 d 1 q 1
@32 clk 0 rst 0 preset 0 d 1 q 1
@33 clk 1 rst 0 preset 0 d 1 q 1
@34 clk 0 rst 0 preset 1 d 1 q 1
@35 clk 1 rst 0 preset 1 d 0 q 1
@36 clk 0 rst 0 preset 0 d 0 q 1
@37 clk 1 rst 0 preset 0 d 1 q 0
@38 clk 0 rst 0 preset 1 d 1 q 1
@39 clk 1 rst 0 preset 1 d 1 q 1
@40 clk 0 rst 0 preset 0 d 1 q 1

Introduction

Let's assume that we have a design which requires us to have counters of various
width, but with the same functionality. Maybe we can assume that we have a design
which requires lots of instants of different depth and width of RAMs of similar
functionality. Normally what we do is creating counters of different widths and then use
them. The same rule applies to the RAM we talked about.

186
Verilog Programming Guide

But Verilog provides a powerful way to overcome this problem: it provides us with
something called parameter; these parameters are like constants local to that particular
module.

We can override the default values, either using defparam or by passing a new set of
parameters during instantiation. We call this parameter overriding.

Parameters

A parameter is defined by Verilog as a constant value declared within the


module structure. The value can be used to define a set of attributes for the module
which can characterize its behavior as well as its physical representation.

• Defined inside a module.


• Local scope.
• Maybe overridden at instantiation time.
o If multiple parameters are defined, they must be overridden in the order
they were defined. If an overriding value is not specified, the default
parameter declaration values are used.
• Maybe changed using the defparam statement.

Parameter Override using defparam

1 module secret_number;
2 parameter my_secret = 0;

187
Verilog Programming Guide
3
4 initial begin
5 $display("My secret number is %d", my_secret);
6 end
7
8 endmodule
9
10 module defparam_example();
11
12 defparam U0.my_secret = 11;
13 defparam U1.my_secret = 22;
14
15 secret_number U0();
16 secret_number U1();
17
18 endmodule
You could download file defparam_example.v here

Parameter Override during instantiating.

1 module secret_number;
2 parameter my_secret = 0;
3
4 initial begin
5 $display("My secret number in module is %d", my_secret);
6 end
7
8 endmodule
9
10 module param_overide_instance_example();
11
12 secret_number #(11) U0();
13 secret_number #(22) U1();
14
15 endmodule
You could download file param_overide_instance_example.v here

188
Verilog Programming Guide

Passing more than one parameter

1 module ram_sp_sr_sw (
2 clk , // Clock Input
3 address , // Address Input
4 data , // Data bi-directional
5 cs , // Chip Select
6 we , // Write Enable/Read Enable
7 oe // Output Enable
8 );
9
10 parameter DATA_WIDTH = 8 ;
11 parameter ADDR_WIDTH = 8 ;
12 parameter RAM_DEPTH = 1 << ADDR_WIDTH;
13 // Actual code of RAM here
14
15 endmodule
You could download file param_more_then_one.v here

When instantiating more than the one parameter, parameter values should be passed in
the order they are declared in the sub module.

1 module ram_controller ();//Some ports


2
3 // Controller Code
4
5 ram_sp_sr_sw #(16,8,256) ram(clk,address,data,cs,we,oe);
6
7 endmodule
You could download file param_more_then_one1.v here

189
Verilog Programming Guide

N-Input Primitives

The and, nand, or, nor, xor, and xnor primitives have one output and any number of inputs

• The single output is the first terminal.


• All other terminals are inputs.

Examples

1 module n_in_primitive();
2
3 wire out1,out2,out3;
4 reg in1,in2,in3,in4;
5
6 // Two input AND gate
7 and u_and1 (out1, in1, in2);
8 // four input AND gate
9 and u_and2 (out2, in1, in2, in3, in4);
10 // three input XNOR gate
11 xnor u_xnor1 (out3, in1, in2, in3);
12
13 //Testbench Code
14 initial begin
15 $monitor (
16 "in1 = %b in2 = %b in3 = %b in4 = %b out1 = %b out2 = %b out3 = %b",
17 in1, in2, in3, in4, out1, out2, out3);
18 in1 = 0;
19 in2 = 0;
20 in3 = 0;
21 in4 = 0;
22 #1 in1 = 1;
23 #1 in2 = 1;
24 #1 in3 = 1;
25 #1 in4 = 1;

190
Verilog Programming Guide

26 #1 $finish;
27 end
28
29 endmodule
You could download file n_in_primitive.v here

in1 = 0 in2 = 0 in3 = 0 in4 = 0 out1 = 0 out2 = 0 out3 = 1


in1 = 1 in2 = 0 in3 = 0 in4 = 0 out1 = 0 out2 = 0 out3 = 0
in1 = 1 in2 = 1 in3 = 0 in4 = 0 out1 = 1 out2 = 0 out3 = 1
in1 = 1 in2 = 1 in3 = 1 in4 = 0 out1 = 1 out2 = 0 out3 = 0
in1 = 1 in2 = 1 in3 = 1 in4 = 1 out1 = 1 out2 = 1 out3 = 0

N-Output Primitives

The buf and not primitives have any number of outputs and one input

• The outputs are the first terminals listed.


• The last terminal is the single input.

Examples

1 module n_out_primitive();
2
3 wire out,out_0,out_1,out_2,out_3,out_a,out_b,out_c;
4 wire in;
5

191
Verilog Programming Guide

6 // one output Buffer gate


7 buf u_buf0 (out,in);
8 // four output Buffer gate
9 buf u_buf1 (out_0, out_1, out_2, out_3, in);
10 // three output Invertor gate
11 not u_not0 (out_a, out_b, out_c, in);
12
13 endmodule
You could download file n_out_primitive.v here

Example - "fork-join"

1 module initial_fork_join();
2 reg clk,reset,enable,data;
3
4 initial begin
5 $monitor("%g clk=%b reset=%b enable=%b data=%b",
6 $time, clk, reset, enable, data);
7 fork
8 #1 clk = 0;
9 #10 reset = 0;
10 #5 enable = 0;
11 #3 data = 0;
12 join
13 #1 $display ("%g Terminating simulation", $time);
14 $finish;
15 end
16
17 endmodule
You could download file initial_fork_join.v here

192
Verilog Programming Guide

Fork : clk gets its value after 1 time unit, reset after 10 time units, enable after 5 time units,
data after 3 time units. All the statements are executed in parallel.

Simulator Output

0 clk=x reset=x enable=x data=x


1 clk=0 reset=x enable=x data=x
3 clk=0 reset=x enable=x data=0
5 clk=0 reset=x enable=0 data=0
10 clk=0 reset=0 enable=0 data=0
11 Terminating simulation

Sequential Statement Groups

The begin - end keywords:

• Group several statements together.


• Cause the statements to be evaluated sequentially (one at a time)
o Any timing within the sequential groups is relative to the previous
statement.
o Delays in the sequence accumulate (each delay is added to the previous
delay)
• Block finishes after the last statement in the block.

193
Verilog Programming Guide

Example - sequential

1 module sequential();
2
3 reg a;
4
5 initial begin
6 $monitor ("%g a = %b", $time, a);
7 #10 a = 0;
8 #11 a = 1;
9 #12 a = 0;
10 #13 a = 1;
11 #14 $finish;
12 end
13
14 endmodule
You could download file sequential.v here

Simulator Output

0a=x
10 a = 0
21 a = 1
33 a = 0
46 a = 1

Parallel Statement Groups

The fork - join keywords:

194
Verilog Programming Guide

• Group several statements together.


• Cause the statements to be evaluated in parallel (all at the same time).
o Timing within parallel group is absolute to the beginning of the group.
o Block finishes after the last statement completes (Statement with highest
delay, it can be the first statement in the block).

Example - Parallel

1 module parallel();
2
3 reg a;
4
5 initial
6 fork
7 $monitor ("%g a = %b", $time, a);
8 #10 a = 0;
9 #11 a = 1;
10 #12 a = 0;
11 #13 a = 1;
12 #14 $finish;
13 join
14
15 endmodule
You could download file parallel.v here

Simulator Output

0a=x
10 a = 0
11 a = 1
12 a = 0
13 a = 1

195
Verilog Programming Guide

Example - Mixing "begin-end" and "fork - join"

1 module fork_join();
2
3 reg clk,reset,enable,data;
4
5 initial begin
6 $display ("Starting simulation");
7 $monitor("%g clk=%b reset=%b enable=%b data=%b",
8 $time, clk, reset, enable, data);
9 fork : FORK_VAL
10 #1 clk = 0;
11 #5 reset = 0;
12 #5 enable = 0;
13 #2 data = 0;
14 join
15 #10 $display ("%g Terminating simulation", $time);
16 $finish;
17 end
18
19 endmodule
You could download file fork_join.v here

Simulator Output

0 clk=x reset=x enable=x data=x


1 clk=0 reset=x enable=x data=x
2 clk=0 reset=x enable=x data=0
5 clk=0 reset=0 enable=0 data=0
15 Terminating simulation

196
Verilog Programming Guide

197

You might also like