Verilog
Salahuddin Ahmed
Module
X1 module ex1 (f, x1, x2, x3);
X2
g input x1, x2, x3;
Model
Structural
f output f;
k h
X3
and ( g, x1, x2 );
not ( k, x2 );
and ( h, k, x3 );
or ( f, g, h );
module ex1 (f, x1, x2, x3);
endmodule
input x1, x2, x3;
output reg f; module ex1 (f, x1, x2, x3);
always @ ( x1 or x2 or x3 input x1, x2, x3;
) output f;
if ( x2 == 1 )
f = x1; assign f = (x1&x2) |
else (~x2&x3);
f = x3; endmodule
endmodule Behavioral Dataflow
Model
Model
Module (cont.)
x p
1
x
module ex2 ( f, g, h, x1, x2, x3,
2 x4 );
x g
input x1, x2, x3, x4 ;
3
x q output f, g, h ;
4
f
r …
or ( r, x1, ~x2 );
h
or ( s, ~x3, x4 );
s …
endmodule
module ex2 ( output f, g, h, input x1, x2, x3, x4 );
assign g = ( x1 & x2 ) | ( x3 & x4 ) ;
assign h = ( x1 | ~x2 ) & ( ~x3 | x4 ) ;
assign f = g | h ;
endmodule
Full Adder
x y x y
Cou Ci Cou FA Ci
t n t n
Su Su
m m
module fulladd ( s, cout, cin, x, y ) ;
input cin, x, y ;
output s, cout ;
xor ( s, x, y, cin ) ;
and ( z1, x, y ) ; and ( z1, x, y ) ,
and ( z2, x, cin ) ; ( z2, x,
and ( z3, y, cin ) ; cin ) ,
or ( cout, z1, z2, z3 ) ; ( z3, y,
endmodule cin ) ;
Full Adder (cont.)
module fulladd ( s, cout, cin, x, y ) ;
input cin, x, y ;
output s, cout ;
assign s = x ^ y
, ^ cin ;
assign cout = ( x & y ) | ( x & cin ) | ( y &
cin ) ;
endmodule
4-bit Adder Hierarchical
x y x y x y x y
3 3 2 2 1 1 0 0
c c c
Cou FA 3 FA 2 FA 1 FA Ci
t n
s s s s
3 2 1 0
module fa4bit ( s3, s2, s1, s0, cout, cin, x3, x2, x1, x0, y3, y2, y1,
y0 ) ;
input cin, x3, x2, x1, x0, y3, y2, y1, y0 ;
output s3, s2, s1, s0, cout ;
fulladd stage0 ( s0, c1, cin, x0, y0 ) ;
fulladd stage1 ( s1, c2, c1, x1, y1 ) ;
fulladd stage2 ( s2, c3, c2, x2, y2 ) ;
fulladd stage3 ( s3, cout, c3, x3, y3 ) ;
endmodule
4-bit Adder – Vector
X[ Y[3 X[ Y[2 X[ Y[1 X[ Y[0
3] ] 2] ] 1] ] 0] ]
C[3 C[2 C[1
Cou FA ] FA ] FA ] FA Ci
t n
S[3 S[2 S[1 S[0
] ] ] ]
module fa4bit ( S, cout, cin, X, Y ) ;
input cin ;
input [3:0] X, Y ;
output cout ;
output [3:0] S ;
wire [3:1] C ;
fulladd stage0 ( S[0], C[1], cin, X[0], Y[0] ) ;
fulladd stage1 ( S[1], C[2], C[1], X[1], Y[1] ) ;
fulladd stage2 ( S[2], C[3], C[2], X[2], Y[2] ) ;
fulladd stage3 ( S[3], cout, C[3], X[3], Y[3] ) ;
endmodule
N-bit Adder – Parametric Sol.
module faNbit ( S, cout, cin, X, Y ) ;
parameter n = 32 ;
input cin ; input [n-1 : 0] X, Y ;
output reg cout ; output reg [n-1 : 0]
S;
reg [n : 0] C ;
integer k ;
always @ ( X, Y, cin )
begin
C[0] = cin ;
for ( k=0; k<n; k=k+1 )
begin
S[k] = X[k] ^ Y[k] ^ C[k] ;
C[k+1] = (X[k] & Y[k]) | (X[k] &
C[k]) | (Y[k] & C[k]) ;
end
cout = C[n] ;
end
endmodule
N-bit Adder – Generate Block
module faNbit ( S, cout, cin, X, Y ) ;
parameter n = 32 ;
input cin ; input [n-1 : 0] X, Y ;
output cout ; output [n-1 : 0] S ;
wire [n : 0] C ;
genvar k ; Similar to integer but must
be
assign C[0] = cinused; within generate
assign cout = C[n] block
;
generate
for ( k=0; k<=n-1; k=k+1 )
begin : addbit
fulladd stage ( S[k], C[k+1],
C[k], X[k], Y[k] ) ;
endGenerates
endgenerate addbit[0].stage, …, addbit[n-
endmodule 1].stage
N-bit Adder, Behavioral Model
module faNbit ( S, cin, X, Y ) ;
parameter n = 32 ;
input cin ; input [n-1 : 0] X, Y ;
output reg [n-1 : 0] S ;
always @ ( X, Y, cin )
S = X + Y + cin ;
endmodule
module faNbit ( S, cout, overflow, cin, X, Y ) ;
…
output reg cout, overflow ;
always @ ( X, Y, cin )
begin
S = X + Y + cin ;
cout = (X[n-1] & Y[n-1]) | (X[n-1] & ~S[n-1]) | (Y[n-
1] & ~S[n-1]) ;
overflow = cout ^ X[n-1] ^ Y[n-1] ^ S[n-1] ;
end
endmodule
N-bit Adder, Behavioral Model
module faNbit ( S, cout, overflow, cin, X, Y ) ;
…
output reg cout, overflow ;
reg [n : 0] Sum ; Use one extra
always @ ( X, Y, cin ) bit
begin to hold the
Sum = { 1’b0,Xcarryout
} + { 1’b0,Y } + cin ;
S = Sum [n-1 : 0] ; Concatena
cout = Sum [n] ; te
overflow = cout ^ X[n-1] ^ Y[n-1] ^
S[n-1] ;
end
endmodule
Adder, Behavioral Model
module faNbit ( S, cout, overflow, cin, X, Y ) ;
parameter n = 32 ;
input cin ; input [n-1 : 0] X, Y ;
output reg [n-1 : 0] S ; output reg cout,
overflow ;
always @ ( X, Y, cin )
begin
{cout, S} = X + Y + cin ;
overflow = cout ^ X[n-1] ^ Y[n-1] ^
S[n-1] ;
end
endmodule
module fulladd ( s, cout, cin, x, y ) ;
input cin, x, y ;
output reg s, cout ;
always @ ( x, y, cin )
{cout, s} = x + y + cin ;
endmodule
Always Block
► Verilog syntax requires that
procedural statement be contained
inside an always block.
► An always block can contain one or more
statement(s).
► Statements inside an always block
are evaluated in the order given in
the code.
► Continuous assignment statements are
evaluated concurrently.
► Part of always block after @ is called
sensitivity list.
► The statements inside an always block
are executed by the simulator only when
one or more of the signals in the
sensitivity list changes value.
Procedural Statement
► Procedural statement must be placed
inside an always block
► e.g. for statement, if-else statement etc.
► Any signal that is assigned a value
by a statement within an always
block must retain this value until it is
re-evaluated.
► Such signals are declared to be of reg
type
► Changes in the sensitivity variables
given in the always statement
invokes the re-evaluation of the
procedural statements
Generate Block
► Generate construct allows instantiation
statements to be included inside for
loops and if-else statement.
► Inside the generate block, loop index
variable has to be declared of type
genvar.
► A genvar can be used only inside generate
blocks.
► A genvar variable is similar to an integer
variable but it can have only positive
values.
► Each instance generated by the compiler
in the for loop will have a unique instance
name based on the for loop label.
Nets
► Connections between logic unit
elements are defined using nets.
► A net represent a node in a circuit.
► By default, all signals are nets.
► There are two types of nets:
► wire
► A wire connects an output of one logic
element in a circuit to an input of another
logic element.
► wire takes the value of logic 0 and 1.
► tri
► tri declares a net to be of tri-state type.
► In addition to logic 0 and 1, a tri net can take
the high-impedance (i.e. Hi-Z) value.
Variables
► Signals produced by procedural statements
are referred to as variables.
► Variables are useful for describing a
circuit’s behavior.
► They do not usually correspond directly to
signals in the resulting circuit.
► Two types of variables:
► reg
► Once a variable’s value is assigned with a
procedural statement, the simulator “registers”
this value and it will not change until the always
block is executed again.
► The keyword reg does not denote a storage
element or register.
► integer
► Normally used for loop index and so forth.
Numbers
► Numbers can be given as constants.
► They can be binary (b), octal (o), hexadecimal
(h) or decimal (d)
► A digit could may be 0, 1, z (hi-z) or x
(unknown)
► z and x values cannot be used with decimal radix
► Format of the sized number:
► <size_in_bit>’<radix_identifier><significant_digits>
► Examples:
12’b10001001001, 12’o4251, 12’h8A9, 12’d2217
► 0 is padded to the left if size exceeds the number of
bits
► Extra digits are ignored if number of bits exceed the
size
► Format of un-sized numbers
► ’<radix_identifier><significant_digits>
Verilog Operators
Operator type Symbols Operation operands Examples
~ 1’s complement 1 C = ~A
& Bitwise AND 2 C=A&B
Bitwise | Bitwise OR 2 C=A|B
^ Bitwise XOR 2 C=A^B
~^ or ^~ Bitwise XNOR 2 C = A ~^ B
! NOT 1 f = !A .
Logical && AND 2 f = A && B = (a1+a0).(b1+b0)
|| OR 2 f = A || B = (a1+a0) + (b1+b0)
& Reduction AND 1 f = &A = a2.a1.a0
~& Reduction NAND 1 f = ~&A .
| Reduction OR 1 f = |A = a2 + a1 + a0
Reduction
~| Reduction NOR 1 f = ~|A .
^ Reduction XOR 1 f = ^A .
~^ or ^~ Reduction XNOR 1 f = ~^A .
Verilog Operators
Operator type Symbols Operation operands Examples
+ Addition 2 C=A+B
- Subtraction 2 C=A–B
Arithmetic - 2’s complement 1 C=–A
* Multiplication 2 C=A*B
/ Division 2 C=A/B
> Greater than 2 Returns 1 if the condition
< Less than 2 true else returns 0. If there
Relational are x or z bits in operands,
>= Greater or equal 2 then the expression takes
<= Less or equal 2 the value of x.
== Logical equality 2 If (A == B ) C = 1
Equality
!= Logical inequality 2
>> Right shift 2 C = A >> 1
Shift
<< Left shift 2 C = A << 1
Concatenation {,} Concatenation Any no C={A, 2’b10} = a2a1a010
Replication {{}} Replication Any no {3{A}, 2{B}} = {A, A, A, B, B}
Latches & Flops
always @( Control or
B) What happens if Control
if( Control ) =0?
A=B
In the absence of an assigned value, the Verilog
compiler assumes that the value of A caused by
the if statement must be maintained until the next
time this if statement is evaluated. This notion of
implied memory is realized by instantiating a latch
in the circuit.
module D_latch ( D, Clk, module D_flipflop ( D, Clk, Q
Q ); );
input D, Clk; input D, Clk;
output reg Q; output reg Q;
always @ (D, Clk) always @ (posedge
if( Clk ) Clk)
Q = D; Q = D;
endmodule endmodule
Blocking and Non-Blocking
► = creates a blocking assignment.
► If a variable is given a value by blocking
assignment statement, then this new
value is used in evaluating all subsequent
statements in the block.
► <= creates a non-blocking assignment
► All non-blocking assignment statements in
an always block are evaluated using the
values that the variables have when the
always block is entered.
► A given variable has the same value for
all statements in the block.
► The meaning of non-blocking is that the
result of each assignment is not seen until
the end of always block
Assignment
D D Q
module non_shift_reg (D, Clk, Q1,
Q 1
Q2);
Cl
input D, Clk; k
output reg Q1, Q2;
D Q
always @(posedge Clk)
begin Q 2
Q1 = D;
Q2 = Q1; The synthesized ckt has 2
end parallel flops, one of which will
likely get deleted during
endmodule
module shift_reg (D, Clk, Q1, Q2); optimization
input D, Clk; Q
D D D Q
output reg Q1, Q2; 1
always @(posedge Clk) Q Q 2
begin Cl
k
Q1 <= D;
Q2 <= Q1; The synthesized ckt has 2
end cascaded flops, which
implements a shift
endmodule register.