Manual Verilog
Manual Verilog
Tutorial
2
Contents
1. Introduction
1. Verilog
2. The Manual
3. Gate Types
2. Lexicography
1. White Space and Comments
2. Operators
3. Numbers
4. Strings
3. DataTypes
1. Nets
2. Registers
3. Vectors
4. Numbers
5. Arrays
6. Tri-state
4. Operators
1. Arithmetic
2. Logical
3. Relational
4. Equality
5. Bitwise
6. Reduction
7. Shift
8. Concatenation and Replication
3
5. System Tasks
1. Output
2. Monitoring a Stimulation
3. Stopping a Simulation
7. Modules
1. Modules
2. Stimulus
8. Ports
1. Port Lists
2. Port Connections
9. Basic Blocks
1. Introduction to Procedural Contructs
2. The initial Block
3. The always Block
4
11. Timing Control
1. Delay Based
2. Event Based
3. Sensitivity (Trigger) List
4. Gates : Information Propagation Delays
12. Branches
1. If-else
2. Case Statement
3. The Conditional Operator
13. Loops
1. Introduction to Looping Constructs
2. While Loop
3. For Loop
4. Repeat Loop
5. Forever Loop
14. Extras
1. Opening Files
2. Writing to a File
3. Closing a File
4. Manipulating Memories Files
15. Appendices
1. Operator Precedance
2. Keywords
3. System Tasks and Functions
4. Nets Types
5. Creating Input Vectors
5
6
1 Introduction
1.2 Forward
This manual is by no means an extensive Verilog manual, it has been written with the
Engineering student in mind. Some features are omitted to allow a simpler introduction.
The manual was initially prepared by Saleem Chauhan and maintained by Gerard M Blair.
While every attempt has been made to validate the information, errors may still exist;
therefore, we offer no guarantees and are grateful for any feedback on the material found
herein.
7
Note the convention of putting the output at the start of the argument list, this is used by the
predefined gates in Verilog, and and throughout this manual.
The buf and not gates each have one input and one or more outputs. The conventional is the
same, the outputs come first and the last argument in the list is the input.
module testgate;
reg b, c;
wire a, d, e;
initial begin
b=1; c=0;
#10 $display("a = %b", a);
end
endmodule
8
2 Lexicography
Verilog, like any high level language has a number of tokens which we will discuss in this
section. Tokens can be comments, delimiters, numbers, strings, identifiers and keywords. All
keywords are in lower case.
Comments
Two types of comments are supported, single line comments starting with // and multiple line
comments delimited by /* ... */. Comments cannot be nested.
It is usually a good idea to use single line comments to comment code and multiple lines
comments to comment out sections of code when debugging.
2.2 Operators
Verilog has three types of operators, they take either one, two or three operands. Unary
operators appear on the left of their operand, binary in the middle, and ternary seperates its
three operands by two operators.
2.3 Numbers
Integers
Integers can be in binary ( b or B ), decimal ( d or D ), hexidecimal ( h or H ) or octal ( o or O ).
Numbers are specified by
1. <size>'<base><number> : for a full description
2. <base><number> : this is given a default size which is machine dependant but at least 32 bits.
3. <number> : this is given a default base of decimal
9
The size specifies the exact number of bits used by the number. For example, a 4 bit binary will
have 4 as the size specification and a 4 digit hexadecimal will have 16 as the size specification
since each hexadecimal digit requires 4 bits.
X and Z values
x represents an unknown, and z a high impedance value. An x declares 4 unknown bits in
hexadecimal, 3 in octal and 1 in binary. z declares high impedance values similarly.
Alternatively z, when used in numbers, can be written as ? This is advised in case expressions
to enhance readability.
Negative numbers
A number can be declared to be negative by putting a minus sign infront of the size. The
minus sign must appear at the start of a number (in all three formats given above), ie. it must
not appear between the size specifier and base, nor between the base and the format
specidications.
Underscore
Underscores can be put anywhere in a number, except the beginning, to improve readability.
Real
Real numbers can be in either decimal or scientific format, if expressed in decimal format
they must have at least one digit either side of the decimal point.
1.8
3_2387.3398_3047
3.8e10 // e or E for exponent
2.1e-9
3. // illegal
10
2.4 Strings
Strings are delimited by " ... ", and cannot be on multiple lines.
11
12
3 Data Types
3.1 Nets
Keywords: wire, supply0, supply1
default value: z
default size: 1 bit
Nets represent the continuous updating of outputs with respect to their changing inputs. For
example in the figure below, c is connected to a by a not gate. if c is declared and initialised
as shown, it will continuously be driven by the changing value of a, its new value will not
have to be explicitly assigned to it.
If the drivers of a wire have the same value, the wire assumes this value. If the drivers have
different values it chooses the strongest, if the strengths are the same the wire assumes the
value of unknown, x.
The most frequently used net is the wire, two others which may be useful are supply0, and
supply1, these model power supplies in a circuit.
3.2 Registers
Keywords: reg
default value: x
default size: 1 bit
The fundamental difference between nets and registers is that registers have to be assigned
values explicitly. That value is held until a new assignment is made. This property can, for
example, be used to model a E-type flip flop as shown in figure below, with corresponding
Verilog code given below.
13
module E_ff(q, data, enable, reset, clock);
output q;
input data, enable, reset, clock;
reg q;
endmodule
module stimulus;
reg data, enable, clock, reset;
wire q;
initial begin
clock = 1'b0;
forever #5 clock = ~clock;
end
initial begin
reset = 1'b0;
#10 reset = 1'b1;
data = 1'b1;
#20 enable = 1;
#10 data = 1'b0;
#10 data = 1'b1;
14
#10 enable = 0;
#10 data = 1'b0;
#10 data = 1'b1;
#10 enable = 1;
#10 reset = 1'b0;
#30 $finish;
end
initial
$monitor($time, " q = %d", q);
endmodule
EXERCISE
Consider the stimulus above and predict the output for q. Then stimulus and check your answer.
3.3 Vectors
Both the register and net data types can be any number of bits wide if declared as vectors.
Vectors can be accessed either in whole or in part, the left hand number is always the most
significant number in the vector. See below for examples of vector declarations.
It is important to be consistant in the ordering of the vector width declaration. Normally the
most significant figure is written first.
15
3.4 Numbers
Integers
Keywords: integer
default value: x
default size: dependant on the host machine, but at least 32 bits
Integers are similar to registers but can store signed (i.e. negative as well as positive numbers)
whereas registers can only store positive numbers.
Real numbers
Keywords: real
default value: x
default size: again host machine dependant, but at least 64 bits
Real numbers can be in decimal or scientific format as shown in the example below. When
written with a decimal point, there must be at least one number on either side of the point. A
real number is converted to an integer by rounding to the nearest integer.
real pedantic_pi;
integer relaxed_pi;
initial begin
pedantic_pi = 3.141596259;
relaxed_pi = pedantic_pi; // relaxed_pi is set to 3
end
An arithmetic operation is treated differently depending on the data type of the operand. A
register operand is treated as an unsigned value and an integer value is treated as a signed
value. Therefore if a negative value, such as -4'd12, is assigned to a register, it will stored as a
positive integer which is its 2's complement value. So when used as an operand the 2's
complement value will be used causing unintentional behaviour. If stored in an integer, the
behaviour would be as expected, using signed arithmetic.
16
3.5 Arrays
Registers, integers and time data types can be declared as arrays, as shown in the example
below. Note the size of the array comes after the variable name in the declaration and after the
variable name but before the bit reference in an assignment. So :-
declaration: <data_type_spec> {size} <variable_name> {array_size}
reference: <variable_name> {array_reference} {bit_reference}
Memories
Memories are simply an array of registers. The syntax is the same as above, we will discuss
modelling RAM and ROM using memories in a later section.
It is always good practice to use informative names like mem16_1024 to help keep track of
memories.
EXERCISE
Instantiated a 2k memory of 8 bit elements.
3.6 Tri-state
A tri-state driver is one which will output either HIGH, LOW or "nothing".
In some architectures, many different modules need to be able to put data onto (to drive) the
same bus, at different times. Thus they all connect to the one common bus - but a set of
control signals seek to ensure that only one of them is driving a signal at any one time.
In Verilog, this is modelled using different signal "strengths". There is a signal value: z,
which is called "high-impedance". This basically means that a node is isolated, that is not
driven. It is possible to assign this value to a net.
Normally if two values are simultaneously written to a net, the result is unknown: x; however,
if a driven value is also assigned to the same net as a high-impedance value, the driven value
will over-ride the z. This is the basis for the following tri-state driver:
17
module triDriver(bus, drive, value);
inout [3:0] bus;
input drive;
input [3:0] value;
endmodule // triDriver
When the drive signal is high, the bus is driven to the data value, otherwise, this driver
outputs only a high-impedance and hence can be over-ridden by any other driven value.
NOTE: the bus is a wire and is designated as an inout variable on the port declarations.
The following example shows the effect of several control combinations on three tri-state
buffers:
module myTest;
wire [3:0] bus;
reg drive0, drive1, drive2;
integer i;
initial begin
for (i = 0; i < 12; i = i + 1) begin
#5 {drive2, drive1, drive0} = i;
#5 $display ($time," %b %b %d", i[2:0], bus, bus);
end
$finish;
end // initial begin
endmodule // myTest
giving output:
10 000 zzzz z
20 001 0001 1
30 010 1111 15
40 011 xx11 X
50 100 0000 0
60 101 0x0x X
70 110 xxxx x
80 111 xxxx x
90 000 zzzz z
100 001 1001 9
110 010 1111 15
120 011 1x11 X
18
4 Operators
module arithTest;
reg [3:0] a, b;
initial begin
a = 4'b1100; // 12
b = 4'b0011; // 3
end
endmodule // arithTest
The unary operators are plus and minus, and have higher precedance than binary operators.
Note If any bit of an operand is unknown: x, then the result of any arithmetic operation is also
unknown.
19
module logicalTest;
reg [3:0] a, b, c;
initial begin
a = 2; b = 0; c = 4'hx;
endmodule // logicalTest
EXERCISE
What do the following evaluate to ?
a) !(67)
b) 0 && 1;
c) 1 || 2;
d) 0 || (1 &&1) || !1
e) What value of gamma is displayed if the following module is run ?
module testlogical;
integer alpha, beta, gamma;
initial begin
alpha = 1'b0;
beta = 1'b0;
gamma = 1'b0;
alpha = !beta;
gamma = alpha || beta;
$display("gamma = %d", gamma);
end
endmodule // testlogical
20
module relatTest;
reg [3:0] a, b ,c, d;
initial begin
a=2;
b=5;
c=2;
d=4'hx;
EXERCISE
How many times will the following while loop execute ?
module relatTest2;
reg [3:0] a, b ,c, d;
initial begin
a = 1;
b = 4;
c = 0;
while (b >= c)
if (b > a) c = c + 1;
$display(c);
end
endmodule // relatTest2
4.4 Equality
keysymbols: ==, !=, ===, !==.
The equality operators are logical equality, logical inequality, case equality and case
inequality. These operators compare the operands bit-by-corresponding-bit for equality.
The logical operators will return unknown if "significant" bits are unknown or high-
impedence (x or z)
The case operators look for "equality" also with respect to bits which are unknown or high
impedence.
If one operand is shorter than the other, it is expanded with 0s unless the most significant bit
is unknown.
21
module equTest;
reg [3:0] a, b ,c, d, e, f;
initial begin
a = 4; b = 7; // these default to decimal bases
c = 4'b010;
d = 4'bx10;
e = 4'bx101;
f = 4'bxx01;
$displayb(3'b101 != 3'b010);
$displayb(4'b0001 == 4'b1);
$displayb(4'b101x == 4'b101x);
$displayb(4'b101x === 4'b101x);
module bitTest;
reg [3:0] a, b ,c;
initial begin
a = 4'b1100; b = 4'b0011; c = 4'b0101;
end
endmodule // bitTest
22
EXERCISE
$displayb(~2'b01);
$displayb(4'b1010 ^ 4'b10);
$displayb(4'bx | 1'b1);
module reductTest;
reg [3:0] a, b ,c;
initial begin
a = 4'b1111;
b = 4'b0101;
c = 4'b0011;
endmodule // reductTest
Note: the bitwise xor and xnor are useful in generating parity checks.
Please note carefully the differences in logical, bitwise and reduction operators. The symbols for bitwise
and reduction overlap but the number of operands is different in those cases.
EXERCISE
What do the following evaluate to ?
$displayb(& 1'b10);
$displayb(| 3'b101x);
$displayb(^ 4'b1101);
23
4.7 Shift Operator
Keysymbols: >>, <<.
The shift operators are shift left and shift right. The shift operator takes a vector and a number indicating
the shift. The empty bits caused by shifting are filled with zeros. See examples below.
module shiftTest;
reg [3:0] a;
initial begin
a = 4'b1010;
endmodule // shiftTest
This operator is useful in modelling shift registers, long multiplication algorithms, etc.
EXERCISE
What does the following evaluate to ?
4.8 Concatenation
keysymbols: {, }
The concatenation operator appends sized nets, registers, bit select, part select and constants.
module concatTest;
reg a;
reg [1:0] b;
reg [5:0] c;
initial begin
a = 1'b1;
b = 2'b00;
c = 6'b101001;
end
endmodule // concatTest
24
4.9 Replication
Replication can be used along side concatenation to repeat a number as many times as
specified, see example below.
module replicTest;
reg a;
reg [1:0] b;
reg [5:0] c;
initial begin
a = 1'b1;
b = 2'b00;
endmodule // replicTest
According to the IEEE standard, replication and concatenation can be combined as in: c =
{4{a}, b} however, the current software at Edinburgh University does not allow this.
EXERCISE
What does d evaluate to in the following ?
module replicTest2;
reg a;
reg [1:0] b;
reg [3:0] c;
reg [9:0] d;
initial begin
a = 1'b1;
b = 2'b01;
c = {4{a}};
d = {b, c, b};
$displayb(d);
end
endmodule // replicTest2
25
26
5 System Tasks
For certain routine operations Verilog provides system tasks. all such tasks are in the form
$keyword. In this section we will discuss writing to output, monitoring a simulation and
ending a simulation.
$display("Hello Dr Blair");
--- output: Hello Dr Blair
counter = 4'b10;
$display(" The count is %b", counter);
--- output: The count is 0010
The formatting syntax is similar to that of printf in the C programming language. For
$display and $display, they are:
-------------------------------------------
| Format Specifications |
-------------------------------------------
| Format | Display |
| -------- | ---------------------------- |
| %d or %D | Decimal |
| %b or %B | Binary |
| %h or %H | Hexadecimal |
| %o or %O | Octal |
| %m or %M | Hierarchical name |
| %t or %T | Time format |
| %e or %E | Real in scientific format |
| %f or %F | Real in decimal formal |
| %g or %G | Real in shorter of above two |
-------------------------------------------
The escape sequence for printing special characters are:
--------------------
| Escape Sequences |
--------------------
| \n | newline |
| \t | tabulate |
| \\ | print \ |
| \" | print " |
| %% | print % |
--------------------
27
$write is identical to $display except it does not automatically put a newline at the end of its
output.
EXERCISE What does $display without any arguments output? What does that tell you about
$write?
If the formatting character is omitted, the various commands default as below:
---------------------------
| Default Format Specs |
---------------------------
| Task | Default |
| --------- | ----------- |
| $display | decimal |
| $displayb | binary |
| $displayh | hexadecimal |
| $displayo | octal |
| $write | decimal |
| $writeb | binary |
| $writeh | hexadecimal |
| $writeo | octal |
---------------------------
Thus
$write(5'b01101);
$writeb(" ", 5'b01101);
$writeh(" ", 5'b01101);
$writeo(" ", 5'b01101,"\n");
produces:
13 01101 0d 15
28
module myTest;
integer a,b;
initial begin
a = 2;
b = 4;
forever begin
#5 a = a + b;
#5 b = a - 1;
end // forever begin
end // initial begin
initial begin
$monitor($time, " a = %d, b = %d", a, b);
end // initial begin
endmodule // myTest
will output:
0 a = 2, b = 4
5 a = 6, b = 4
10 a = 6, b = 5
15 a = 11, b = 5
20 a = 11, b = 10
25 a = 21, b = 10
30 a = 21, b = 20
35 a = 41, b = 20
initial begin
clock = 1'b0;
... // whatever you want to be doing
#200 $stop // this will suspend the simulation and put it in
// interactive mode
#500 $finish // this will end the simulation alltogether.
end
29
30
6 Large Worked Example: Multiplexor
In this section we will work through a Verilog design line by line. This section is for those
who want to jump ahead and get a full flavour of the language before learning all the nitty
gritty.
The example program will be a 4 to 1 multiplexor and will be implemented using three
method, each a higher level of abstraction than the last.
31
6.2 Gate Level Implementation.
Here is the gate level implementation of the given multiplexor.
output out;
input in1, in2, in3, in4, cntrl1, cntrl2;
wire notcntlr1, notcntrl2, w, x, y, z;
or (out, w, x, y, z);
endmodule
Now we break up the code and go through it line by line.
The first line of any module description is the keyword module followed by the module name
by which it can be referenced. Then the port list, this is all that can be seen from outside the
module. The order of the port list is conventionally output first.
The line is ended with a semicolon, this may seem strange to C programmers but is required
in Verilog.
output out;
input in1, in2, in3, in4, cntrl1, cntrl2;
All the ports in the port list must be declared as input, output or inout, these are then assumed
to be wire data types unless declared otherwise. When declared as wire Verilog expects a
implicit assignment to the output and values to be driven into the inputs by an external
module.
This declares the internal wires, these represent connections between hardware elements.
Values are driven onto them by the output of the devices to whicih they are connected.
32
If you look are the logic diagram, it is clear what is happening here. This is a description of a
not gate, the output is notcntrl1 and the input is cntrl1. Note the gate has no name, naming is
not compulsory for predefined gates provided by verilog. Earlier we said that a value will be
driven into notcntrl1, this is what the not gate does; everytime the value of the input, cntrl1
changes, the value of notcntrl1 is updated automatically.
or (out, w, x, y, z);
These drive the values into w, x, y and z respectively in the same way described above. The
connections in the logic diagram can be used to verify the connection are correct. Note: each
line ends with a semicolon (;).
endmodule
The end of a module is indicated by the keyword endmodule.
This is a higher level of abstraction than the gate level description, it is still fairly
unintelligible, we will see it becoming more and more intelligible as we move up levels of
abstractions in the following sections.
The first few lines must stay the same so any module which is accessing the multiplexor does
not have to change, ie. the communication stays the same.
33
This is a continuous assignment to the wire out. It is reevaluated and assigned to out
everytime any of the operands change.
The first three lines are the same as in the previous section.
But now we have out defined as a register, this is because we are going to assign values to it
explicitly and not drive them, this is called procedural assignment. A wire data type cannot be
assigned to explicitly, it must have its value driven into it by a device (eg. another module, a
gate, etc), called continuous assignment
If this is read as it is written, " always at [a change in] (in1 or in2 or...." it is clear what is going
on. This is a construct containing statements which are only executed when any of the variables
in the list of variables change. The list of variables is called the sensitivity list, because this
construct is sensitive to their change. The keyword are always @( expr or expr ... );
34
This is a case statement indicated by the keyword case, it is similar to the case statement in C.
The conditional is ({cntrl2,cntrl1}), the concatenation of cntr2 and cntr1 into a 2-bit number.
The test values are 2'b00 etc, and the actions are out= in1; etc. It has a default if none of the
tests are met, and ends with a endcase.
Note the difference in procedural and continuous assignments, here the control signals are
tested and out is assigned a value accordingly.
endmodule
Below is the stimulus for the multiplexor examples given in the previous sections, the same
stimulus can be applied to each of the designs above since they look the same externally and
are performing the same function, only in different ways.
module muxstimulus;
reg IN1, IN2, IN3, IN4, CNTRL1, CNTRL2;
wire OUT;
initial begin
IN1 = 1; IN2 = 0; IN3 = 1; IN4 = 0;
$display("Initial arbitrary values");
#0 $display("input1 = %b, input2 = %b, input3 = %b, input4 = %b\n",
IN1, IN2, IN3, IN4);
35
{CNTRL1, CNTRL2} = 2'b11;
#1 $display("cntrl1=%b, cntrl2=%b output is %b", CNTRL1, CNTRL2, OUT);
end
endmodule
module muxstimulus;
This is a top level module it, ie. nothing else calls it to use its functionality, so it doesn't need
a port list. The keyword module remains and the module name should be chosen to to
indicate that it is a stimulus module.
Remember the inputs to the multiplexor are in1, in2, in3, in4, cntrl1 and cntrl2; and the output
from the multiplexor is out. The idea of the stimulus is to apply artificial stimulus to the
inputs and see what values are assigned to out by the multiplexor4_1 module.
So we want to be able to assign values to the inputs and values to be driven into the output. It
follows that the inputs must be reg data types and the output must be a wire.
initial begin
IN1 = 1; IN2 = 0; IN3 = 1; IN4 = 0;
$display("Initial arbitrary values");
#0 $display("input1 = %b, input2 = %b, input3 = %b, input4 = %b\n",
IN1, IN2, IN3, IN4);
The main part of the simulation is enclosed in the construct initial begin ... end. This is a way
of grouping statements which may run concurrently, since there is only one initial block in
this example, its use is not fully illustrated.
36
First the inputs are assigned arbitrary values and these are displayed using $display. Note the
#0 before the display statement. This is to ensure that the display is made after the assignment
of values to the input. The assignments are made at simulation time 0, putting a #0 ensures
that the $display is executed at the end of the 0 time slice. The execution of an assignment
using = is always in the order given so these don't have to be time controlled.
The syntax of the $display is similar to that of printf in C,
$display( expr1, expr2, ...., exprN); exprN can be variables, expressions or quotes strings.
The first line is an assignment to the control signals and is the same as saying
CNTRL1 = 0;
CNTRL2 = 0;
The concatenation operator { } can be used to make group assignments. The number of bits in
the assignment must be the same as the number of bits in the variables.
Now that the inputs and control signals have values multiplexor4_1 module will drive a value
into out. We want to test whether this value is the one we expect so we can check it using
$display.
end
endmodule
In the same way the values of the control signals are changed and the value of the output is
checked via the display.
Note the $display statements have a delay associated with them, the first is delayed by 1 time
unit, the second by 1 after that (ie. 2 units from the start of the simulation). This is to ensure
the displays are delayed until the correct values have been assigned to the control signals.
This test file does not fully exercise the multiplexor, but it is a good initial check.
37
38
7 Design Blocks
7.1 Modules
The E-type flip flop is made of a D-type flip flop, an inverting multiplexor and a nor gate. We
see this hierarchy in the figure below. We can break the mutliplexor down further but this
level of detail is sufficient for this section.
There are two angles to approach the design of the E-type flip flop in Verilog:
Topdown- start with the E-type flip flop and add more detail.
Bottom up- start with the basic flip flop an inverting multiplexor and a nor gate, and build up,
ie generalise the detail.
We will use a bottom up methodology, but typically a combination of both is used.
We start with the D-type, it is encapsulated as a module, enclosed in the keywords
module <module_name> ... endmodule, as below.
39
The top level E-type will use the functionality enclosed in the D-type and the multiplexer. To
call a module we have to call it by name and give it another name by which it will be known
in the higher level module.
To instantiate, ie. call and use, a users defined modue we use the syntax
name_of_module instance_name (port_list);
7.2 Stimulus
To test whether modules we have written are doing what we intended them to, we have a way
of applying stimulus to the inputs and checking whether the outputs correspond. This is called
a stimulus module. The syntax is exactly the same as the modules seen already, but a stimulus
module does not have a port list because it has no input and explicit outputs. We would like to
apply waveforms to the clock, enable and reset to see how the output of the module
e_ffbehaves
module e_ffStimulus;
reg data, enable, reset, clock;
wire q;
initial begin
clock = 1'b0;
forever clock = #5 ~clock;
end
initial begin
enable = 1'b0; // initialize enable variable
reset = 1'b1; // the E type has an active high reset, so
#20 reset = 1'b0; // we begin by resetting.
data = 1'b1; // set the data HIGH
#10 enable = 1'b1; // and then enable data latching
#10 data = 1'b1; // change the data value
#20 data = 1'b0; // change the data value
#30 data = 1'b1; // change the data value
#10 data = 1'b0; // change the data value
#10 data = 1'b1; // change the data value
#20 enable = 1'b0; // disable data latching
#10 data = 1'b0; // change the data value - no effect?
#10 reset = 1'b1; // reset again
#20 $finish; // finally we must end the simulation using
end // $finish this also stops the clock
40
initial begin
$display($time, " reset, enable, data, q ");
$display($time, " %d %d %d %d",
reset, enable, data, q);
forever #10 $display($time, " %d %d %d %d",
reset, enable, data, q);
end
endmodule // e_ffStimulus
EXERCISE
a) Run the stimulus using, cut and paste, with the code from the previous section - interpret
the output
b) Write a single behavioural module for the E-type flipflop and test it using the above
stimulus
41
42
8 Ports
Ports provide a means for a module to communicate through input and output. Let us go back
to the E-type flip flop example given in the previous section. The input/ ouput of the D-type
relative to the E-type is shown below.
43
8.2 Connection Rules
We will talk of two type of modules, the outer and inner modules, as an analogy the outer
module is the E-type and the inner module is the D-type. It might be useful to take a look at
the section on modules to understand this.
8.2.1 Inputs
In an inner module inputs must always be of a net type, since values will be driven into them.
In the outer module the input may be a net type or a reg.
8.2.2 Outputs
In an inner module outputs can be of a net type or a reg. In an outer module the output must
be of a net type since values will be driven into them by the inner module.
8.2.3 Inouts
Inouts must always be of a net type.
Connecting Ports
Ports can be connected by either ordered list or by name. The ordered list method is
recommended for the beginner, in this method the port list in the module instantiation is in the
same order as in the module definition. See example below.
44
The second method is by name, when instantiating, the ports in the definition are
accompanied by the corresponding port name in the instantiation. EXERCISE
a) Draw a diagram for your own reference illustrating the constraints on the input, output and
inouts.
b) Using the module interfaces for the d_ff and the e_ff modules above, write code to
complete them AND a toggle flip-flop: t_ff, based upon a call to the e_ff module. The
function of the toggle flipflop is to either change its output or to hold its output on each new
rising clock edge according to a control signal: toggle. It should also have a synchronous
reset.
45
46
9 Basic Blocks
initial
clock = 1'b0; // variable initialization
initial
begin // multiple statements have to be grouped
alpha = 0;
#10 alpha = 1; // waveform generation
#20 alpha = 0;
#5 alpha = 1;
#7 alpha = 0;
#10 alpha = 1;
#20 alpha = 0;
end;
47
EXERCISE
a) Note that the first initial block in the example does not contain the keywords begin and
end. Why is this ?
module pulse;
reg clock;
endmodule
EXERCISE
Using the initial and always constructs describe the wave for the following.
reg clock;
reg [1:0] alpha;
48
49
10 Large Worked Example: The Binary
counter
50
10.2 Gate level Description: Binary Counter
Basic Code
and a1(t1, increment, q[0]); // increment signals are derived from the
and a2(t2, t1, q[1]); // the previous increment signal by and-ing
and a3(t3, t2, q[2]); // with the output form the previous
//ET-type
endmodule // counter4_bit
endmodule // et_ff
endmodule // mux
51
module dff(q, data, reset, clock);
output q;
input data, reset, clock;
reg q;
endmodule
endmodule // recog12
module stumulus;
wire [3:0] q;
reg [3:0] d;
reg load_data, global_reset, clk, increment;
initial begin
global_reset = 0;
clk = 0;
increment = 0;
load_data = 0;
d = 4'b0100;
#10 global_reset = 1;
#20 global_reset = 0;
#20 load_data = 1;
#20 load_data = 0;
#20 increment = 1;
#200 global_reset = 1;
#20 global_reset = 0;
#50 load_data = 1;
#20 load_data = 0;
#10 increment = 0;
#20 $finish;
end // initial begin
endmodule // stimulus
52
Break down
The first line is the start of the module, declaring the name and the port list. The output is q
and there other signals are all inputs. t1, t2, t3, see12 and reset are all declared as internal
wires which connect the various gates/sub-modules within the module.
There are 4 Enable/Toggle flip flops in the logic diagram, each of which is instatiated here.
Note each instantiation has a name. q.
The increment signal is anded with the output from the last E-T flipflop to assert the toggle
signal for the next E-T flipflop; this can be seen in logic diagram.
Everytime q changes the value of see12 is updated; when it reaches 12, the internal reset
signal is raised by the or gate and the flipflops will all be reset on the next rising clock edge.
53
10.3 Behavioural Model
In the previous section we saw the gate level description of a binary counter, now we will
implement the same counter using a behavioural description. It uses the same stimulus
module but is a lot easier to understand and modify.
reg [3:0] q;
endmodule // counter4_bit
It would be a good idea to compare the port declarations of both implementations at this point and see
the similarities. The only difference is that the output q is now also declared as a register. EXERCISE
why?
EXERCISE Using the stimulus defined in the gate-level description, simulate the behavioural
model and verify that the same (correct ?) results are obtained.
This implementation is a lot easier to update than the previous gate level implementation.
Circuits are thus normally written in this form and reduced to gate level descriptions by
Verilog applications (ie synthesis).
To convert the above into a down counter, all we need to do is changed the + sign in the third
if to a - and alter the "end" condition so that 0 is followed by 12. Because of this, it is
convenient to make the "global_reset" condition equal to 12 also. While this is not necessary
for the Verilog behavioural code, it simplifies the gate level implementation [why?].
54
// 4-bit binary down-counter - of period 13
module counter4_bit(q, d, decrement, load_data, global_reset, clock);
endmodule
Up-Down counter
If a counter has a period which is a power of two, it is simpler to design since the counter
"wraps round" and the 'end" condition does not need to be explicitly detected. Thus for a four
bit register, 15 + 1 = 0 and 0 - 1 = 15.
Below is the code for a 4-bit counter (with period 16) which can either count up or down
according to an extra input signal.
endmodule
55
56
11 Timing Control
There are three types of timing control, delay based, event based and level sensitive. We will
discuss the useful aspects of each in turn.
11.1 Delay-Based
Syntax: timing_control_statement::== delay_based statement*
delay_based::== # delay_value
This method introduces a delay between when a statement is encountered and when it is
executed.
initial begin
a = 0; // executed at simulation time 0
#10 b = 2; // executed at simulation time 10
#15 c = a; // ... at time 25
#b c = 4; // ... at time 27
b=5; // ... at time 27
end
The delay value can be specified by a constant or variable. Note the time is not in seconds, it
is relative to the current unit of time. A common example is the creation of a clock signal:
initial begin
clock = 1'b0;
forever #5 clock = ~clock;
end
This will make the clock flip every 5 time units giving a wave form as shown.
EXERCISE
In the following module what would be the values of
a) a at time 15 units;
b) b at 17 units
c) c at 18 units
d) a at 30 units
57
module testdelay(a, b, c);
output [3:0] a, b, c;
reg [3:0] a, b, c;
initial begin
#10 a = 3;
#5 b = 4;
#6 c = 5;
#8 a = a + b;
end
endmodule
11.2 Event-Based
Syntax:
event_control_statement::==
@ event_identifier
| @ (event_expression)
event_expression::==
| exp
| event_id
| posedge exp
| negedge exp
| event_exp or event_exp.
Event-based timing control allows conditional execution based on the occupance of a named
event. Verilog waits on a predefined signal or a user defined variable to change before it
executes a block.
Triggers
Triggers can be understood from the following example.
This can be read as: at every negative clock edge, check if data[8] is 1, if so assert data_in.
When data_in is asserted, the statement if the second always is executed.
58
11.3 Sensitivity List
Syntax: event_list_statement::==
@ (event_exp or event_exp)
event_exp::==
(event_exp or event_exp).
If we wish to execute a block when any of a number of variables change we can use the
sensitivity list to list the triggers seperated by or
A change in any of the variables will cause execution of the second statement. As you can see
this is just a simple extention to the idea of event based timing control described in the
previous section.
delay_exp::==
# delay_time
This type of delay is only associated with the primitive gates defined within Verilog.
59
60
12 Branch Statements
12.1 The if statement.
Syntax: if (conditional_expression) statement{ else statement}
The if statement causes a conditional branch. If the conditional expression evaluates to true
the first statement or set of statements is executed, else the second statement or set of
statements is executed, ( the syntax is very similar to that of pascal). To group statements use
the keywords begin... end
To illustrate the use of an if statement consider the 4 to 1 multiplexor in figure A,
implemented using a logic equation in example B and using an if statement in example C.
assign out = (~cntrl2 & ~cntrl1 & in1) | // The output is in1 when both
( cntrl2 & ~cntrl1 & in2) | // cntrls are low, etc.
(~cntrl2 & cntrl1 & in3) |
( cntrl2 & cntrl1 & in4) ;
// Note this is a continous assignment, if an operand on the right
// hand side changes, the left hand side will reflect the change.
endmodule
61
Example B : Above : Implementation of a 4 to 1 multiplexor using a logic equation.
endmodule
Example C : Above : Implementation of a 4 to 1 multiplexor using a if statement.
EXERCISE
Write the stimulus block for the above multiplexor, you will have to show that the correct
input is selected according to the values of the control bits.
62
The stimulus block is the same as the one for the above multiplexor descriptions.
Variants of the case statement are casez and casex. Whereas the case statement compares the
expression to the condition bit by bit, insuring the 0, 1, x, and zs match, the casez treats all the
zs in the condition and expression as ?s, ie irrelevants. The casex similarly treats all the xs
and zs as ?s. These alteratives, if not used carefuly and sparingly can easily lead to bugs.
EXERCISE
What is the output from the following:
module testCase(value);
input [4:0] value;
always @(value)
casez (value)
5'b010zx : $display("%b: Matched OK", value);
default : $display("%b: Did not match", value);
endcase // casez (value)
endmodule // testCase
module runTest;
reg [4:0] value;
initial begin
#10 value = 5'bzz01x;
#10 value = 5'bxxxzx;
#10 value = 5'b010xz;
#10 value = 5'bzzz0z;
#10 $finish;
end // initial begin
endmodule // runTest
The true and false expressions can themselves be conditional operators, so enabling more than
one interdependant conditional_expression. Conditional operators can be useful in modelling
conditional data assignment.
63
EXERCISE
Implement a 4 to 1 multiplexor using a nested conditonal operator, making sure it uses the
same simulation block as before
64
13 Looping Constructs
13.1 Introduction
The four looping constructs in Verilog are while, for, repeat and forever. All of these can
only appear inside initial and always blocks.
The basic idea of each of the loops is :
while: executes a statement or set of statements while a condition is true.
for: executes a statement or a set of statements. This loop can initialise, test and increment the
index variable in a neat fashion.
forever: executes a statement or a set of statements forever and ever, or until the simulation is
halted.
module cup_and_jugs;
integer cup, jug;
initial begin
cup = 0; jug = 0;
while (jug < `JUGVOL) begin
jug = jug + `CUPVOL;
cup = cup + 1;
end // while (jug < JUG_VOL)
endmodule // cup_and_jugs
65
Notice the use of the "define" statement.
EXERCISE
How many times does the folowing while loop say hello?
initial begin
a = 5;
c = 0;
while (a != c) begin
$display("Hello");
c = c + 1;
end
end
initial begin
for(index = 0; index < 32; index = index + 1)
list[index] = index + index;
end
EXERCISE Initialise the following memory so that each location contains its own address
plus 24 ie. memory16_256[0] contains 0000000000011000, (24 in decimal).
66
module comply;
int count;
// counting down from 128
initial begin
count = 128;
repeat (count) begin
$display("%d seconds to comply", count);
count = count - 1;
end
end
endmodule
Note: The loop will execute 128 times regardless of whether the value of count changes after
entry to the loop.
EXERCISE
Think of a situation where the for loop would be prefered over a repeat loop.
reg clock;
initial begin
clock = 1'b0;
forever #5 clock = ~clock; // the clock flips every 5 time units.
end
reg clock;
initial begin
clock = 1'b0;
#5 forever clock = ~clock; // the clock flips every 5 time units.
end
67
68
14 Extras
initial begin
handleA = $fopen("myfile.out);
// handleA = 0000_0000_0000_0000_0000_0000_0000_0010
handleB = $fopen("anotherfile.out");
// handleB = 0000_0000_0000_0000_0000_0000_0000_0100
end
Now we can write to any of the opened files. There is a maximum of 31 files open.
69
// using the handles described in the previous section
integer channelsA;
initial begin
channelsA = handleA | 1; // now th 2 MSBs are set to output
$fdisplay(channelsA, "Hello"); // will be to 'myfile' and
standard outut
end
@003
00000011
00000100
00000101
00000110
00000111
00001000
00001001
With the above file it can be seen if the memory is large it would become very tedious to
work out the address of a specific byte, so it is normally a good idea to use milestones along
the memory file, so a larger file may look something like the following:
70
@003
00000011
00000100
00000101
@006
00000110
00000111
@008
00001000
00001001
or if the data is contiguous, omit the address entirely.
Now that a memory file exists to access it, it has to be initialised for memory reading. This
can be done by the following.
module testmemory;
reg [7:0] memory [9:0];
integer index;
initial begin
$readmemb("mem.dat", memory);
1000_0001
1000_0010
0000_0000
0000_0001
0000_0010
0000_0011
0000_0100
0000_0101
0000_0110
0000_0000
71
EXERCISE
Store the above data in a file and run the above programme
Consider and understand the following code (run it to check):
module fileDemo;
initial begin
handle = $fopen("mem.dat");
channels = handle | 1;
$display("Generating contents of file mem.dat");
$fdisplay(channels, "@2");
$fclose(handle);
$readmemb("mem.dat", memory);
endmodule // fileDemo
72
A. Operator Precedence
If no parentheses are used to separate operands then Verilog uses the following rules of
precedence. It is normally a good idea to use parentheses to make expressions readable.
Below is a list of all operators provided by Verilog and their precedence rules.
73
Operator Precedence
-----------------------------------
| Operator | Precedence |
-----------------------------------
| + - ! ~ (unary) | highest |
| * / % | |
| + - (binary) | |
| << >> | |
| < <= > >= | |
| == != === !== | |
| & ~& | |
| ^ ^~ | |
| | ~| | |
| && | |
| || | |
| ?: (conditional) | lowest |
-----------------------------------
74
B. Keywords
Below is a list of keywords provided by verilog in alphabetical order.
always
and
assign
attribute
begin
buf
bufif0
bufif1
case
casex
casez
cmos
deassign
default
defpram
disable
edge
else
end
endattribute
endcase
endfunction
endmodule
endprimitive
endspecify
endtable
endtask
event
for
force
forever
fork
function
highz0
highz1
if
initial
inout
input
integer
join
large
macromodule
meduim
module
nand
negedge
nmos
nor
not
notif0
notif1
or
75
output
parameter
pmos
posedge
primitive
pull0
pull1
pulldown
pullup
rcmos
real
realtime
reg
release
repeat
rtranif1
scalared
signed
small
specify
specpram
strength
strong0
strong1
supply0
supply1
table
task
time
tran
tranif0
tranif1
tri
tri0
tri1
triand
trior
trireg
unsigned
vectored
wait
wand
weak0
weak1
while
wire
wor
xnor
xor
76
C. System Tasks and functions
The following are the system tasks and function provided by Verilog.
$bitstoreal
$countdrivers
$display
$fclose
$fdisplay
$fmonitor
$fopen
$fstrobe
$fwrite
$finish
$getpattern
$history
$incsave
$input
$itor
$key
$list
$log
$monitor
$monitoroff
$monitoron
$nokey
77
78
D. Net Types
The net types provided by Verilog are given below.
supply0
supply1
tri
triand
trior
trireg
tri0
tri1
wand
wire
wor
79
80
E. Verilog Input Vectors
To create input vectors for our simulations, we need only a very small subset of Verilog.
These pages give some examples
initial
begin
clk = 1'b0;
globalReset = 1'b1;
in = 1'b1;
end
The expression: 1'b0 indicates a binary number of value 0. In fact, for setting the values zero
and one, you need only type 0 and 1.
There are two main sections:
initial
begin
-----
end
always
begin
-----
end
Notice that "blocks" of code in Verilog are "bracketed" by the keywords begin and end - in C
this is done by "{" and "}".
The initial block is started at the beginning of the simulation. Thus it is the place to initialize
signals and to define a sequence of signal changes.
The always clock is a sequence of signals which is repeated throughout the simulation.
The delay between signal changes (or events) is specified by a number following a # sign.
Thus:
#160 globalReset = 0;
#160 in = 0;
#160 in = 1;
#320 in = 0;
says: wait 160 time units and set globalReset to zero, then wait 160 time units and set the in to
zero, then etc
Notice that the delay is measured from the last event rather than from the beginning of the
simulation.
The most common us of the always block is to define the clock signal. The following:
always
begin
#10 clk = ~clk;
end
81
says that clk should be set to the inverse of the value of clk every 10 time units - which
defines a clock signal of period 20 time units.
Thus the general approach is to setup the clock and other regularly alternating signals in
always blocks and to define the sequence of changing signals in the initial block.
Warning: it is wise to end the initial block with a statement:
#<delay> $finish;
This causes the simulation to finish at the end of the initial block - if this is not present, the
interactive simulation will continue until you press the interrupt button on the interactive
simulator panel (probably long after useful information has been produced).
The repeat command may be useful. If you have a sequence of signal changes with is repeated
for a given number (say 10) times then this can be coded as follows:
repeat(10)
begin
#40 in = 0;
#20 in = 1;
end
{$random} % n
(The smudgy character is the percent sign "%" - which is difficult to read in some netscape
fonts).
The exception is random ones and zeros because some random number generators are not
quite random in the least significant bit (lsb). For this it is necessary to divide the first term by
an even number to remove the lsb before the modulus operation.
{$random} / 16 % 2
Combining these two commands we have the following which is a sequence of 14 random
inputs changing ever 20 time units:
repeat(14)
begin
#20 in = {$random} / 16 % 2;
end
Note:
• every statement (though not the blocks) must end with a ";"
82