Thursday, October 10, 2019

How class based uvm test top connected in module

When import the uvm package in module, the task run_test(string testname="") will be visible as global task from the file uvm_globals.svh  
This task is a Convenience function for uvm_top.run_test() , it calls uvm_root class run_test which creates the test class object and manages/spawns uvm phases.

UVM_ROOT:

The ~uvm_root~ class serves as the implicit top-level and phase controller for
all UVM components. Users do not directly instantiate ~uvm_root~. The UVM
automatically creates a single instance of <uvm_root> that users can
access via the global (uvm_pkg-scope) variable, ~uvm_top~.

Friday, April 3, 2015

Sunday, March 1, 2015

The "wildcard bins" in SV useful for covering addresses/register coverage with specific


 This is useful in finding register bit specific coverage
 If reg1 is a 32 bits wide and we were interested in LSB [3:0] in combine with msb [31]=1

  REG1_BITS_CP : coverpoint reg1 {  
                                     wildcard bins ={32'b1000_0000_0000_0000_0000_0000_0000_????};
                                 }

So with this cover point you will get  16 bins ,32'b1000_0000_0000_0000_0000_0000_0000_0000,32'b1000_0000_0000_0000_0000_0000_0000_0001 to 32'b1000_0000_0000_0000_0000_0000_0000_1111.


Wednesday, May 1, 2013

shallow copy vs deep copy


Packet p1;
Packet p2;
p1 = new;
p2 = new p1;//shallow copy
The last statement has new executing a second time, thus creating a new object p2, whose class properties
are copied from p1. This is known as a shallow copy. All of the variables are copied across integers, strings,
instance handles, etc. Objects, however, are not copied, only their handles; as before, two names for the
same object have been created. This is true even if the class declaration includes the instantiation operator
new.
It shall be illegal to use a typed constructor call for a shallow copy (see 8.8).
A shallow copy executes in the following manner:

1) An object of the class type being copied is allocated. This allocation shall not call the object’s constructor
or execute any variable declaration initialization assignments.
2) All class properties, including the internal states used for randomization and coverage, are copied to
the new object. Object handles are copied; this includes the object handles for covergroup objects
(see Clause 19). An exception is made for embedded covergroups (see 19.4). The object handle of
an embedded covergroup shall be set to null in the new object. The internal states for randomization
include the random number generator (RNG) state, the constraint_mode status of constraints, the
rand_mode status of random variables, and the cyclic state of randc variables (see Clause 18).
3) A handle to the newly created object is assigned to the variable on the left-hand side.
NOTE—A shallow copy does not create new coverage objects (covergroup instances). As a result, the properties of the new object are not covered.

Several things are noteworthy. First, class properties and instantiated objects can be initialized directly in a
class declaration. Second, the shallow copy does not copy objects. Third, instance qualifications can be
chained as needed to reach into objects or to reach through objects:
b1.a.j // reaches into a, which is a property of b1
p.next.next.next.val // chain through a sequence of handles to get to val
To do a full (deep) copy, where everything (including nested objects) is copied, custom code is typically
needed. For example:
Packet p1 = new;

Packet p2 = new;
p2.copy(p1);
where copy(Packet p) is a custom method written to copy the object specified as its argument into its
instance.



Tuesday, April 23, 2013

Command line arguments to configure DUT parameters

$value$plusargs (string, variable)
This system function searches the list of plusargs (like the $test$plusargs system function) for a user specified string. If a string is found, the remainder of the string is converted to the type specified in the user string and the resulting value stored in the variable provided. If a string is found the function returns the value 1'b1. If no string is found matching, the function returns the value 1'b0 and the variable provided is not modified.
The user string must be of the form: "'plusarg_string''format_string'". The plusarg string is a name followed by either = or + . The format strings are the same as the $display system tasks. These are the only valid ones (upper and lower case as well as a leading 0 forms are valid):
%b - binary conversion
%d - decimal conversion
%e - real exponential conversion
%f - real decimal conversion
%g - real decimal or exponential conversion
%h - hexadecimal conversion
%o - octal conversion
%s - string (no conversion)
%x - (undergound equivalent for %h)
The first string, from the list of plusargs provided to the simuator, that matches the plusarg_string portion of the string specified by the user will be the plusarg string available for conversion. The remainder string of the matching plusarg (the remainder is the part of the plusarg string after the portion that matches the users plusarg_string) will be converted from a string into the format indicated by the format string and stored in the variable provided.
If the size of the variable is larger than the value after conversion, the value stored is zero padded to the width of the variable. If the variable can not contain the value after conversion, the value will be truncated. If the value is negative, the value shall be considered larger than the variable provided. If characters exist in the string available for conversion that are illegal for the specified conversion, the register should be written with the value 'bx.
2. Examples:
<simulator> +FINISH=10000 +TESTNAME=this_test +FREQ=5.6666 +FREQUENCY
// Get clock to terminate simulation if specified.
if ($value$plusargs("FINISH=%d", stop_clock)) begin
repeat (stop_clock) @(posedge clk);
$finish;
end
// Get testname from plusarg.
if ($value$plusargs("TESTNAME=%s", testname)) begin
$display("Running test %0s.", testname);
startTest();
end
// Get frequency from command line; set default if not specified.
if (!$value$plusargs("FREQ=%0F", frequency))
frequency = 8.33333; // 166MHz;
forever begin
#frequency clk = 0;
#frequency clk = 1;
end
This code would have the following effects:
1. The variable 'stop_clock' obtains the value 10000.
2. The variable 'testname' obtains the value 'this_test'.
3. The variable 'frequency' obtains the value '5.6666'; note the final plusarg +FREQUENCY does not affect the value of the variable 'frequency'.
 

Need for abstract class

Prior to SV 1800-2012, abstract classes served two purposes:
  1. A partially implemented class - Abstract classes act as expressions of general concepts from which more specific classes can be extended. An abstract class defines some default functionality with virtual methods, and requires you to add additional functionality with pure virtual methods (method prototypes with no implementation). Although the language does not require having a pure virtual method in your abstract class, there is usually no point in using the abstract class without extending it and providing some virtual method overrides. You cannot create an object of an abstract class type; however, you can reference extended objects from an abstract class typed variable. You are using polymorphism to access the virtual method in the extended class, and those virtual methods will access members of the extended class.
  2. An interface class containing only pure virtual methods - a completely unimplemented class. This is a way for one class to communicate with another class through a published API that is made up of the pure virtual method prototypes. That one class just needs to contain an abstract class variable to reference the other implemented object. Since SystemVerilog only allows for single inheritance, this also serves to keep the inheritance hierarchies of the two classes separate.
-
The difference between these two contrivances is a matter of degree in implementation inside the base class. However, SystemVerilog 2012 has formalized the concept of interface classes in a way that allows for multiple inheritance of interface classes. These are all concepts borrowed from Java, so you can search for more information in that domain.

why we making an interface as virtual

An instance of a SV Interface (like module in Verilog) is a static object which shall be created during elaboration which is alive throught-out the course of the simulation.
Where as a class object is dynamic which can be allocated memory and can be freed during the course of simulation. So, we cannot instantiate any static objects (let it be interfaces or modules) inside the class.
For that reason, a physical interface is assigned to a virtual interface defined (which is just a handle) inside a monitor/driver class through which you can access the real interface signals.

Sunday, March 17, 2013

fork join_none inside a for loop

To spawn multiple threads with each thread having an index input argument like

for (int i = 0;i < 5;i++) begin
fork
thread(i)
join_none
end

since 'i' is a common variable for all threads, all threads are spawned with index 4.
I don't want to use join_all as i want all threads to be spawned simultaneously.


To work as expected try the below 
This is explained in the LRM. See the last example in section 9.3.2 Parallel blocks that explains fork/join_none.

for(int i = 0; i < 5; i++) begin
automatic int j;
j = i;
fork
thread(j);
join_none
end

What makes it work is that for each iteration of the for loop, a local automatic variable is created with a lifetime that is extended by the lifetime of the fork/join_none block that references it. The statements inside the fork/join_none block begin execution after finishing the for loop. It doesn't mater if the function/task call passes its arguments by value or by reference; each call has an independent copy of the automatic variable that was set to a value as the for loop went through its iterations.

Saturday, December 15, 2012

Scoreboard Vs Checker

A checker is used to check whether a given transaction has taken place correctly .

This may include data correctness and correct signalling order.
A Scoreboard is used to keep track of how many transactions were initiated,
how many finished and how many are pending and whether a
given transaction passed or failed.

    To find the differences between scoreboard and checker we have to understand the meaning of transaction:
"The transaction is quantum of activity that occurs in design bounded by time"
"A transaction is a single transfer of control or data between 2 entities"
"A transaction is a function call"

More on checker:

   checker,endchecker are sv constructs refer sv 1800-2009 LRM section-17 .

checker is a place holder for assertions. LRM says

“The checker construct in SystemVerilog was specifically created to represent such verification blocks encapsulating assertions along with the modeling
code. The intended use of checkers is to serve as verification library units, or as building blocks for creating
abstract auxiliary models used in formal verification.”

Thursday, November 8, 2012

UVM RAL

                                                  UVM RAL

  UVM library has the reg directory uvm-1.1b/src/reg has all the uvm ral base classes.
<
       The UVM register layer classes are used to create a high-level, object-oriented model for memory-mapped registers and memories in a design under verification.
 
<         UVM register layer defines several base classes that, when properly extended, abstract the read/write operations to registers and memories in a design-under verification.
 
<         The abstraction mechanism allows verification environments and tests to be migrated from block to system levels without any modifications. Below diagram explains the test bench architecture with UVM RAL.Here spec can be in fle formats like .doc,.xl,.csr ,.ralf,.xml formats.Generator may be IDESIGNSPEC from Agnisys Inc and RALGEN from VCS , CSRCOMPILER from semifore. 



overall tb architecture



Sunday, August 5, 2012


Using event based modeling in verilog to avoid Racing between always blocks.

In most of our designs, we have to perform some operation on the posedge of clock. To implement this, we normally use different always block with the posedge of clock in the sensitivity list.
Some times, we need to use the signal in one always block, which is getting assigned a value from another, and here the actual problem starts.
Since the all the always blocks execute concurrently in the design, which may create racing between signals, which is again varies among simulator to simulator.
For this scenario, the signals may get value from one always block before/after it is used in another one.
Using “event” in the verilog programming can be one way to take care this kind of situation.
Example 1 :
Here two always blocks are shown,
In this case we are trying to set some modes by looking into some conditions. Also, we want to use the modes at the posedge of clock and perform some other operation.
Since both always blockes are working at the same posedge of clock, which may create a racing between the mode signals.
This is a small example but in real-time scenario, it might be more complex and big.
It may take the new value of mode of continue with the older value, depends on the simulator’s algorithm.
Block – 1 :
always (posedge clock)
begin
    if (condition1)
        mode1 = 1′b1;
    else if (condition2)
        mode2 = 1′b1;
    else
        mode3 = 1′b0;
end
Block – 2 :
always (posedge clock)
begin
    if( mode1 && conditions3)
        output <= input1;
    else if (mode2 && condition4)
        output <= input2
    else
        output <= 2′b0;
end
Now, Lets try to avoid the racing between these two always blocks.
Here, we use an “event” to trigger the other always block, and the triggering will take place at the last of first always block.
Since we wanted to run the both always block at the posedge of the clock, which is also happening here.
By using the event in the sensitivity list of other always block makes sure that this block will execute when the first will be completed, and it will be able to use the new values assigned to the mode variables.
We can have multiple events in the design.
// event declaration
event ev_mode
Block – 1 :
always (posedge clock)
begin
    if (condition1)
        mode1 = 1′b1;
    else if (condition2)
        mode2 = 1′b1;
    else
        mode3 = 1′b0;
    -> ev_mode
end
Block – 2 :
always (ev_mode)
begin
    if( mode1 && conditions3)
        output <= input1;
    else if (mode2 && condition4)
        output <= input2
    else
        output <= 2′b0;
end

Design synthesis and relevant verilog code for DFF

---------Basic componet of RTL Synthesis
For RTL Coding, one should know that what code will infer which hardware in the design and vise versa.
The Design engineer should be aware of relevant code and the output logic so he can be able to minimize the design and the no of gates using.
In this post we will see deferent DFF and their verilog codes
DFF ( D- Flip-Flop)
reg q;
always @ (posedge clk)
q <= d;
In this code, the value of D(data) will be assigned to output (q) at the posegde of the clock and it will remain untouched till next posedge of the clock since the q is defined as reg.
D-Flip Flop
D-Flip Flop
DFF ( D- Flip-Flop) with Asynchronous reset.
reg q;
always @ (posedge clk or posedge reset)
if (reset)
q <= 1′b0;
else
q <= d;
According to above code, the reset is positive edge triggered and asynchronous so it is kept in the sensitivity list of always block with the posedge.
Inside the always block, there are a conditional statement to check whether the reset is true (1), otherwise it behaves as normal DFF
DFF - Async Reset
DFF - Async Reset
DFF ( D- Flip-Flop) with synchronous reset
reg q;
always @ (posedge clk)
if (reset)
q <= 1′b0;
else
q <= d;
Synchronous reset means the flop will be reset only with the posedge of clock, hence the sensitivity list does not have the reset signal; However it check the reset for true whenever the posedg of clock comes.
DFF - Sync Reset
DFF - Sync Reset
DFF ( D- Flip-Flop) with gated clock.
reg q;
wire gtd_clk = enable && clk;
always @ (posedge gtd_clk)
q <= d;
Many times it becomes required to apply clock to the design only when the enable is active. This is done by the gated clock. The clock and enable both are the inputs to a and gate and the output of the gate goes to the clock input of the flop.
DFF - Gated Clock
DFF - Gated Clock
Data Enabled DFF
reg q;
always @ (posedge clk)
if (enable)
q <= d;
Data Enabled flops has a mux at the data input, which is controlled by the enable signal. Now even the posedge of clock comes to the flop, flop will not change the value until enable is not active.
DFF - Data Enable
DFF - Data Enable
Negative Edge triggered DFF
reg q;
always @ (negedge clk)
q <= d;
In this code, the value of D(data) will be assigned to output (q) at the negedge of the clock and it will remain untouched till next negedge of the clock since the q is defined as reg.
DFF -Negative Edge
DFF -Negative Edge

What is Timescale in verilog codes

The ‘timescale is one of the compiler directive to specify the unit for the delays used in the design with their precision.
The timescale line is very important in the verilog simulation, because there are no any default delays specified by the verilog.
Syntax :
`timescale <time unit>/<time precision>
Here :
time unit : This is the time to be used as one unit for all the delays used in the design.
time precision : This represents the minimum delay which needs to be considered during simulation or it decides that how many decimal point would be used with the time unit.
Range of Timescale :
The range for time unit can be from seconds to femto-seconds, which includes all the time units including s (second), ms(mili-second), us(micro-second), ns(nano-second), ps(pico-second) and fs(femto-second).
Example :
`timescale 1ns/1ps
Here :
1ps = 0.001 ns
#1; // = 1ns delay
#1.003; // = will be considered as a valid delay
#1.0009; // = will be taken as 1 ns only since it is out of the precision value.

What are sequential and parallel blocks, what is fork and join statements? How it is deffer than begin and end?

In verilog, we have two types of block – sequential blocks and parallel blocks. Lets look into both blocks one by one
1. Sequential Blocks –
In the sequential blocks, begin and end keywords are used to group the statements, All the statement in this group executes sequentially. ( this rule is not applicable for nonblocking assignments). If the statements are given with some timing/delays then the given delays get added into. It would be clearer with following examples.
Example -1 -
reg a,b,c;
initial
begin
     a = 1′b1;
     b = 1′b0;
     c = 1′b1;
end
The Example -1 is showing the sequential block without delays, All the statements written inside the begin-end will execute sequentially and after the execution of initial block, final values are a=1, b=0 and c=1
Example -2 -
reg a,b,c;
initial
begin
     #5 a = 1′b1;
     #10 b = 1′b0;
     #15 c = 1′b1;
end
The Example -2 is showing the sequential block with delays, In this case, the same statements are given with some delays, Since All the statements execute sequentially, the a will get value 1 after 5 time unit, b gets value after 15 time unit and c will take value 1 after 30 time unit
2. parallel Blocks –
The statements written inside the parallel block, execute parallel, If the sequencing is required then it can be given by providing some delays before the statements. In parallel blocks, all the statements occur within fork and join
Example -3 -
reg a,b,c;
initial
fork
     #5 a = 1′b1;
     #10 b = 1′b0;
     #15 c = 1′b1;
join
Form Example -3, all the statements written inside the fork and join, executes parallel, it means the c with have value ‘1′ after 15 time unit, in case of sequential blocks it was 30 time unit ( example 2)
The fork and join statements can be nested with begin-end
Example -4 ( Nested block)
reg a,b,c,d;
initial
begin
fork
     #5 a = 1′b1;
     #10 b = 1′b0;
     #15 c = 1′b1;
join
  1. 30 d = 1′b0;
end
From Example -4, the initial block contains begin-end and fork-join both. In this case c takes value after 15 time unit, and d takes the value after 30 time unit.


What is sensitivity list in verilog?

 A simple always block runs forever it means as it touches the “end” again starts from beginning.Sensitivity list is a medium to make a controlled always block.

Example of normal always block

    always
    begin
        // statements
    end

     always @ ( sensitivity list)
      begin
           // statements
      end

The syntax of sensitivity list can be –

     A. always @ ( x or y or z)
     B. always @ ( posedge x )
     C. always @ ( posedge x or A )
     D. always @ ( posedge x or negedge y )
     E. always @ ( x, y, z)
     F. always @(*)
     G. always @*
   
The E, F and G are the new constructs added in the verilog 2001.
Usage of different syntaxes in verilog –
Point A and E are same in behavior, taking an example for syntax A and E
Example :1     Always @ ( x,y,z)
     Begin
         Sum = x + y + z
     End

Point B, C and D are normally used for sequential logic implementation
Example : 2
     always @ ( posedge clock or negedge reset )
     begin
     if (!reset)
         q<= 0;
     else
         q<= data
     end
Point F and G are equivalent in behavior. These are some easy options to use without bothering about the sensitivity list
Example : 3     Always @ (*)
     Begin
         Sum = x + y + z
     End

In this case whatever values are used in the right hand side (RHS) would be taken in the sensitivity list So there is any change in the x , y or z values, the always block would be executed..
 

What is the difference between a function and a task? in verilog

  1. behavior –
Function : function call happens in real time OR no simulation delay can be inserted during the function call
Task : Tasks can be inserted with a delay
  1. No of outputs :
Function : A function can have at least one input arg to be passed, and also it can have only one output to drive
Task : Task can have any no of inputs and outputs.
  1. Nesting :
Function : A function can call a function inside it but not a task
Task : Task can call either a function or a task inside it.
  1. Synthesis :
Function : A function can be synthesized
Task : Tasks are not synthesizable
  1. Limitations :
Function : A function does not allow any delay, timing, event inside it
Task : Tasks can have delays, events inside it
  1. Usage :
Function : A can be used for RTL as well as behavioral coding ( mostly for combinational logic)
Task : Tasks can be used for behavioral modeling only.

What is the difference between blocking and nonblocking statements in verilog

In verilog, we have two types of assignment operators i.e. blocking (=) and non- blocking (<=). These two have theirs special usages – Here are the differences
1. behavior  –
The blocking statements are as similar as any sequential programming language. In short, they execute sequentially.
The non-blocking statements are executed concurrently; it means if five statements are written together then it would depend on the simulator to execute which statement first. Ideally all the statements should execute at the same time.
  1. Synthesis –
The blocking statements infer simple “connection OR wire” during the synthesis,
Non-blocking statements infer Flop/latch.
  1. Usage -
The blocking statements are used normally for combinational logic implementation OR whenever the synchronization/sequence required between the assignments,
Non blocking statements are used for sequential implementation

Universal Logic : Mux to Logic gates conversion

In this post, we will see haw a 2:1 MUX can be used to create different logic gates.
1. Designing an Inverter using 2:1 MUX.
To design an inverter using 2:1 mux, we have to use the input as the select line of the MUX and the “zeroth” select line would be tied with “Logic 1 ” and “First” select line would be tired with “Logic 0″, Now when the select line (Input) goes to “1″ the out put will be “0″ ( inverted).
Image : MUX to inverter -
2:1 mux as an inverter
2. Designing an AND Gate using 2:1 MUX.
To design an AND using 2:1 mux, we need to tie the “zeroth” input to “Logic 0″ and the “First” input to the one of the input of the AND Gate. The other input of AND gate would be connected with the select line of the MUX.
Now, the out put of the MUX would be “1″ only if the both of the inputs are “1″ otherwise it would be “0″ for all conditions.
Image : MUX to AND Gate -
2:1 MUX as an AND gate
3. Designing an OR Gate using 2:1 MUX.
To design an OR using 2:1 mux, we need to tie the “First” input to “Logic 1″ and the “Zeroth” input to the one of the input of the OR Gate. The other input of OR gate would be connected with the select line of the MUX.
Now, the output of the MUX would be “1″ when any oth the two inputs would be “1″ otherwise it would be “0″ for all conditions.
Image : MUX to OR Gate -
2:1 MUX as an OR Gate
4. Designing an NOR Gate using 2:1 MUX.
To design the NOR using 2:1 mux, we need to tie the “Zeroth” input of mux to one of the input of NOR and another input of MUX is tied to “0″ . The another input of NOR gate would be applied to the select line of the MUX.
Now, the output of the MUX would be A’B’ = (A+B)’. which is as same as the output of NOR Gate.
Image : MUX to NOR Gate -
2:1 mux as a NOR Gate
5. Designing an NAND Gate using 2:1 MUX.
To design the NAND using 2:1 mux, we need to combine the AND Gate and inverter implementation
6. Designing an XOR Gate using 2:1 MUX.
To design the XOR using 2:1 mux, we need to tie the “Zeroth” input of mux to one of the input of XOR and another input of MUX to the inverted of first input. The another input of XOR gate would be applied to the select line of the MUX.
Now, the output of the MUX would be AB’ + A’B which is as same as the output of XOR Gate.
Image : MUX to XOR Gate -
2:1 Mux as a XOR gate
7. Designing an XNOR Gate using 2:1 MUX.
To design the XNOR using 2:1 mux, we need to tie the “First” input of mux to one of the input of XOR and another input of MUX to the inverted of first input. The another input of XOR gate would be applied to the select line of the MUX.
Now, the output of the MUX would be A’B’ + AB which is as same as the output of XNOR Gate.
Image : MUX to XNOR Gate -
2:1 mux as a XNOR Gate