SV-NOTES-APR2020
SESSION#1(5/APR)
Revision:
o ASIC FLow
o ASIC vs FPGA
o Front End FLow
– Design
– RTL
– Functional Verification or RTL Verification
– If some issues are found here in the RTL it is easy to fix them.
– TestBench
o Synthesis
– Input : RTL
– Output : Netlist
o Gate Level Simulations(Verification) are performed on this.
- DUT is not RTL but netlist.
- What if there are issues here?
- They will try to fix as an ECO.
o ECO is that they fix the design in the netlist, so that another Synthesis is saved.
- IF ECO is difficult to be done, then they go for re-synthesis by fixing it in RTL.
Doubts:
Notes:
o TestBench:
– Generator, BFM(Driver) , Monitor -> Agent
o Generator will generate the data required for testing and give it to the BFM.
o BFM will drive the data onto the DUT according to the protocol. BFM will convert the object level info to the signal level activity on the interface
o Monitor will observere the interface and sample the meaningful activity on the interface, collect it form an object and send it to the other Testbench components which require this info(Functional coverage, Reference Model).
– Reference Model
O It is a duplicate model of design under test with the same functionality.
o SOC Architecture’
– Every SOC will have a processor. This will be master in the SOC.
– Mostly all mobile SOCs will have ARM processor. The interface will be AMBA standard. AMBA -> APB, AHB, AXI
– AMBA stands for Advanced Microcontroller Bus Architecture
- For performance and power efficiency, we use a combination of all these proocols. APB, AHB and AXI.
o Various Verifications
– IP Level
– A small design
– Subsystem Level
o Subsystem – COnsists of several IPs and there will be a processor in that.
– SOC Level
o SOC consists of several subsystems + IPs
o Code coverage
– if(a) b<=0;
else b<=1;
- JUst enable the coverage in the tool while running the testcases.
- Code coverage consists of FLBEST coverage.
o Functional coverage
– purely for System Verilog
– Verification has to decide which all things he has to consider as part of functional coverage.
o For example, in traffic light controller, he wil make a plan that the values 5 to 10 should be programmed for the delay registers.
– Also, decides he has to cover Blinking mode, High Traffic Mode,Manual Mode and so on.
o IN SV we will be having constrained random stimulus.
o I may run only 1 test, but i can get different configurations out of that test.
– Suppose you ran the same test 5 times.
– Who is going to keep track of your inputs.
o Tool Stages
- Compilation
o All the items that got memory during compile time are called static elements.
– int, reg , static Arrays, static properties of the class,struct,unions,….. - Elaboration
- Simulation (Run Time)
o There are run time memory allcoation and deallocations happening in runtime in SV.- Classes, Dynamic Arrays, Queues, Associative Arrays,…. o Arrays SV we have various types of arrays.
o based on how memory is allocated.
- Unpacked
- Packed o based on “when” the memory is allocated.
- when here indicates at the “compile time” or at the “run time”
o Static Arrays -> int arr[10];
o Dynamic Arrays- Dynamic Arrays -> int darr[];
- At run time, user has to explicitly say the amount of memory he requires.
- darr = new[20];
- The memory requirement for array can be increased or decreased during run time.
- darr = new[10];
….. - darr = new[40];
- darr = new[10];
- Can only be in the unpacked dimension.
- bit [] arr [10];// illegal
- bit [] arr; //illegal
- bit darr [] []; //not possible.
- At run time, user has to explicitly say the amount of memory he requires.
- Queues -> int que[$]
– It does need to get created. Dont need to use new[].
– The size of the queue automatically increases and decreases as you keep filling or removing entries from the queue.
que = {1,2,3,4};
que = {1,2,3,4,5,6};
que = {4,5,6}; - Associative Arrays -> int aa[int];
int aa[*];
– This also doesnot require it to be created.
– It keeps adjusting as we fill entries.
– This is similar to a content addressible memory.
int aa [string];
aa[“vlsi”] = 10;
aa[“guru”] = 30;- Application is the places where we have a very big memory but we are using it sparsely. - int a [100000]; a[0]=10; a[500]=20; a[50000]=40; a[1]=30; a[600]=40; ... . - In such scenarios we need to use associative array. - int aa [int]; - Memory will get allocated only on filling. a[0]=10; a[500]=20; a[50000]=40; a[1]=30; a[600]=40; ... .
Verilog :
reg [3:0] mem [0:1023]
- Dynamic Arrays -> int darr[];
- mem has a depth of 1024(1024 locations) and each location is 4 bit wide. [0:1023] is called unpacked dimension.
- unpacked means each index takes a new address location. [3:0] is called packed dimension.
- packed because all the bits here are at the same address location. System Verilog:
- The above is valid in SV.
- int [3:0] mem; //Is it possible? – Not possible
- Packed dimensions are valid only for the data types that comes without a fixed width.(Eg, wire,logic, bit,reg.. ..)
- int mem[0:3]; //Is it possible? – Yes
- bit [1023:0] mem; // This will be at a single address location with 1024 bit width. o Dynamic Arrays
- Classes, Dynamic Arrays, Queues, Associative Arrays,…. o Arrays SV we have various types of arrays.
SESSION#2(11/APR)
Revision:
o understanding Testbench Architecture
– Driver/BFM, Monitor, Generator
– Reference Model,Scoreboard,checker
– Why functional coverage?
o SOC Architecture
o Various levels of verification
– IP/Module level
– Subsystem Level
– SOC Level
o Tool Simulation Steps
– compilation
– Elaboration
– Simulation
o Arrays
– How the memory is allocated for the array
– Unpacked – each element in the array is at a different address location.
o implies only a single element can be accessed at once.
– Packed – all the elements are packed into a single address location.
o more than one element can be accessed at once.
– Based on when the memory for the array is allocated
o Static Array – ALso known as Fixed size array ->[2]
o Dynamic Array
– Dynamic Array -> []
– Associative Array -> [int]
– Queues ->[$]
Doubts:
o bit [3:0] darr[];
Notes:
o Simulation Example of Dynamic Array.
o Functions provided by the Language
-o Dynamic Array
– new[]
– size()
–
o Unpacked and Packed
– Packed
o Slice operation is possible. One or more than one element can be accessed.
o bit [3:0] b;
– bit [3:0] [1:0] b;
– Unpacked
o Unpacked array can be static or dynamic
int sa[10];
int da[];
da=sa; -> only when da size is 10.
o Slice operation not possible.
o Whole array cannot be accessed at once.
- Exception is for copy.
- The whole array can be copied at once.
- There is a condition. Both the array sizes should be same.
- The indexes need not be the same. Lower index to lower index and upper to upper will be copied.
o int upa [3:0];
upa ='{1,2,3,4}
o int a [1:3][1:2];
o int a [1:3][1:2][0:1];
o int a [2:3][9:10][1:2];
- a[2][10][1]
- Multidimension in packed and unpacked
o bit [2:0] mda [4:0]
o mda[1][2] -> wil lead to a single bit
o mda[2][1:0]
o mda[3][2:1]
o mda[0]
o foreach
for(int i=0; i<3;i++)
if you are doing it for an array where you dont know its size, you will use arr.size();
for(int i=0; i<arr.size();i++)
-> foreach(arr[i])
Associative Arrays
o denoted by [string]
o int aa [string]
o int aa[int]
o string aa [int] -> index=int data=string
o index is also called as key
o Methods (refer example)
– first
– next
– last
– prev
– exists
– num
– delete
Queues
o denoted by [$]
– int q [$]; -> This means queue is having infinite capacity
– int q [$:255] -> This means my queue is bounded by the index 255
- initialize a queue
o q = {1,2,3,4};
o q = {q,5}; -> adding an element at the end of the queue.
o q = {q[0:4],6,7,8}; -> q = {1,2,3,4,6,7,8}
o q = {q[0:4],5,q[5:$]}; -> insert 5 in between 4 and 6. -> q.insert(5,5)
o q = {0,q[0:$]}; adding an elemnet at the start of the queue
- Methods
o insert -> to insert in a given position
q.insert(index, value)
o delete
q.delete(5); //deletes the element from index 5
o q[0] -> i will be able to read the 1st element. BUt i am not removing that entry from the queue.
q = {q[1:$]};
o val=q.pop_front();
o val=q.pop_back();
o q.push_front(val);
o q.push_back(val);
-
SESSION#3(12/APR)
Revision:
o Dynamic Arrays
– Methods provided by the language
– new
– size
– delete
o FUnction
- gets executed in 0 simulation time
Task
- consumes some simulation time.
In SV, both functions and tasks collectively are called Methods.
o Associative Arrays
o Queues
Doubts:
Notes:
- SV Language Concepts
- DataTypes int a; int -> DataType -> language provided datatypes
a -> identifier, variable my_int a;
my_int -> user defined datatype
- Definition phase
Language provided : No
User defined : Yes - Instantiation
Language provided : Yes
User defined : Yes - Creation
Static : No
– Examples: Struct (User defined datatype),union –
Dynamic : Yes
– Examples: classes, - Assignmet
a=10; a=$random;
obj.randomize(); Handles:
- pointer in C
int a;
int *p;
p=&a; - Handle in SV
- same as a pointer in C. It is named as handle in SV.
- There is a small difference here. * is not required here to indicate a handle. Another variable is also not required to store the address.
Every variable is a handle to itself.
int a;
a is a variable. a is also a handle to itlsef.
handle name and variable name are same in system verilog. - Depending on the context, tool will differentiate.
- if i want to pass the handle and not the value i have to use ref keyword. Classes and OOPS Concepts:
- class
- It is a dynamic data type. creation is mandatory.
- It consists of properties, methods and constraints.
- class – properties
class – properties + methods
class – properties + methods + constraints
- class – properties
- The instantiation of the class is called an object handle.
- on creation, it becomes an object.
- Object is a basic building block of a testbench.
- All the class properties and methods can be accessed using dot operator.
- objects are created by calling new() and new is called constructor.
- There is no desctructor in SV, deallocation of memory happens automatically. o We can have data hiding feature in SV classes.
- local – The property can be accessed only inside the class where it is defined.
- protected – Along with that class, the property can be accessed by the child class as well.
- public – Anyone can access it class eth_pkt;
bit [3:0] sa;
bit [3:0] da; function void print();
endfunction //constraints can be added to help constrained randomization
constraint constr_name {sa >=3; sa<=13; da<=14; da>=1;}
endclass eth_pkt pkt; //pkt is an object handle. handle
pkt = new(); //created the object called pkt.
pkt.sa =3;
pkt.da =4; o Inheritance
– class eth_pkt;
local int l; //l can only be accessed in the eth_pkt
protected int a; // a in both eth_pkt and extended_Class
int p; //everywhere
function printa();
endfunction
endclassclass extended_Class extends eth_pkt; int b; // this class has a and printa method endclass
o extended_Class is called as a child class or derived class
o eth_pkt is called as a base class or parent class.
o super is used to access the parent’s properties and methods. o Static properties
- static properties get their memory allocated at the compile time,
- They are unique memory locations for the whole environment.
- Have none or multiple objects makes no difference. Still there will be a unique location.
- we can access that unique location using any object handle or class_name and scope resolution operator
- eth_pkt::count
- we can access that unique location using any object handle or class_name and scope resolution operator
- on creation of the objects the static property will not get another memory location. o Static Methods
- To make a method static, we have to add static keyword before the function.
- No non-static property is allowed inside a static function.
- Static properties can be used in non-static functions.
SESSION#4(18/APR)
Revision:
o Data Types
– Stages involved in the usage of datatypes and variables
– Definition
– Instantiation
– Creation
– Assignment
o Handle
– pointer equivalent of C
– EVery variable is a handle to itself with the same name.
o classes
– properties, methods
– handles
– object creation
– new method – constructor
– no destructor – memory deallocation is take care by the tool automatically
– Encapsulation
– datahiding – local, protected, public
– local – property can be accessed only in the class where it is declared.
– protected – in the class and in its child classes
– public – can be accessed anywhere in the testbench
– Inheritance
-class B extends A;
– A : parent class
– B : child class
– Static properties
– class properties will get the memory allocated in run time.
– If we some variable to take static memory location, static keyword to be used before the property declaration.
– At compile time memory is allocated for this variable/property.
– class_name:: can be used to access static properties
– object handles can also be used to access static properties.
– object creation is not mandatory.
– Static functions
– Static keyword is used before the function definition to make it a static function.
– Static functions can use only static variables/properties.
– Accessing a non static property inside a static will lead to compile error.
- The advantage of using static is that we can access these from anywhere in our testbench, just by using class_name :: operator.
No instantiation is required.
Doubts :
Notes:
- Inheritance & Polymporphism
- Inheritance
class C extends P;
C is the child clas
P is parent - overriding a function or property means redefining it in the class.
- Use this operator to refer to the current class and esuper to refer to its parent.
- class P;
int a;
string s;
function void print();
$display(“a=%d”,a);
$display(“s=%s”,s);
endfunction endclass class C extends P;
int e;
function void print_C();
print();
$display(“e=%d”,e);
endfunction
endclass - How many functions class C have? – 2 -> 1 -from parent and 1 – its own initial begin
C c;
c=new();
c.print_C();
end If C defintion was as below
class C extends P;
int e; function X();
print();
endfunction
function void print(); //overriding print defintion
super.print();
$display(“e=%d”,e);
endfunction
endclass How many functions C has ? initial begin
C c;
c=new();
c.print(); -> will print only e variable;
end
- Inheritance
- Polymporphism means that depending on which class my handle is pointing, the function definition should be picked from that particular class
- By default polymorphism will not happen.
- Virtual keyword should be added before function defintion, for the polymporphism to take effect.
- As a rule of thumb, always declare virtual before your function definitions.
- //int a; string s;
//s =a;
c = p; also gives similar error.- parent handles can’t be assigned to child handles. In other words, a chid handle can never point to parent object.
Only p=c is allowed.
- parent handles can’t be assigned to child handles. In other words, a chid handle can never point to parent object.
- $cast
- It is a run time type check and assignment.
- $cast(dest, src);
- If the types are incompatible then a run time error is issued and the dest handle remains unchanged.
- $cast can behave as a function or as a task.
- It will return 1, if the cast is succesful and it will return 0 if the cast is unsuccesful, when it is used as a function. No error will be issued.
success_flag = $cast(c1,p);
if($cast(c1,p)) $display(“Success”)
else $display(“error”); - If the cast fails, It will give a run time error if it is used as a task.
$cast(c1,p)
- It will return 1, if the cast is succesful and it will return 0 if the cast is unsuccesful, when it is used as a function. No error will be issued.
- This is dynamic casting.
o Static casting
- rand
- randomize function call will assign random values(after solving constraints) to all the properties that are declared rand.
- When randomization fails, then it will return 0 and none of the rand variables will get random values. they will retain old values.
- Randomization will fail if any of the constraint is unresolved.
- constraints
- constraint_mode can be used to enable or disable constraints.
- constraint_name.constraint_mode(0) -> to disable the constraint constraint_name
- constraint_name.constraint_mode(1) -> to enable the constraint constraint_name
SESSION#5(19/APR)
Revision :
o Inheritance
– Function overriding
– property overriding
– If we want to access parent’s property or methods then we must use super.
o To refer to the current class scope use this.
– class handle assignments.
– parent = child -> possible
– child = parent -> error
o Polymporphism
– If we want the function definition to be chosen based on which class object it points to then we need to use virtual before the function definition.
– This is applicable only for classes that has parent-child relationship.
o $cast is used to perform dynamic checks and does the class assignment.
– If it is type compatible, it results in the handle assignment, else dest handle remains unchanged.
– $cast can be a function or a task
o Function : it return 1 on success and 0 on failure
o Task : gives out error on failure
o Static casting
o randomize
– randomize is an inbuilt function provided by the SV language.
– It will solve the constraints and assign random values to the properties that are declared rand.
– If randomization fails, then it will return 0 else 1.
o constraints
– they are a bunch of conditions that you want the constraint solver to satisfy to get a legal set of random values.
– If any constraint is dissatisfied, it leads to randomization error.
o
Doubts:
Notes:
o Recompilation is a costly affair most of the times, as your environment may be very big.
o Svalue$plusargs and $test$plusargs are there to save recompilation effort.
– i.e, we can make run time selections without recompiling
– If there are 100 tests and in few tests i need to have some extra code or exclusion of some code i can do that with the help of these plusargs.
– All the 100 tests can be run at the same time.
-$test$plusargs will check just if that arg string is provided.
-$value$plusarg will check if tha arg string is provided and also read the value that is passed.
string testname;
$value$pluargs(“TEST=%s”,testname);
Usage in command line : vsim +TEST=”TEST1″ top;
int testname;
$value$plusargs("TEST=%d",testname);
Usage in command line : vsim +TEST=3 top;
o
o randc
– randc means random cyclic.
– difference between rand and randc is that randc will remember what are the random values assigned prior.
– If the legal values are from 0 to 7, then if we had assigned 7, then in the next randomization 7 will not be assigned until all values 0 to 6 are used at least once. Value repetition will not happen.
– rand will not remember, if 7 is assigned once, then in next randomization, 7 may come. value repetition happens
– The values that were assigned are lost on object creation.
o Seed
– Seed is the one that decides the random values that are coming.
– If same seed is provided, we will get the same random results or randomization values.
– vsim -sv_seed random
o std::randomize()
– this is used to randomize any variables. that variable neither be declared rand nor it should be belonging to a class.
o pre_randomize and post_randomize
Usually if i want to fine tune my randomization, I have no option. because randomize is a function implemented by the tool vendor.
So, they have provided us a hook inside the randomize function, through which we can add some additional code at the start and end of the randomize function.
function void pre_randomize();
var4=10;
endfunction
function void post_radomize();
endfunction
function int randomize();
pre_randomize();
//ALgorithm to do the constraint solve
post_randomize();
endfunction
o Same is the concept behind call backs
o Inline constraints are give along with ramdomize function.
Care should be taken that they are not conflicting with the existing constraints.
o Some constraints can exist in soft mode. These are called soft constraints.
These constraints will not be applicable in case of any conflict.
o eth_pkt pkt_sa[10];
pkt_sa[0]=new();
pkt_sa[1].preamble //Bad handle error will be generated.
as the pkt_sa[1] handle is pointing to null. no object created. only for pkt_sa[0] the object is created.
pkt_sa[1]=new(); Only now the object got created
o eth_pkt pkt_da[];
pkt_da = new[10];
pkt_da[0] = new();
o int a;
a is signed, by default.
int unsigned i;
i is unsigned now.
bit signed b;
o extern is used to indicate that the definition is outside the class. class_name:; should be used before the function name
class eth_pkt;
//properties
// methods
extern function void print();
// constraints
endclass
class pcie_pkt;
//properties
// methods
extern function void print();
// constraints
endclass
function void eth_pkt::print();
//….
endfunction
function void pcie_pkt::print()
//…
endfunction
SESSION#6(25/APR)
Revision :
o ifdef OPTion1 /..code1
else
/..code2
`endif
o $value$plusargs or $test$plusargs
if($test$plusargs(“OPTION1”)
//..code1
else
//..code2
– We are saving recompilation effort.
o rand – randomize your properties on calling randmoize
randc – will also do the same but the difference is for the same object, it will remember what are the previous random values assigned.
This makes sure that the values assigned are not repetitive. A value will be assigned only once until all possible values are assigned.
o std::randomize
o pre_randomize , post_randomize
– these are hooks provided to tweak our randomization
– when we call randomize, pre_randomize is automatically called first, then at the end of randomize, post_randomize is called automatically.
– By default, these are empty implementations.
– User can override these empty definitions for their use.
o Inline constraints
– these are additional constraints provide during randomize call, valid only for that particular call.
– care should be taken that there is no conflicting constraint provided here.
o Whatever is the default behaviour(signed or unsigned) can be changed during declaration.
o extern is used to indicate that the definition will be outside the class.
if the definition is outside the class, then we have to add class name :: before the functon name.
function void eth_pkt::print();
endfunction
o class can be declared inside a module as well
– scope of that class definition will be within that module
module top;
class eth_pkt;
int pre;
endclass
endmdodule
module t;
eth_pkt pkt;
endmodule
Doubts:
Notes:
- Set membership operator
– y >=3 ; y<=15; -> y consists values are 3 to 15.
Suppose if i dont want 6,8,10 , constraint should be written as below
– y>=3;y<=15;y!=6;y!=8,y!=10;
– there is a operator called set_membership operator.
y inside {3,4,5,7,9,11,12,13,14,15};
y inside {[3:5],7,9,[11:15]}
– inside is a set membership operator - copy method
- copy is not language provide. print is also not lanuage provided. these are user-defined functions
- Handle copy does not mean object copy.
o 2 handles and one object. Assingning handles will appaear as copy.
(copy of handle)
eth_pkt pkt,pkt1;
pkt =new();
pkt1=new();
pkt1=pkt; - To create an object copy, you can write your own method.
- Shallow copy
- Shallow copy will create the object and copy the properties.
pkt1= new pkt; - Why not we use this always? why we need to write our own method.
- because there is a limitation with shallow copy.
- Limitation is that it copies only hierarchy and does not copy the hierarchies deep.(from 2nd level onwards).
- Shallow copy will create the object and copy the properties.
- As per example, understand how the shallow copy affects if there is any object inside out pkt class.
- TO resolve this user defined copy method has to be used.
- compare
function bit compare(input eth_pkt pkt_loc);
if(pkt_loc.len != this.len)
return(0);
foreach (pkt_loc.payload[i]) begin
if(pkt_loc.payload[i] != this.payload[i])
return(0);
end
if(pkt_loc.preamble != this.preamble)
return(0);
endfunctionUsage: flag = pkt.compare(pkt1);
- Streaming operator
- This operator will split a stream of information into many chunks of data.
- We can specify what the chunk size is.
- Refer example
- Mailbox
- Mailbox is a construct provided by SV language. It is a (parameterized) class.
- So, we need to instantiate and create memory or assign some handle.
- It is similar in behaviour to FIFO.
mailbox mbox; - it comes with pre_implemented methods.
o new – to create the mailbox
– It takes 1 optional argument. This will represent the size of the mailbox.
mbox=new(3);
– If we dont pass this argument, the default will consider it to be of infinite size.
mbox=new();
o num – It will tell the number of entries in mailbox
o put
– It will make an entry into the mailbox.
– put is a blocking method.
– put will wait until the write happens in the mailbox.
Usage : mbox.put(10);
mbox.put(21);
mbox.put(32);
mbox.put(1); //suppose mailbox size is 3, this will keep waiting until 1 is written into the mailbox
mbox.put(3);
o try_put
– same as put except that it is a non-blocking method.
Usage : mbox.try_put(10);
mbox.try_put(21);
mbox.try_put(32);
mbox.try_put(3);
mbox.try_put(4);
mbox.put(1); //suppose mailbox size is 3, this will keep waiting until 1 is written into the mailbox o get
– It will remove an entry from the mailbox.
– It is a blocking method.
– It will wait until there is an entry into the mailbox,
Usage : mbox.get(a);
mbox.get(pkt);
o try_get
– It is same as get except that it is non-blocking in nature.
o peek
– it is similar to get but it will not remove an entry from the mailbx.
– It will just copy the mbox read content.
o - Mailbox is a paramterized class.
– The parameter is the datatype that the mailbix can handle.
– If during instantiation we mention the datatype, then that datatype entries only should be made.
Otherwise error will be generated.
- classes can be parameterized.
- Unlike module, classes can have the datatype also as a parameter.
- module #(parameter WIDTH=32) counter(input [WIDTH-1:0] load_value,
input clk,
output reg [WIDTH-1:0] count_val);
- module #(parameter WIDTH=32) counter(input [WIDTH-1:0] load_value,
- counter#(4) counter4()
- counter counter32;
- class #(int WIDTH=32) counter_class;
bit [WIDTH-1:0] count_var;
endclass counter_class#(2) counter2;
counter_class counter32; - class counter_type_class#(type T=bit,int WIDTH=4) ; //generic class
T c_var;
bit [WIDTH-1:0] count_var;
T [WIDTH-1:0] load_val;
static int cnt; //there is only cnt, but 1 cnt for every specialization endclass
//
counter_type_class#(reg) counter_reg_4,cnt1;
counter_type_class counter_def,cnt2;
counter_type_class#(.WIDTH(3)) counter3,cnt3;
// - This particular instantiation is called as a specialization.
- counter_type_class#(reg,4) – this is one specialization -> class counter_type_class_#_(reg,4);
reg c_var;
bit [3:0] count_var;
reg [3:0[ load_val;
static int cnt ;
endclasscounter_type_class#(reg,4)::cnt
- counter_type_class#(bit,4) – this is another specialization -> class counter_type_class_#_(bit,4)
bit c_var;
bit [3:0] count_var;
bit [3:0[ load_val;
static int cnt ;
endclass
counter_type_class#(bit,4)::cnt - counter_type_class#(bit,3) – another specialization -> class counter_type_class_#_(bit,3);
bit c_var;
bit [2:0] count_var;
bit [2:0[ load_val;
static int cnt ;
endclass
counter_type_class#(bit,3)::cnt
- counter_type_class#(reg,4) – this is one specialization -> class counter_type_class_#_(reg,4);
- Each specialization has its own static variables,
0 If my requirement is that, irrespective of specialization, i need to have only a single static element for the parameterized class(generic class)- define a base class with that static property.
- class #(type T=int) gen_class extends base_class;
Base class Derived class
Parameterized No No
No Yes
Yes No class eth_driver extends uvm_driver#(eth_pkt);
Yes Yes class my_driver #(type T=int) extends uvm_driver#(int)
class my_driver1#(type T=int) extends uvm_driver#(T)
o class D4#(type P=C#(real)) extends P; class D4#(type P=eth_pkt) extends P; D4#(eth_ext_pkt) d4_pkt;
D4#(pcie_pkt) d4_pcie_pkt;
D4 epkt;
typedef my_int eth_pkt
D4#(my_int) ipkt;
instantion: D4#(pcie_pkt) dinst; class D4#(type P=eth_pkt) extends eth_pkt;
class D4#(type P=eth_pkt) extends my_int; - Unlike module, classes can have the datatype also as a parameter.
SESSION#7(26/APR)
Revision:
o Set membership operator – inside
if(y inside {3,5,7,[10:15],17}
o Handle copy
– doesnot provide another object. it just gives another handle to the existing object.
pkt1=pkt; means pkt1 and pkt handles point to the same object.
o Shallow copy
– pkt1 = new pkt; this will create another object and it will copy the pkt properties into that object.
pkt1 and pkt are pointing to different objects.
– There is a limitation to this. If any property is a class handle, then only handle is copied and not the total object.
i.e, to that class object there are 2 handles – 1 from pkt and another from pkt1.
– We need to take care of that (inner) object copy manually and this is known as deep copy.
o Streaming Operator – Pack/Unpack
– {>>size{stream}}
By default if size is not specified it will be 1.
– {<<size{stream}}
o Mailbox
– is a parameterized class.
– If datatype at instantiation is not mentioned, then it can accept any data type
– If datatype is mentioned, it will accept only that particular datatype. For others, error will be reported.
– Methods
– new – creates the mailbix. Takes an argument for size. default 0, which means infinite size.
– num – how many entries are currently made in the mailbox
– put – to make an etry into the mailbox. Blocking in nature. Task
– try_put – same as put. Non blocking. Function, return 1 if entry is made else 0.
– get – remove an entry from the mailbox. Task. FIFO behaviour. 1st put will be removed first. blocking in nature
– try_get – remove an entry. Non blocking. Function
– peek – just copy the entry from the mailbox. the mailbox still has the read info. Blocking
– try_peek – non_blocking
o Parameterized classes :
– CLasses can be parameterized for data type and value.
– type keyword will indicate that is a datatype parameter.
Doubts:
Notes:
- Parameterized classes
- Notes made in previous session notes
- Assignment
1. Declare a eth_pkt class with following
Fields: Count(int), SA [48 bits], LEN [10bits]
Methods : print method to print SA, LEN2. Declare 3 derived classes, (extends) eth_good_pkt, eth_bad_pkt, eth_ill_pkt eth_good_pkt : new field count_good eth_bad_pkt : new field count_bad eth_ill_pkt : new field count_ill print method : Print all packet fields by using print from base class 3. Code eth_gen.sv Generate in total 10 packets of above 3 packets in random manner Put these packets in to mailbox in run task 4. Code eth_bfm.sv get the above 10 packets from mailbox in run task of BFM call print method of each of these 5. Code eth_env.sv Instantiate eth_bfm, eth_gen, and mailbox to connect these two components Call eth_bfm & eth_gen object ‘run’ method in the eth_env ‘run’ task 6. Code eth_top.sv Instantiate eth_env Create eth_env object call run method of eth_env object</code></pre></li>Interface It is a bundle of signals or ports For few blocks, few signals are inputs and the signals are outputs for other blocks.
As they will be using the same interface, modport will specify the direction.
IF they are used by 2 blocks, there will be 2 modports Everything will be input to the monitor. virtual class eth_pkt;
virtual function eth_pkt copy();
endfunction
endclass
eth_pkt pkt;
pkt=new(); //no object creationn is allowed. Error class eth_ext_pkt extends eth_pkt;
function eth_pkt copy();
endfunction
endclass eth_ext_pkt p;
p =new();
pkt =p; pure virtual function virtual class ex_class;
pure virtual function void print();
endclass
class ext_class extends ex_class;
function void print();
endfunction
endclass class eth_pkt;
const int len=20;
const int sa;
function new(int sa_temp);
sa = sa_temp;
endfunction
endclass
initial begin
eth_pkt pkt =new(20);
eth_pkt pkt1 =new(40);
pkt.len=10; //error
pkt.sa = 30; //error
end class eth_env;
typedef enum {RED,BLUE} colors_t;
class eth_pkt;
static int count;
endclass
colors_t c;
endclass eth_env::eth_pkt::count=10;
eth_env e;
e.c= eth_env::RED; Literals Rules provided by the language time t; t=10ns; array='{1,2,4} string s; s= "vlsi"; bit [3:0] b; b=3'b101; b= 4'hc; Operators
a+=b;
=> a = a+b;
a-=b;
=> a = a-b;
|a -> or all the bits of a
SESSION#8(02/MAY)
o doubts
- mbox =new(3);
mbox.put(1);
mbox.put(5); mbox.get(a)
mbox.put(7);
success=mbox.try_put(10);
mbox.get(a);
; o revision
o set membership operator -> inside
o deep copy
o shallow copy- its limitations
o handle copy
o compare
o streaming operator
o parameterized classes - basis of total uvm
o eth_assignment
o interface - modports
o abstract classes - virtual before class declaration or definition
- object creation is not allowed.
- we have to inherit this class and then we have to create the object.
- handle assignment is possible.
- pure virtual function can also be present. the child class has to implement this method(be if it is an empty definition)
o const keyword - they are not supposed to change once they are declared and initialized.
- initialization can happen in new function as well.
o scope resolution operator
o in operators, we have seen both unary operators and binary operators.- unary operators: those that require a single operand
o ++, –, |a , &a , ^a - equality and case equality operators
o if any operand is x, then == and != will result x. -> == can return 1 or 0 or x
o if any operand is x, then it will try to look for x in both the places. -> === can result 0 or 1. - wild card equality operators
==? !=?
a ==? b
if b has any x in it, it will be treated as a dont care and try to match with 1 or 0 with the a operand.
a = 4’h1011;
b = 4’h1x11;
$display(“a==?b =%b”,a==?b);
o interprocess synchronization
o any time consuming code is a process
o in sv, interprocess synnchronization(ips) can be achieved by 3 constructs - mailbox
- semaphore
- event
o mailox – done - it is the handle that is put into the mailbox.
o semaphore - semaphore will have keys and whenever some component requests key, it will wait until semaphore provides it key.
- semaphore smp;
smp =new(1); // argument will be the number of keys that you want semaphore to have. smp.get(1); //component requesting 1 key from semaphore
smp.put(1); //component returning 1 key back to semaphore
time step = 1ns
time precision = 1ns
#1 -> 1* timestep = 11ns = 1ns ->i am asking the tool to take 1 ns delay #1.1 -> 1.1timestep = 1.1*1ns = 1.1 ns -> will be 1ns delay `timescale 10ns/1ns
time step = 10ns
time precision = 1ns 1 -> 1 *timestep = 1 * 10ns = 10ns 1.1 -> 1.1 *timestep = 1.1 * 10ns = 11ns -> 11 ns delay 1.11 -> 1.11 *timestep = 1.11 * 10ns = 11.1ns -> 11 ns delay will be considered 1ns -> explicit delay mentioned – 1ns will be the delay. `timescale 1ns/1ps
time step = 1ns
time precision = 1ps 1 -> 1 *timestep = 1 * 1ns = 1ns ->1 * 1000 ps = 1000ps 1.1 -> 1.1 *timestep = 1.1 * 1ns = 1.1ns -> 1.1 *1000 ps = 1100 ps 1.11 -> 1.11 *timestep = 1.11 * 1ns = 1.11ns -> 1.11*1000ps = 1110 ps 1.111 -> 1.111 *timestep = 1.111 * 1ns = 1.111ns -> 1.111*1000ps = 1111 ps 1.1111 -> 1.111 *timestep = 1.1111 * 1ns = 1.1111ns -> 1.1111*1000ps = 1111.1 ps ->1111 ps `timescale 1ns/10ps
time step = 1ns
time precision = 10ps 1 -> 1 *timestep = 1 * 1ns = 1ns ->1 * 1000 ps = 1000ps 1.1 -> 1.1 *timestep = 1.1 * 1ns = 1.1ns -> 1.1 *1000 ps = 1100 ps 1.11 -> 1.11 *timestep = 1.11 * 1ns = 1.11ns -> 1.11*1000ps = 1110 ps 1.111 -> 1.111 *timestep = 1.111 * 1ns = 1.111ns -> 1.111*1000ps = 1111 ps -> will be considered as 1110 ps delay o scheduling semantics- active region
- all module statements will work
- reactive region
- all program block statements will be executed here.
//modules
initial begin
a=1; b=0; 1 a=0; 1 b=1; end
//program
initial begin
a=1; 4 a=1; end
//declaration
initial begin
a=1;
end
endprogram o interface is a static construct. new is not required.- so, while instantiating interface in a class, virtual is required.
- this is known as a virtual interface. you are trying to refer or access the physical interface through virtual interface handle.
- the interface instantiated in the module is known as physical interface.
- its limitations
SESSION#9(03/MAY)
Doubts
Revision
o Operators
– ===,==, ==?
o Interprocess Synchronization
– process – what it is?
– 3 constructs that help in Interprocess Synchronization
o Mailbox
o Sempahore
o Event – will do today
– Semaphore
o Semaphore has some keys. The consumer of the common resource will have to first request the key before using the resource.
o when the consumer of common resources requests, if the keys are available, semaphore provides the key to it allowing it to use the resource
o The consumer will be blocked until the requested number of keys are provided to it by the semaphore
– This will be the case when get is used
– when try_get is used, the requestor(consumer of the common resource) will not be blocked.
o semaphore smp = new(num_of_keys);
o `timescale
– Time step
– Time precision
o Scheduling Semantics
– VArious execution regions in a time step
– 13 in SV compared to 4 in verilog
– All the module constructs are scheduled to happen in the Active region
– All the program block constructs are scheduled to happen in the Reactive region which follows Active region. Hence, avoiding the race between design and testbench.
o program block
– It is entry point for the testbench.
– It is similar to module except that always blocks are not allowed here and also there can be a final block(only one) which will get executed at the end of simulation.
o Interface
– Bundle of wires.
– Modport will give a sense of direction.
– How interface is instantiated.
o In module – It is a static entity. new() is not required. This is also known as a physical interface.
o In class – This is a virtual interface. Just handle is declared and no memory is allocated. No need to have ports here. We need to assign this handle with the physical interface handle so that the mapping is proper and the signals are connnected with DUT.
Notes
- Interface
- we can instantiate the virtual interface in the class using modport.
o virtual mem_intf.bfm_mp vif; - clocking blocks
- It will provide us flexbility on when a signal should be driven by the interface and when a signal should be sampled by the interface.
- Whenever we use clocking blocks, we should use non blocking assignment
- If no specific skews are mentioned in the clocking block, the default values that the SV mentions is
- For input it will be 1 timestep (i.e, 1 time step before the reference edge)
- For output, it will be 0 timestep (i.e, immediately after the reference edge)
- We can change the language defined defalut values to our own default values.
- default input #2;
- default output #1;
- we can mention the skew for a particular signal as well and if we dont mention, it will take the default.
- mem mem_inst(clk,rst, intf.addr,intf.wr_data,… )
Above is done when the module is defined as below,
module mem (input clk,rst,
input [7:0] addr,
input [31:0] wr_data,…_);
if(!rst) beginend else begin if(wr_rd) begin end end
endmodule - Suppose the mem design is a sv file and the module was defined as below.
module mem(mem_intf intf);
if(!intf.rst) beginend else begin if(intf.wr_rd) begin end end endmodule
In the top, mem mem_inst(intf)- verilog does not support interfaces
- we can instantiate the virtual interface in the class using modport.
- Creating vcd file
- vcd – value change dump
- $dumpfile(“filename.vcd”);
o This will create the vcd file - $dumpvars;
o this will starting recording the value changes into the file created using $dumpfile.
o this comes in various flavours
– $dumpvars;
o It means dump everything,
– $dumpvars(depth,module_name);
o It will start dumping all the signals in the module_name and its instances.
o top
– full_adder
– ha1
-h1
– ha2
-h2
– xyz
-x1
-xy1
-y1
-xy2
-z1
o $dumpvars(0,top)
– It will dump top, full_Adder(ha1,ha2,h1,h2), xyz(x1,xy1,y1,xy2,z1)
o $dumpvars(1,top)
– you will get only top, full_adder,xyz and nothing below that
– $dumpon and $dumpoff
- Event
event is same like verilog, just that an enhancement is done to it module top;
event e;
//process1
-> trigger event here (->e) //process2
-> wait for the event to be triggered. (@e)
- events are also handles in SV.
- Event handles can be assigned, in that case one handle triggered will be seen by the other handle that was waiting for the event.
module top;
event e;
event e1; initial begin
$display(“process1::event waiting”);
e=e1;
@e;
$display($time,,”process1 done”);
end initial begin $display($time,,”process2 started”);
->e1; //triggering e1 will be seen as event e occured.
end
endmodule o System verilog brings in something called as persistent triggering.
Waiting for the trigger will not be done using @e.
But wait(e.triggered) will be used.
o triggered will be set to 1 when the event is triggered and maintains the value throught out the time step. - Suppose event trigger happened at 0 ns and the time step is 10ns, the triggered value set to 1 will be maintained 1 till the 10ns.
TBD
- fork .. join fork join_none //It does not for any of the fork processes to start. It will continue the main thread fork
join_any // It will wait for atleast one fork process to be finished, before continuing the main thread. The remaining fork processes will keep running and they will not get killed automatically, User has to call disable fork explicitly. - Array of 4 integers
int sa4[4]; typedef int intsa4[4]; new datatype intsa4 is created, which is nothing but array of 4 integers.
intsa4 sa4; -> sa4 will be an integer array with 4 elements - Assignment
Assignment:
Declare Queue of Array(5) of integers
Fill all the elements with random value between 10 to 20
$display them in for loop - structure
struct {
bit [55:0] preamble;
bit [7:0] sof;
bit [47:0] da;
int count;
} eth_pkt_st,eth1,eth2; //it is not a data type eth_pkt_st is not a datatype.
typedef struct {
bit [55:0] preamble;
bit [7:0] sof;
bit [47:0] da;
int count;
} eth_pkt_st_type;
eth_pkt_st_type is a datatype.
eth_pkt_st_type eth1,eth2;
eth_pkt_st_type eth4;
SESSION#10(9/MAY)
Revision
o Interface
– modport
– clocking blocks
– Input skew
– by default it is 1 timestep before the active edge of the clock.
– we can have our own skews as well. For that we need to explicitly mention the skew.
– output skew
– by default it is 0 timestep after the active edge of the clock.
– we can have our own skews as well. For that we need to explicitly mention the skew.
- Physical Interface
- Interface is static construct,Hence instantiation creates memory, hence known as physical interface
- Virtual Interaface
- Interface instance in a class has to be virtual.
o Events
– Used for synchronizing the processes
– Event is a handle in system verilog.
– Event handles can be assigned with another event handles.
– e = e1;
-> Triggering e1 will cause the process waiting on the trigger of e to be unblocked.
– SV introduced something called as persistent tiggering.
– Event trigger active for whole timestep.
– e.triggered
o $dumpvars, $dumpfile
o typedef
o fork
- fork .. join
- fork .. join_any
- fork .. join_nne
- disable fork
- this construct will kill all the threads in fork
o Structure, union, ..
- this construct will kill all the threads in fork
Doubts
Notes
- Constraints
- constraints are virtual by default.
- we dont need to have virtual keyword declared before the constraint definition for polymorphism to take effect.
- Refer example.
o Distribution operator - constraint c1 { x inside {1,2,5};} // x value should be chosen among 1, 2 and 5
total no of elements 3 -> prob. =no. of favourable events/Total no. of events P(1) = 1/3; P(2)= 1/3 ; P(5)= 1/3; P(odd) = 2/3; p(even) = 1/3 - constraint c_d {x dist {1:=1,2:=4,5:=2};}
p(1) = 1/7 ; P(2) = 4/7 ; P(5) = 2/7; - constraint c1 {x inside {1,3,[7:11]};} //x can take values 1,3,7,8,9,10,11
- constraint c1d {x inside {1:=2,3:=1,[7:11]:=1};} //x can take values 1,3,7,8,9,10,11
– = means each and every element will have the specified weightage
– p(1) = 2/8 ; P(3)=1/8 ; p(7)=1/8 ; P(8) = 1/8; p(9)=1/8; p(10)=1/8 ; p(11) =1/8 - constraint c1d {x inside {1:=2,3:=1,[7:11]:/1};} //x can take values 1,3,7,8,9,10,11 – :/ means the total range is having the specified weightage. not the individual element in the range – p(1) = 2/4 ; P(3)=1/4 ; p([7:11])=1/4 -> p(7)=1/41/5 ; P(8) = 1/41/5; p(9)=1/4*1/5; p(10)=1/4 *1/5; p(11) =1/4*1/5 o Implication operator
- I can choose my constraint based on some condition.
if that condition is true, the constraint is taken for evaluation, else the constraint is ignored.
( pkt_type == SMALL) -> (len==5);
- I can choose my constraint based on some condition.
- Inside module if you want get floating point numbers
module top;
real i,j;
initial begin
//i should be a random number between 3.55and 3.95
i = ($urandom_range(355,395))/100.0 ;
$display(“i=%f”,i);
end
endmodule - Iterative constraints
constraint c1 {foreach (A[i]) A[i] inside { 2,4,8,16};}
-> A = {2,16,8,…}
constraint c1 {foreach (A[j]) A[j]>2*j;} A[0] can be within 2,4,6,8,16
A[0]>0;
Finally, A[0] can be within 2,4,6,8,16 A[1] can be within 2,4,6,8,16
A[1] > 2*1
Finally, A[0] can be within 4,6,8,16 A[2] can be within 2,4,6,8,16
A[2] > 2*2
Finally, A[0] can be within 6,8,16 - case(a)
0:
1:
2:
endcase randcase
1 :
4 :
1 :
endcase for randcase weight is mentioned - coverage
- We are doing functional verification of the design
- the design is in the form of RTL.
- coverage means how much design we have covered as part of our testing.
- code coverage
FBEST - There is no additional coding required to do the code coverage.
- we need to just enable coverage in the tool and tool will take care of recording and generating the coverage reports.
- code coverage
- how much functionality is tested.
- what are the scenarios that i have given to test the features of the design.
- Are the possible scenarios are applied?
- Are all the design specifications are covered by my testing?
- Functional coverage
- checking whether the testcases we are having are enough to test all the specified design specifications.
- Are we missing out verifying any feature.
- We have to code the Functional coverage. It is user defined.
-> covergroup -> multiple coverpoints -> Each coverpoint can have multiple bins. - If no bins are specified, the bins are automatically generated.
- illegal_bins means value that it is not supposed to take. If that is taken error has to be generated.
- ignore_bins means value that we dont bother even if it takes and it is not our point of interest.
Both ignore_bins and illegal_bins are not part of coverage computation - covergroup is a user-defined datatype. It needs to be instantiated and created before using.
- covergroup can be instantiated in a module as well.
o WHen it is defined in a class. Instantiation happens implicitly. that instance name is same as the covergroup name.
when in a module when inside a class
covergroup eth_cg; covergroup eth_cg;
endgroup endgroup
eth_cg cg_inst; //statement is implicit here — eth_cg eth_cg;
cg_inst =new(); eth_cg=new(); - option.auto_bin_max=4;
o when a coverpoint does not have any bins, automatically bins are generated for all the possible values.
o auto_bin_max option will specify the number of bins that are to be generated automatically.
o By default, it is 64. - when we have bins specified,the bins that we specified come into existence.
If 16 values are possible, there is no requirement that all 16 should be in seperate bins.
They can be combined into bins as well.
bins b1 = {1};
bins b2= {[3:7],15};
b2 will be covered if 3 or 4 or 5 or 6 or 7 or 15 is sampled.
- We are doing functional verification of the design
SESSION#11(10/MAY)
Revision
o constarints
- COnstarints are by default virtual.
- The constraints if having same name in both the parent class and child class means that it is overridden in the child class.
- we can give some weightage to the random values that are generated in the constraints using dist operator.
[1:5]:=1
o This means that 1,2,3,4,5 each has weightage 1.
[1:5]:/1
o The [1:5] has wightage 5 and not that 1,2,3.. each has weightage 1/5. - Implication Operator
(condition)-> constraint
The constraint is taken into consideration only when condition is true. - Iterative constraints
foreach A[i] A[i] inside {1,2,3,4}; - if.. else inside constraints
o randcase - we wont be providing any selection value, but there will be weights mentioned randcase 0: block1 //This has weightage 0 – 1: block2 //this has weightage 1 -prob.of sleection = 1/7 5: block3 //weightage=5; prob = 5/7 1: o coverage:
- code coverage
- User need not do anything except enable the coverage in the tool.
- Tool will generate the report. Verification need to analyse and improve testcases to cover them. IF not possible to cover, get waivers from designers.
These exclusions can be provided to ignore the uncovered things in the coverage report.
- Functional coverage
- User defined. User has to code to get the functional coverage in effect.
- covergroup comes in action to sample the values only when cg_inst.sample method is called or when the even trigger happens.
- option.auto_bin_max=4 -> This is to stop the no of automatic bins generated to be 4 maximum.
- illegal bins -> not part of coverage.. give an error when this bin is hit.
- ignore bins -> not part of coverage.. does not give any error when this bin is hit.
- bins b ={1,2,[4:6]}; //b will be covered when the coverpoint value is sampled as either 1 or 2 or 4 or 5 or 6. b is a single bim
- bins ba[] = {1,2,[4:6]}; // there will be 5 bins formed here
- bins bal[3] = {1,2,[4:6], 8,10}; // there will be 3 bins formed. The bin values are => 1,2 – 4,5 – 6,8,7
- code coverage
Doubts
Notes
- cross coverage
cross will take 2 coverpoints and will make all possible combinations out of it.
the possible combinations will be the bins that are present in both coverpoints. - Transition coverage
This checks for a sequence.
bins b ={ 5=>6=>7}; bins b2={5=>6=>8}
The bin b is hit only when 5 to 6 to 7 transition happens.
bins b1 ={5=>6=>7,[7:8],10 =>11,12};
the bin b1 will be covered when the sequence 5 to 6to 7 happens. OR 7=>11 OR 7=>12 OR 8=>11 OR 8 =>12 OR 10=>11 OR 10=>12
bins b3[] ={5=>6=>7,[7:8],10 =>11,12};
there will be 7 bins formed. The bins take the sequence 5 to 6 to 7, 7=>11 , 7=>12 , 8=>11 , 8 =>12 , 10=>11 , 10=>12 - Assertions
- Assertions are some checks written on the protocol/interface.
- 2 types of assertions
- Immediate Assertion
- will happen only at that instance of time.
assert(pkt.randomize());
- will happen only at that instance of time.
- concurrent Assertion
- From the time they are triggered, they can be active, over a period
- assert property (prop_name);
Name can be given to the assertion. - my_assertion : assert property (prop_name);
- property prop_name;
@(posedge clk) antecedent|->consequent; //consequent will be checked or assertion will be triggered only when antecedent is true.
endproperty
OR - property prop_name;
@(posedge clk) antecedent|=>consequent; //consequent will be checked or assertion will be triggered only when antecedent is true.
endproperty
OR - property prop_name;
@(posedge clk) check;
endproperty o assert property(prop_name);- this will check if the property is satisfied or not.
o assume property(prop_name); - this will be given to the formal tools so that stimulus is generated such that the property conditions are satisfied.
o cover property(prop_name); - it will just a coverage on this property.
- Assertions only fail will give out error, if they are pass no message wil be printed.
sometimes it can so happen that antecedent is false, hence consequent never triggered. then, no error message prints, leading to the assumption that the assertion passed, where as it is a false pass. These kind of pAss is known vacuous pass.
- this will check if the property is satisfied or not.
- Assertions work on some clock cycles. 1 -> 1 timestep delay 1ns -> 1ns delay 1 -> 1 clock cycle delay 2 -> 2 clock cycle delay [2:3] -> 2 to 3 clock cycles delay
whenever antecedent is true, it will start consequent immediately from that clock edge.
o antecedent |=> consequent (non overlappng implication operator)
whenever antecedent is true, it will start consequent from the next clock edge. o property -> sequence (This seq may be formed with multiple sequences) -> Each sequence consists of boolean expresssions o Property Specification layer
property prop_name;
@(posedge clk) seq1 |-> seq2;
endproperty property prop_name;
@(posedge clk) seq1 |-> seq2 and seq3;
endproperty
o a##[2:4] b
-> tool will treat this as below
a##2b or a##3 b or a##4b
o Sequence operators
o [] Repetition operator Ex: a ##1 b[3] ##2 c
-> a ##1 b ##1 b ##1 b ##2 c
o [=] Non-consecutive repetion operator Ex: a ##1 b[=2] ##1 c;
adefbxyzvfbyuvc ->sequence pass
adefbxyzvfbybvc -> sequence Fail as b is coming 3 times
o [->] goto operator Ex: a ##1 b[->2] ##1 c;
adefbxyzvfbc ->sequence pass
adefbxyzvfbyvc -> sequence Fail as c shoudl come immediately after b
o the design gives out same input as an output after 5 clocks. How to write assertion?
property p;
@(posedge clk) valid_din ##5 (d_out==d_in) //wrong
property p;
int x;
@(posedge clk) (valid_din,x=din)|->##5 (d_out == x);
endproperty
o sequence Match operators
and, intersect , or, first_match
o $rose
->. previous sampled value=0 and current sampled value = 1 , then $rose will return 1.
similar to posedge
o $fell
->. previous sampled value=1 and current sampled value = 0 , then $fell will return 1. Otherwise it will return 0.
o $stable
-> prev value same as current value. $stabel will return 1.
A library is a named collection of cells(modules, program, Interface etc).
A complex design typically consists of many sub designs, each of them with lot of verilog files.
These sub block verilog files are compiled in to separate libraries(default library is work)
When we are compiling top most module, it gets the definition of the sub modules from above compiled libraries.
Above libraries are all mapped to ‘work’ library
Incremental Compilation:
While compiling a list of files, if there is no change in sub block modules, there is no need to recompile those, The precompiled library can be used as part of top module compile.
Saves the time in compiling complete list of files(which typically runs in to hours for big designs)
User can give custom name to each sub block module library(ex: gpu_lib for GPU files)
User need to map all these libraries to common library by name work, top most module gets the definitions from this ‘work’ library
If we maintain single library, we have to recompile whole database on change of single file, where as using incremental compile we only compile the required modules, and hierarchies above which are dependent on modified libraries.
o package
c