System Verilog For Verification: Dr.R.Jayagowri
System Verilog For Verification: Dr.R.Jayagowri
Dr.R.Jayagowri
Verilog
Verilog Data Types and Values
• Bits - value on a wire
– 0, 1
– X - don’t care/don’t know
– Z - undriven, tri-state
• Vectors of bits
– A[3:0] - vector of 4 bits: A[3], A[2], A[1], A[0]
– Treated as an unsigned integer value
• e.g. , A < 0 ??
– Concatenating bits/vectors into a vector
• e.g., sign extend
• B[7:0] = {A[3], A[3], A[3], A[3], A[3:0]};
• B[7:0] = {3{A[3]}, A[3:0]};
– Style: Use a[7:0] = b[7:0] + c;
Not: a = b + c; // need to look at declaration
clk
endmodule
9/6/2007 EECS 150, Fa07, Lec 04-HDL 18
Behavioral with Bit Vectors
//Behavioral model of 32-bitwide 2-to-1 multiplexor.
module mux32 (in0,in1,select,out);
input [31:0] in0,in1;
input select;
output [31:0] out; • Notes:
// – inputs, outputs 32-bits wide
reg [31:0] out;
always @ (in0 or in1 or select)
if (select) out=in1;
else out=in0;
endmodule // Mux
mux2
m0 (.select(select[0]), .in0(in0), .in1(in1), .out(w0)),
m1 (.select(select[0]), .in0(in2), .in1(in3), .out(w1)),
m3 (.select(select[1]), .in0(w0), .in1(w1), .out(out));
endmodule // mux4
Which select?
9/6/2007 EECS 150, Fa07, Lec 04-HDL 20
Verilog if
• Same syntax as C if statement
• Sequential meaning, action “at once”
always @(sel or A or B or C or D)
if (sel == 2’b00) Y = A;
else if (sel == 2’b01) Y = B;
else if (sel == 2’b10) Y = C;
else if (sel == 2’b11) Y = D;
endmodule
9/6/2007 EECS 150, Fa07, Lec 04-HDL 21
Verilog if
// Simple 4-1 mux
module mux4 (sel, A, B, C, D, Y);
input [1:0] sel; // 2-bit control signal
input A, B, C, D;
output Y;
reg Y; // target of assignment
always @(sel or A or B or C or D)
if (sel[0] == 0)
if (sel[1] == 0) Y = A;
else Y = B;
else
if (sel[1] == 0) Y = C;
else Y = D;
endmodule
always @(sel or A or B or C or D)
case (sel)
2’b00: Y = A;
2’b01: Y = B; Conditions tested in
2’b10: Y = C; top to bottom order
2’b11: Y = D;
endcase
endmodule
9/6/2007 EECS 150, Fa07, Lec 04-HDL 23
Verilog case
• Without the default case, this example would create a latch for Y!
– your generating hardware, not programming
• Assigning X to a variable means synthesis is free to assign any value
always @(A)
case (A)
8’b00000001: Y = 0;
8’b00000010: Y = 1;
8’b00000100: Y = 2;
8’b00001000: Y = 3;
8’b00010000: Y = 4;
8’b00100000: Y = 5;
8’b01000000: Y = 6;
8’b10000000: Y = 7;
default: Y = 3’bX; // Don’t care when input is not 1-hot
endcase
endmodule
9/6/2007 EECS 150, Fa07, Lec 04-HDL 24
Verilog case (cont)
• Cases are executed sequentially
– The following implements a priority encoder
// Priority encoder
module encode (A, Y);
input [7:0] A; // 8-bit input vector
output [2:0] Y; // 3-bit encoded output
reg [2:0] Y; // target of assignment
always @(A)
case (1’b1)
A[0]: Y = 0;
A[1]: Y = 1;
A[2]: Y = 2;
A[3]: Y = 3;
A[4]: Y = 4;
A[5]: Y = 5;
A[6]: Y = 6;
A[7]: Y = 7;
default: Y = 3’bX; // Don’t care when input is all 0’s
endcase
endmodule
9/6/2007 EECS 150, Fa07, Lec 04-HDL 25
Parallel Case
• A priority encoder is more expensive than a simple encoder
– If we know the input is 1-hot, we can tell the synthesis tools
– “parallel-case” pragma says the order of cases does not matter
// simple encoder
module encode (A, Y);
input [7:0] A; // 8-bit input vector
output [2:0] Y; // 3-bit encoded output
reg [2:0] Y; // target of assignment
always @(A)
case (1’b1) // synthesis parallel-case
A[0]: Y = 0;
A[1]: Y = 1;
A[2]: Y = 2;
A[3]: Y = 3;
A[4]: Y = 4;
A[5]: Y = 5;
A[6]: Y = 6;
A[7]: Y = 7;
default: Y = 3’bX; // Don’t care when input is all 0’s
endcase
endmodule
// simple encoder
module encode (A, Y);
input [7:0] A; // 8-bit input vector
output [2:0] Y; // 3-bit encoded output
reg [2:0] Y; // target of assignment
• // synthesis full_case
– Tells compiler that cases left out can be treated as don’t
cares
– Avoids incomplete specification and resulting latches
initial
begin – A variety of other “system functions”, similar to
s=0; a=0; b=1; expected=0; monitor exist for displaying output and controlling
#10 a=1; b=0; expected=1;
the simulation.
#10 s=1; a=0; b=1; expected=1;
end
initial
$monitor(
"select=%b in0=%b in1=%b out=%b, expected out=%b time=%d",
s, a, b, f, expected, $time);
endmodule // testmux
Integer types use integer arithmetic and can be signed or unsigned.The data types
byte, shortint, int, integer, and longint default to signed. The data types bit, reg,
and logic default to unsigned, as do arrays of these types.
To use these types as unsigned, user has to explicitly declare it as unsigned.
reg[31:0] a = 32'hffffffff;
Systemverilog Adds the ability to specify unsized literal single bit values
with a preceding (').'0, '1, 'X, 'x, 'Z, 'z // sets all bits to this value.
reg[31:0] a = '1;
'x is equivalent to Verilog-2001 'bx
'z is equivalent to Verilog-2001 'bz
'1 is equivalent to making an assignment of all 1's
'0 is equivalent to making an assignment of 0
• Time Literals
EXAMPLE
0.1ns
40ps
Array literals are syntactically similar to C initializers, but with the replicate operator
( {{}} ) allowed.
EXAMPLE
int n[1:2][1:3] = '{'{0,1,2},'{3{4}}};
The nesting of braces must follow the number of dimensions, unlike in C. However,
replicate operators can be nested. The inner pair of braces in a replication is
removed. A replication expression only operates within one dimension.
EXAMPLE:
int n[1:2][1:6] = '{2{'{3{4, 5}}}}; // same as '{'{4,5,4,5,4,5},'{4,5,4,5,4,5}}
Structure Literals
Structure literals are structure assignment patterns or pattern expressions with
constant member expressions A structure literal must have a type, which may be
either explicitly indicated with a prefix or implicitly indicated by an assignment-like
context.
EXAMPLE
typedef struct {int a; shortreal b;} ab;
ab c;
c = '{0, 0.0}; // structure literal type determined from
// the left-hand context (c)
The C-like alternative '{1, 1.0, 2, 2.0} for the preceding example is not allowed.
EXAMPLE: default values
c = '{a:0, b:0.0};
c = '{default:0};
d = ab'{int:1, shortreal:1.0};
STRINGS
• In Verilog, string literals are packed arrays of a width
that is a multiple of 8 bits which hold ASCII values. In
Verilog, if a string is larger than the destination string
variable, the string is truncated to the left, and the
leftmost characters will be lost. SystemVerilog adds
new keyword "string" which is used to declare string
data types unlike verilog. String data types can be of
arbitrary length and no truncation occurs.
SystemVerilog also includes a number of special methods to work with strings. These
methods use the built-in method notation. These methods are:
1. str.len() returns the length of the string, i.e., the number of characters in the string.
2. str.putc(i, c) replaces the ith character in str with the given integral value.
3. str.getc(i) returns the ASCII code of the ith character in str.
4. str.toupper() returns a string with characters in str converted to uppercase.
5. str.tolower() returns a string with characters in str converted to lowercase.
6. str.compare(s) compares str and s, and return value. This comparison is case
sensitive.
7. str.icompare(s) compares str and s, and return value .This comparison is case
insensitive.
8. str.substr(i, j) returns a new string that is a substring formed by index i through j of
str.
9. str.atoi() returns the integer corresponding to the ASCII decimal representation in
str.
10. str.atoreal() returns the real number corresponding to the ASCII decimal
representation in str.
11. str.itoa(i) stores the ASCII decimal representation of i into str (inverse of atoi).
12. str.hextoa(i) stores the ASCII hexadecimal representation of i into str (inverse of
atohex).
13. str.bintoa(i) stores the ASCII binary representation of i into str (inverse of atobin).
14. str.realtoa(r) stores the ASCII real representation of r into str (inverse of atoreal)
• EXAMPLE : String methods
module str;
string A;
string B;
initial
begin
A = "TEST ";
B = "Bench";
$display(" %d ",A.len() );
$display(" %s ",A.getc(5) );
$display(" %s ",A.tolower);
$display(" %s ",B.toupper);
$display(" %d ",B.compare(A) );
$display(" %d ",A.compare("test") );
$display(" %s ",A.substr(2,3) ); A = "111";
$display(" %d ",A.atoi() );
end
endmodule
RESULTS :
5
test
BENCH
-18
-32
ST
111
• String Pattren Match
Use the following method for pattern matching in SystemVerilog. Match method
which is in OpenVera or C , is not available in SystemVerilog . For using match
method which is in C , use the DPI calls . For native SystemVerilog string match
method, hear is the example.
CODE:
function match(string s1,s2);
int l1,l2;
l1 = s1.len();
l2 = s2.len();
match = 0 ;
if( l2 > l1 )
return 0;
for(int i = 0;i < l1 - l2 + 1; i ++)
if( s1.substr(i,i+l2 -1) == s2)
return 1;
endfunction
• EXAMPLE: str1 = "this is first string";
program main; str2 = "this is ";
if(match(str1,str2))
string str1,str2; $display(" str2 : %s : found in
int i; :%s:",str2,str1);
• Equality
Syntax : Str1 == Str2
Checks whether the two strings are equal. Result is 1 if they are equal and 0 if they are not. Both strings can be of type
string. Or one of them can be a string literal. If both operands are string literals, the operator is the same Verilog equality
operator as for integer types.
EXAMPLE
program main;
initial
begin
string str1,str2,str3;
str1 = "TEST BENCH";
str2 = "TEST BENCH";
str3 = "test bench";
if(str1 == str2)
$display(" Str1 and str2 are equal");
else
$display(" Str1 and str2 are not equal");
if(str1 == str3)
$display(" Str1 and str3 are equal");
else
$display(" Str1 and str3 are not equal");
end
endprogram
RESULT
Str1 and str2 are equal
Str1 and str3 are not equal
• Inequality.
• RESULT
Str1 and str2 are equal
Str1 and str3 are not equal
• Comparison.
Syntax:
• Str1 < Str2
• Str1 <= Str2
• Str1 > Str2
• Str1 >= Str2
Syntax : {multiplier{Str}}
Returns a byte, the ASCII code at the given index. Indexes range from 0 to N-1,
where N is the number of characters in the string. If given an index out of range,
returns 0. Semantically equivalent to Str.getc(index)
EXAMPLE
program main;
initial
begin
string Str1;
Str1 = "WWW.TESTBENCH.IN";
for(int i =0 ;i < 16 ; i++)
$write("%s ",Str1[i]);
end
endprogram
RESULT
WWW.TESTBENCH.IN
USERDEFINED DATATYPES
• System verilog allows the user to define data
types. There are different ways to define user
defined data types. They are
1. Class.
2. Enumarations.
3. Struct.
4. Union.
5. Typedef.
• ENUMARATIONS
You'll sometimes be faced with the need for variables that have a
limited set of possible values that can be usally referred to by name.
For example, the state variable like IDLE,READY,BUZY etc of state
machine can only have the all the states defined and Refraining or
displaying these states using the state name will be more
comfortable. There's a specific facility, called an enumeration in
SystemVerilog . Enumerated data types assign a symbolic name to
each legal value taken by the data type. Let's create an example using
one of the ideas I just mentioned-a state machine .
You can define this as follows:
red
red
blue
1
blue
TIP: If you want to use X or Z as enum values, then define it using 4-state data type
explicitly.
enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next;
STRUCTURES AND UNIOUNS
• Structure:
my_data_struct.a = 123;
$display(" a value is %d ",my_data_struct.a);
• Assignments To Struct Members:
my_data_struct = `{1234,8'b10,8'h20};
my_data_struct = `{a:1234,default:8'h20};
Union
• Unions like structure contain members whose
individual data types may differ from one another.
However the members that compose a union all
share the same storage area. A union allows us to
treat the same space in memory as a number of
different variables. That is a Union offers a way
for a section of memory to be treated as a
variable of one type on one occasion and as a
different variable of a different type on another
occasion.
• union {
int a;
byte b;
bit [7:0] c;
} my_data;
struct packed {
integer a;
byte b;
bit [0:7] c;
} my_data;
my_data.b = 8'b10;
$display("%d", my_data.a);
My_data [15:8] // b
void = function_call();
ARRAYS
•
Arrays hold a fixed number of equally-sized data elements.
• Individual elements are accessed by index using a
consecutive range of integers.
• Some type of arrays allows to access individual elements
using non consecutive values of any data types.
• Arrays can be classified as fixed-sized arrays (sometimes
known as static arrays) whose size cannot change once their
declaration is done, or dynamic arrays, which can be
resized.
Types of arrays
• Arrays
– Fixed
• Packed
• Unpacked
– Dynamic
• Unpacked
– Associative array
Fixed Arrays:
// Unpacked Arrays
wire status [31:0]; // 1 dimensional unpacked array
wire status [32]; // 1 dimensional unpacked array
integer dyna_arr_1[],dyn_arr_2[],multi_dime_dyn_arr[][];
Allocating Elements:
New[]:The built-in function new allocates the storage and initializes the
newly allocated array elements either to their default initial value.
– exists() : The exists() function checks if an element exists at the specified index
within the given array. It returns 1 if the element exists, otherwise it returns 0.
– first() : The first() method assigns to the given index variable the value of the
first (smallest) index in the associative array. It returns 0 if the array is empty,
and 1 otherwise.
– last() : The last() method assigns to the given index variable the value of the
last (largest) index in the associative array. It returns 0 if the array is empty,
and 1 otherwise.
– next() : The next() method finds the entry whose index is greater than the
given index. If there is a next entry, the index variable is assigned the index of
the next entry, and the function returns 1. Otherwise, index is unchanged, and
the function returns 0.
– prev() : The prev() function finds the entry whose index is smaller than the
given index. If there is a previous entry, the index variable is assigned the
index of the previous entry, and the function returns 1. Otherwise, the index is
unchanged, and the function returns 0.
– num() : The num() method returns the number of entries in the associative
array. If the array is empty, it returns 0.
– delete() : If the index is specified, then the delete() method removes the entry
at the specified index. If the entry to be deleted does not exist, the method
issues no warning.
module integer_associative_array ();
integer as_mem [integer];
integer i;
initial begin
// Add element array
as_mem[100] = 101;
$display ("value stored in 100 is %d", 101);
as_mem[1] = 100;
$display ("value stored in 1 is %d", 100);
as_mem[50] = 99;
$display ("value stored in 50 is %d", 99);
as_mem[256] = 77;
$display ("value stored in 256 is %d", 77);
// Print the size of array
$display ("size of array is %d", as_mem.num()); Simulation Output - Associative Arrays
// Check if index 2 exists value stored in 100 is 101
$display ("index 2 exists %d", as_mem.exists(2)); value stored in 1 is 100 value stored in 50 is 99
// Check if index 100 exists value stored in 256 is 77 size of array is 4
$display ("index 100 exists %d", as_mem.exists(100)); index 2 exists 0 index 100 exists 1 value at first
// Value stored in first index index 1 value 100 value at last index 256 value
if (as_mem.first(i)) begin 77 Deleted index 100 value at first index 1
$display ("value at first index %d value %d", i, as_mem[i]);
value 100
end
27 // Value stored in last index
28 if (as_mem.last(i)) begin
29 $display ("value at last index %d value %d", i, as_mem[i]);
30 end
31 // Delete the first index
32 as_mem.delete(100);
33 $display ("Deleted index 100");
34 // Value stored in first index
35 if (as_mem.first(i)) begin
36 $display ("value at first index %d value %d", i, as_mem[i]);
37 end
38 #1 $finish;
39 end
41 endmodule
QUEUES
•
A queue is a variable-size, ordered collection of
homogeneous elements.
• A Queue is analogous to one dimensional unpacked
array that grows and shrinks automatically.
• Queues can be used to model a last in, first out buffer
or first in, first out buffer.
• Queues support insertion and deletion of elements
from random locations using an index.
• Queues Can be passed to tasks / functions as ref or
non-ref arguments. Type checking is also done.
• Queue Operators:
Queues and dynamic arrays have the same assignment and argument passing
semantics. Also, queues support the same operations that can be performed on
unpacked arrays and use the same operators and rules except as defined below:
int q[$] = { 2, 4, 8 };
int p[$];
int e, pos;
e = q[0]; // read the first (leftmost) item
e = q[$]; // read the last (rightmost) item
q[0] = e; // write the first item
p = q; // read and write entire queue (copy)
q = { q, 6 }; // insert '6' at the end (append 6)
q = { e, q }; // insert 'e' at the beginning (prepend e)
q = q[1:$]; // delete the first (leftmost) item
q = q[0:$-1]; // delete the last (rightmost) item
q = q[1:$-1]; // delete the first and last items
q = {}; // clear the queue (delete all items)
q = { q[0:pos-1], e, q[pos,$] }; // insert 'e' at position pos
q = { q[0:pos], e, q[pos+1,$] }; // insert 'e' after position pos
• EXAMPLE
module queues;
byte qu [$] ;
initial
begin
qu.push_front(2);
qu.push_front(12);
qu.push_front(22);
qu.push_back(11);
qu.push_back(99);
$display(" %d ",qu.size() );
$display(" %d ",qu.pop_front() );
$display(" %d ",qu.pop_back() );
qu.delete(3);
$display(" %d ",qu.size() );
end
endmodule
RESULTS :
5
22
99
• module queue_data();
• 2
• 3 // Queue is declated with $ in array size
• 4 integer queue[$] = { 0, 1, 2, 3, 4 };
• 5 integer i;
• 6
• 7 initial begin
• 8 $display ("Initial value of queue");
• 9 print_queue;
• 10 // Insert new element at begin of queue
• 11 queue = {5, queue};
• 12 $display ("new element added using concate");
• 13 print_queue;
• 14 // Insert using method at begining
• 15 queue.push_front(6);
• 16 $display ("new element added using push_front");
• 17 print_queue;
• 18 // Insert using method at end
•
• 19 queue.push_back(7);
• 20 $display ("new element added using push_back");
• 21 print_queue;
• 22 // Using insert to insert, here 4 is index
• 23 // and 8 is value
• 24 queue.insert(4,8);
• 25 $display ("new element added using insert(index,value)");
• 26 print_queue;
• 27 // get first queue element method at begining
• 28 i = queue.pop_front();
• 29 $display ("element poped using pop_front");
• 30 print_queue;
• 31 // get last queue element method at end
• 32 i = queue.pop_back();
• 33 $display ("element poped using pop_end");
• 34 print_queue;
• 35 // Use delete method to delete element at index 4 in queue
• 36 queue.delete(4);
• 37 $display ("deleted element at index 4");
• 38 print_queue;
• 39 #1 $finish;
• 40 end
• 41
• 42 task print_queue;
• 43 integer i;
• 44 $write("Queue contains ");
• 45 for (i = 0; i < queue.size(); i ++) begin
• 46 $write (" %g", queue[i]);
• 47 end
• 48 $write("\n");
• 49 endtask
• 50
• 51 endmodule
•
• Simulation Output - Queues
•
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, <<<=,>>>=.
if((a=b)) is equivalent to
a=b;
if(a)
• EXAMPLE
module assignment();
int a,b,c;
initial begin
a = 1; b =2;c =3;
if((a=b))
$display(" a value is %d ",a);
a = (b = (c = 5));
$display(" a is %d b is %d c is %d ",a,b,c);
end
endmodule
RESULT
a value is 2
a is 5 b is 5 c is 5
Equality :
• The different types of equality (and inequality)
operators in SystemVerilog behave differently when
their operands contain unknown values (X or Z).
• The == and != operators may result in X if any of their
operands contains an X or Z.
• The === and !== check the 4-state explicitly, therefore,
X and Z values shall either match or mismatch, never
resulting in X.
• The ==? and !=? operators may result in X if the left
operand contains an X or Z that is not being compared
with a wildcard in the right operand.
• EXAMPLE : logical Equality
program main;
reg[3:0] a;
reg[7:0] x, y, z;
initial begin
a = 4'b0101;
x = 8'b1000_0101;
y = 8'b0000_0101;
z = 8'b0xx0_0101;
if (x == a)
$display("x equals a is TRUE.\n");
if (y == a)
$display("y equals a is TRUE.\n");
if (z == a)
$display("z equals a is TRUE.\n");
end
endprogram
RESULTS:
y equals a is TRUE.
• Relational :
•
SystemVerilog added two new logical operators logical
implication (->), and logical equivalence (<->). The logical
implication expression1 -> expression2 is logically equivalent
to (!expression1 || expression2), and the logical equivalence
expression1 <-> expression2 is logically equivalent to
((expression1 -> expression2) && (expression2 ->
expression1)).
• SystemVerilog added two new logical operators logical
implication (->), and logical equivalence (<->). The logical
implication expression1 -> expression2 is logically equivalent
to (!expression1 || expression2), and the logical equivalence
expression1 <-> expression2 is logically equivalent to
((expression1 -> expression2) && (expression2 ->
expression1)).
• Bitwise :
CONTROL STATEMENTS
• - if-else Statement
- case Statement
- repeat loop
- for loop
- while loop
- do-while
- foreach
- Loop Control
• EXAMPLE : if
program main ;
integer i;
initial begin
i = 20;
if( i == 20)
$display(" I is equal to %d ",i);
else
$display(" I is not equal to %d ",i);
end
endprogram
RESULTS
I is equal to 20
• EXAMPLE : case and repeat
program main ;
integer i;
initial begin
repeat(10)begin
i = $random();
case(1) begin
(i<0) :$display(" i is less than zero i==%d\n",i);
(i>0) :$display(" i is grater than zero i=%d\n",i);
(i == 0):$display(" i is equal to zero i=%d\n",i);
end
end
end
endprogram
RESULTS
i is grater than zero i=69120
i is grater than zero i=475628600
i is grater than zero i=1129920902
i is grater than zero i=773000284
i is grater than zero i=1730349006
i is grater than zero i=1674352583
i is grater than zero i=1662201030
i is grater than zero i=2044158707
i is grater than zero i=1641506755
i is grater than zero i=797919327
• EXAMPLE : forloop
program for_loop;
integer count, i;
initial begin
for(count = 0, i=0; i*count<50; i++, count++)
$display("Value i = %0d\n", i);
end
endprogram
RESULTS
Value i = 0
Value i = 1
Value i = 2
Value i = 3
Value i = 4
Value i = 5
Value i = 6
Value i = 7
• EXAMPLE : whileloop
program while_loop;
integer operator=0;
initial begin
while (operator<5)begin
operator += 1;
$display("Operator is %0d\n", operator);
end
end
endprogram
RESULTS
Operator is 1
Operator is 2
Operator is 3
Operator is 4
Operator is 5
• EXAMPLE : dowhile
program test;
integer i = 0;
initial begin
do
begin
$display("i = %0d \n", i);
i++;
end
while (i < 10);
end
endprogram
RESULTS
i=0
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
• EXAMPLE : foeach
program example;
string names[$]={"Hello", "SV"};
int fxd_arr[2][3] = '{'{1,2,3},'{4,5,6}};
initial begin
foreach (names[i])
$display("Value at index %0d is %0s\n", i, names[i]);
foreach(fxd_arr[,j])
$display(fxd_arr[1][j]);
end
endprogram
RESULTS
Value at index 0 is Hello
Value at index 1 is SV
4
5
6
• EXAMPLE : randcase
program rand_case;
integer i;
initial begin
repeat(10)begin
randcase
begin
10: i=1;
20: i=2;
50: i=3;
end
$display(" i is %d \n",i);end
end
endprogram
RESULTS
i is 3
i is 2
i is 3
i is 3
i is 3
i is 3
i is 1
i is 1
i is 1
i is 2
• Enhanced For Loop
In Verilog, the variable used to control a for loop must be declared prior to the loop.
If loops in two or more parallel procedures use the same loop control variable, there
is a potential of one loop modifying the variable while other loops are still using it.
SystemVerilog adds the ability to declare the for loop control variable within the for
loop. This creates a local variable within the loop. Other parallel loops cannot
inadvertently affect the loop control variable.
For example:
module foo;
initial begin
for (int i = 0; i <= 255; i++)
...
end
initial begin
loop2: for (int i = 15; i >= 0; i--)
...
end
endmodule
Doubts on array index
• reg [ LEFT_BIT_INDEX : RIGHT_BIT_INDEX ] my_vector;
• Whether LEFT > RIGHT, or LEFT < RIGHT does not change the bit order:
• Arrays :
• reg [ L : R ] my_array [ FIRST_INDEX : LAST_INDEX]
• Whether FIRST < LAST or FIRST > LAST, does not change the element order.
• module top;
• reg [7:0] array1 [0:2] = { 8'haa, 8'hbb, 8'hcc };
• reg [7:0] array2 [2:0] = { 8'haa, 8'hbb, 8'hcc };
• initial begin
• #1;
• assert (array1 == array2);
• assert (array1[0] == array2[2]); // FIRST equals FIRST
• assert (array1[0] != array2[0]); // FIRST not equal LAST
• end
• endmodule
• Todays class(8/3/2018)
• The module is the basic building block in
Verilog which works well for Design. However,
for the testbench, a lot of effort is spent
getting the environment properly initialized
and synchronized, avoiding races between the
design and the testbench, automating the
generation of input stimuli, and reusing
existing models and other infrastructure.
program block
• Systemverilog adds a new type of block called program block. It is
declared using program and endprogram keywords.
-> The program block helps ensure that test bench transitions do not have
race conditions with the design
-> It does not allow always block. Only initial and methods are
allowed, which are more controllable.
-> Just like a module, program block has ports. One or more
program blocks can be instantiated in a top-level netlist, and
connected to the DUT
module based testbench
• module DUT();
reg q = 0;
reg clk = 0;
initial
#10 clk = 1;
always @(posedge clk)
q <= 1;
endmodule
• module Module_based_TB();
always @ (posedge DUT.clk) $display("Module_based_TB : q =
%b\n", DUT.q);
endmodule
Program based testbench
• program Program_based_TB();
initial
forever @(posedge DUT.clk) $display("Program_based_TB :
q = %b\n", DUT.q);
endprogram
•
RESULT:
Module_based_TB : q = 0
program_based_TB : q = 1
PROCEDURAL BLOCKS
• Verilog procedural statements are in initial or
always blocks, tasks, or functions.
SystemVerilog adds a final block that executes
at the end of simulation.SystemVerilog final
blocks execute in an arbitrary but
deterministic sequential order. This is possible
because final blocks are limited to the legal set
of statements allowed for functions.
• EXAMPLE :
module fini;
initial
#100 $finish;
final
$display(" END OF SIMULATION at %d ",$time);
endmodule
RESULTS:
END OF SIMULATION at 100
• Jump Statements:
EXAMPLE:
module latch (output logic [31:0] y, input [31:0] a, input en
able);
always @(a iff enable == 1)
y <= a; //latch is in transparent mode
endmodule
• Always:
EXAMPLE:
always_comb
a = b & c;
always_latch
if(ck) q <= d;
always_ff @(posedge clock iff reset == 0 or posedge reset)
r1 <= reset ? 0 : r2 + 1;
FORK JOIN
• A Verilog fork...join block always causes the
process executing the fork statement to block
until the termination of all forked processes.
With the addition of the
• join_any and
• join_none keywords,
• SystemVerilog provides three choices for
specifying when the parent (forking) process
resumes execution.
Fork Join None
When defining a fork/join block, encapsulating the entire fork inside begin..end, results
in the entire block being treated as a single thread, and the code executes
consecutively.
• EXAMPLE : fork/join none
program main ;
initial
begin
#10;
$display(" BEFORE fork time = %d ",$time );
fork
begin
# (20);
$display("time = %d # 20 ",$time );
end
begin
#(10);
$display("time = %d # 10 ",$time );
end
begin
#(5);
$display("time = %d # 5 ",$time );
end
join_none
$display(" time = %d Outside the main fork ",$time );
#(40);
end
endprogram
• RESULTS
BEFORE fork time = 10
time = 10 Outside the main fork
time = 15 # 5
time = 20 # 10
time = 30 # 20
Fork Join Any
• The parent process blocks until any one of the
processes spawned by this fork completes.
• EXAMPLE : fork/join any
program main;
initial begin
#(10);
$display(" BEFORE fork time = %d ",$time );
fork
begin
# (20);
$display("time = %d # 20 ",$time );
end
begin
#(10);
$display("time = %d # 10 ",$time );
end
begin
#(5);
$display("time = %d # 5 ",$time );
end
join_any
$display(" time = %d Outside the main fork ",$time );
#(40);
end
endprogram
• RESULTS
BEFORE fork time = 10
time = 15 # 5
time = 15 Outside the main fork
time = 20 # 10
time = 30 # 20
For Join All
•
• RESULTS
BEFORE fork time = 10
time = 15 # 5
time = 20 # 10
time = 30 # 20
time = 30 Outside the main fork
• EXAMPLE : sequential statement in fork/join
program main ;
initial begin
#(10);
$display(" First fork time = %d ",$time );
fork
begin
# (20);
$display("time = %d # 20 ",$time);
end
begin
#(10);
$display("time = %d # 10 ",$time);
end
begin
#(5);
$display("time = %d # 5 ",$time);
#(2);
$display("time = %d # 2 ",$time);
end
join_any
$display(" time = %d Outside the main fork ",$time );
#(40);
end
endprogram
• RESULTS:
First fork time = 10
time = 15 # 5
time = 17 # 2
time = 17 Outside the main fork
time = 20 # 10
time = 30 # 20
CLOCKING BLOCK
Synchronous events
Input sampling
Synchronous drives
• clocking cb @(posedge clk);
default input #10ns output #2ns;
output read,enable,addr;
input negedge data;
endclocking
• In the above example, the first line declares a clocking block called cb that
is to be clocked on the positive edge of the signal clk.
• The second line specifies that by default all signals in the clocking block
shall use a 10ns input skew and a 2ns output skew by default.
• The next line adds three output signals to the clocking block: read, enable
and addr.
• The fourth line adds the signal data to the clocking block as input. Fourth
line also contains negedge which overrides the skew ,so that data is
sampled on the negedge of the clk.
Skew
• If an input skew is specified then the signal is
sampled at skew time units before the clock
event.
• If output skew is specified, then output (or
inout) signals are driven skew time units after
the corresponding clock event.
• A skew must be a constant expression, and
can be specified as a parameter.
• Skew can be specified in 3 ways.
#d : The skew is d time units. The time unit depends on the timescale of the
block.
#dns : The skew is d nano seconds.
#1step : Sampling is done in the preponed region of current time stamp.
• If skew is not specified, default input skew is 1step and output skew is 0.
Specifying a clocking block using a SystemVerilog interface can
significantly reduce the amount of code needed to connect the TestBench
without race condition.
• Clocking blocks add an extra level of signal hierarchy while accessing
signals.
• Interface declaration with clocking block:
• module Test_Counter;
timeunit 1ns;
reg Clock = 0, Reset, Enable, Load, UpDn;
reg [7:0] Data;
wire [7:0] Q;
reg OK;
// Clock generator
always
begin
#5 Clock = 1;
#5 Clock = 0;
end
// Test stimulus
initial
begin
Enable = 0;
Load = 0;
UpDn = 1;
Reset = 1;
#10; // Should be reset
Reset = 0;
#10; // Should do nothing - not enabled
Enable = 1; #20; // Should count up to 2
UpDn = 0;
#40; // Should count downto 254
UpDn = 1;
// etc. ...
end
// Instance the device-under-test
COUNTER G1 (Clock, Reset, Enable, Load, UpDn, Data, Q);
• The testbench using clocking will look like this:
• module Test_Counter_w_clocking;
timeunit 1ns;
reg Clock = 0, Reset, Enable, Load, UpDn;
reg [7:0] Data;
wire [7:0] Q;
// Clock generator
always
begin
#5 Clock = 1;
#5 Clock = 0;
end
// Test program
program test_counter;
// SystemVerilog "clocking block"
// Clocking outputs are DUT inputs and vice versa
clocking cb_counter @(posedge Clock);
default input #1step output #4;
output negedge Reset;
output Enable, Load, UpDn, Data;
input Q;
endclocking
• // Apply the test stimulus
initial begin