0% found this document useful (0 votes)
56 views158 pages

System Verilog For Verification: Dr.R.Jayagowri

This document provides an overview of SystemVerilog for verification. It discusses Verilog data types and values such as bits, vectors of bits, numbers, and operators. It also covers Verilog variables such as wires, regs, modules, continuous assignments, behavioral modeling using always blocks, and how Verilog determines what gets synthesized as combinational logic versus storage elements.

Uploaded by

Adithya Reddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
56 views158 pages

System Verilog For Verification: Dr.R.Jayagowri

This document provides an overview of SystemVerilog for verification. It discusses Verilog data types and values such as bits, vectors of bits, numbers, and operators. It also covers Verilog variables such as wires, regs, modules, continuous assignments, behavioral modeling using always blocks, and how Verilog determines what gets synthesized as combinational logic versus storage elements.

Uploaded by

Adithya Reddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 158

System verilog for verification

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

9/6/2007 EECS 150, Fa07, Lec 04-HDL 3


Verilog Numbers
• 14 - ordinary decimal number
• -14 - 2’s complement representation
• 12’b0000_0100_0110 - binary number with
12 bits (_ is ignored)
• 12’h046 - hexadecimal number with 12 bits
• Verilog values are unsigned
– e.g., C[4:0] = A[3:0] + B[3:0];
– if A = 0110 (6) and B = 1010(-6)
C = 10000 not 00000
i.e., B is zero-padded, not sign-extended

9/6/2007 EECS 150, Fa07, Lec 04-HDL 4


Verilog Operators

9/6/2007 EECS 150, Fa07, Lec 04-HDL 5


Verilog Variables
• wire
– Variable used simply to connect components together
• reg
– Variable that saves a value as part of a behavioral
description
– Usually corresponds to a wire in the circuit
– Is NOT necessarily a register in the circuit
• usage:
– Don’t confuse reg assignments with the combinational
continuous assign statement! (more soon)
– Reg should only be used with always blocks (sequential
logic, to be presented …)

9/6/2007 EECS 150, Fa07, Lec 04-HDL 6


Verilog Module
• Corresponds to a circuit component
– “Parameter list” is the list of external connections,
A B Cin
aka “ports”
– Ports are declared “input”, “output” or “inout”
• inout module
portsname
used on tri-state busesports
– Port declarations imply that the variables are wires
module full_addr (A, B, Cin, S, Cout); Cout S
input A, B, Cin;
inputs/outputs
output S, Cout;

assign {Cout, S} = A + B + Cin;


endmodule

9/6/2007 EECS 150, Fa07, Lec 04-HDL 7


Verilog Continuous Assignment
• Assignment is continuously evaluated
• assign corresponds to a connection or a simple
component with the described function
• Target is NEVER a reg variable
• Dataflow style use of Boolean operators
(~ for bit-wise, ! for logical negation)
assign A = X | (Y & ~Z);
bits can take on four values
assign B[3:0] = 4'b01XX; (0, 1, X, Z)

variables can be n-bits wide


assign C[15:0] = 4'h00ff; (MSB:LSB)

assign #3 {Cout, S[3:0]} = A[3:0] + B[3:0] +


use of arithmetic operator
Cin;
multiple assignment (concatenation)

delay of performing computation, only used by simulator, not synthesis


9/6/2007 EECS 150, Fa07, Lec 04-HDL 8
Comparator Example

module Compare1 (A, B, Equal, Alarger, Blarger);


input A, B;
output Equal, Alarger, Blarger;

assign Equal = (A & B) | (~A & ~B);


assign Alarger = (A & ~B);
assign Blarger = (~A & B);
endmodule
When evaluated?
What is synthesized?

9/6/2007 EECS 150, Fa07, Lec 04-HDL 9


Comparator Example
// Make a 4-bit comparator from 4 1-bit comparators

module Compare4(A4, B4, Equal, Alarger, Blarger);


input [3:0] A4, B4;
output Equal, Alarger, Blarger;
wire e0, e1, e2, e3, Al0, Al1, Al2, Al3, B10, Bl1, Bl2, Bl3;

Compare1 cp0(A4[0], B4[0], e0, Al0, Bl0);


Compare1 cp1(A4[1], B4[1], e1, Al1, Bl1);
Compare1 cp2(A4[2], B4[2], e2, Al2, Bl2);
Compare1 cp3(A4[3], B4[3], e3, Al3, Bl3);

assign Equal = (e0 & e1 & e2 & e3);


assign Alarger = (Al3 | (Al2 & e3) |
(Al1 & e3 & e2) |
(Al0 & e3 & e2 What& would be a “better” behavioral version?
e1));
assign Blarger = (~Alarger
9/6/2007
& ~Equal);
EECS 150, Fa07, Lec 04-HDL 10
endmodule
Simple Behavioral Model - the
always block
• always block
– Always waiting for a change to a trigger signal
– Then executes the body
module and_gate (out, in1, in2);
input in1, in2;
output out; Not a real register!!
reg out; A Verilog register
Needed because of
assignment in always
always @(in1 or in2) begin block
out = in1 & in2;
end
Specifies when block is executed
endmodule I.e., triggered by which signals

9/6/2007 EECS 150, Fa07, Lec 04-HDL 11


always Block
• A procedure that describes the function of a circuit
– Can contain many statements including if, for,
while, case
– Statements in the always block are executed
sequentially
• “blocking” assignment
• Continuous assignments <= are executed in parallel
– Non-blocking
– The entire block is executed ‘at once’
• But the meaning is established by sequential interpretation
– Simulation micro time vs macro time
– synthesis
– The final result describes the function of the circuit for
current set of inputs
• intermediate assignments don’t matter, only the final result
• begin/end used to group statements
9/6/2007 EECS 150, Fa07, Lec 04-HDL 12
What Verilog generates storage elements?

• Expressions produce combinational logic


– Map inputs to outputs
• Storage elements carries same values forward
in time

9/6/2007 EECS 150, Fa07, Lec 04-HDL 13


State Example
module shifter (in, A,B,C,clk);
input in, clk;
input A,B,C;
reg A, B, C;
always @ (posedge clk) begin
C = B;
B = A;
A = in;
end
in A B C
endmodule

clk

• Block interpreted sequentially, but action happens “at once”

9/6/2007 EECS 150, Fa07, Lec 04-HDL 14


State Example2 – Non blocking
module shifter (in, A,B,C,clk);
input in, clk;
input A,B,C;
reg A, B, C;
always @ (posedge clk) begin
B <= A;
A <= in;
C <= B; A B C
in
end
endmodule
clk

• Non-blocking: all statements interpreted in parallel


– Everything on the RHS evaluated,
– Then all assignments performed
9/6/2007 EECS 150, Fa07, Lec 04-HDL 15
State Example2 – interactive quiz
module shifter (in, A,B,C,clk); • Variable becomes a
input in, clk;
storage element if its
value is preserved
input A,B,C;
(carried forward in time)
reg A, B, C; despite changes in
always @ (posedge clk) begin variables the produce it.
A = in; • Not whether it is declared
B = A; as a wire or a reg!
C = B;
end
in A
endmodule
B
C
clk

9/6/2007 EECS 150, Fa07, Lec 04-HDL 16


“Complete” Assignments
• If an always block executes, and a variable is not
assigned
– Variable keeps its old value (think implicit state!)
– NOT combinational logic ⇒ latch is inserted (implied
memory)
– This is usually not what you want: dangerous for the
novice!
• Any variable assigned in an always block should
be assigned for any (and every!) execution of the
block.

9/6/2007 EECS 150, Fa07, Lec 04-HDL 17


Incomplete Triggers
• Leaving out an input trigger usually results in a sequential circuit
• Example: The output of this “and” gate depends on the input history

module and_gate (out, in1, in2);


input in1, in2;
output out;
reg out;

What Hardware would this generate?


always @(in1) begin
out = in1 & in2;
end

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

//Behavioral model of 32-bit adder.


module add32 (S,A,B);
input [31:0] A,B;
output [31:0] S;
reg [31:0] S;
always @ (A or B)
S = A + B;
endmodule // Add
9/6/2007 EECS 150, Fa07, Lec 04-HDL 19
Hierarchy & Bit Vectors
• Notes:
//Assuming we have already – instantiation similar to primitives
// defined a 2-input mux (either – select is 2-bits wide
// structurally or behaviorally,
– named port assignment
//4-input mux built from 3 2-input muxes
module mux4 (in0, in1, in2, in3, select, out);
input in0,in1,in2,in3;
input [1:0] select;
output out;
wire w0,w1;

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”

// 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 == 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

9/6/2007 EECS 150, Fa07, Lec 04-HDL 22


Verilog case
• Sequential execution of cases
– Only first case that matches is executed (no break)
– Default case can be used
// 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)
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

// Simple binary encoder (input is 1-hot)


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 (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

9/6/2007 EECS 150, Fa07, Lec 04-HDL 26


Verilog casex
• Like case, but cases can include ‘X’
– X bits not used when evaluating the cases
– In other words, you don’t care about those bits!

9/6/2007 EECS 150, Fa07, Lec 04-HDL 27


casex Example
// Priority encoder
module encode (A, valid, Y);
input [7:0] A; // 8-bit input vector
output [2:0] Y; // 3-bit encoded output
output valid; // Asserted when an input is not all 0’s
reg [2:0] Y; // target of assignment
reg valid;

always @(A) begin


valid = 1;
casex (A)
8’bXXXXXXX1: Y = 0;
8’bXXXXXX10: Y = 1;
8’bXXXXX100: Y = 2;
8’bXXXX1000: Y = 3;
8’bXXX10000: Y = 4;
8’bXX100000: Y = 5;
8’bX1000000: Y = 6;
8’b10000000: Y = 7;
default: begin
valid = 0;
Y = 3’bX; // Don’t care when input is all 0’s
end
endcase
end
endmodule

9/6/2007 EECS 150, Fa07, Lec 04-HDL 28


• for is similar to C
Verilog for
• for statement is executed at compile time (like macro expansion)
– Result is all that matters, not how result is calculated
– Use in testbenches only!

// 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

integer i; // Temporary variables for program only


reg [7:0] test;

always @(A) begin


test = 8b’00000001;
Y = 3’bX;
for (i = 0; i < 8; i = i + 1) begin
if (A == test) Y = N;
test = test << 1;
end
end
endmodule
9/6/2007 EECS 150, Fa07, Lec 04-HDL 29
Another Behavioral Example
• Computing Conway’s Game of Life rule
– Cell with no neighbors or 4 neighbors dies; with 2-3 neighbors lives

module life (neighbors, self, out);


input self;
input [7:0] neighbors; integers are temporary compiler variables
output out;
reg out; always block is executed instantaneously,
integer count; if there are no delays only the final result is used
integer i;

always @(neighbors or self) begin


count = 0;
for (i = 0; i<8; i = i+1) count = count + neighbors[i];
out = 0;
out = out | (count == 3);
9/6/2007 out = out | ((self EECS
== 150,
1)Fa07,&Lec(count
04-HDL == 2)); 30
Verilog while/repeat/forever
• while (expression) statement
– Execute statement while expression is true
• repeat (expression) statement
– Execute statement a fixed number of times
• forever statement
– Execute statement forever

9/6/2007 EECS 150, Fa07, Lec 04-HDL 31


full-case and parallel-case
• // synthesis parallel_case
– Tells compiler that ordering of cases is not important
– That is, cases do not overlap
• e. g., state machine - can’t be in multiple states
– Gives cheaper implementation

• // synthesis full_case
– Tells compiler that cases left out can be treated as don’t
cares
– Avoids incomplete specification and resulting latches

9/6/2007 EECS 150, Fa07, Lec 04-HDL 32


Sequential Logic
//Parallel to Serial converter
module ParToSer(LD, X, out, CLK);
input [3:0] X;
input LD, CLK;
output out;
reg out;
reg [3:0] Q;
assign out = Q[0];
always @ (posedge CLK)
if (LD) Q=X;
else Q = Q>>1; • Notes:
endmodule // mux2 – “always @ (posedge CLK)” forces Q register to
be rewritten every simulation cycle.
module FF (CLK,Q,D);
input D, CLK; – “>>” operator does right shift (shifts in a zero
output Q; reg Q; on the left).
always @ (posedge CLK) Q=D; – Shifts on non-reg variables can be done with
endmodule // FF concatenation:
wire [3:0] A, B;
assign B = {1’b0, A[3:1]}

9/6/2007 EECS 150, Fa07, Lec 04-HDL 33


Testbench
Top-level modules written specifically to test sub-modules.
Generally no ports.
• Notes:
module testmux; – initial block similar to always except only executes
reg a, b, s; once (at beginning of simulation)
wire f;
reg expected; – #n’s needed to advance time
– $monitor - prints output
mux2 myMux (.select(s), .in0(a), .in1(b), .out(f));

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

9/6/2007 EECS 150, Fa07, Lec 04-HDL 34


Final thoughts
• Verilog looks like C, but it describes hardware
– Multiple physical elements, Parallel activities
– Temporal relationships
– Basis for simulation and synthesis
– figure out the circuit you want, then figure out how to express it
in Verilog
• Understand the elements of the language
– Modules, ports, wires, reg, primitive, continuous assignment,
blocking statements, sensitivity lists, hierarchy
– Best done through experience
• Behavioral constructs hide a lot of the circuit details but you
as the designer must still manage the structure,
data-communication, parallelism, and timing of your design.

9/6/2007 EECS 150, Fa07, Lec 04-HDL 35


SYSTEM VERILOG
Data types
• SystemVerilog adds extended and new data types to Verilog for
better encapsulation and compactness.
• SystemVerilog extends Verilog by introducing C like data types.
• SystemVerilog adds a new 2-state data types that can only have
bits with 0 or 1 values unlike verilog 4-state data types which can
have 0, 1, X and Z.
• SystemVerilog also allows user to define new data types.
• SystemVerilog offers several data types, representing a hybrid of
both Verilog and C data types.
• SystemVerilog 2-state data types can simulate faster, take less
memory, and are preferred in some design styles.
• Then a 4-state value is automatically converted to a 2-state value,
X and Z will be converted to zeros.
• Var(default)
Var logic w;
• Net
Wire logic v;
• Logic
logic v1;
logic [7:0];
Port list:: net
Other part of the code::var
<data objects> <data type> <data entity name>
• Integer datatype
– Int, shortint, longint
– Integer
– Time
– Bit,byte
• Real type
– Real
– Shortreal
– Realtime
• String type
• Enumeration data type
• Struct, union
• Classes
• Events
• Constants
TIP : If you don't need the x and z values then use the System Verilog int and bit types
which make execution faster.
• Signed And Unsigned :

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.

int unsigned ui;


int signed si
byte unsigned ubyte;

User can cast using signed and unsigned casting.

if (signed'(ubyte)< 150) // ubyte is unsigned


LITERALS
• Integer And Logic Literals
In verilog , to assign a value to all the bits of vector, user has to specify
them explicitly.

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

Time is written in integer or fixed-point format,


followed without a space by a time unit (fs ps ns us ms
s step).

EXAMPLE
0.1ns
40ps

The time literal is interpreted as a realtime value


scaled to the current time unit and rounded to the
current time precision.
• Array Literals

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)

Nested braces should reflect the structure.


EXAMPLE
ab abarr[1:0] = '{'{1, 1.0}, '{2, 2.0}};

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.

string myName = "TEST BENCH";


• String Methods :

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);

str2 = "first string";


initial if(match(str1,str2))
begin $display(" str2 : %s : found in :%s:",str2,str1);
str1 = "this is first string";
str1 = "this is first string";
str2 = "this"; str2 = "first string ";// one space at end
if(match(str1,str2)) if(match(str1,str2))
$display(" str2 : %s : found in $display(" str2 : %s : found in :%s:",str2,str1);
:%s:",str2,str1);
end
str1 = "this is first string"; endprogram
str2 = "first";
if(match(str1,str2)) RESULTS:
$display(" str2 : %s : found in
:%s:",str2,str1); str2 : this : found in :this is first string:
str2 : first : found in :this is first string:
str2 : string : found in :this is first string:
str1 = "this is first string"; str2 : this is : found in :this is first string:
str2 = "string"; str2 : first string : found in :this is first string:
if(match(str1,str2))
$display(" str2 : %s : found in
:%s:",str2,str1);
String Operators
• SystemVerilog provides a set of operators that can be used to manipulate combinations of string
variables and string literals. The basic operators defined on the string data type are

• 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.

Syntax: Str1 != Str2


Logical negation of Equality operator. Result is 0 if they are equal and 1 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 not equal");
else
$display(" Str1 and str2 are equal");
if(str1 != str3)
$display(" Str1 and str3 are not equal");
else
$display(" Str1 and str3 are equal");
end
endprogram

• RESULT
Str1 and str2 are equal
Str1 and str3 are not equal
• Comparison.

Syntax:
• Str1 < Str2
• Str1 <= Str2
• Str1 > Str2
• Str1 >= Str2

Relational operators return 1 if the corresponding condition is true using the


lexicographical ordering of the two strings Str1 and Str2. The comparison
uses the compare string method. Both operands can be of type string, or one
of them can be a string literal.
• EXAMPLE
program main;
initial
begin
string Str1,Str2,Str3;
Str1 = "c";
Str2 = "d";
Str3 = "e";
if(Str1 < Str2)
$display(" Str1 < Str2 ");
if(Str1 <= Str2)
$display(" Str1 <= Str2 ");
if(Str3 > Str2)
$display(" Str3 > Str2");
if(Str3 >= Str2)
$display(" Str3 >= Str2");
end
endprogram
RESULT Results are in white colour

Str1 < Str2


Str1 <= Str2
Str3 > Str2
Str3 >= Str2
• Concatenation.
Syntax: {Str1,Str2,...,Strn}

Each operand can be of type string or a string


literal (it shall be implicitly converted to type
string). If at least one operand is of type string,
then the expression evaluates to the
concatenated string and is of type string. If all the
operands are string literals, then the expression
behaves like a Verilog concatenation of integral
types; if the result is then used in an expression
involving string types, it is implicitly converted to
the string type.
• EXAMPLE
program main;
initial
begin
string Str1,Str2,Str3,Str4,Str5;
Str1 = "WWW.";
Str2 = "TEST";
Str3 = "";
Str4 = "BENCH";
Str5 = ".IN";
$display(" %s ",{Str1,Str2,Str3,Str4,Str5});
end
endprogram
RESULT
WWW.TESTBENCH.IN
• Replication.

Syntax : {multiplier{Str}}

Str can be of type string or a string literal. Multiplier must


be of integral type and can be nonconstant. If multiplier is
nonconstant or Str is of type string, the result is a string
containing N concatenated copies of Str, where N is
specified by the multiplier. If Str is a literal and the
multiplier is constant, the expression behaves like numeric
replication in Verilog (if the result is used in another
expression involving string types, it is implicitly converted to
the string type).
• EXAMPLE
program main;
initial
begin
string Str1,Str2;
Str1 = "W";
Str2 = ".TESTBENCH.IN";
$display(" %s ",{{3{Str1}},Str2});
end
endprogram
RESULT
WWW.TESTBENCH.IN
• Indexing.
Syntax: Str[index]

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:

enum {IDLE,READY,BUZY} states;


• This declares an enumerated data type called states, and variables
of this type can only have values from the set that appears
between the braces, IDLE,READY and BUZY. If you try to set a
variable of type states to a value that isn't one of the values
specified, it will cause an error. Enumerated data type are strongly
typed.
One more advantage of enumerated datatypes is that if you don't
initialize then , each one would have a unique value. By defaule
they are int types. In the previous examples, IDLE is 0, READY is 1
and BUZY is 2. These values can be printed as values or strings.
The values can be set for some of the names and not set for other
names. A name without a value is automatically assigned an
increment of the value of the previous name. The value of first
name by default is 0.
• // c is automatically assigned the
increment-value of 8
enum {a=3, b=7, c} alphabet;

// Syntax error: c and d are both assigned 8


enum {a=0, b=7, c, d=8} alphabet;

// a=0, b=7, c=8


enum {a, b=7, c} alphabet;
• Enumarated Methods:

SystemVerilog includes a set of specialized methods to enable iterating over


the values of enumerated.
The first() method returns the value of the first member of the enumeration.
The last() method returns the value of the last member of the enumeration.
The next() method returns the Nth next enumeration value (default is the
next one) starting from the current value of the given variable.
The prev() method returns the Nth previous enumeration value (default is the
previous one) starting from the current value of the given variable.
The name() method returns the string representation of the given
enumeration value. If the given value is not a member of the enumeration,
the name() method returns the empty string.
• EXAMPLE : ENUM methods
module enum_method;
typedef enum {red,blue,green} colour;
colour c;
initial
begin
c = c.first();
$display(" %s ",c.name);
c = c.next();
$display(" %s ",c.name);
c = c.last();
$display(" %s ",c.name);
c = c.prev();
$display(" %s ",c.name);
end
endmodule
RESULTS :
red
blue
green
blue
• Enum Numerical Expressions

Elements of enumerated type variables can be used in


numerical expressions. The value used in the
expression is the numerical value associated with the
enumerated value.
An enum variable or identifier used as part of an
expression is automatically cast to the base type of the
enum declaration (either explicitly or using int as the
default). A cast shall be required for an expression that
is assigned to an enum variable where the type of the
expression is not equivalent to the enumeration type
of the variable.
• EXAMPLE:
module enum_method;
typedef enum {red,blue,green} colour;
colour c,d;
int i;
initial
begin
$display("%s",c.name());
d = c;
$display("%s",d.name());
d = colour'(c + 1); // use casting
$display("%s",d.name());
i = d; // automatic casting
$display("%0d",i);
c = colour'(i);
$display("%s",c.name());
end
endmodule
RESULT

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:

The disadvantage of arrays is that all the elements


stored in then are to be of the same data type. If we
need to use a collection of different data types, it is
not possible using an array. When we require using a
collection of different data items of different data
types we can use a structure. Structure is a method of
packing data of different types. A structure is a
convenient method of handling a group of related
data items of different data types.
• struct {
int a;
byte b;
bit [7:0] c;
} my_data_struct;

The keyword "struct" declares a structure to holds the


details of four fields namely a,b and c. These are members
of the structures. Each member may belong to different or
same data type. The structured variables can be accessed
using the variable name "my_data_struct".

my_data_struct.a = 123;
$display(" a value is %d ",my_data_struct.a);
• Assignments To Struct Members:

A structure literal must have a type, which may be either


explicitly indicated with a prefix or implicitly indicated by an
assignment-like context.

my_data_struct = `{1234,8'b10,8'h20};

Structure literals can also use member name and value, or


data type and default value.

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;

• memory allocation for the above defined struct "my_data_struct”

Memory allocation for the above defined union "my_data_union".


• Packed Structures:

In verilog , it is not convenient for subdividing a vector into subfield. Accessing


subfield requires the index ranges.
For example

reg [0:47] my_data;


`define a_indx 16:47
`define b_indx 8:15
`define c_indx 0:7
my_data[`b_indx] = 8'b10; // writing to subfield b
$display(" %d ",my_data[`a_indx]); // reading subfield a
• A packed structure is a mechanism for subdividing a vector into subfields
that can be conveniently accessed as members. Consequently, a packed
structure consists of bit fields, which are packed together in memory
without gaps. A packed struct or union type must be declared explicitly
using keyword "packed".

struct packed {
integer a;
byte b;
bit [0:7] c;
} my_data;
my_data.b = 8'b10;
$display("%d", my_data.a);

Memory allocation for the above defined packed struct "my_data".


One or more bits of a packed structure can be selected as if it were a
packed array, assuming an [n-1:0] numbering:

My_data [15:8] // b

(i) If all members of packed structure are 2-state, the structure as a


whole is treated as a 2-state vector.
(ii)If all members of packed structure is 4-state, the structure as a
whole is treated as a 4-state vector.
(iii)If there are also 2-state members, there is an implicit conversion
from 4-state to 2-state when reading those members, and from
2-state to 4-state when writing them.
• TYPEDEF
A typedef declaration lets you define your own
identifiers that can be used in place of type specifiers
such as int, byte, real. Let us see an example of
creating data type "nibble".

typedef bit[3:0] nibble; // Defining nibble data type.


nibble a, b; // a and b are variables with nibble data
types.
• Advantages Of Using Typedef :

Shorter names are easier to type and reduce typing errors.


Improves readability by shortening complex declarations.
Improves understanding by clarifying the meaning of data.
Changing a data type in one place is easier than changing all
of its uses throughout the code.
Allows defining new data types using structs, unions and
Enumerations also.
Increases reusability.
Useful is type casting.
• Example of typedef using struct, union and enum data types.

typedef enum {NO, YES} boolean;


typedef union { int i; shortreal f; } num; // named union type
typedef struct {
bit isfloat;
union { int i; shortreal f; } n; // anonymous type
} tagged_st; // named structure
boolean myvar; // Enum type variable
num n; // Union type variable
tagged_st a[9:0]; // array of structures
• Void :

The void data type represents nonexistent data.


This type can be specified as the return type of
functions to indicate no return value.

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:

• "Packed array" to refer to the dimensions declared before


the object name and
• "unpacked array" refers to the dimensions declared after
the object name.

SystemVerilog accepts a single number, as an alternative to
a range, to specify the size of an unpacked array. That is,
[size] becomes the same as [0:size-1].

int Array[8][32]; is the same as: int Array[0:7][0:31];


• // Packed Arrays
reg [0:10] vari; // packed array of 4-bits
wire [31:0] [1:0] vari; // 2-dimensional packed array

// Unpacked Arrays
wire status [31:0]; // 1 dimensional unpacked array
wire status [32]; // 1 dimensional unpacked array

integer matrix[7:0][0:31][15:0]; // 3-dimensional unpacked array of integers


integer matrix[8][32][16]; // 3-dimensional unpacked array of integers

reg [31:0] registers1 [0:255]; // unpacked array of 256 registers; each


reg [31:0] registers2 [256]; // register is packed 32 bit wide
• Operations On Arrays

The following operations can be performed on all arrays, packed


or unpacked:

register1 [6][7:0] = `1; // Packed indexes can be sliced


register1 = ~register1 ; // Can operate on entire memory
register1 = register2 ; // Reading and writing the entire array
register1[7:4] = register2[3:0] // Reading and writing a slice of the
array
register1[4+:i]= register2[4+;i] // Reading and writing a variable
slice
if(register1 == register2) //Equality operations on the entire array
int n[1:2][1:3] = `{`{0,1,2},`{4,4,3}};// multidimensional assignment
int triple [1:3] = `{1:1, default:0}; // indexes 2 and 3 assigned 0
DYNAMIC ARRAYS
• Verilog does not allow changing the dimensions of the array
once it is declared. Most of the time in verification, we need
arrays whose size varies based on the some behavior. For
example Ethernet packet varies length from one packet to other
packet. In verilog, for creating Ethernet packet, array with
Maximum packet size is declared and only the number of
elements which are require for small packets are used and
unused elements are waste of memory.

• To overcome this deficiency, System Verilog provides Dynamic


Array. A dynamic array is unpacked array whose size can be set
or changed at runtime unlike verilog which needs size at
compile time. Dynamic arrays allocate storage for elements at
run time along with the option of changing the size.
• Declaration Of Dynmic 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.

dyna_arr_1 = new[10] ;// Allocating 10 elements


multi_dime_dyn_arr = new[4];// subarrays remain unsized and
uninitialized
• Initializing Dynamic Arrays:

The size argument need not match the size of the


initialization array. When the initialization array~Rs size is
greater, it is truncated to match the size argument; when it
is smaller, the initialized array is padded with default values
to attain the specified size.

dyna_arr_2 = new[4]('{4,5,6}); // elements are {4,5,6,0}


• Resizing Dynamic Arrays:

Using new[] constructor and its argument, we can


increase the array size without losing the data
content.

Dyna_arr_1 = new[100] (dyna_arr_1); // Previous 10


data preserved
• Copying Elements:
Copy constructor of dynamic arrays is an easy and faster way of creating
duplicate copies of data.

Dyna_arr_2 = new[100](dyna_arr_1);// allocating and copying 100


elements.
Dyna_arr_1 = [1000]; // Previous data lost. 1000 elements are allocated.
ASSOCIATIVE ARRAYS
• Dynamic arrays are useful for dealing with contiguous
collections of variables whose number changes
dynamically.
• Associative arrays give you another way to store
information.
• When the size of the collection is unknown or the data
space is sparse, an associative array is a better option.
• In Associative arrays Elements Not Allocated until
Used.
• Index Can Be of Any Packed Type, String or Class.
• Associative elements are stored in an order that
ensures fastest access.
• The syntax to declare an associative array is:

data_type array_id [ key _type];

data_type is the data type of the array elements.


array_id is the name of the array being declared.
key_type is the data-type to be used as an key.
• Examples of associative array declarations are:

int array_name[*];//Wildcard index. can be indexed by any


integral datatype.
int array_name [ string ];// String index
int array_name [ some_Class ];// Class index
int array_name [ integer ];// Integer index
typedef bit signed [4:1] Nibble;
int array_name [ Nibble ]; // Signed packed array

Associative array literals use the '{index:value} syntax with an
optional default index.

//associative array of 4-state integers indexed by strings, default is


'1.
integer tab [string] = '{"Peter":20, "Paul":22, "Mary":23, default:-1
};
• To work with associative arrays, System Verilog provides following
methods

– 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

• Initial value of queue


• Queue contains 0 1 2 3 4
• new element added using concate
• Queue contains 5 0 1 2 3 4
• new element added using push_front
• Queue contains 6 5 0 1 2 3 4
• new element added using push_back
• Queue contains 6 5 0 1 2 3 4 7
• new element added using insert(index,value)
• Queue contains 6 5 0 1 8 2 3 4 7
• element poped using pop_front
• Queue contains 5 0 1 8 2 3 4 7
• element poped using pop_end
• Queue contains 5 0 1 8 2 3 4
• deleted element at index 4
• Queue contains 5 0 1 8 3 4
OPERATORS 1
• The SystemVerilog operators are a combination of Verilog
and C operators. In both languages, the type and size of the
operands is fixed, and hence the operator is of a fixed type
and size. The fixed type and size of operators is preserved in
SystemVerilog. This allows efficient code generation.
Verilog does not have assignment operators or increment
and decrement operators. SystemVerilog includes the C
assignment operators, such as +=, and the C increment and
decrement operators, ++ and --.
Verilog-2001 added signed nets and reg variables, and
signed based literals. There is a difference in the rules for
combining signed and unsigned integers between Verilog
and C. SystemVerilog uses the Verilog rules.
Operators In Systemverilog
Assignment Operators
• In addition to the simple assignment operator, =, SystemVerilog includes
the C assignment operators and special bitwise assignment operators:

+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, <<<=,>>>=.

An assignment operator is semantically equivalent to a blocking


assignment, with the exception that any left-hand side index expression is
only evaluated once.
For example:

a[i]+=2; // same as a[i] = a[i] +2;


• Assignments In Expression

In SystemVerilog, an expression can include a blocking assignment. such


an assignment must be enclosed in parentheses to avoid common
mistakes such as using a=b for a==b, or a|=b for a!=b.

if ((a=b)) b = (a+=1); // assign b to a


a = (b = (c = 5));// assign 5 to c

if(a=b) // error in systemverilog

(a=b) statement assigns b value to a and then returns a value.

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 :

# > >= < <= relational


Arithmetic :
EXAMPLE :Arithmetic
program main;
integer a,b;
initial RESULTS
begin
b = 10; -(nagetion) is -22
a = 22; a + b is 32
a - b is 12
$display(" -(nagetion) is %0d ",-(a) ); a * b is 220
$display(" a + b is %0d ",a+b); a / b is 2
$display(" a - b is %0d ",a-b); a modules b is 2
$display(" a * b is %0d ",a*b);
$display(" a / b is %0d ",a/b);
$display(" a modulus b is %0d ",a%b);
end
endprogram
OPERATORS 2
• Logical :


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.

• Example:// system verilog

• 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 serves these basic purposes:


-> Separates the testbench from the DUT.

-> The program block helps ensure that test bench transitions do not have
race conditions with the design

-> It provides an entry point to the execution of testbenches.

-> It creates a scope that encapsulates program-wide data.


-> It provides a syntactic context that specifies scheduling in
the Reactive region which avoids races.

-> It does not allow always block. Only initial and methods are
allowed, which are more controllable.

-> Each program can be explicitly exited by calling the $exit


system task. Unlike $finish, which exits simulation
immediately, even if there are pending events.

-> 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:

SystemVerilog has statements to control the


loop statements.
break : to go out of loop as C
continue : skip to end of loop as C
return expression : exit from a function
return : exit from a task or void function
• Event Control:

Any change in a variable or net can be detected using the @


event control, as in Verilog. If the expression evaluates to a
result of more than 1 bit, a change on any of the bits of the
result (including an x to z change) shall trigger the event
control.
SystemVerilog adds an iff qualifier to the @ event control.

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:

In an always block that is used to model combinational logic, forgetting an


else leads to an unintended latch. To avoid this mistake,
• SystemVerilog adds specialized always_comb and
• always_latch blocks, which indicate design intent to simulation, synthesis,
and formal verification tools.
• SystemVerilog also adds an always_ff block to indicate sequential logic.

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

• The parent process continues to execute


concurrently with all the processes spawned
by the fork. The spawned processes do not
start executing until the parent thread
executes a blocking statement.

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

The parent process blocks until all the


processes spawned by this fork complete.
• EXAMPLE : fork/join all
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
$display(" time = %d Outside the main fork ",$time );
#(40);
end
endprogram

• 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

• SystemVerilog adds the clocking block that identifies


clock signals, and captures the timing and
synchronization requirements of the blocks being
modeled.
• A clocking block assembles signals that are
synchronous to a particular clock, and makes their
timing explicit.
• The clocking block is a key element in a cycle-based
methodology, which enables users to write
testbenches at a higher level of abstraction.
• Simulation is faster with cycle based methodology.
• Depending on the environment, a testbench
can contain one or more clocking blocks, each
containing its own clock plus an arbitrary
number of signals. These operations are as
follows:

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:

interface intf (input clk);


logic read, enable,
logic [7:0] addr,data;
clocking cb @(posedge clock); // clocking block for testbench
default input #10ns output #2ns;
output read,enable,addr;
input data;
endclocking
modport dut (input read,enable,addr,output data);
modport tb (clocking cb); // synchronous testbench modport
endinterface :intf
module testbench(intf.tb tb_if);
......
initial
tb_if.cb.read <= 1; //writing to synchronous signal read
...
endmodule
Example of clocking block
• module COUNTER (input Clock, Reset, Enable, Load, UpDn,
input [7:0] Data, output reg[7:0] Q);
always @(posedge Clock or posedge Reset)
if (Reset)
Q <= 0;
else
if (Enable)
if (Load)
Q <= Data;
else
if (UpDn)
Q <= Q + 1;
else
Q <= Q - 1;
endmodule
• The testbench to test this counter, without using the clocking construct, might look like this:

• 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

// Set all inputs at the beginning


Enable = 0;
Load = 0;
UpDn = 1;
Reset = 1;

// Will be applied on negedge of clock!


##1 cb_counter.Reset <= 0;
// Will be applied 4ns after the clock!
##1 cb_counter.Enable <= 1;
##2 cb_counter.UpDn <= 0;
##4 cb_counter.UpDn <= 1;
// etc. ...
end

// Check the results - could combine with stimulus block


initial begin
##1
// Sampled 1ps (or whatever the precision is) before posedge clock
##1 assert (cb_counter.Q == 8'b00000000);
##1 assert (cb_counter.Q == 8'b00000000);
##2 assert (cb_counter.Q == 8'b00000010);
##4 assert (cb_counter.Q == 8'b11111110);
// etc. ...
end

// Simulation stops automatically when both initials have been completed


endprogram

// Instance the counter


COUNTER G1 (Clock, Reset, Enable, Load, UpDn, Data, Q);

// Instance the test program - not required, because program will be


// instanced implicitly.
// test_COUNTER T1 ();
• // Check the results
initial
begin
OK = 1;
#9;
if (Q !== 8'b00000000)
OK = 0;
#10;
if (Q !== 8'b00000000)
OK = 0;
#20;
if (Q !== 8'b00000010)
OK = 0;
#40;
if (Q !== 8'b11111110)
OK = 0;
// etc. ...
end
endmodule
• Initialise a=10,b=20 Blocking
always
Begin
a=b;
b=a;
end a=20,b=20

always Non blocking


Begin
A<=b;
B<=a;
End a=20,b=10

You might also like