Verilog HDL
Hardware Description Language
HDL – a language for describing hardware
Two industry IEEE standards:
Verilog
VHDL (Very High Speed Integrated Circuit HDL)
Verilog
Originally designed for simulation and verification
Gateway Design Automation, 1983
Functionality later added for synthesis
CAD Design Process
Design conception
DESIGN ENTRY
Truth table Schematic capture Verilog
Simple synthesis Translation
Merge
INITIAL SYNTHESIS TOOLS Boolean equations
Functional simulation
No
Design correct?
Yes
Logic synthesis, physical design, timing simulation
Synthesis Using Verilog
There are two ways to describe circuits in Verilog
Structural
Use Verilog gate constructs to represent logic gates
Write Verilog code that connects these parts together
Behavioral flow
Use procedural and assign constructs to indicate what
actions to take
The Verilog compiler converts to the schematic for you
Verilog Miscellanea
Comments: just like C++
// this is a single line comment
/* this is a multi-line
comment */
White space (spaces, tabs, blank lines) is ignored
Identifier names
Letters, digits, _, $
Can t start with a digit
Case-sensitive!
There are also reserved words can t be one of these
Verilog Types
There are NO user-defined types
There are only two data types:
wire
Represents a physical connection between structural elements
(think of this as a wire connecting various gates)
This is the most common type for structural style
wire is a net type and is the default if you don t specify a type
reg
Represents an abstract storage element (think of this as an
unsigned integer variable)
This is used in the behavioral style only
Verilog Modules and Ports
Circuits and sub-circuits are described in modules
module … endmodule
The arguments to the module are called ports
Ports are of type
input
output
inout bidirectional port; of limited use to us
Ports can be scalar (single bit) or vector (multi-bit)
Ports are a scalar wire type unless you specify otherwise
Example:
input [3:0] A; // a 4 bit (vector) input port (wire) called A
Verilog Structural Synthesis
The half-adder (sum part only):
module halfAdder(S,A,B);
input A, B;
output S;
wire AC, BC, X, Y;
not(AC,A); // AC ~A
not(BC,B); // BC ~B
and(X,A,BC); // X A & BC
and(Y,B,AC); // Y B & AC
or(S,X,Y); // S X | Y
endmodule
Verilog Primitive Gates
and(f,a,b,…) f = (a · b …)
or(f,a,b,…) f = (a + b + …)
not(f,a) f = a'
nand(f,a,b,…) f = (a · b …)'
nor(f,a,b,…) f = (a + b + …)'
xor(f,a,b,…) f = (a ⊕ b ⊕ …)
xnor(f,a,b,…) f = (a b …)
You can also name the gates if you like …
and And1(z1,x,y); // this gate is named And1
Comments on Structural Design
Order of statements in structural style is irrelevant
This is NOT like a typical programming language
Everything operates concurrently (in parallel)
Primitive gates can have any number of inputs
(called fan in)
The Verilog compiler will decide what the practical limit is
and build the circuit accordingly (by cascading the gates)
All structural elements are connected with wires
Wire is the default type, so sometimes the declarations
are omitted
Example: 3 Way Light Control
Example: 3 way light control
1 light L A B C L
3 light switches (A, B, C) 0 0 0 0
A is a master on/off: 0 0 1 0
If A = off, then light L is always off 0 1 0 0
If A = on, the behavior depends 0 1 1 0
on B and C only
1 0 0 0
Let 0 represent off 1 0 1 1
Let 1 represent on 1 1 0 1
1 1 1 0
SOP Equation?
SOP: L = ABC + AB C
Example: 3 Way Light Control
The SOP implementation of the 3 way light control
with gates:
with Verilog:
module light3Way(L,A,B,C);
input A, B, C;
output L;
not Not1(BC,B), Not2(CC,C);
and And1(f,A,B,CC), And2(g,A,BC,C);
or Or1(L,f,g);
endmodule
Behavioral Synthesis Using Verilog
Behavioral style uses Boolean algebra to express
the behavior of the circuit
L = (A B' C)+(A B C') for the 3 way light control
module light3Way(L,A,B,C);
input A, B, C;
output L;
assign L = (A & ~B & C) | (A & B & ~C);
endmodule
Continuous Assignment
The assign statement is key in data flow synthesis
The RHS is recomputed when a value in the RHS changes
The new value of the RHS is assigned to the LHS after the
propagation delay (default delay is 0)
The LHS must be a net (i.e. wire) type
Example: assign L = (A & ~B & C) | (A & B & ~C);
If A or B or C changes, then L is reassigned
The Verilog compiler will construct the schematic for you
Operators
Category Examples Bit length
Bitwise ~A, A & B, A | B, A^B (xor), A~^B (xnor) L(A)
Logical !A, A&&B, A||B 1
Reduction &A, ~&A, |A, ~|A, ^~A, ~^A 1
Relational A==B, A!=B, A>B, A<B, A>=B, A<=B 1
Arithmetic A+B, A-B, -A, A*B, A/B Max(L(A),L(B))
Shift A<<B, A>>B L(A)
Concatenate {A,….,B} L(A)+…+L(B)
Replication {B{A}} B*L(A)
Condition A?B:C Max(L(B),L(C))
Behavioral Style for Full-Adder
module fullAdder(S,Cout,A,B,Cin);
input A,B,Cin;
output S,Cout;
assign S = A ^ B ^ Cin;
assign Cout = (A & B) | (A & Cin) | (B & Cin);
endmodule
Another Behavioral Style for Full-Adder
module fullAdder(S,Cout,A,B,Cin);
input A,B,Cin;
output S,Cout;
assign {Cout,S} = A+B+Cin; // + means addition
endmodule
Verilog also supports arithmetic operations!
compiles them down to library versions of the circuit
Gate Delays
Gates may be specified with a delay – optional
not #3 Not1(x,A);
or #5 Or1(F,B,x);
The propagation delay is in units which can be set
independently from the code
Propagation delays have no meaning for synthesis,
only for simulation
Hence, we won t use them
Typical Design Process
Graphical Entry Waveform/Timing Diagram
Compiler
HDL Entry Timing Analysis
UP2 Board Program the FPGA
Combinational Logic in Verilog
Verilog for Combinational Circuits
How can Verilog be used to describe the various
combinational building blocks?
Can always use structural style
This can get tedious
Data flow style is more convenient
assign x = a & ~b (etc, etc)
Behavioral style is also good – we ll look at this shortly
Verilog: 2x1 MUX
Uses the conditional ?: operator
Software designers detest this operator
Hardware designers revel in its beauty
Verilog: 4x1 MUX (Data Flow Style)
This is getting complicated!
Need a way to specify a group of bits like w[0:3]
Need a way to replace ?: with if then else
Vectored Signals in Verilog
Format is [MSB:LSB]
Signals can be grouped as bit vectors
The order of the bits is user determined
W has 4 lines with the MSB = W[0] and the LSB = W[3]
S has two lines with the MSB = S[1] and the LSB = S[0]
Hierarchical Design of a 16x1 MUX
s0
s1 Structural style Verilog
w0
w3
w4 s2
s3
w7
w8
w11
The Verilog code for mux4x1 must be either in
the same file as mux16x1, or in a separate file
w12 (called mux4x1.v) in the same directory as
mux16x1
w15
Hierarchical Design of a 4 to 16 Decoder
w0 w0 y0 y0 Structural style Verilog
w1 w1 y1 y1
y2 y2
En y3 y3
w0 y0 y4
w1 y1 y5
y2 y6
w2 w0 y0 En y3 y7
w3 w1 y1
y2
En En y3 w0 y0 y8
w1 y1 y9
y2 y10
En y3 y11
w0 y0 y12
w1 y1 y13
y2 y14 dec2to4 to be presented soon ….
En y3 y15
Behavioral Style in Verilog
Must be reg type when used as LHS in
an always block
Sensitivity list: statements inside the always
block are only executed when one or more
signals in the list changes value
Always Blocks
All LHS signals must be variables type reg
The simulator registers the value and maintains it until the
statements in the always block are executed again
Statements are re-executed only when a signal in the
sensitivity list changes value
The sensitivity list must include all signals on which
the LHS variables depend in the always block
Order counts inside the always block!!!!
If … else is called a procedural statement
All procedural statements must be inside an always block
Single vs Multiple Statements
In Verilog, all constructs permit only a single
statement
If you need > 1 statement inside a construct, use
begin
You won t find much use for begin … end
… most constructs really do include just a single
… statement
end
This is similar to Pascal syntax
Verilog is generally more like C though
Representation of Numbers
Numbers can be given as constants in
Binary (b)
Octal (o)
Hex (h)
Decimal (d)
For numbers of a specified size:
TFAE:
12 d2217 Numbers are 0-extended to the left, if
necessary, to fill out the number of bits
12 h8A9
12 o4251 If the value exceeds the # of bits allocated,
the extra bits are ignored!
12 b100010101001
#bits given in decimal
4x1 MUX: Behavioral Styles
More on Representation of Numbers
Negative numbers:
-4'b101 the 4 bit 2 s complement of 5 1011
For numbers of an unspecified size:
2217
d2217
h8A9
o4251
b100010101001
The Verilog compiler chooses the size to fit with the other
operands in the expression
Case Statement
Comparisons in a case statement are
made bit by bit.
No break statement needed – first
match executes and then case is
exited.
Use begin … end if > 1 statement
required in a case.
If not all cases are enumerated, make
sure to use default case.
2 to 4 Decoder: Behavioral Style
4 to 2 Binary Encoder
Left extended by x to fill 2 bits
4 to 2 Priority Encoder
casex vs case
Case, Casez, Casex
Case treats each value 0, 1, x, and z literally
4 b01xz only matches 4 b01xz
Example: 4 b0110 does not match 4 b01xx in a case
Casez treats 0, 1, and x literally
Casez treats z as a don t care
Example: 4 b0110 matches 4 b01zz, but not 4 b01xz
No match here
Casex treats 0 and 1 literally
Casex treats both x and z as don t cares
Example: 4 b0110 matches 4 b01xx and also 4 b01xz
BCD to 7 Segment Display Converter
For Loop
When a circuit exhibits regularity, a for loop can be
used inside an always statement to simplify the
design description (for loop is a procedural
statement only inside an always block)
C style syntax: for (k = 0; k < 4; k = k+1)
Loop index must be type integer (not reg!)
Can t use the convenience of k++
Use begin … end for multiple statements in the loop
Each iteration of the loop specifies a different piece
of the circuit
Has nothing to do with changes over time
2 to 4 Decoder Using a For Loop
4 to 2 Priority Encoder Using a For Loop
A signal that is assigned a value multiple
times in an always block retains its last value
priority scheme relies on this for correct
setting of Y and z
Arithmetic Circuits
Machine Arithmetic
Arithmetic combinational circuits are required for
Addition
Subtraction
Multiplication
Division (hardware implementation is optional)
Addition / subtraction can be done easily using full
adders and a minimum of additional logic
Ripple-Carry Adder
A ripple carry adder cascades full adders together
Simple, but not the most efficient design
Carry propagate adders are more efficient
xn – 1 yn – 1 x1 y1 x0 y0
c1
cn FA cn -1 c2 FA FA c0
sn – 1 s1 s0
MSB position LSB position
Behavioral Style Full Adder
We ve done full adders many ways already
data flow styles
behavioral style
Behavioral Style Ripple-Carry Adder
Allows a generic size to be specified
For n = 2, the for loop is equivalent to:
S[0] = X[0] ^ Y[0] ^C[0];
C[1] = (X[0] & Y[0]) | (X[0] & C[0]) | (Y[0] & C[0]);
S[1] = X[1] ^ Y[1] ^C[1];
C[2] = (X[1] & Y[1]) | (X[1] & C[1]) | (Y[1] & C[1]);
Higher Level Behavioral Style for Adder
This won't work! Can't loop over subcircuits
subcircuits to be instantiated like this
are not allowed in a for loop
Functions / Tasks
Subcircuits can't directly be instantiated in for loops
Can t create a separate module for fulladder and then
instantiate that inside a for loop
Need to create a function or a task for the subcircuit
Functions and tasks provide modular code without
defining separate modules
Defined within a module
Code is placed in-line by the Verilog compiler
Functions and tasks are behavioral only
Functions
Functions provide modular code without defining
separate modules
Defined within a module
Can have many inputs (must have > 0), but only one output
Function is called like C++ functions that have a non-void
return value
Functions can be called in a continuous assignment or in a
procedural statement
Functions contain only procedural statements
Function code is placed in-line by the Verilog compiler
More on Functions
Functions must have > 0 inputs
Order of inputs is dictated by the order in which they are
declared in the function
Functions can call other functions, but not tasks
May return a vectored signal by declaring the
function as:
function [3:0] foo; // the range indicates a 4 bit result
…
endfunction
Function Example: 16x1 MUX
begin … end required if more than 1
procedural statement in a function
Tasks
Tasks also provide modular code without defining
separate modules
Also defined within a module
Can have many inputs and outputs
Task is called like C++ functions that have a void return type
Outputs are returned via the output variables (like the ports in
a module)
Task can only be called in a procedural statement
Tasks contain only procedural statements
Task code is placed in-line by the Verilog compiler
More on Tasks
Tasks may have any number of inputs and outputs
Order of inputs and outputs is dictated by the order in which
they are declared in the task
Tasks can call other tasks or functions
All arguments to a task are implicitly of type reg
begin … end block required in a task if you use > 1
procedural statement
Ripple-Carry Adder Using a Task
Generate Statement
Verilog 2001 provides a new statement for
instantiating separate modules inside a for
loop
Permits structural style to use for loops
generate … endgenerate
Use genvar datatype in place in integer
Ripple-Carry Adder Using Generate
compiler produces n modules with names
addstage[0].addbit, addstage[1].addbit, …,
addstage[n-1].addbit
Macrofunctions
Libraries of common circuits, such as adders, are
available in most commercial CAD tools
Sometimes called macrofunctions or megafunctions
Example: Quartus II provides a Library of
Parametrized Modules (LPM)
Each module is parametrized, e.g. the user can set the
number bits used in the module
LPM_ADD_SUB is an n-bit adder / subtractor where you
can pick the n it will use
LPM_WIDTH
Available in the megafunctions arithmetic library
LPM_ADD_SUB Module
add_sub = 1 dataa + datab + cin
add_sub = 0 dataa - datab + (cin-1)
Multi-bit signals
must be named
with [MSB..LSB]
Sample Application: BCD Adder
Build a 4 bit BCD adder with carry-out
Examples:
X= 0010 X= 1000 X= 0110
Y= 0110 Y= 1001 Y= 0101
Binary Sum= 1000 Binary Sum= 0001 Binary Sum= 1011
BCD Sum= 1000 BCD Sum= 0111 BCD Sum= 0001
Cout= 0 Cout= 1 Cout= 1
What s the rule???
If the binary sum exceeds 9 (including the carry out), then
add an additional 6 to it to get the BCD sum
cout = 1 if cout from binary add, or if cout from +6 add
Block Diagram for BCD Adder
X Y
4-bit adder cin
carry-out
Detect if
sum 9>
6 0
MUX
Adjust
cout
compute cout
out 4-bit adder 0
Adjust = (carry-out) |
cout
(Z[3] & (Z[2] | Z[1]))
S
Structural Verilog for BCD Adder
Using positional notation for arguments
Note: add_sub = 1 is the default and so need
not be specified
Specifying the size of the
adders using defparam
Behavioral Verilog for BCD Adder