0% found this document useful (0 votes)
72 views38 pages

SystemVerilog Overview and Features

system verilog

Uploaded by

aakashkhaliq39
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)
72 views38 pages

SystemVerilog Overview and Features

system verilog

Uploaded by

aakashkhaliq39
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

System Verilog

By Muhammad Aakash Khaliq


What is SystemVerilog?
● HDLs (Verilog + VHDL): hardware behaviour → digital blocks
● Need for a complex and more featured language, which also include OOP
concepts for testing of hardware, “Hardware Verification Language”.
● SystemVerilog: Complex test bench structure + random stimuli + coverage
Why not Verilog?
● In the 1990s, Verilog was used to verify the functionality of the design.
● Complex designs require more features of testing
● SystemVerilog:
○ Constrained random stimulus
○ OOP features
○ Functional coverage
○ Assertions etc
What is verification?
● Process of ensuring that hardware works as expected

● Chip design is extensive and time-consuming process

● Functional defects caught later in the design flow shall use up more time,
resources, and money.

● If entire design flow is repeated, it’s called a “respin” of the chip


Level of abstractions
module tb_top;
bit resetn;
task apply_reset ();

#5 resetn <= 0;

#20 resetn <= 1;

endtask

initial begin

apply_reset();

end endmodule

Here apply_reset() is the task that is called by the test writer, and test writer does
not bother about how and instead focus on when these tasks should be put to use.
SystemVerilog Data Types
Data Types
● Floating point/exponentials
○ Real pi 3.14;
○ Real freq 1e6;
○ $display(“value of pi = %f and pi up to three digits = %0.3f, freq = %0d”, pi, pi, freq)
● Strings
○ One character is stored in 8 bits
● Structure
○ Contains elements of different data types (int, real, string etc) that can be referenced as a
whole or individually by their names
○ Struct (elements of different data types) vs Array (elements of same data type)
■ Examples of arrays are int array [10]; bit [7:0] mem [256];
■ Ex of structure: struct { byte val1; int val2; string val3; } struct_name;
■ Syntax: struct { list of variables separated by ;} struct_name;
Always_comb Module alu(
Input logic [3:0] a,Input logic [3:0] b,input logic
Intent to model combination [1:0]op_code, output logic[3:0]);
logic. No need to write
Always_comb begin
sensitivity list for it
case(op_code)

SystemVerilog’s always_comb 2’b00:begin result = a+b; end;


removes the always@* limitation by 2’b01:begin result = a-b; end;
making the block sensitive to signals
2’b10:begin result = a&b; end;
used both directly and within called
2’b11:begin result = a|b; end;
functions
Endcase

always_comb begin // End


infers x and y z =
endmodule
func_and (x, y); end
Module data_selector_wth_latch(
Always_latch Input wire a, input wire b, input
This procedural block is used wire sel, input wire enable, output
when the intent is to model reg data_out)
the latch-based logic.
Wire mux_out;

In addition, always_latch executes


Assign mux_out = sel ? a:b;
once at time zero to make sure the
Always_latch begin
latch outputs are consistent with the
inputs at the very start of simulation.
if(en)

Data_out = mux_out;

End

endmodule
Module sync_counter_3bit (input wire clk,
Always_ff input wire reset_n, output reg [2:0]
count);
This procedural block is used
to model synthesizable
sequential logic. Such as
always_ff@(posedge clk or negedge
flip-flops. reset_n)begin
Requires explicit sensitivity
list if(!reset_n)

Count <= 3’b000;

Else

Count <= count + 1;

End
endmodule
Struct cont’
Example: structure of st_fruit that contains fruit name, count and expiry

Module tb;

Struct {
String fruit;

Int count;

Byte expiry;

} st_fruit;

Initial begin

st_fruit = {apple; 5; 20}; $display(“struct variable = %p”, st_fruit);

//change fruit name to pineapple

St_fruit.name = “pineapple”;

$display (“st_fruit = %p “, st_fruit);

End

endmodule
Struct cont’
● If there is a need to create more variables of the struct, then it's good to
create a user-defined data type of the structure by “typedef”. Now st_fruit
becomes data type
● Structure can also be declared before the module.
Example: typedef struct {string fruit; int count; byte expiry;}st_fruit;

Module tb;

Initial begin

st_fruit fruit_1 = ‘{“apple”,5, 25}; st_fruit fruit_2; fruit_2 = fruit_1 (display will show the pineapple, count as 5 and expiry as 25)
Packed structure
Mechanism of dividing a vector into fields. The first member is most significant,
and the rest follow in decreasing order. Denoted with keyword “packed” which is
unsigned

Example: bit [7:0] ctrl_reg; ctrl_reg [0] en; ctrl_reg [3:1] cfg; ctrl_reg [7:4] mode

Typedef struct packed { bit [3:0] mode; bit [2:0] cfg; bit en;} st_ctrl;

Module tb; st_ctrl ctrl_reg ; initial begin ctrl_reg = ‘{4’ha, 3’h5, 1}; end
ctrl_reg = '{mode:'ha, cfg:'h5, en:'h1}
Fixed Arrays
Module tb; Assign value to location 5 in 1D array

Int array_1 [7:0]; //an array of 8 locations; each location Assign value to location 1,1 in 2D array
can store 32 bits
Initial begin
array_1[5] = 32’hcafe_face;
Int array_2 [8]
myArray[1][1] = 7;
1-D array Memory view: its like a fifo
Iterate through each location
0,0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 Foreach(array[i]) begin

$display(“entry %0d, value %0h ”,i, array_1[i]);


2-D array:
Iterate through each element of multidimensional array
Int myArray [2][3]; //int array [rows] [columns]
foreach(myArray[i])
0,0 0,1 0,2
foreach(myArray[i][j])
1,0 1,1 1,2
Correct loop for 2-D array
Void: Nonexisting data and specified as return type of System Verilog logic:
functions and tasks to indicate no return value Types that can have unknown (X) and high-impedance (Z) value in
addition to zero (0) and one (1) are called 4-state types. In Verilog,
Real to Int conversion: all nets (eg. wire) and variables (eg. reg) use 4-state values. Note
that reg can only be driven in procedural blocks like always and
Casting: int’(2.0 *3.0) -> cating only rounds the values initial while wire can only be used in assign statements
after the decimal to the closest. If decimal part is 0.5 it
will be rounded away from zero
Logic can be driven through procedural and block and continuous
int’(2.9) => 3 and int’(2.1) => 2 assignment. However, a signal having more than one driver needs
to be declared as wire so that systemVerilog can resolve the final
System Tasks: truncate the decimal part
value based on Strength:
$rtoi(integer_value): $rtoi(2.9)=> 2
$rtoi(-2.9) => 0 truncates toward zero
$itor(5) => 5.0 (exact conversion) 4 state to 2 state conversion:
When a 4-state value is converted to a 2-state value, unknown (X)
or high-impedance (Z) bits shall be converted to zeros.
Data Types (signed unsigned)
Byte, init, shortint, longint all are 2 state signed data Signed data types can represent both positive and negative values,
whereas unsigned data types can only represent non-negative values
types. (zero and positive numbers). Signed data types use one bit (MSB) for the
sign, which reduces the maximum positive value that can be represented
compared to unsigned types of the same bit width. This means that while
Module tb; both signed and unsigned types may have the same number of bits, the
unsigned type has a larger range of positive values.
Byte m_var; Byte unsigned u_byte; //unsigned byte
Byte s_byte; //signed byte
Initial begin
Sign Casting

#5 m_var = 2**7-1; // 127 Module tb;


Shortint unsigned var_us;
//since it signed 8 bit, it can store 127 to -128 bits Shortint var_s;

Initial begin
#10 m_var = 2**7; -128 var_us = 2**16 -1; //convert it to signed 65535
var_s = -1; //conver it to unsgned

M_var = ‘b1000_0000; //MSB is a signed bit and 1 so $display(“var_us = %0d, var_us = %0d”, signed’(var_us), var_us);

sign will be negative number and its also out of range m_var_us=-1 m_var_us= 65535
of 127. So it wraps around to -128
m_var_s=65535 m_var_s=-1
Data Types
String:

A single ASCII character required 8 bits (1 byte)

Example:
String [16*8-1:0] my string; //can store 16
characters

My_string = “how are you” //5 zeros padded from


MSB

My_string = “how are you doing?”


//18 characters. My string will get “w” are you
doing and “ho” will be truncated since we only
have 16 locations in the strin variable.

Displayed with %s
Basic String methods
Enumerations
Defines a set of named variables. By default the first Enumerated data type:
element of the list takes 0 value and the rest get the values
A custom data type can be created so that it can be used to declare
in incrementing fashion 1, 2 ,3.
other variables as well.
enum {RED, GREEN, YELLOW} light_1;
//int type: RED =0, GREEN = 1, YELLOW = 2 Module tb;

Enum {RED, GREEN, YELLOW} light_2; // bit type: Typedef enum {TRUE, FALSE} boolean_en;
Any value can be assigned to enumerated name
Initial begin
If I assign RED =2 then Green and yellow takes the
increment from the RED and their values will be 3 and 4
respectively. Boolean_en answer ;

Answer = TRUE;
enum {RED = 2, YELLOW, GREEN = 3} light_5; // Error :
YELLOW and GREEN are both assigned 3
%display(“Answer is = %s”, [Link]);

enum bit[0:0] {RED, YELLOW, GREEN} light_6; // Error: End


minimum 2 bits are required

Note that an enumeration name cannot start with a number !


endmodule
Enumerations
typedef enum {GREEN, YELLOW, RED, BLUE} GREEN = 0 YELLOW = 1 RED = 2 BLUE 3
color_set_1;

typedef enum {MAGENTA=2, VIOLET=7, PURPLE, MAGENT = 2, VIOLET = 7, PURPLE = 8, PINK = 9


PINK} color_set_2;

BLACK0 = 0, BLACK1 = 1, BLACK2 = 2, BLACK3 =3


typedef enum {BLACK[4]} color_set_3;

typedef enum {RED[3] = 5} color_set_4; RED0 = 5, RED1 = 6, RED2 = 7

typedef enum {YELLOW[3:5]} color_set_5;


YELLOW3 =1, YELLOW4 = 2, YELLOW5 = 3

typedef enum {WHITE[3:5] = 4} color_set_6; WHITE3 =4, WHITE4 = 5, WHITE5=6


Enumerated types methods
// GREEN = 0, YELLOW = 1, RED = 2, BLUE = 3
[Link]() = 0
typedef enum {GREEN, YELLOW, RED, BLUE} colors;
[Link]() = 3
module tb;
[Link]() = 2
initial begin
[Link]() = 0
colors color;
// Assign current value of color to YELLOW [Link]() = 4
color = YELLOW;
$display ("[Link]() = %0d", [Link]()); // First
value is GREEN = 0 [Link]() = YELLOW

$display ("[Link]() = %0d", [Link]()); TYPE CHECKING: Explicit cast


// Last value is BLUE = 3
Why light = 0; is invalid
$display ("[Link]() = %0d", [Link]());
// Next value is RED = 2
In SystemVerilog, enum types are strongly [Link] though under the
hood RED = 0, GREEN = 1, BLUE = 2 (default integer encodings),
you cannot directly assign an int literal (0, 1, etc.) to an enum variable.
$display ("[Link]() = %0d", [Link]());
// Previous value is GREEN = 0

$display ("[Link]() = %0d", [Link]());


light = e_light'(1); // cast the int 1 into enum type e_light
// Total number of enum = 4
This tells the compiler:
$display ("[Link]() = %s" , [Link]()); “Interpret the integer value 1 as belonging to the enum type e_light.”So now
// Name of the current enum light = GREEN.

end

endmodule
Arrays (static, dynamic, associative, queues)
Static Array: An array whose size is known before compile In the example shown below, a static array of 8-bit wide is declared,
time assigned some value and iterated over to print its value.

Packed array or vector: A packed array is guaranteed to be Module tb;


represented as a contiguous set of bits. Bit [7:0] array;
Bit [2:0][7:0] p_array;
Initial begin
Bit [number of such arrays][such array] array = 8’hAF;

for(i=0; i<$size(array); i++) begin


P_array[2] | parray_[1]| p_array[0]
Each p_array is of 8 bits $display(“element of array[%0d] = %0b” i,
array[i]);
Unpacked array:
Bit [7:0] up_array [2:0]; End
End
Up_array[0] endmodule
Up_array[1]
Up_array[2]

Storing unpacked array as a non-contiguous set of bits.


Arrays (static, dynamic, associative, queues)
3-D packed array: bit [2:0] [3:0] [7:0] p_array;
Think of it as:
3 “banks” ([2:0])
Each bank has 4 “rows” ([3:0])
Each row is 8 bits ([7:0]), 7 = MSB, 0 = LSB

bank 2 bank 1 bank 0

p_array[2][3][7:0] ... p_array[1][3][7:0] ... p_array[0][3][7:0] ...

p_array[2][2][7:0] ... p_array[1][2][7:0] ... p_array[0][2][7:0] ...

p_array[2][1][7:0] ... p_array[1][1][7:0] ... p_array[0][1][7:0] ...

p_array[2][0][7:0] ... p_array[1][0][7:0] ... p_array[0][0][7:0] ...

^ MSB rows at top ^ ^ LSB rows at bottom


Arrays (static, dynamic, associative, queues)
Module tb;
Bit [2:0][3:0][7:0] p_array;

Initial begin
p_array[0]= 32’hface_cafe;
p_array[1]= 32’hcafe_face;
p_array[2]= 32’haaaa_5555;

foreach(p_array[i])
foreach(p_array[i][j]);
$display(“p_array[%0d][%0d]= %0h ” , i, j, p_array[i][j])
end
endmodule
Arrays (static, dynamic, associative, queues)
Unpacked array: 1-D Unpacked array: 2-D
Module tb; Module tb;

Byte stack[8]; Byte stack[2][3]; //2 rows, 3 columns

Initial begin Initial begin

foreach(stack[i])begin Foreach (stack[i]) begin

Stack[i] = $random; foreach( stack[i][j]) begin

End Stack[i][j] = $random;

End End
end
endmodule
$display(“stack = %p”, stack)

End

endmodule

stack = '{'{'h24, 'h81, 'h9, 'h63}, '{'hd, 'h8d, 'h65, 'h12}}


Arrays (static, dynamic, associative, queues)
Bit [3:0][7:0] stack [2][4]

Packed and unpacked multidimensional array


Dynamic array
It is an unpacked array whose size The new() function is used to allocate a size for the array and initialize its elements if
required.
can be set or changed at run time. By
// Create a dynamic array that can hold elements of type
default size of dynamic array is zero int
until it is set by new() constructor.
Module tb;

Dimensions specified by [ ] Int d_array [];

Bit [7:0] stack []; dynamic array of 8 bit Initial begin


vector
d_array = new[5]; //specify the size of dynamic array

String names []; dynamic array of d_array= ‘{32, 33, 55, 87};
strings
foreach(d_array[i]) begin
d_array.size(): size of the array
$display(“d_array[%0d] = %0d “, i, d_array[i]);
d_array.delete() empty the array
end

endmodule
Dynamic array
Add new elements to existing Module tb;
dynamic array without losing Int array [];
the existing contents.
Int id [];

Initial begin

array= new[5];

array=’{1,2,4,6,8};

Id = array;//copied the 5 entries to id from array

// Grow size by 1 and copy existing elements to the new [Link]


"id" // need to add 1 new location to have space for new element

Id = new[[Link]()+1](id);

id[[Link]()-1] = 10;

// Assign value 6 to the newly added location [index 5]

end

endmodule
Associative Array
Index of the array need not
only be integer it can be
string as well.

array1 = '{1:22, 6:34}

array2 = '{"Joey":60,
"Ross":100}

array3 =
'{"Apples":"Oranges",
"Pears":"44"}
Array manipulation methods
Specifying an iterator argument without the with clause is illegal.
Array manipulation methods
Array reduction methods
Queues
A system verilog queue is a first in first
out scheme which has variable size to
store elements of the same data type.
Here data type is an important thing to
note.

Bounded queue:
int bounded_q [$:10];
Unbounded queue:
Int un_bounded_q [$];
String que [$];
Bit [3:0] q [$];

Bit [7:0] bounded_q [$:127];

Int integer_q1 [$] = {1,3,5,7,9};


Int integer_q2 [$];
Int tmp;

Tmp = integer_q1[0];
Tmp = integer_q1[$];
Integer_q2 = integer_q1;
Integer_q1 = {};

Integer_q1[2]=15;
integer_q1.insert(2,15);
integer_q2={integer_q2,22};
integer_q2= {99, integer_q2};
integer_q2= integer_q2[1:$];
integer_q2= integer_q2[0:$-1];
integer_q2= integer_q2[1:$-1];
Queue slice expressions? Select subset of existing variable
Queue of dynamic arrays in SystemVerilog.

Typedef str_darray [];

Module tb;

Str_darray list[$];

Initial begin

Str_darry fruits = ‘{“apple”, “bannana”};

Str_darry heroes = ‘{“hulk”, “spiderman”, “superman”};

list.push_back(fruits);
list.push_back(heros);

foreach(list[i])
foreach(list[i][j])
%display(“list[%0d][%0d] = %s”, i, j, list[i][j]);
%display(“Print queue = %p” list);

End
endmodule
Tasks and functions.
The difference between a task and a function (no timing event like delay or event to
happen, etc.) task (can put timing control, delay, wait for an event to happen)

Static vs. automatic task:


When a task is invoked, a memory is created at the back end. For a static task, the
same memory will be used whenever a task is invoked.
But for an automatic task, a separate memory will be created for each invocation.
Static vs automatic task

[Link]
utm_source=share&utm_medium=member_desktop&rcm=ACoAADCOIQ8BF4fApe2Hu2p7MXRnQ_xX8EZ0K8M
Argument passed by:

1- value

2- name

3- reference
[Link]
hare&utm_medium=member_desktop&rcm=ACoAADCOIQ8BF4fApe2Hu2p7MXRnQ_xX8EZ0K8M

You might also like