You are on page 1of 89

VERILOG

•HDL
•What is Verilog?
•Scope of Verilog
•Basic Concept of Verilog
•Lexical Convention
•Data Types
•System Task
•Modules
•Module instances
•Compiler Directive
•Modules & ports
•Port Declaration
•Various Modelling in Verilog
HDL AND ITS IMPORTANCE

A Hardware Description Language(HDL) is a software programming language


used to model the intended operation of a piece of hardware.
EDA tools are computer based software systems to design Very Large Scale
Integrated circuits.
Now EDA tools are available for almost every stage of VLSI design flow.
Initially we must convey design idea to EDA tool in such a way that the tool is
able to understand that and generate a highly optimized design implementation.
This transfer of idea from human beings to machines is called Design Entry.
There are two methods of design entry: graphical and textual.
Graphical method includes schematic entry and state diagram entry while
textual method implies use of HDL's (Hardware Description Languages).
Graphical method works fairly well up to a certain level of circuit complexity
but in larger circuits they become cumbersome and time consuming.
VLSI Design Flow
HDL’s Advantages
Compact description.
Easy to edit.
Highly portable.
Supports a higher level of abstraction.
Rapid prototyping of design.
Availability of extensive vendor libraries.
Increasing capability of synthesis tools.
LIMITATIONS OF HDLs

No support for analog behavior.


Need to learn coding styles that ensures
synthesizable results.

Support for hardware concurrency and time frame are


two main features that distinguishes HDLs from other
programming languages.
HISTORY OF VERILOG

A CAE software company called Gateway Design


Automation was founded by Prabhu Goel.
One of Gateway’s first employees was Phil Moorby.
In 1983 Gateway released the Verilog Hardware Description
Language known as “Verilog HDL” or simply “Verilog”
together with a Verilog simulator.
In 1989 Cadence bought Gateway.
In 1990 “Open Verilog International”(OVI) was formed to
control the language specification.
In 1995 the Verilog was reviewed and adopted by the IEEE
as IEEE standard 1364.
An upgraded IEEE Standard 1364 – 2001 for Verilog was
released.
DESIGN METHODOLOGY

The most common approach for solving any design


problem is "Divide and Rule".
We divide top block into sub-blocks unless we reach at
cells which cannot be further subdivided and are basic
design elements.
We generally follow top-down approach during design
process, but while implementing our design we start
with basic unit cells we have (e.g. and, or, not,
flip-flops etc.) and build up bigger blocks on these.
These blocks are further used to build bigger blocks
until we build top level block.
This is called bottom-up approach. So a combination of
both top-level and bottom-up approaches is used.
TOP
MODULE

SUB SUB SUB


MODULE MODULE MODULE
1 2 3

cell cell cell Sub Sub cell cell


Module 4 Module5

cell cell cell cell cell


FIRST VERILOG PROGRAM : HALF ADDER

in1
sum
in2

carry

module half_adder(sum, carry, in1,


in2) ;

output sum, carry ;


input in1, in2 ;

xor (sum, in1, in2) ;


and (carry, in1, in2) ;

endmodule
module Module_Name (Port_List) ;

...
...

<Module Internals>

...
...

endmodule
MODULE IN VERILOG
Module is a basic functional unit in Verilog. A module can be
seen as a design block with some inputs and outputs. How
that block works is written inside that module.
All the distinct blocks in design tree corresponds to a module
in Verilog. So module is just like black box with input and
output terminals and that black box interacts with the outside
environment through these terminals only.
The relationship between these input and output terminals is
hidden from the environment.
Every module definition begins with a keyword module and
ends with keyword endmodule.
Only within these two keywords functionality of a module is
specified. Each module has a module name and port list.
Module name is an identifier for that particular module and
port list contains the list of all input and output terminals for
the module.
FULL ADDER

To build a full adder from the half adder defined just now
we have to create an instance of halfadder module in
fulladder module.
This instance is given a name and ports are connected
appropriately.
Certain predefined modules of basic hardware elements
are provided in Verilog and we call them as primitives.
These primitives can be instantiated inside modules in
same way but giving them names is optional.
So a module may contain instances of primitives and
other modules.
Full Adder

carry_in HALF sum


ADDER

a
HALF carry_out
ADDER
b

module full_adder(sum, carry_out, a, b, carry_in) ;

output sum, carry_out ;


input a, b, carry_in ;

wire w1, w2, w3;

half_adder ha1(w1, w2, a, b);


half_adder ha2(sum, w3, w1, carry_in);

or (carry_out, w2, w3);

endmodule
module Module_Name(Port_List) ;
<Port Declarations>
<Internal Signals Declaration>
<Functionality>
endmodule

The port list in module definitions contains names of


ports (terminals) only and we must specify whether they
are input, output or bi-directional terminals. So port
declarations are the first thing we write in module
internals. Ports are declared using Verilog keywords
input, output and inout. Keyword inout is used
for bi-directional ports.
All internal signals between various hardware units
must be assigned some name and declared its type. So
second thing we write in module internals is internal
signal declaration.
Then follows the actual module functionality.
LANGUAGE ELEMENTS
VERILOG ELEMENTS
White space

Blank spaces \b
tabs \t
new lines \n
White spaces have no syntactical significance and can be inserted for
better readability. Whitespace is not ignored in strings.

Comments
// The rest of the line is a comment.

/* Multiple line
comments */

/* Nesting /* comments */ is NOT allowed */


Comments make life easier for you and others also. So insert a lot of
meaningful comments in your code.
OPERATORS

Operators are of three types:


Unary, binary and ternary.
a=~b;
a= b && c;
A=b ? c:d ;
VERILOG ELEMENTS

Signal Values

0 Logic Zero
1 Logic One
x or X Unknown
z or Z High Impedance

Representation of Numbers

Decimal d or D
Hex h or H
Octal o or O
Binary b or B
NUMBER FORMAT

<size> '<radix> <number>


size specifies number of bits to be occupied by number and is written only in
decimal.
radix determines the arithmetic base of number.
number is the value expressed in the indicated base only.

Number #Bits Base Storage


2'b10 2 Binary 10
3'd6 3 Decimal 110
6'o57 6 Octal 101111
3'O4 3 Octal 100
8'H2d 8 Hex 00101101
32'haA19 32 Hex 1010101000011001
5'B110x0 5 Binary 110x0
6'ozz 6 Octal zzzzzz
12'hZXb 12 Hex zzzzxxxx1011
NUMBER FORMATS

If we do not specify the size it takes default value which is machine


and simulation dependent but is at least 32 bits.
Also if we do not specify radix default is decimal base.

Number #Bits Base Storage


'bz >= 32 Binary zz..zzz
'h9 >= 32 Hex 0000..1001
3 >= 32 Decimal 000...011

If the size is greater than the value of number, the number in the
most significant bit is extended for MSB = 0, x or z
zero extended if MSB = 1.

Number #Bits Base Storage


8'bx001 8 Binary xxxxx001
5'o1 5 Octal 00001
15'hzf 15 Hex zzzzzzzzzzz1111
9'd5 9 Decimal 000000101
NUMBER FORMATS

For negative numbers we place a minus sign before the number


representation. Negative numbers are stored as 2's complement.

Number #Bits Base Storage


-6'd3 6 Decimal 111101
-3'b11 3 Binary 101

Underscores can be inserted in numbers to enhance readability and


are ignored by Verilog.

12'b000111010100
12'b000_111_010_100
12'o07_24
IDENTIFIERS

Identifiers are names given to different objects so that they


can be referenced in design. An identifier is any sequence of
letters [A-Z] and [a-z], digits [0-9], underscore [ _ ] and $
character.
Cannot begin with $ or digits and are case sensitive. An
identifier may contain up to 1024 characters.
myid valid
m_y_id valid
3my_id invalid
$myid invalid
_myid4 valid
myid != invaIid
ESCAPED IDENTIFIERS

Escaped Identifiers are special identifiers which can


include any printable ASCII character. An escaped
identifier starts with a backslash[ \ ] and ends with
whitespace.

\5467
\.*.&
\{***}
\a+b-c
\InGate#3
KEYWORDS
Keywords are special words reserved by language, their meaning is
predefined and cannot be used as identifiers. All keywords are in lowercase.

always for pmos supply1


and force posedge table
assign forever primitive task
begin fork pull0 time
buf function pull1 tran
bufif0 highz0 pulldown tranif0
bufif1 highz1 pullup tranif1
case if rcmos tri
casex initial real tri0
casez inout realtime tri1
cmos input reg triand
deassign integer release trior
default join repeat trireg
defparam large rnmos vectored
disable macromodule rpmos wait
edge medium rtran wand
else module rtranif0 weak0
end nand rtranif1 weak1
endcase negedge scalared while
endfunction nmos small wire
endmodule nor specify wor
endprimitive not specparam xnor
endspecify notif0 strength xor
endtable notif1 strong0
endtask output strong1
event parameter supply0
DATA TYPES
Predefined Verilog data types
Nets Registers
(connectivity) (storage)
wire reg
tri integer
wand real
wor time
triand realtime
trior
supply0
supply1
tri0
tri1
trireg
NETS
Nets represent the interconnection between hardware elements. Value of a net
variable is determined throughout the simulation by output of the components they are
connected to (called Drivers). If no driver is connected to a net, the net defaults to a
value of Z. Most commonly used type of net is wire.
module my_ckt (f, a, b, c, d, e);
a n1
output f ;
b
x0 input a, b, c, d, e ;
wire n1;
wire m1, x0, x1 ;
c m1 f …
d …
x1

e
endmodule

In above circuit n1, m1, x0, x1 are nets. They are declared inside module by keyword wire.
Some other type of nets will be discussed later in advance Verilog concepts. Any undeclared nets
default to type wire.
REGISTERS

Register Type Usage


reg Stores a logic value
integer Supports computation
time Stores time as a 64-bit unsigned quantity
real Stores values (e.g. delays) as real numbers
realtime Stores time values as real numbers

Registers are variables that store values. It is an abstraction of a


hardware storage element, but it need not correspond directly to
physical storage elements in a circuit. Registers retain value until
another value is placed onto them.Unlike a net, a register does not need
a driver. A register object may be assigned value within a procedural
statement, a user sequential primitive,task, or function.
reg
The reg kind of register data type is the one most commonly used. A
reg data type models the feature of hardware that allows a logic value to
be stored in a flip-flop or a latch. A reg object may never be the output of
primitive gate or the target of a continuous assignment. The default
value for a reg data type is X.

integer
The integer data type supports numeric computation in procedural code.
Integers are represented internally to the word length of the host
machine (at least 32 bits). A negative number is stored in 2’s
complement format. Registers declared as data types reg store values
as unsigned quantities,whereas integers store values as signed
quantities.
real
Accurate modeling of delay values might require the use of real data
types. Real objects are stored in double precision, typically a 64-bit
value. Real values can be specified in decimal and exponential
notation. An object of type real may not be connected to a port or
terminal of a primitive.Real numbers cannot have a range declaration
and their default value is 0.

time
The data type time supports time-related computations within
procedural code in Verilog models. Time variables are stored as
unsigned 64-bit quantities. A variable of type time may not be used in a
module port; nor may it be an input or output of a primitive. Data type
realtime stores time values in real number format. The system function
$time is invoked to get the current simulation time.
VECTORS
Nets or reg data types can be declared as vectors (multiple bit
widths). If bit width is not specified, the default is scalar (1-bit).
wire conect ;
wire [7:0] dbus ;
wire [0:15] cbus1, cbus2, cbus3 ;
reg clk ;
reg [31:0] accr ;

In vector declaration, the left number in square brackets is


always the most significant bit of the vector.
It is possible to address bits or parts of vector
dbus[6]
cbus2[3:9]
accr[31:16]
dbus = cbus1[2:9];
ARRAYS
Arrays are allowed in Verilog for reg, integer, time data types. Arrays are
not allowed for real variables. Multidimensional arrays are also not
permitted in Verilog
integer count [1:15] ; // 5 integers
reg var [-15:16] ; // 32 1-bit regs
reg [7:0] mem [0:1023] ; // 1024 8-bit regs
reg mda[1:100] [1:100] ; // INVALID

Array element can be accessed by using subscript. Array part-select or


entire array cannot be accessed at once.
mem[10] = 8’b10101010 ;
var[2:9] = 8’b11011101 ; // INVALID
var = 32’d567 ; // INVALID
ARRAYS

An array of regs is called memory e.g.


reg [31:0] cachememory [0:1023] ;

Word Size Memory Name Memory Size

✔ Bit-select and part-select are not valid with memories.


✔ Reference may be made to only a word of memory.
STRING
A string is a sequence of characters that are enclosed by double quotes.
The restriction on a string is that it must be contained on a single line, that
is, without a carriage return. It cannot be on multiple lines. Strings are
treated as a sequence of one-byte ASCII values.
Verilog does not have a distinct data type for strings. Instead, a string must
be stored within a properly-sized register. A properly sized reg (array) has
eight bits of storage for each character of the string that it is to hold. If the
width of the register is greater than the size of the string, Verilog fills bits to
the left of the string with zeroes. If the register width is smaller than the
string width, Verilog truncates the leftmost bits of the string.
reg [8*num_char-1 : 0] string_holder ;
reg [8*12:0] string_val ; // can hold up to 13 characters
string_val = “Hello Verilog” ;
string_val = “hello” ; //most significant bits are filled with 0
string_val = “I am overflowed” ; // “I “ is truncated
STRING

Special characters can be displayed in strings only when they are


preceded by escape characters.

\n newline
\t tab
%% %
\\ \
\” “
CONSTANTS
A constant in Verilog is declared with the keyword parameter, which
declares and assigns values to the constant. The value of a constant
may not be changed during simulation but parameters (or constants)
can be changed at module instantiation or by using the defparam
statement.

parameter high_index = 22 ;
parameter av_delay = (min_delay + max_delay) / 2 ;
parameter initial_state = 8’b1011_1000 ;
GATE LEVEL MODELING
PRIMITIVES
Verilog provides a robust set of built-in gate primitives.
Primitives are like predefined modules. A logic circuit is described on gate
to gate basis using these primitives.
Primitives can be instantiated only within modules and use of identifier
name with primitive instantiation is optional.
The port list of a primitive have output(or outputs) written first, followed by
inputs.

and if any of the input is 0, output is 0


else if any of input is x or z , output is x
else if all inputs are 1, output is 1

nand if any of the input is 0, output is 1


else if any of input is x or z , output is x
else if all inputs are 1, output is 0
or if any of the input is 1, output is 1
else if any of input is x or z , output is x
else if all inputs are 0, output is 0

nor if any of the input is 1, output is 0


else if any of input is x or z , output is x
else if all inputs are 0, output is 1
xor if any of the input is x or z, output is x
else if odd number of inputs are 1, output is 1
else output is 0

xnor if any of the input is x or z, output is x


else if even number of inputs are 1, output is 1
else output is 0
We can instantiate multiple primitives of same type by a single
statement using comma-separated lists e.g.
nand G1(y1, a1, a2, a3), (y2, b1, b2, b3), M2(d3, e1, e2);

Verilog gate level description of a and-or-invert logic gate


module AOI(out, in1, in2, in3, in4) ;
output out ;
input in1, in2, in3, in4 ;
wire y1, y2 ;

and (y1, in1, in2) ;


and a1(y2, in3, in4) ; in1
in2 y1
nor (out, y1, y2);
out
endmodule
in3 y2
in4
DATAFLOW MODELING
DATA FLOW
Data flow modeling describes the design in terms of expressions
instead of primitive gates. A continuous assignment statement is the
most basic statement in the dataflow modeling. It is used to assign a
value to a net. It starts with the keyword assign followed by actual
assignment e.g.
assign A = x | (Y & ~Z) ;
assign B[3:0] = 4’b10xx ;
assign C[15:0] = F[15:0] ^ E[15:0] ;

Left hand side of the assignment must be nets(scalar or vector), but


right hand side expression can have registers, nets or function calls as
operands.
The continuous assignment statement are continuously active and they
all execute in parallel. Whenever value of any operand on right side
changes expression is reevaluated and new value is assigned to the
corresponding net.
DATA FLOW (CONTD..)

Continuous assignments can be made implicitly by associating the right


hand side expression with the declaration of target net e.g.
Instead of
wire cout ;
assign cout = cin1 + cin2 ;
we can write
wire cout = cin1 + cin2 ;
Multiple assignments can be made with one assign keyword using
comma-separated lists e.g.
assign y1 = a1 ^ a2, y2 = a2 | a3, y3 = a1 + a3 ;
assign data = s[3:0] + r[5:2], m = a & g ;

Verilog dataflow style description of a 1-bit full adder


module f_add_1bit ( sum, cout, a, b, cin) ;
output sum, cout ;
input a, b, cin ;

assign sum = a ^ b ^ cin ;


assign cout = (a & cin) | (b & cin) | (a & b) ;

endmodule
OPERATORS

Verilog has a robust set of built-in operators that


manipulate the various types of data implemented in the
language to produce values on nets and registers.
Some of the operators are used within expressions on
right-hand side of continuous assignment statements and
procedural statements; others are used in Boolean
expressions in conditional statements or with conditional
operators.
https://www.chipverify.com/verilog/verilog-operators
OPERATORS continued…..
Functional Group Operator Name
Logical && logical and
|| logical or
! Logical not
Bitwise & bitwise and
| bitwise or
~ bitwise not
^ bitwise xor
~^ or ^~ bitwise xnor

Shift >> right Shift


<< left Shift
OPERATORS continued…..
Functional Group Operator Name

Reduction & reduction and


~& reduction nand
| reduction or
~| reduction nor
^ reduction xor
~^ or ^~ reduction xnor

Concatenation { } concatenation
{ { } } replication

Relational > greater than


< less than
>= greater than or equal to
<= less than or equal to
OPERATORS continued…..
Functional Group Operator Name
Equality == equality
!= inequality
=== case equality
!== case inequality
Conditional ?: conditional

Arithmetic + add
- subtract
* multiply
/ divide
% modulus
LOGICAL OPERATORS

&& - logical AND


|| - logical OR
! - logical NOT
Logical operators evaluates to one bit value 0, 1, or x. These operators gives result on the
basis of logical values of operands I.e.
If operand has zero value, it is taken as logical false (0)
If operand has non-zero value, it is taken as logical true (1)
If a bit in any of the operand is x or z, whole operand is treated as x

A = 6 A && B 1 && 0 0
B = 0 A || (!B) 1 || 1 1
C = x C || B x || 0 x
C && B x && 0 0
REDUCTION OPERATORS

& reduction AND


| reduction OR
^ reduction XOR
~& reduction NAND
~| reduction NOR
~^ or ^~ reduction XNOR
Reduction operators are unary operators i.e. they act on single operands. They create a single-bit
result by operating on a multibit operand.
&(010101) 0 & 1 & 0 & 1 & 0 & 1 0
a = 4’b1001
b = ^a b = 1 ^ 0 ^ 0 ^ 1 b = 0

|(010x10) 0 | 1 | 0 | x | 1 | 0 1
BITWISE OPERATORS

& - bitwise AND


| - bitwise OR
~ - bitwise NOT
^ - bitwise XOR
~^ or ^~ - bitwise XNOR
Bitwise operators acts on individual bits of the operands. The operands may be scalar or vector.
If one of the operand is shorter than the other, it will be zero extended to match the length of the
longer operand. The bitwise not operator negates the individual bits of an operand.
a = 4’b1010
b = 4’b1100
c = ~a c = ~(1010) c = 0101
d = a & b d = 1010 & 1100d = 1000
e = (101011) ^ b e = 101011 ^ 1100
e = 101011 ^ 001100 e = 100111
SHIFT OPERATORS

>> shift right


<< shift left
Verilog shift operators operate on a single operand and shift (left or right) the bit pattern
of the operand by a specified number of positions, filling zeroes in the position that are
vacated.

a = 4’b1010
d = a >> 2 d = 0010
c = a << 1 c = 0100
CONCATENATION OPERATOR
{ op1, op2, … }
This operator concatenates op1, op2, … to a single number. The operand should be sized, no
unsized constant operand is allowed.
If the operand A is bit pattern 1011 and
the operand B is the bit pattern 0001,
then {A, B} is the bit pattern 1011_0001
{0011, {{01}, {10}}} = 0011_0110
Replication of same operand can be expressed by using a replication constant which specifies how
many times to replicate the number inside the brackets ({ }).
a = 1’b1
b = 3’b010
c = 3’b101
catr = { 4{a}, b, 2{c} }
catr = {1, 1, 1, 1, 010, 101, 101}
catr = 1111010101101
RELATIONAL OPERATOR

> greater than


< less than
>= greater than or equal to
<= less than or equal to
The Verilog relational operators compare operands and produce a Boolean 0 or 1 (true or false)
result. If any bit in one of the operands is unknown (x), the result is unknown.

1 > 0 1
‘b1x1 <= 0 x
10 < z x
EQUALITY OPERATORS

== logical equality
!= logical inequality
=== case equality
!== case inequality
The case equality operators are used to determine whether two operands match identically on a bit
by bit basis, including bits that have values “x” or “z”, so they produce either 0 or 1 result.
The logical equality operators do the same purpose but produce a “x” result if any bit of any
operand is “x” or “z”.
4’b1z0x == 4’b1z0x x
4’b1z0x != 4’b1z0x x
4’b1z0x === 4’b1z0x 1
4’b1z0x !== 4’b1z0x 0
CONDITIONAL OPERATORS
? :
The Verilog conditional operator selects an expression for evaluation based on the value of
a conditional expression.
conditional_expn ? true_expn : false_expn
If the conditional_expn evaluates to Boolean true (logical 1), then true_expn is
evaluated; otherwise if it evaluates to Boolean false (logical 0), then false_expn is
evaluated. In case result is ambiguous (x) then both true_expn and false_expn are
evaluated and their results are compared, bit by bit, to return for each bit position an x if the
bits are different and the value of bit if they are same.
Conditional operators can be nested to any depth.
bus_data = control_data ? Adder_out : 24’bz;
out = (a == 5) ? (cntrl ? m : n) : (cntrl ? S : t);
The action of conditional operator is like a 2:1 multiplexer.

A
Y = (sel)
Y ? A : B ;

sel
ARITHMETIC OPERATORS
+ add - subtract
* Multiply / divide
% modulus
Arithmetic operations are fully implemented in Verilog for scalar and vector
nets and registers as 2’s complement arithmetic. The size of the result of an
arithmetic expression is determined by the largest of the sizes of operands
and left hand side target.
Negative numbers are stored in 2’s complement form. In case of a net, a
reg register and an integer constant in base format notation, stored number
is interpreted as unsigned value. We can store signed value in an integer
register or an integer constant in decimal notation.
If any of the operand is x, the result is also x. the operators + and - can
also work as unary operators for specifying sign of the operand. Modulus
operator which produces remainder from the division of two operands,
takes sign of first operand as sign of the remainder.
PRECEDENCE OF OPERATOR
+ - ! ~ unary HIGHEST PRECEDENCE
* / %
+ - binary
<< >>
< <= => >
== != === !==
& ~&
^ ^~ ~^
| ~|
&&
||
? : conditional LOWEST PRECEDENCE
PROPAGATION DELAYS

Propagation delays of gates can be specified in gate level description.


There are three types of delays from input to output of a primitive.

Rise delay -When gate output transits to a 1 value from 0, x or z


Fall delay -When gate output transits to a 0 value from 1, x or z
Turn-off delay -Used for tristate gates and associated with a transition
to z state from 0, 1 or x .

If output changes to x, minimum of three delays is considered.


If a single delay is specified, it is used for all the transition. If two delays are
specified they are rise delay and fall delay. Turn-off delay is minimum of
both. If no delay value is specified, the default value is zero delay.

primitive_name # (delay1, delay2, delay3) optional_identifier (port_list)


;
and (y, x1, x2) ; // all delays are zero
and #1 (y, x1, x2) ; // unit delay
and #3 (y, x1, x2) ; // all delays are 3 units
and #(2, 3) ; // rise delay = 2
// fall delay = 3
bufif0 #(3, 5, 2) (out, x, cntrl) ; // rise delay = 3
// fall delay = 5
// turn-off delay = 2
For each type of delay we can also specify minimum, typical and
maximum values. Any one of these values can be chosen at the time
of compilation. The method of choosing is simulator dependent.
Generally, typical value is taken as default.
min:typ:max
and #(4:6:8) a1(y, x1, x2) ;
or #(1:2:3, 2:3:4) o1(y_out, x1_in, x2_in) ;
notif1 #(0:2:4, 1:2:4, 2:3:5) n1(out, in, ctrl) ;

Any input pulse should stay for the duration of propagation delay of a
gate so that it could affect the output.
Delay time between the change in a right-hand-side operand and when
the new value is assigned to the left hand side can be specified in
continuous assignment statements similar to specification of gate delays.

Here for any change in value of


assign #7 c = a & b ; a & b the results will be
calculated after 7 time units.
If a or b changes value before
wire #5 n = r + t ; 7 time units the value of a and
b at the end of those 7 time
units will be considered for
evaluation.
BEHAVIORAL MODELING
Topics to be covered
•Always Block • Clocks and Flipflops
– Synthesising flip-flops & latches
• Event control – Avoiding simulation race hazards
• If statements – Nonblocking assignments
• Begin-end – Asynchronous & synchronous resets
• Incomplete assignment and latches – Clock enables
• FPGAs and latches – Synthesizable always templates
• Unknown and don’t care – RTL synthesis technology
• Conditional operator – Inferring flip-flops
• Tristates – Making best use of RTL synthesis

•Procedural Statements
• Case, casez and casex statements
• full_case and parellel_case directives
• For, repeat, while and forever loops
• integers
• Self-disabling blocks
• Combinational logic synthesis
• Tasks, Functions and
• Finite State Machines
• Designing state machines
Memories
– Understanding tasks
• State machine architectures – Task arguments
• Verilog code-based FSM strategy – Task synchronization
– Tasks and synthesis
• State encoding – Functions
• Unreachable states & safe design – Memory arrrays
practices – RAM modelling and synthesis
• One-hot machines – $readmemb and $readmemh

•Synthesis of Arithmetic • Test Fixtures


– Designing test fixtures
and Counters – Writing to files
• Arithmetic operators and their synthesis – File access using MCDs
– Reading from files
• Signed and unsigned values • Adder – Programming Language Interface (PLI)
architectures – Automated design verification using Verilog
• WYSIWYG arithmetic synthesis – Force and release
• Resource sharing – Gate-level simulation
• Integer and vector arithmetic – Back annotation using SDF
– PLD and ASIC design flow
– Verilog libraries
– Command-line options
– Behavioural modelling
•Behavioural Verilog • Project Management
• Algorithmic coding
• Synchronization using waits &
& Good Practice
– Writing Verilog for simulation and synthesis
event control – Coding standards for synthesis
• Concurrent-disabling of always – File organisation
blocks – Design data control
• Named events – Functional validation
• Fork & join – Methodical testing
– Hierarchical design
• High-level modelling using tasks, – Gated clocks
Implicit FSMs and – Asynchronous design
concurrent-disabling
• Understanding intra-assignment
controls
• Overcoming clock skew
• Blocking and nonblocking
assignments
• Continuous procedural assignment
Understanding unsynthesizable
Verilog constructs
BEHAVIORAL MODELING

In behavioral modeling, we write Verilog code for desired functionality


(behavior) of the circuit and leave the issue of hardware implementation to
synthesis tools. With the availability of the state of the art synthesis tools.
With the availability of state of the art synthesis tools and supporting cell
libraries, this coding style is gaining popularity.
The two basic language constructs used are always and initial
procedure blocks. Each always and initial block represents a
separate activity flow (or hardware process) in Verilog starting at
simulation time 0.
The initial block starts execution at tsim = 0 and stops after a single
execution while always block also starts execution at tsim = 0, but it keeps
on executing continuously in a loop. If there are multiple initial and
always blocks, each of them starts to execute concurrently at the time = 0
and finishes execution independent of other blocks. A module may contain
any number of blocks but these cannot be nested.
initial always
module clk_gen ;
reg clk ;

initial starts at tsim = 0 and


clk = 1’b0 ; execute once only

always starts at tsim = 0 and


#5 clk = ~clk ; execute repeatedly

initial starts at tsim = 0 and


#1000 $finish ; scheduled to execute
endmodule after 1000 time units

OUTPUT = ?
The statements written inside these blocks are called procedural
assignments (statements) and normally they execute sequentially. These
statements assigns values to the register data type variables(reg, integer,
real or time).
Left hand side of procedural assignments can be any of register
variables, their bit select, part select or concatenation, while right hand
side should be an expression that evaluates to a value and may use any
of the operators.
There are two types of procedural assignments : blocking and
non-blocking.
Blocking assignments written inside an always or initial block execute in
the same order in which they are written. A statement that follows a
blocked statement in sequential flow cannot be executed until the
preceding statement has completed execution. These assignment use
the = operator.
target1 = expression1 ; executed 1st
target2 = expression2 ; executed 2nd
target3 = expression3 ; executed 3rd
Non-blocking assignment behave differently than blocked assignments, it
does not block the execution of the statements that follows it in listed code.
Non-blocking are made using <= operator.
The RHS expression of all non-blocking assignments in a block are
evaluated concurrently and independent of their order with respect to each
other, later the assignments are made to LHS.

target1 <= expression1 ;


target2 <= expression2 ; all starts executing at tsim = 0
target3 <= expression3 ;
initial initial

begin begin

A= 1 ; A= 1 ;

B = 0 ; B = 0 ;

. . . . . .

A <= B ; // uses B = 0 B <= A ; // uses A = 1

B <= A ; // uses A = 1 A <= B ; // uses B = 0

end end

initial initial
begin begin
A= 1 ; A= 1 ;
B = 0 ; B = 0 ;
. . . . . .
A = B ; // uses B = 0 B = A ; // uses A = 1
B = A ; // uses A = 0 A = B ; // uses B = 1
end end
DELAYS
Three types of delay specification are allowed for procedural assignments.
1. Regular Delay - It is specified by simply placing a non-zero number with # to the left of a
procedural statements. It delays the execution of statement by specified number of time units
relative to the time when statement is encountered in the activity flow.
#3 tran = pas1 & pas2 ;
2. Intra Assignment Delay - If we write delay format (#delaytime) to the right of assignment
operator, then it computes the RHS expression at the same time but delays the assignment
of computed value to LHS target by specified number of time units.
tran = #5 pas1 & pas2 ;
3. Zero Delay - This delay specification is used to ensure that a statement is executed in the
last, after all other statements are executed in that simulation time. It is specified by placing
#0 before the assignment (to left most).
tran1 = pas11 & pas12 ;
#0 tran2 = pas21 & pas22 ; // executed last
tran3 = pas31 & pas32 ;
● How would the following code execute?
module
BLOCK_NONBLOCK(clock,a1,b1,c1,a2,b2,c2,a3,b3,c3,a4,b4,c4,y1,y2,y3,y4);
input clock, a1,b1,c1,a2,b2,c2,a3,b3,c3,a4,b4,c4;
output y1,y2,y3,y4 ;
reg y1,y2,y3,y4;
reg m1,m2,m3,m4;

always@(a1 or b1 or c1 or m1) always@(posedge clock)


begin
begin
m1= #3(a1 & b1);
m3=#3(a3 & b3);
y1= #1(m1 | c1);
y3=#1(m3 | c3);
end
end

always@(a2 or b2 or c2 or m2) always@(posedge clock)


begin begin
m2= #3(a2 & b2); m4=#3(a4 & b4);
y2= #1(m2 | c2); y3=#1(m4 | c4);
end
end

endmodule
EVENT CONTROL
Frequently, we want to continue execution only when some specified event
(signal transition) occurs. We have two types of event control mechanisms
in Verilog: edge triggered and level sensitive.
1. Edge Triggered - Operator @ is used to delay the execution until occurrence of the specified
edge transition.
@(event) proc_statement ; 1 -> x
1 -> z
@(sig) // continue execution at transition in sig
1 -> 0
@(posedge sig) // continue execution at positive edge transition in sig x -> 0
z -> 0
0 -> x
0 -> z
@(negedge sig) // continue execution at negative edge transition in sig 0 -> 1

@(clk or sig1 or negedge sig2) // events can be ored to indicate x ->1


z -> 1
// “if any of event happens”
always @ (posedge sig)
begin // event control in always
. . . // affects whole always block
. . .
end
We can declare, trigger and recognize our own events. Declaration is done by using
keyword event, whereas triggering is done by using operator ->. The occurrence
(triggering) of event can be recognized by @operator.
event my_event ; // event declared
always@(negedge clk)
begin
if(control_sig)
-> my_event // event triggered
end
always @(my_event) // event recognized
data = in1 & in2 ;
2. Level Triggered - Activity flow is suspended(but not terminated) until a condition is
“TRUE”. Keyword wait is used for this event control mechanism
wait (condition)
proc_statement
Procedural Statement is executed if condition is true
wait (enable) reg_a = reg_b ;
PROCEDURAL STATEMENTS : if

if (expr1)
module mux4_1 (out, in, sel);
true_stmt1; output out;
else if (expr2) input [3:0] in;
input [1:0] sel;
true_stmt2;
.. reg out
wire [3:0] in;
else wire [1:0] sel;

def_stmt; always @ (in or sel)


if (sel == 0)
out = in[0];
else if (sel ==1)
out = in[1];
else if (sel == 2)
out = in[2];
else
out = in[3];
endmodule
PROCEDURAL STATEMENTS : case

case (expr) module mux4_1 (out, in, sel);


item_1, …, item_n: stmt1; output out;
input [3:0] in;
item_n+1, …, item_m : input [1:0] sel;
stmt2; reg out;
.. wire [3:0] in;
default def_stmt; wire [1:0] sel;
always @ (in or sel)
case (sel)
endcase 0 : out = in[0]
1 : out = in[1]
2 : out = in[2]
3 : out = in[3]
endcase
endmodule
PROCEDURAL STATEMENTS : for

for (init_assignment; cond; step_assignment) stmt;


module count (Y, start);
output [3:0] Y;
input start;

reg [3:0] Y;
wire start;
integer I;
initial
Y = 0;
always @ (posedge start)
for (I = 0, I<3; i = i+1)
# 10 Y = Y + 1;
endmodule
PROCEDURAL STATEMENTS : while
module count (Y, start);
while (expr) stmt; output [3:0] Y;
input start;
reg [3:0] Y;
wire start;
integer I;
initial
Y = 0;
always @ (posedge start)
begin
I = 0;
while (I < 3)
begin
# 10 Y = Y + 1;
i =iI + 1;
end
end
end module
PROCEDURAL STATEMENTS : repeat

repeat (times) stmt;

module count (Y, start);


output [3:0] Y;
input start;
Can be either an reg [3:0] Y;
integer or a variable
wire start;

initial
Y = 0;
always @ (posedge start)
repeat (4) # 10 Y = Y + 1;
end module
PROCEDURAL STATEMENTS : forever

forever stmt;
clock generation in test modules
module test; T = 20 time units
clk

reg clk;
Executes until sim
finishes initial
begin
clk = 0;
forever # 10 clk = ~ clk;
end
other_module1 01 (clk, ..);
other_module2 02 (..,clk,..);

endmodule
Difference between if-else and ternary(X
:) operator

value =1'bx ? B : C;

if (1'bx)
value = B;
else
value = C;

value = 1'bx ? 4'b 010X : 4'b 0111


value = 4'b 01XX
Hardware Modeling Examples - “Case statement”

“Case” Statement
always@(sel, a, b, c, d)
case sel is
0: y = A;
1: y =B;
2: y =C;
Default: y = D;
end case;

A 00

B 01
Y
C 10
D 11

SEL
D Flip Flop
T Flip Flop

You might also like