Design domain and levels of abstraction
Verilog HDL Basics
What is Verilog
• Hardware Description Language (HDL)
• Developed in 1984 by cadence systems
• Brought to public in 1990
• Standard: IEEE 1364, Dec 1995
• Revised in 2001
Basic Limitation of Verilog
Description of digital systems only
Module
module my_module(out1, .., inN);
in1 my_module out1 output out1, .., outM;
in2 out2 input in1, .., inN;
f .. // declarations
inN outM .. // description of f (maybe
.. // sequential)
endmodule
Everything you write in Verilog must be inside a module
exception: compiler directives (can be inside or out side)
Ex: `include
`if def
Example: Half Adder
A module half_adder(S, C, A, B);
S
output S, C;
B input A, B;
C
wire S, C, A, B;
A S assign S = A ^ B;
Half assign C = A & B;
Half
B Adder
Adder C
endmodule
Main Language Concepts (i)
Verilog has its own language constructs in most cases they
resemble like c language
Verilog is case sensitive
• Verilog has 7 types of lexical tokens
• Operators
• Keywords
• Identifiers
• White spaces
• Comments
• Numbers
• Strings
User Identifiers
• Formed from {[A-Z], [a-z], [0-9], _, $}, but ..
• .. can’t begin with $ or [0-9]
– myidentifier
– m_y_identifier
– 3my_identifier
– $my_identifier
– _myidentifier$
• Case sensitivity
– myid Myid
Comments
• // The rest of the line is a comment
• /* Multiple line
comment */
• /* Nesting /* comments */ do NOT
work */
Verilog Value Set
• 0 represents low logic level or false condition
• 1 represents high logic level or true condition
• x represents unknown logic level
• z represents high impedance logic level
Numbers in Verilog (i)
<size>’<radix> <value>
No
Noof of Binary
Binary
bbororBB Consecutive chars
bits Octal o or O Consecutive chars
bits Octal o or O 0-f,
0-f,x,x,zz
Decimal
Decimal
ddororDD
Hexadecimal
Hexadecimal hhororHH
– 8’h ax = 1010xxxx
– 12’o 3zx7 = 011zzzxxx111
Numbers in Verilog (ii)
• You can insert “_” for readability
– 12’b 000_111_010_100
– 12’b 000111010100 Represent the same number
– 12’o 07_24
• Bit extension
– MS bit = 0, x or z extend this
• 4’b x1 = 4’b xx_x1
– MS bit = 1 zero extension
• 4’b 1x = 4’b 00_1x
Numbers in Verilog (iii)
• If size is ommitted it
– is inferred from the value or
– takes the simulation specific number of bits or
– takes the machine specific number of bits
• If radix is ommitted too .. decimal is
assumed
– 15 = <size>’d 15
Nets (i)
• Can be thought as hardware wires driven by logic
• Equal z when unconnected
• Various types of nets
– wire
– wand (wired-AND)
– wor (wired-OR)
– tri (tri-state)
• In following examples: Y is evaluated,
automatically, every time A or B changes
Nets (ii)
A wire Y; // declaration
Y
B assign Y = A & B;
wand Y; // declaration
assign Y = A;
A assign Y = B;
Y
B
wor Y; // declaration
assign Y = A;
assign Y = B;
dr
tri Y; // declaration
A Y
assign Y = (dr) ? A : z;
Registers
• Variables that store values
• Do not represent real hardware but ..
• .. real hardware can be implemented with registers
• Only one type: reg
reg A, C; // declaration
// assignments are always done inside a procedure
A = 1;
C = A; // C gets the logical value 1
A = 0; // C is still 1
C = 0; // C is now 0
• Register values are updated explicitly!!
Vectors
• Represent buses
wire [3:0] busA;
reg [1:4] busB;
reg [1:0] busC;
• Left number is MS bit
• Slice management
busC[1] = busA[2];
busC = busA[2:1];
busC[0] = busA[1];
• Vector assignment (by position!!)
busB[1] = busA[3];
busB[2] = busA[2];
busB = busA;
busB[3]
= busA[1];
busB[4] = busA[0];
Integer & Real Data Types
• Declaration
integer i, k;
real r;
• Use as registers (inside procedures)
i = 1; // assignments occur inside procedure
r = 2.9;
k = r; // k is rounded to 3
• Integers are not initialized!!
• Reals are initialized to 0.0
Time Data Type
• Special data type for simulation time measuring
• Declaration
time my_time;
• Use inside procedure
my_time = $time; // get current sim time
• Simulation runs at simulation time, not real time
Arrays (i)
• Syntax
integer count[1:5]; // 5 integers
reg var[-15:16]; // 32 1-bit regs
reg [7:0] mem[0:1023]; // 1024 8-bit regs
• Accessing array elements
– Entire element: mem[10] = 8’b 10101010;
– Element subfield (needs temp storage):
reg [7:0] temp;
..
temp = mem[10];
var[6] = temp[2];
Arrays (ii)
• Limitation: Cannot access array subfield or
entire array at once
var[2:9] = ???; // WRONG!!
var = ???; // WRONG!!
• No multi-dimentional arrays
reg var[1:10] [1:100]; // WRONG!!
• Arrays don’t work for the Real data type
real r[1:10]; // WRONG !!
Strings
• Implemented with regs:
reg [8*13:1] string_val; // can hold up to 13 chars
..
string_val = “Hello Verilog”;
string_val = “hello”; // MS Bytes are filled with 0
string_val = “I am overflowed”; // “I ” is truncated
• Escaped chars:
– \n newline
– \t tab
– %% %
– \\ \
– \“ “
Logical Operators
• && logical AND
• || logical OR
• ! logical NOT
• Operands evaluated to ONE bit value: 0, 1 or x
• Result is ONE bit value: 0, 1 or x
A = 6; A && B 1 && 0 0
B = 0; A || !B 1 || 1 1
C = x; C || B x || 0 x
but
butC&&B=0
C&&B=0
Bitwise Operators (i)
•& bitwise AND
•| bitwise OR
•~ bitwise NOT
•^ bitwise XOR
• ~^ or ^~ bitwise XNOR
• Operation on bit by bit basis
Bitwise Operators (ii)
c = ~a; c = a & b;
• a = 4’b1010;
b = 4’b1100;
c = a ^ b;
• a = 4’b1010;
b = 2’b11;
Reduction Operators
• & AND
• | OR
• ^ XOR
• ~& NAND
• ~| NOR
• ~^ or ^~ XNOR
• One multi-bit operand One single-bit result
a = 4’b1001;
..
c = |a; // c = 1|0|0|1 = 1
Shift Operators
• >> shift right
• << shift left
• Result is same size as first operand, always zero filled
a = 4’b1010;
...
d = a >> 2; // d = 0010
c = a << 1; // c = 0100
Concatenation Operator
• {op1, op2, ..} concatenates op1, op2, .. to single
number
• Operands must be sized !!
reg a;
reg [2:0] b, c;
..
a = 1’b 1;
b = 3’b 010;
c = 3’b 101;
catx = {a, b, c}; // catx = 1_010_101
caty = {b, 2’b11, a}; // caty = 010_11_1
catz = {b, 1}; // WRONG !!
• Replication ..
catr = {4{a}, b, 2{c}}; // catr = 1111_010_101101
Relational Operators
•> greater than
•< less than
• >= greater or equal than
• <= less or equal than
• Result is one bit value: 0, 1 or x
1 > 0 1
’b1x1 <= 0 x
10 < z x
Equality Operators
• == logical equality
Return 0, 1 or x
• != logical inequality
• === case equality
Return 0 or 1
• !== case inequality
– 4’b 1z0x == 4’b 1z0x x
– 4’b 1z0x != 4’b 1z0x x
– 4’b 1z0x === 4’b 1z0x 1
– 4’b 1z0x !== 4’b 1z0x 0
Conditional Operator
• cond_expr ? true_expr : false_expr
• Like a 2-to-1 mux ..
A
1
Y
B Y = (sel)? A : B;
0
sel
Arithmetic Operators (i)
• +, -, *, /, %
• If any operand is x the result is x
• Negative registers:
– regs can be assigned negative but are treated as unsigned
reg [15:0] regA;
..
regA = -4’d12; // stored as 216-12 = 65524
regA/3 evaluates to 21861
Arithmetic Operators (ii)
• Negative integers:
– can be assigned negative values
– different treatment depending on base specification or not
reg [15:0] regA;
integer intA;
..
intA = -12/3; // evaluates to -4 (no base spec)
intA = -’d12/3; // evaluates to 1431655761 (base spec)
Operator Precedence
Use parentheses to
enforce your
priority
Hierarchical Design
Top
TopLevel
Level E.g.
Module
Module
Full
FullAdder
Adder
Sub-Module
Sub-Module Sub-Module
Sub-Module
11 22
Half
HalfAdder
Adder Half
HalfAdder
Adder
Basic
BasicModule
Module Basic
BasicModule
Module Basic
BasicModule
Module
11 22 33
Module
module my_module(out1, .., inN);
in1 my_module out1 output out1, .., outM;
in2 out2 input in1, .., inN;
f .. // declarations
inN outM .. // description of f (maybe
.. // sequential)
endmodule
Everything you write in Verilog must be inside a module
exception: compiler directives
Example: Half Adder
A module half_adder(S, C, A, B);
S
output S, C;
B input A, B;
C
wire S, C, A, B;
A S assign S = A ^ B;
Half assign C = A & B;
Half
B Adder
Adder C
endmodule
Example: Full Adder
in1 A Half S I1 A Half S sum
Half Half
Adder
Adder11 I2 Adder
Adder
in2 B C B C I3
ha1
ha1 ha2
ha2 cout
cin
module full_adder(sum, cout, in1, in2, cin);
output sum, cout;
input in1, in2, cin;
wire sum, cout, in1, in2, cin;
Module wire I1, I2, I3; Instance
name name
half_adder ha1(I1, I2, in1, in2);
half_adder ha2(sum, I3, I1, cin);
assign cout = I2 || I3;
endmodule
Hierarchical Names
ha2.A
in1 A Half S I1 A Half S sum
Half Half
Adder
Adder11 I2 Adder
Adder
in2 B C B C I3
ha1
ha1 ha2
ha2 cout
cin
Remember to use instance names,
not module names
Port Assignments
module
• Inputs reg or net net
module
reg or net net
• Outputs
module
net net
• Inouts
Continuous Assignements
a closer look
• Syntax:
assign #del <id> = <expr>;
optional
optional net
nettype
type!!!!
• Where to write them:
– inside a module
– outside procedures
• Properties:
– they all execute in parallel
– are order independent
– are continuously active
Structural Model (Gate Level)
• Built-in gate primitives:
and, nand, nor, or, xor, xnor, buf, not, bufif0,
bufif1, notif0, notif1
• Usage:
nand (out, in1, in2); 2-input NAND without delay
and #2 (out, in1, in2, in3); 3-input AND with 2 t.u. delay
not #1 N1(out, in); NOT with 1 t.u. delay and instance name
xor X1(out, in1, in2); 2-input XOR with instance name
• Write them inside module, outside procedures
Example: Half Adder,
2nd Implementation
A module half_adder(S, C, A, B);
S
output S, C;
B input A, B;
C
wire S, C, A, B;
xor #2 (S, A, B);
and #1 (C, A, B);
Assuming:
• XOR: 2 t.u. delay endmodule
• AND: 1 t.u. delay
Behavioral Model - Procedures
(i)
• Procedures = sections of code that we know
they execute sequentially
• Procedural statements = statements inside a
procedure (they execute sequentially)
• e.g. another 2-to-1 mux implem:
begin
if (sel == 0)
Execution
Y = B;
Flow Procedural
Proceduralassignments:
assignments:
else YYmust
mustbe
bereg
reg!!!!
Y = A;
end
Behavioral Model - Procedures
(ii)
• Modules can contain any number of procedures
• Procedures execute in parallel (in respect to
each other) and ..
• .. can be expressed in two types of blocks:
– initial they execute only once
– always they execute for ever (until simulation
finishes)
“Initial” Blocks
• Start execution at sim time zero and finish
when their last statement executes
module nothing;
initial
$display(“I’m first”); Will
Willbebedisplayed
displayed
atatsim
simtime
time00
initial begin
#50; Will
Willbe bedisplayed
displayed
$display(“Really?”); atatsim
simtime
time50
50
end
endmodule
“Always” Blocks
• Start execution at sim time zero and
continue until sim finishes
Events (i)
• @
always @(signal1 or signal2 or ..) begin
..
end execution
executiontriggers
triggersevery
every
time
timeany
anysignal
signalchanges
changes
always @(posedge clk) begin
execution
executiontriggers
triggersevery
every
.. time
timeclk
clkchanges
changes
end from 0 to 1
from 0 to 1
execution triggers every
always @(negedge clk) beginexecution triggers every
time
time clk
clk changes
changes
..
from
from 11toto 00
end
Examples
• 3rd half adder implem • Behavioral edge-triggered
module half_adder(S, C, A, DFF implem
B); module dff(Q, D, Clk);
output S, C; output Q;
input A, B; input D, Clk;
reg S,C; reg Q;
wire A, B; wire D, Clk;
always @(A or B) begin always @(posedge Clk)
S = A ^ B; Q = D;
C = A && B;
end endmodule
endmodule
Events (ii)
• wait (expr)
always begin
wait (ctrl)
execution
executionloops
loopsevery
every
#10 cnt = cnt + 1;
#10 cnt2 = cnt2 + 2;
time
timectrl
ctrl==11(level
(level
sensitive
sensitivetiming
timingcontrol)
control)
end
• e.g. Level triggered DFF ?
Example
always @(res or posedge clk) begin
res if (res) begin
a Y = 0;
b Y W = 0;
end
else begin
c W Y = a & b;
W = ~c;
clk end
end
Timing (i)
d
initial
initial begin
begin
#5
#5 cc == 1;
1; c
#5
#5 bb == 0;
0;
#5 b
#5 dd == c;
c;
end
end
0 5 10 15
Time
Each assignment is
blocked by its previous one
Timing (ii)
d
initial
initial begin
begin
fork
fork c
#5
#5 cc == 1;
1;
#5 b = 0; b
#5 b = 0;
#5
#5 dd == c;
c;
join 0 5 10 15
join
end
end Time
Assignments are
not blocked here
Procedural Statements: if
E.g. 4-to-1 mux:
module mux4_1(out, in, sel);
output out;
if (expr1) input [3:0] in;
true_stmt1; input [1:0] sel;
reg out;
else if (expr2) wire [3:0] in;
wire [1:0] sel;
true_stmt2;
.. always @(in or sel)
if (sel == 0)
else out = in[0];
def_stmt; else if (sel == 1)
out = in[1];
else if (sel == 2)
out = in[2];
else
out = in[3];
endmodule
Procedural Statements: case
E.g. 4-to-1 mux:
module mux4_1(out, in, sel);
case (expr) output out;
input [3:0] in;
input [1:0] sel;
item_1, .., item_n: stmt1;
reg out;
item_n+1, .., item_m: stmt2; wire [3:0] in;
.. wire [1:0] sel;
default: def_stmt; always @(in or sel)
case (sel)
0: out = in[0];
endcase 1: out = in[1];
2: out = in[2];
3: out = in[3];
endcase
endmodule
Procedural Statements: for
for (init_assignment; cond; step_assignment)
stmt;
E.g.
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
E.g.
module count(Y, start);
output [3:0] Y;
input start;
reg [3:0] Y;
wire start;
integer i;
while (expr) stmt;
initial
Y = 0;
always @(posedge start) begin
i = 0;
while (i < 3) begin
#10 Y = Y + 1;
i = i + 1;
end
end
endmodule
Procedural Statements: repeat
E.g.
module count(Y, start);
output [3:0] Y;
input start;
repeat (times) stmt; reg [3:0] Y;
wire start;
initial
Can
Canbebeeither
eitheran
an Y = 0;
integer
integeror
oraavariable
variable
always @(posedge start)
repeat (4) #10 Y = Y + 1;
endmodule
Procedural Statements:
forever
Typical example:
clock generation in test modules
module test;
reg clk; TTclk ==20
20time
timeunits
units
clk
forever stmt;
initial begin
clk = 0;
forever #10 clk = ~clk;
Executes
Executesuntil
untilsim
sim end
finishes
finishes other_module1 o1(clk, ..);
other_module2 o2(.., clk, ..);
endmodule
Mixed Model
Code that contains various both structure and behavioral styles
module simple(Y, c, clk, res);
output Y;
input c, clk, res;
reg Y;
wire c, clk, res;
res wire n;
c n Y not(n, c); // gate-level
clk
always @(res or posedge clk)
if (res)
Y = 0;
else
Y = n;
endmodule
System Tasks
Always
Alwayswritten
writteninside
insideprocedures
procedures
• $display(“..”, arg2, arg3, ..); much like printf(), displays formatted
string in std output when encountered
• $monitor(“..”, arg2, arg3, ..); like $display(), but .. displays string
each time any of arg2, arg3, .. Changes
• $stop; suspends sim when encountered
• $finish; finishes sim when encountered
• $fopen(“filename”); returns file descriptor (integer); then, you can
use $fdisplay(fd, “..”, arg2, arg3, ..); or $fmonitor(fd, “..”, arg2, arg3, ..);
to write to file
• $fclose(fd); closes file
• $random(seed); returns random integer; give her an integer as a
seed
$display & $monitor string
format
Compiler Directives
• `include “filename” inserts contents of file into current
file; write it anywhere in code ..
• `define <text1> <text2> text1 substitutes text2;
– e.g. `define BUS reg [31:0] in declaration part:
`BUS data;
• `timescale <time unit>/<precision>
– e.g. `timescale 10ns/1ns 50ns
later:
50ns #5 a = b;
Parameter
in[3:0] p_in[3:0]
out[2:0]
s
wu
A.
A.Implelementation
Implelementation
without
withoutparameters
parameters
wd
clk
module dff4bit(Q, D, clk); module dff2bit(Q, D, clk);
output [3:0] Q; output [1:0] Q;
input [3:0] D; input [1:0] D;
input clk; input clk;
reg [3:0] Q; reg [1:0] Q;
wire [3:0] D; wire [1:0] D;
wire clk; wire clk;
always @(posedge clk) always @(posedge clk)
Q = D; Q = D;
endmodule endmodule
Parameter
s (ii)
module top(out, in, clk);
output [1:0] out;
A. input [3:0] in;
A.Implelementation
Implelementation input clk;
without
withoutparameters
parameters(cont.)
(cont.)
wire [1:0] out;
wire [3:0] in;
wire clk;
wire [3:0] p_in; // internal nets
wire wu, wd;
assign wu = p_in[3] & p_in[2];
assign wd = p_in[1] & p_in[0];
dff4bit instA(p_in, in, clk);
dff2bit instB(out, {wu, wd}, clk);
// notice the concatenation!!
endmodule
Parameters
(iii)
module top(out, in, clk);
B.
B.Implelementation
Implelementation output [1:0] out;
with input [3:0] in;
withparameters
parameters input clk;
wire [1:0] out;
module dff(Q, D, clk); wire [3:0] in;
wire clk;
parameter WIDTH = 4;
output [WIDTH-1:0] Q; wire [3:0] p_in;
input [WIDTH-1:0] D; wire wu, wd;
input clk;
assign wu = p_in[3] & p_in[2];
reg [WIDTH-1:0] Q; assign wd = p_in[1] & p_in[0];
wire [WIDTH-1:0] D;
wire clk; dff instA(p_in, in, clk);
// WIDTH = 4, from declaration
always @(posedge clk) dff instB(out, {wu, wd}, clk);
Q = D; defparam instB.WIDTH = 2;
// We changed WIDTH for instB only
endmodule
endmodule
Testing Your
Modules
module top_test;
wire [1:0] t_out; // Top’s signals
reg [3:0] t_in;
reg clk;
top inst(t_out, t_in, clk); // Top’s instance
initial begin // Generate clock
clk = 0;
forever #10 clk = ~clk;
end
initial begin // Generate remaining inputs
$monitor($time, " %b -> %b", t_in, t_out);
#5 t_in = 4'b0101;
#20 t_in = 4'b1110;
#20 t_in[0] = 1;
#300 $finish;
end
endmodule
The Veriwell Simulator
• Assuming that modules dff, top and top_test
reside in files dff.v, top.v and top_test.v
respectively, run:
~hy225/veriwell/sparc_bin/veriwell dff.v top.v
top_test.v
• result:
.. (initial messages)
0 xxxx -> xx
5 0101 -> xx
25 1110 -> xx
30 1110 -> 00
45 1111 -> 00
50 1111 -> 10
70 1111 -> 11
.. (final messages)