Download as pdf or txt
Download as pdf or txt
You are on page 1of 92

Re Configurable Computing

CS G553

Introduction to Verilog
Hardware Description Languages (HDL)
• The 'capture language'—often beginning with a high-level algorithmic
description.
• Resemble concurrent programming languages.
• HDL design generally ends at the synthesis stage
• HDLs, 'compiler' refers to synthesis, a process of transforming the HDL
code listing into a physically realizable gate netlist
• Simulation by a test bench. Even driven.
• Two widely used hardware description languages
— VHDL
— Verilog
• HDL languages can describe circuits from two perspectives
— function
— structure
• Verilog introduced by Gateway Design automation in 1985.
Levels of Abstraction
• Switch Level: Module implemented with switches and
interconnects. Lowest level of Abstraction
• Gate Level: Module implemented in terms of logic gates
and interconnection between gates
• Dataflow Level: Module designed by specifying dataflow.
Designer is aware of how data flows between hardware
registers and how the data is processed in the design
• Behavioral Level :Module can be implemented in terms of
the desired design algorithm without concern for the
hardware implementation details. Very similar to C
programming.
Module
• Basic building block in
Verilog.
• module name (port_list)
• A module definition starts Interface
• port declarations
with the keyword • parameter declarations
module ends with the Optional add-ons
• include directives
keyword endmodule • variable declarations
Body • assignments
• low-level module instantiation
• initial and always blocks
• task and function
• End module
Ex: Module
module toggle(q, clk, reset);
… reset toggle
q
<functionality of module>

endmodule clk

• The internal of each module can be defined at four levels of


abstraction
o Behavioral or algorithmic level
o Dataflow level
o Gate level
o Switch level

• Verilog allows different levels of abstraction to be mixed in the same


module.
Number specification
• Comments are designated by // to the end of a line or by /* to */
across several lines.

<size>’<base format><number>

specifies the
number of bits
in the number d or D for decimal Number
Examples: h or H for hexadecimal depends on
• 4’b1111 b or B for binary the base
• 12’habc o or O for octal
• 16’d235
• 12’h13x X or x: don’t care
• -6’d3 Z or z: high impedence
• 12’b1111_0000_1010 _ : used for readability
Net
• Represents connections between
hardware elements.
• Continuously driven by output of
connected devices.
• Declared using the keyword
wire.

wire a;//Declare net a for above ckt


wire b, c;//Declare two wires b,c
wire d=1’b0;
Ex: Net declaration

…… addr

Processor
wire r_w; // scalar signal

Memory
data
wire [7:0] data; // vector signal
wire [9:0] addr; // vector signal r_w
……
Port
Provide interface by
which a module can
communicate with
its environment

module fulladd4(sum, c_out, a, b, c_in); //Module with a list of ports


module Top; // No list of ports, top-level module in simulation

Verilog Type of
keyword port

input Input port

output Output port

inout Bi-
directional
Ex: Port

module DFF(q, d, clk, reset);


output q;
reg q;
input d, clk, reset;
...
...
endmodule
Port connection rules
• Internally, input ports must
always be of the type net.
• Externally, the inputs can be
connected to a variable which is a
reg or a net.
• Internally, outputs ports can be
of the type reg or net.
• Externally, outputs must always
be connected to a net.
• Internally, inout ports must
always be of the type net.
• Externally, inout ports must
always be connected to a net.
• Legal to connect internal and
external items of different sizes
when making intermodule port
connections.
• Allows ports to remain
unconnected
Nets vs Ports
Nets are internal signals that cannot be accessed by outside
environment
Ports are external signals to interface with outside environment
—input ports can be read but cannot be written
— output ports can be written but cannot be read
— inout ports can be read and written

pc
module pc (clk, rst, status, i_o);
input clk, rst; clk
output [3:0] status;
addr[9:0]
inout [7:0] i_o;
rst

Processor
wire r_w;

Memory
wire [7:0] data; data[7:0]
wire [9:0] addr; status[3:0]
…… r_w
endmodule i_o[7:0]
Register
 Registers represent data storage elements.
 They retain value until another value is placed
onto them.
 In Verilog, a register is merely a variable that can
hold a value.
 They do not need a clock as hardware registers
do.

reg reset;
initial
begin
reset = 1’b1;
#100 reset=1’b0;
end
Register declaration

 A register declaration starts with keyword reg.


 Registers can be used to describe the behaviour of
sequential circuits
 Registers can also be used to implement registered
output ports

module pc (clk, rst, status, i_o);


input clk, rst;
output [3:0] status;
reg [3:0] status;
inout [7:0] i_o;
……
Vectors
• A net or register can be declared as vectors.
• wire a;
• wire [7:0] bus;
• wire [31:0] busA, busB, busC;
• reg clock;
• reg [0:40] virt_address;

•Possible to address bits or parts of vectors


• busA[7]
• bus[2:0]
• virt_addr[0:2]
Real

 declared with the keyword real


 cannot have a range declaration
 default value is 0

•real delta;
• initial
• begin
• delta = 4e10;
• delta = 2.13;
• end
• integer i;
• initial
• i = delta;
Arrays
 Arrays are multiple elements that are 1-bit or n-bits wide.
 Possible to have arrays of type reg, integer, real
 Arrays of nets can also be used to connect ports of generated
instances

• integer count[0:7];
• reg [4:0] port_id[0:7]; // Array of 8 port_ids; each port_id is 5 bits wide
• integer matrix[4:0][0:255]; // Two dimensional array of integers
Memory
 Used to model register files, RAMs and ROMs.
 A memory component can be defined using reg variables
 Modeled in Verilog as a one-dimensional array of registers.

reg mem1bit[0:1023]; // Memory mem1bit with 1K 1-bit words


reg [7:0] membyte[0:1023]; // Memory membyte with 1K 8-bit words(bytes)
membyte[511] // Fetches 1 byte word whose address is 511.

myMem[0]

myMem[1]

reg [7:0] myMem [3:0]; myMem[2]

myMem[3]
Parameters
 Define constants .
 Makes code easy to read and modify
 Can’t be used as variables.

• parameter port_id=5;
• parameter bussize = 8;
• reg [bussize-1 : 0] databus1;
• reg [bussize-1 : 0] databus2;
Strings

Strings can be stored in reg.


The width of the register variables must be large enough to hold the
string.
• reg [8*19:1] string_value;
• initial
• string_value = “Hello Verilog World”;
Modules and ports

module fulladd4(sum, c_out, a, b,


All port declarations (input, c_in);
output, inout) are implicitly output [3:0] sum;
declared as wire
output c_out;
input [3:0] a, b;
input c_in;


endmodule

module DFF(q, d, clk, reset);


output reg q;
If the output hold their value,
input d, clk, reset;
they must be declared as reg …

endmodule
Module declaration (ANSI C style)

module fulladd4(output reg[3:0] sum,


output reg c_out,
input [3:0] a, b,
input c_in);


endmodule
Module instantiation

module Top;
reg [3:0] A, B;
reg C_IN;//externally, inputs can be a reg or a wire; internally must be wires
wire [3:0] SUM; //externally must be wires
wire C_OUT;
// one way
fulladd4 FA1(SUM, C_OUT, A, B, CIN);
// another possible way
fulladd4 FA2(.c_out(C_OUT), .sum(SUM), .b(B), .c_in(C_IN), .a(A));

endmodule

module fulladd4(sum, c_out, a, b, c_in);


output [3:0] sum;
output c_out;
input [3:0] a, b;
input c_in;


endmodule
Module instantiation..

Port connecting rules

input net or reg

inout net

output net
Module instantiation…
Signal assignment follows port list order
Module instantiation..
Signal assignment by port names

— The two methods cannot be mixed!


Module instantiation..
Unconnected ports

by port list order

by name
Gate level modeling (structural)

 The circuit is described in terms of gates.


 Hardware design at this level is intuitive
 All instances are executed concurrently just as in hardware
 Instance name is not necessary
 The first terminal in the list of terminals is an output and the other
terminals are inputs

.
wire Z, Z1, OUT, OUT1, OUT2, IN1, IN2;
and a1(OUT1, IN1, IN2);
nand na1(OUT2, IN1, IN2);
xor x1(OUT, OUT1, OUT2);
not (Z, OUT);
buf final (Z1, Z);
.
Predefined gate primitives
 supports basic logic gates as predefined primitives.
 instantiated like any other modules.

a
and (d, a, b, c) b d
c

buf (a, b) b a

a
not (a, b, c) c
b
Predefined gate primitives

tri-state gates: bufif1, bufif0, notif1, notif0

e.g. c
bufif1 (a, b, c) b a

c
e.g.
notif0 (a, b, c) a
b
Example of structural Verilog code
Example of using predefined gate primitives
Array of gate instances

wire [7:0] OUT, IN1, IN2;

// array of gates instantiations


nand n_gate [7:0] (OUT, IN1, IN2);

// which is equivalent to the following


nand n_gate0 (OUT[0], IN1[0], IN2[0]);
nand n_gate1 (OUT[1], IN1[1], IN2[1]);
nand n_gate2 (OUT[2], IN1[2], IN2[2]);
nand n_gate3 (OUT[3], IN1[3], IN2[3]);
nand n_gate4 (OUT[4], IN1[4], IN2[4]);
nand n_gate5 (OUT[5], IN1[5], IN2[5]);
nand n_gate6 (OUT[6], IN1[6], IN2[6]);
nand n_gate7 (OUT[7], IN1[7], IN2[7]);
User Defined Primitives (UDPs)
• custom-built primitives
• do not instantiate other
modules or primitives
//UDP name and terminal list
• instantiated exactly like gate-
primitive <udp_name> (
level primitives <output_terminal_name>(only one allowed)
<input_terminal_names> );
//Terminal declarations
output <output_terminal_name>;
input <input_terminal_names>;
reg <output_terminal_name>;(optional; only for
sequential UDP)
// UDP initialization (optional; only for sequential UDP
initial <output_terminal_name> = <value>;
//UDP state table
table
<table entries>
endtable
//End of UDP definition
endprimitive
Combinational UDPs
primitive <udp_name> (
Example: 2-to-1 multiplexer <output_terminal_name>
<input_terminal_names> );
output <output_terminal_name>;
input <input_terminal_names>;
table
<table entries>
endtable
endprimitive

— Combinational UDPs don’t need initialization


— The first signal in the port list is always output. However, in the truth table
the output signal value is at the end (after a colon).
— Input order in the truth table must follow the order given in the port list.
— Output for unspecified combination is always X.
Sequential UDPs
primitive <udp_name> (
Example: D-Latch <output_terminal_name> <input_terminal_names> );
output <output_terminal_name>;
input <input_terminal_names>;
reg <output_terminal_name>;
initial <output_terminal_name> = <value>;
table
<table entries>
endtable
endprimitive

— Output Q is initialized by initial block.


— In the truth table Q is the current state, Q* is the next state.
— Symbol – indicates the next state is the same as the current state.
Sequential UDPs
Example: D Flip-Flop

— r for rising edge, same as (01)


— f for falling edge, same as (10)
— p for positive edge, same as (01), (0X), (X1)
— n for negative edge, same as (10), (1X), (X0)
— * for any change, same as (??)
Using UDPs
Example: 4-bit synchronous counter

Defining UDPs

— Cannot be defined
within modules.
— Can be defined after
or before the module in
the same file.
— Can be defined
in a separate file
and use include
directive to include
to the code.
Dataflow modeling

 Module is designed by specifying the data flow.


 Designer is aware of how data flows between hardware registers
and how the data is processed in the design
 Continuous assignment is one of the main constructs used in
dataflow modeling
 assign out = i1 & i2;
 assign addr[15:0] = addr1[15:0] ^ addr2[15:0];
 assign {c_out, sum[3:0]}=a[3:0]+b[3:0]+c_in;

 A continuous assignment is always active and the assignment


expression is evaluated as soon as one of the right-hand-side
variables changes
 Left-hand side must be a scalar or vector net.
 Right-hand side operands can be registers, nets, integers, real, …
Operators in dataflow expressions

• Similar to C except that there are no ++ or –

• Arithmetic: *, /, +, -, % and **
• Logical: !, && and ||
• Relational: >, <, >= and <=
• Equality: ==, !=, === and !==
• Bitwise: ~, &, |, ^ and ^~
• Reduction: &, ~&, |, ~|, ^ and ^~
• Shift: <<, >>, >>> and <<<
• Concatenation: { }
• Replication: {{}}
• Conditional: ?:
Example

module mux4(out, i0, i1, i2, i3, s1, s0);


output out;
input i0, i1, i2, i3;
output s1, s0;

assign out = (~s1 & ~s0 & i0) |


(~s1 & s0 & i1) |
(s1 & ~s0 & i2) |
(s1 & s0 & i3);

// OR THIS WAY
assign out = s1 ? (s0 ? i3:i2) : (s0 ? i1:i0);

endmodule
Example: A 2-to-4 decoder

Circuit schematic

Data flow code


Structural code
Arithmetic operators

 Available operators: +, -, *, /, % (modulo)


 Arithmetic operators treat register operands as unsigned values
 Example:

integer A; reg [7:0] A;


A = -12; A = -12;
A/4 -3 A/4 61
Shifter operators

<< : shift left

reg [3:0] A;
1 1 0 1 A << 2 0 1 0 0

— zeros are moved in from the right end

>> : shift right

reg [3:0] A;
1 1 0 1 A >> 2 0 0 1 1
Concatenation operators

Example

reg [7:0] A, B, Data;


reg c;
……
A = 10101101; B= 00110011;
c = 0;
Data = {A[3:0], B[7:6], c, c}; // Data = 11010000

Data 1 1 0 1 0 0 0 0

c c
A[3:0] B[7:6]
Continuous assignment
 Continuous assignment starts with keyword
assign.
 The left hand side of a continuous assignment
command must be a net-type signal

Example
a x
b AND

OR o
c

module cir1 (o, a, b, c); module cir1 (o, a, b, c);


output o; output o;
input a, b, c; input a, b, c;
wire x; OR wire x = a & b;
assign x = a & b; assign o = x | c;
assign o = x | c; endmodule
endmodule
Rules:
 The left hand side of an assignment must always be a scalar
or vector net
 It cannot be a scalar or vector register.
 Continuous assignments are always active.
 The assignment expression is evaluated as soon as one of
the right-hand-side operands changes and the value is
assigned to the left-hand-side net.
 The operands on the right-hand side can be registers or
nets.
 Delay values can be specified for assignments in terms of
time units. Delay values are used to control the time when a
net is assigned the evaluated value.
Conditional assignment
A conditional assignment has three signals at the right hand side.
 The first signal is the control signal
 If the control signal is true, the second signal is assigned to
the left hand side (LHS) signal ; otherwise, the third signal
is assigned to LHS signal.
Adding delay to continuous assignment

 Delay is added by # t after keyword assign, t is the number of


delayed time units.
 Time unit is defined by `timescale

Example

`timescale 10ns/1ns // <ref_time_unit>/<time_precision>


module buf1 (o, i);
output o;
input i;
….
assign #3 o = 1; // delay for 3 time units
….
endmodule
Delay in procedural assignments

Delay specified in front of procedural assignment statements


(e.g. #3 a = b&c;) delay the execution of the entire statement.

Module delayTest;
integer a, b, c;
initial begin
a = 2; b = 3; Change a from 2 to 4
end after 3 time unit
initial #3 a = 4;
initial #5 c = a+b; Execution order:
endmodule 1. delay
2. evaluation
3. assignment

Result: c=7
Delay in procedural assignments

Delay specified right after = in procedural assignment statements


(e.g. a = #3 b&c;) just delay the assignment operation. The evaluation
of the right hand side expression is executed without delay.

Module delayTest;
integer a, b, c;
initial begin
a = 2; b = 3; Change a from 2 to 4
end after 3 time unit
initial #3 a = 4;
initial c = #5 a+b; Execution order:
endmodule 1. evaluation
2. delay
3. assignment

Result: c=5
Behavioral or algorithmic modeling
• Design is expressed in algorithmic level, .
which frees designers from thinking in .
terms of logic gates or data flow. reg a, b, c;
• Designing at this model is very similar to
programming in C. initial a=1’b0;
• All algorithmic statements in Verilog can .
appear only inside two statements: .
always and initial. always
begin
• Each always and initial statement b = a ^ 1’b1;
represents a separate activity flow in c = a + b;
Verilog. end
• Activity flows in Verilog run in parallel. .
• You can have multiple initial and .
always statements but you can’t nest
them.
Behavioral blocks

 In additional to assignment, other functional description


codes are included in two-type behavioural blocks:
 initial blocks
 always blocks
 A module can have multiple blocks, but blocks cannot be
nested.
 When a block has multiple statements, they must be
grouped using
begin and end (for sequential statements) or
fork and join (for concurrent statements).
 An initial block is executed at the beginning of simulation. It
is executed only once.
 Always blocks are repeatedly executed until simulation is
stopped.
Initial statement
• An initial block start at time 0, executes exactly once
and then never again.
• If there are multiple initial blocks, each block starts to
execute concurrently at time 0 and each block finishes
execution independently of the others.
• Multiple behavioral statements must be grouped using
begin and end. If there is one statement then grouping is
not necessary.

reg x, y, m;
initial m=1’b0;

initial
begin
x=1’b0;
y=1’b1;
end
Example

A 2-to-4 decoder behavioral Verilog code


always statement
• The always statement starts at time 0 and executes the
statements in the always block continuously in a looping
fashion.
• It models a block of activity that is repeated
continuously in a digital circuit.
• Multiple behavioral statements must be grouped using
begin and end. If there is one statement then grouping is
not necessary.

integer count;
count=0;
always
begin
count=count+1;
end
Events-based timing control
• An event is the change in the value on a register or a net.
• Events can be utilized to trigger the execution of a statement of a
block of statements.
• The @ symbol is used to specify an event control.
• Statements can be executed on changes in signal value or at a
positive (posedge) or negative (negedge) transition of the signal.

input clock; input clock1, clock 2;


integer count; integer count;

count=0; count=0;

always @(clock) always @(clock1 or clock2)


begin begin
count=count+1; count=count+1;
end end
Procedural assignments
• Procedural assignments update values of reg, integer,
or real variables.
• The value will remain unchanged until another
procedural assignment updates the variable with a
different value → different from dataflow continuous
assignments.
• Two types of procedural assignments: blocking and
nonblocking. Nonblocking
statements
Blocking statements,
specified using the = • specified using the
reg x, y; reg x, y;
operator. <= operator
are executed in the initial • are executed without initial
order they are specified begin blocking the begin
in a sequential block. x=1’b1; statements that flow x<=1’b1;
y=1’b0; in a sequential y<=1’b0;
end block. end
Blocking assignments v.s. Non-blocking assignments

Blocking assignments are performed sequentially.

initial begin
a = #1 1; // assignment at time 1
b = #3 0; // assignment at time 4 (3+1)
c = #6 1; // assignment at time 10 (6+3+1)
end

Non-blocking assignments are performed concurrently.

initial begin
#1 a < = 1; // assignment at time 1
#3 b <= 0; // assignment at time 3
#6 c <= 1; // assignment at time 6
end
Parallel blocks

 Parallel block is a more flexible method to write concurrent statements.


It uses fork and join, instead of begin and end, in block description.

Sequential block with Sequential block with


blocking assignments Non-blocking assignments

Parallel block
Event control statements
 An event occurs when a net or register changes it value.
 The event can be further specified as a rising edge (by posedge) or
falling edge (by negedge) of a signal.
 An event control statement always starts with symbol @

@ (clk) Q = D; // assignment will be performed whenever


signal clk changes to its value

@ (posedge clk) Q = D; // assignment will be performed whenever


signal clk has a rising edge (01, 0X,
0Z, X1, Z1)

@ (negedge clk) Q = D; // assignment will be performed whenever


signal clk has a falling edge (10, 1X,
1Z, X0, Z0)
Uses of nonblocking assignments
 If the intention is to swap the contents of a and b, which one of
these will work?
always @(posedge clock) always @(posedge clock)
begin begin
a = b; a <= b;
b = a; b <= a;
end end

 Nonblocking assignments eliminate the race conditions.


At the positive edge of clock, the values of all the RHS
variables are “read”, expressions evaluated and then
assigned to the LHS.
Conditional statements
• Very similar to C .
• Can always appear inside if(alu_control == 0)
always and initial blocks y = x + z;
else if (alu_control == 1)
y = x – z;
else if (alu_control == 2)
. y = x * z;
if(x) else
begin y = x;
y= 1’b1; .
z= 1’b0;
end reg [1:0] alu_control;
expression
. ..
if (count < 10) case (alu_control)
count = count+1; 2’d0 : y = x + z;
else 2’d1 : y = x – z;
count = 0; 2’d2 : y = x * z;
. default: y=x;
endcase
Loops
 Four types of loops integer count;
integer y=1;
 while, for, repeat, and forever integer x=2;

 Can appear only inside an initial initial


for (count = 0; count < 128; count = count + 1)
or always block. begin
 Can contain delay expressions. x <= x + y;
y <= x;
end

Must contain a
number or a
signal value;
initial initial only evaluated
once at the
count = 0; count = 0; beginning

while (count < 128) repeat(128)


begin begin
. .
. .
count = count +1; count = count +1;
end end
Loop Example..
Synthesizing registers
Wait statements
Allow designers to more specifically control when to execute statements.
Starts with keyword wait followed by a logic condition

module testWait;
integer a, b, c;
reg en;
initial a = 0;
initial #3 a = 3;
intial #6 a = 7;
wait (a==7) b = 1; // assign 1 to b when a=7
wait (en) c = 2; // assign 2 to c when en is true
endmodule
Case statement

 Readable alternative to nested if-else statements.


Sensitivity list

 Sensitivity list specifies events on which signals activate or block

//A level-sensitive latch with asynchronous reset


always @( reset or clock or d)
//Wait for reset or clock or d to change
begin
if (reset) //if reset signal is high, set q to 0.
q = 1'b0;
else if(clock) //if clock is high, latch input
q = d;
end
Hierarchical naming

• As described, every module instance, signal, or variable is identified with


an identifier.
• Each identifier has a unique place in the design hierarchy.
• Hierarchical name referencing allows us to denote every identifier in the
design hierarchy with a unique name.
• A hierarchical name is a list of identifiers separated by dots “.” for each
level of hierarchy
• Examples: stimulus.q, stimulus.m1.Q, stimulus.m1.n2
Named blocks
• Blocks can be given names
— Local variables can be declared from the names block
— Variables in a named block can be accessed by using
hierarchical name referencing
— Named blocks can be disabled

always
begin : block1
integer i;
i=1;

end

always
begin : block2
integer j;
j = block1.i^1;
end
Disabling named blocks
• The keyword disable provides a way to terminate the
execution of a named block.
• Disable can be used to get out of loops, handle error
conditions, or control execution of pieces of code based on
control signal
• Disabling a block causes the execution control to be passed
to the statement immediately succeeding the block
initial
begin
i=0;
flag=8’b0010_0101;
begin: block1
while (i < 16)
begin
if (flag[i]) disable block1;
i = i+1;
end
end
Tasks and functions
• Often it is required to implement the same functionality at
many times in a behavioral design.
• Verilog provides tasks and functions to break up large
behavioral code into smaller pieces.
• Tasks and functions are included in the design hierarchy.
Like named blocks, tasks and functions can be addressed
by means of hierarchical names.
• Tasks have input, output and inout arguments
• Functions have input arguments
• Tasks and functions are included in the design hierarchy.
Like named blocks, tasks or functions can be addressed by
means of hierarchical names
Tasks
• Tasks are declared with the module …
keywords task and endtask. …
• Tasks can have input, inout, always
and output arguments to begin
pass values (different than BOP (AB_AND, AB_OR, AB_XOR, A, B);
in modules). BOP (CD_AND, CD_OR, CD_XOR, C, D);
• Tasks or functions can have end
local variables but cannot
have wires.
task BOP;
• Tasks and functions can only output [15:0] ab_and, ab_or, ab_xor;
contain behavioral input [15:0] a, b;
statements. begin
• Tasks and functions do not ab_and = a & b;
contain always or initial ab_or = a | b;
statements but are called ab_xor = a ^ b;
from always blocks, initial end
blocks, or other tasks and endtask
functions. …
• Can operate directly on reg endmodule
variables defined in the
module
Module vs task instantiation
module …
• Instantiated modules create …
duplicate copies in hardware. always
BOP (AB_AND, AB_OR, AB_XOR, A, B);
• In contrast tasks are static in
nature. All declared items are always
statically allocated and they are BOP (CD_AND, CD_OR, CD_XOR, C, D);
shared across all uses of the
task.
task automatic BOP;
• If a task is called from within a
output [15:0] ab_and, ab_or, ab_xor;
behavioral block, only one copy input [15:0] a, b;
is needed begin
• However, a task/function might ab_and = a & b;
be called concurrently form ab_or = a | b;
different behavioral blocks, ab_xor = a ^ b;
which can lead to incorrect end
endtask
operation → avoid by using the

automatic keyword to make a endmodule
task re-entrant
Functions
• Functions are typically used for
combinational modeling (use for
conversions and commonly used module …

calculations).
reg [31:0] parity;
• Need at least one input argument
but cannot have output or inout always @(addr)
begin
arguments.
parity = calc_parity(addr);
• The function is invoked by end
specifying function name and input
function calc_parity;
arguments, and at the end
input [31:0] address;
execution, the return value is begin
placed where the function was calc_parity = ^address;
invoked end
endfunction
• Functions cannot invoke other …
tasks; they can only invoke other endmodule
functions. Recursive functions are
not synthesizable
Functions vs Tasks

Functions Tasks

A function can enable another A task can enable other tasks


function but not another task. and functions.
Functions always execute in 0 Tasks may execute in non-zero
simulation time. simulation time.
Functions must not contain any Tasks may contain delay, event,
delay, event, or timing control or timing control statements.
statements.
Functions must have at least Tasks may have zero or more
one input argument. They can arguments of type input,
have more than one input. output, or inout.
Functions always return a Tasks do not return with a
single value. They cannot have value, but can pass multiple
output or inout arguments. values through output and
inout arguments.
Avoiding unwanted latches
Incomplete system specifications (if-else, or case) lead to unwanted latches

— Latch-prone code — Latch-free code


Creating testbench

Used to verify the designed circuit.


Testbench example

Testbench Unit under test

Simulation result
Example: clock display

minutes seconds
HEX3 HEX2 HEX1 HEX0
Task to display digits

task digit2sev(input integer digit, output [6:0] disp);


begin
if (digit == 0) disp = 7'b1000000;
else if (digit == 1) disp = 7'b1111001;
else if (digit == 2) disp = 7'b0100100;
else if (digit == 3) disp = 7'b0110000;
else if (digit == 4) disp = 7'b0011001;
else if (digit == 5) disp = 7'b0010010;
else if (digit == 6) disp = 7'b0000011;
else if (digit == 7) disp = 7'b1111000;
else if (digit == 8) disp = 7'b0000000;
else if (digit == 9) disp = 7'b0011000;
end
endtask
task display_time(input [5:0] s, input [5:0] m);
begin
digit2sev(s%10, HEX0);
digit2sev(s/10, HEX1);
digit2sev(m%10, HEX2);
digit2sev(m/10, HEX3);
end
endtask

task digit2sev(input integer digit, output [6:0] disp);


begin
if (digit == 0) disp = 7'b1000000;
else if (digit == 1) disp = 7'b1111001;
else if (digit == 2) disp = 7'b0100100;
else if(digit == 3) disp = 7'b0110000;
else if(digit == 4) disp = 7'b0011001;
else if(digit == 5) disp = 7'b0010010;
else if(digit == 6) disp = 7'b0000011;
else if(digit == 7) disp = 7'b1111000;
else if(digit == 8) disp = 7'b0000000; HEX3 HEX2 HEX1 HEX0
else if(digit == 9) disp = 7'b0011000;
end
endtask
endmodule
Implementation
module clock(CLOCK_50, HEX0, HEX1, HEX2, HEX3);
output reg [6:0] HEX0, HEX1, HEX2, HEX3;
input CLOCK_50; integer count=0;
reg [3:0] d1=0, d2=0, d3=0, d4=0;

always @(posedge CLOCK_50) module clock(CLOCK_50, HEX0, HEX1, HEX2, HEX3);


begin input CLOCK_50;
count=count+1; output reg [6:0] HEX0, HEX1, HEX2, HEX3;
if (count == 50_000_000) integer count=0;
begin reg [15:0] ticks=16'd0;
count=0; d1 = d1+1; reg [5:0] seconds=6'd0, minutes=6'd0;
if(d1 == 10)
begin initial display_time(seconds, minutes);
d1 = 0; d2 = d2+1;
if(d2 == 6) always @(posedge CLOCK_50)
begin begin
d2 = 0; d3 = d3 + 1; count = count+1;
if(d3 == 10) if (count == 50_000_000)
begin begin
d3 = 0; d4 = d4 + 1; count=0;
if(d4 == 6) d4 = 0; ticks = ticks + 1;
seconds = ticks % 60;
end minutes = ticks / 60;
end display_time (seconds, minutes);
end end
digit2sev(d1, HEX0); digit2sev(d2, HEX1); end
digit2sev(d3, HEX2); digit2sev(d4, HEX3);

end
end Alt-2
task digit2sev; Alt-1

endtask

endmodule
Resource utilization=Alt 1

Resource utilization is 152 LEs


Resource utilization for Alt-2
• Circuit consumes 611 LEs (2% of the chip logic resources).
• You have to be careful! Changing ticks, seconds and
minutes to integer increases area to become 2500 LEs (8%
of the utilization)
Synthesis tips

 Nested if-else leads to lengthy mux-chain, which is normally slow.


Using case instead.
 However, case results in mux with multiple inputs, which makes
routing more difficult.
 Using instantiated module to implement arithmetic operators,
instead of directly using arithmetic operators. Good partition
leads to better results.
 Assign values to all outputs in all cases (to avoid unwanted
latches).
Synthesis for Reusability

 Register all the outputs of critical design blocks


 Avoid path that traces through number of hierarchies
and then return back to same hierarchy
 Partition the design based on functional goals and the
clock domains
 Avoid instantiating technology specific modules
 Use parameters and declare them at the top with
meaningful names
 Avoid internally generated clocks and resets
 Avoid glue logic at the top level
References

•“Verilog HDL” by Samir Palnitkar; Pearson


•Verilog Interactive tutorial by Aldec
•Design guidelines: http://www.inno-logic.com/resourcesTips.html

You might also like