Introduction to Verilog
Introduction to Verilog
INTRODUCTION
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.
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.
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
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:
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
11
Verilog Programming Guide
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
13
Verilog Programming Guide
14
Verilog Programming Guide
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
• 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.
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
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.
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
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.
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:
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
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
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
Syntax
input [net_type] [range] list_of_names; // Input port
28
Verilog Programming Guide
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
29
Verilog Programming Guide
How to define vector signals (signals composed of sequences of more than one bit)?
Verilog provides a simple way to define these as well.
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
Data Types
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
Summary
• 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.
32
Verilog Programming Guide
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
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
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
36
Verilog Programming Guide
• 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
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
Logical Operators
Operator Description
!logic negation
|| logical or
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
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
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
42
Verilog Programming Guide
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
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
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
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
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
Operator Precedence
Operator Symbols
Logic &&, ||
Conditional ?:
49
Verilog Programming Guide
Arithmetic * Multiply
/ Division
+ Add
- Subtract
% Modulus
+ Unary plus
- Unary minus
|| Logical or
Equality == Equality
!= inequality
~& nand
50
Verilog Programming Guide
| or
~| nor
^ xor
^~ xnor
~^ xnor
Concatenation {} Concatenation
Conditional ? conditional
//////////////////////////////////////Lesson #2///////////////////////////////////
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
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
60
Verilog Programming Guide
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.
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
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.
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).
64
Verilog Programming Guide
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
////////////////////////////////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.
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
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
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 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.
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
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.
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
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
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.
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.
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.
Rules:
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.
Syntax
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.
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
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.
83
Verilog Programming Guide
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
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 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
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:
90
Verilog Programming Guide
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.
91
Verilog Programming Guide
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.
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.
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.
99
Verilog Programming Guide
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.
102
Verilog Programming Guide
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.
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.
• Blank spaces
• Tabs
• Carriage returns
• New-line
• Form-feeds
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
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
• 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
107
Verilog Programming Guide
NOTE : Never use Verilog keywords as unique names, even if the case is different.
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).
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.
109
Verilog Programming Guide
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
Syntax: <size>'<radix><value>;
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.
Integer Stored as
6'hCA 001010
6'hA 001010
111
Verilog Programming Guide
16'bZ ZZZZZZZZZZZZZZZZ
8'bx xxxxxxxx
Real Numbers
1.2 1.2
0.6 0.6
3.5E6 3,500000.0
112
Verilog Programming Guide
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
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
Strings
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.
Character Description
\t Tab 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
116
Verilog Programming Guide
In real circuits, logic gates have delays associated with them. Verilog provides the
mechanism to associate delays with gates.
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.
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.
117
Verilog Programming Guide
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
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
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
1 module delay();
2 reg in;
3 wire rise_delay, fall_delay, all_delay;
4
5 initial begin
6 $monitor (
122
Verilog Programming Guide
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
124
Verilog Programming Guide
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;
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
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 compares an expression to a series of cases and executes the
statement or statement group associated with the first matching case:
128
Verilog Programming Guide
case ()
.....
endcase
Normal Case
Example- case
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
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.
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
Special versions of the case statement allow the x ad z logic values to be used as "don't
care":
131
Verilog Programming Guide
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
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
134
Verilog Programming Guide
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
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
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 loop executes continually, the loop never ends. Normally we use forever
statements in initial blocks.
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
The repeat loop executes < statement > a fixed < number > of times.
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 executes as long as an < expression > evaluates as true. This is the same
as in any other programming language.
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 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 >
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/////////////////////////////////////////
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 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
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.
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
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
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
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
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.
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.
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
• Delay controls.
• Edge-Sensitive Event controls.
• Level-Sensitive Event controls-Wait statements.
• Named Events.
151
Verilog Programming Guide
Delay Controls
Example - clk_gen
Simulation Output
152
Verilog Programming Guide
Waveform
syntax : @ (< posedge >|< negedge > signal) < statement >;
153
Verilog Programming Guide
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
155
Verilog Programming Guide
Delays execution of the next statement until < expression > evaluates to true
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
Simulator Output
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
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.
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
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
161
Verilog Programming Guide
Waveform
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
These return the current simulation time as a 64-bit integer, a 32-bit integer, and a real
number, respectively.
$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
$random
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 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
Examples
Declaration
Here [7:0] is the memory width and [0:255] is the memory depth with the following
parameters:
166
Verilog Programming Guide
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);
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
168
Verilog Programming Guide
$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.
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
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.
Example - Arbiter
171
Verilog Programming Guide
Verilog Code
• Encoding style.
• Combinational part.
• Sequential part.
Encoding Style
• 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.
172
Verilog Programming Guide
Binary Encoding
Gray Encoding
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
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.
175
Verilog Programming Guide
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
177
Verilog Programming Guide
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
180
Verilog Programming Guide
181
Verilog Programming Guide
Simulator Output
182
Verilog Programming Guide
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
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
185
Verilog Programming Guide
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
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
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
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.
189
Verilog Programming Guide
N-Input Primitives
The and, nand, or, nor, xor, and xnor primitives have one output and any number of 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
N-Output Primitives
The buf and not primitives have any number of outputs and one 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
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
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
194
Verilog Programming Guide
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
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
196
Verilog Programming Guide
197