Friday, November 17, 2017

Difference between |->(implication) and ##delay

Implication operator
|- >  work like a trigger
the simulation will be divided into two parts left and right 
will wait first for left side simulation, then will simulate right side


Delay :
##delay : simulation will occur on one line
so implication operator is beneficial as it will save a lot of tool effort and simulation will be faster

Wednesday, October 18, 2017

uvm_void : example of abstract class in uvm

1. The uvm_void class is the base class for all UVM classes.
2. uvm_void is an abstract class with no data member or function.
3. It allows for generic containers of objects to be created, similar to a void pointer in the C programming language
4. User classes derived directly from uvm_void inherit none of the UVM functionality, but such classes may be placed in uvm_void-typed containers along with other UVM objects.

Monday, October 16, 2017

uvm_component

1.The uvm_component class is the foundation of testbench structure,
examples :
i. uvm_monitor
ii. uvm_driver
iii. uvm_sequencer
iv. uvm_scoreboard

2. The UVM builds testbenches and runs them by calling the uvm phase methods in all components in a set order.
3.you define your component by overriding the phase methods and relying upon the UVM to call them in the right order
4.all uvm_component classes need a new () method with two arguments: name and parent

5. class hierarchy of uvm_component :
uvm_void > uvm_object > uvm_report_object > uvm_component
comaparison with uvm_seq_item :
uvm_void > uvm_object > uvm_transaction > uvm_sequence_item

Note : uvm_component exist throughout the simulation whereas uvm_transaction doesn't .

6. more information:
uvm_component provides the following interfaces:

1.Hierarchy provides methods for searching and traversing the component hierarchy.
2.Phasing defines a phased test flow that all components follow
3.Configuration provides methods for configuring component topology and other parameters ahead of and during component construction.
4.Reporting provides a convenience interface to the uvm_report_handler. All messages, warnings, and errors are processed through this interface.
5.Transaction recording provides methods for recording the transactions produced or consumed by the component to a transaction database (vendor specific).
6.Factory provides a convenience interface to the uvm_factory. The factory is used to create new components and other objects based on type-wide and instance-specific configuration.
7.Objection Interface These methods provide object level hooks into the uvm_objection mechanism.

The uvm_component is automatically seeded during construction using UVM seeding, if enabled. All other objects must be manually reseeded, if appropriate. See uvm_object::reseed for more information. (TBU)
for details of each interfaces :https://www.vmmcentral.org/uvm_vmm_ik/files3/base/uvm_component-svh.html

Note 2:
Transactions & Sequences are examples of Dynamic components while Driver & Sequencer are the examples of Static one

Note 3:
as we seen above uvm_component defines a phased test flow (all uvm phases) whereas uvm_transaction doesn't. that is why there is no phases in uvm sequences and sequence item.




I am trying to write a separate post for each UVM components, feedback/suggestions are most welcome.
Thanks!


Monday, September 25, 2017

Formal Verification

Formal verification is a technique used in different stages in ASIC project life cycle like front end verification, Logic Synthesis, Post Routing Checks and also for ECOs. But when you go deep into it, the formal verification used for verifying RTLs is entirely different from others. There are different formal techniques available as follows
Formal Equivalence Checking (LEC or logic equivalence checking)
Formal Property Checking.


Formal Equivalence can be used to verify if following models are equivalent:


1) RTL Design & Synthesized Netlist (Gate level model)
2) RTL Design & Reference Model
3) Two RTL designs
4) Two Gate level models
5) Two reference models


Tool Used for formal Verification - Jasper Gold 

Friday, September 15, 2017

Setup and hold time Questionaire


Significance of negative setup and hold time
What do you mean by negative setup and hold time i.e what happens if hold time is negative or setup time is negative. Does -ve setup or hold have any advantage ?

Setup times and hold times describe the limits relative to the active clock edge of a "window" within which the input data must be valid for the data to be reliably recognized. The diagram below (you can ignore the bottom Q output part) shows the situation for assumed positive hold and setup times, but you can imagine them negative.

If setup time is negative, then the absolute latest that the data can become valid is actually after the active clock edge, Obviously the hold time must be positive and of greater magnitude or there would be no window for data validity.

If the hold time is negative, then the absolute earliest the data no longer needs to be valid is before the active clock edge, so it can change just before the clock edge and the previous value will be correctly recognized. Obviously, the setup time must be positive and of greater magnitude or there would be no window.

As to possible advantages- think about the situation where you are trying to increase clock frequency as much as possible.

For Hold Time > If the difference between the data path and the clock path is negative, then a timing violation has occurred.

For Setup Time > If the difference between the clock path and the data path is negative, then a timing violation has occurred.

By negative setup and hold times do you mean positive slack time?
Positive slack means the data arrival times are not violating the timing of the circuit. It basically tells you how much timing you have to lose and still be acceptable.

slack time, setup time, hold time

A zero setup time means that the time for the data to propagate within the component and load into the latch is less than the time for the clock to propagate and trigger the latch.

A negative setup or hold time means that there is an even larger difference in path delays, so that even if the data is sent later than the clock (for setup time), it still arrives at the latch first.

slack is different from this because it is the required time - arrival time....


Say an FF as setup time of 1ns.(positive 1ns)
Now re-design this FF, and put a buffer in the clock path with a propagation delay of 2 ns.
Now the setup time of this redesigned FF would be -1ns (negative).

So if the clock is delayed w.r.t data, then you can see negative setup times.


Re: Negative setup and hold time
Negative setup time flops are used on hard-to-meet data paths.
Negative hold time flops already have an "inbuilt hold buffer" embedded and hold closure is eased.


What is metastability?
Whenever there are setup and hold time violations in any flip-flop, it enters a state where its output is unpredictable: this state is known as metastable state (quasi stable state); at the end of metastable state, the flip-flop settles down to either '1' or '0'. This whole process is known as metastability. In the figure below Tsu is the setup time and Th is the hold time. Whenever the input signal D does not meet the Tsu and Th of the given D flip-flop, metastability occurs.

When a flip-flop is in metastable state, its output oscillate between '0' and '1' as shown in the figure below (here the flip-flop output settles down to '0') . How long it takes to settle down, depends on the technology of the flip-flop.

If we look deep inside of the flip-flop we see that the quasi-stable state is reached when the flip-flop setup and hold times are violated. Assuming the use of a positive edge triggered "D" type flip-flop, when the rising edge of the flip-flop clock occurs at a point in time when the D input to the flip-flop is causing its master latch to transition, the flip-flop is highly likely to end up in a quasi-stable state. This rising clock causes the master latch to try to capture its current value while the slave latch is opened allowing the Q output to follow the "latched" value of the master. The most perfectly "caught" quasi-stable state (on the very top of the hill) results in the longest time required for the flip-flop to resolve itself to one of the stable states.


How long does it stay in this state?
The relative stability of states shown in the figure above shows that the logic 0 and logic 1 states (being at the base of the hill) are much more stable than the somewhat stable state at the top of the hill. In theory, a flip-flop in this quasi-stable hilltop state could remain there indefinitely but in reality it won't. Just as the slightest air current would eventually cause a ball on the illustrated hill to roll down one side or the other, thermal and induced noise will jostle the state of the flip-flop causing it to move from the quasi-stable state into either the logic 0 or logic 1 state.



What are the cases in which metastability occurs?
As we have seen that whenever setup and hold violation time occurs, metastability occurs, so we have to see when signals violate this timing requirement:


When the input signal is an asynchronous signal.
When the clock skew/slew is too much (rise and fall time are more than the tolerable values).
When interfacing two domains operating at two different frequencies or at the same frequency but with different phase.
When the combinational delay is such that flip-flop data input changes in the critical window (setup+hold window) 


What is MTBF?
MTBF is Mean time between failure, what does that mean? Well MTBF gives us information on how often a particular element will fail or in other words, it gives the average time interval between two successive failures. The figure below shows a typical MTBF of a flip-flop and also it gives the MTBF equation. I am not looking here to derive MTBF equation :-)


So how do I avoid metastability?
In reality, one cannot avoid metastability and increased clock-to-Q delays in synchronizing asynchronous inputs, without the use of tricky self-timed circuits. So a more appropriate question might be "How do I tolerate metastability?"


In the simplest case, designers can tolerate metastability by making sure the clock period is long enough to allow for the resolution of quasi-stable states and for the delay of whatever logic may be in the path to the next flip-flop. This approach, while simple, is rarely practical given the performance requirements of most modern designs.



The most common way to tolerate metastability is to add one or more successive synchronizing flip-flops to the synchronizer. This approach allows for an entire clock period (except for the setup time of the second flip-flop) for metastable events in the first synchronizing flip-flop to resolve themselves. This does, however, increase the latency in the synchronous logic's observation of input changes.


Neither of these approaches can guarantee that metastability cannot pass through the synchronizer; they simply reduce the probability to practical levels.

In quantitative terms, if the Mean Time Between Failure (MTBF) of a particular flip-flop in the context of a given clock rate and input transition rate is 33.33 seconds then the MTBF of two such flip-flops used to synchronize the input would be (33.33* 33.33) = 18.514 Minutes. Well I have taken the worst flip-flop ever designed in history of man kind :-). The figure below shows how to connect two flip-flops in series to achieve this and also the resultant MTBF.

Normally,
We can use a metastable hardened flip-flop
Cascade two or three D-Flip-Flops (two or three stages synchronizer).

Sunday, September 10, 2017

Randomizations and constraint overriding in SV : Part2

Pre_randomize and Post_randomize  :

1. Every class contains pre_randomize() and post_randomize() methods
2. which are automatically called by randomize() before and after computing new random values.
3. When randomize() is called it invokes three methods in below order :
    i. pre_randomize()
    ii. randomize()
    ii. post_randomize()


Note : post_randomize() will be only invoked if the randomize() was successful 

These methods can be used as hooks for the user to perform operations
for example : setting initial values and performing functions after assigning random variables.

///////////////////////////////////////
program pre_post_15;
class simple;
function void pre_randomize;
$display(" PRE_RANDOMIZATION ");
endfunction

function void post_randomize;
$display(" POST_RANDOMIZATION ");
endfunction

endclass
simple obj = new();
initial
void'(obj.randomize());
endprogram
////////////////////////////////////////////////////////


Output:

PRE_RANDOMIZATION
POST_RANDOMIZATION
$finish at simulation time 0
V C S S i m u l a t i o n R e p o r t

------------------------------------------------------------------------------------------------------------
NowI have changed a function with randomize in place of pre_randomize :
VCS compiler has given below error :

The user declared method 'randomize' in class 'simple' clashes with built-in
method name. Please change the name of the user declared method/identifier.

4. Overriding of pre_randomize and post_randomize functions is allowed by child class.


5. The pre_randomize() and post_randomize() methods are not virtual. However, because they are automatically called by the randomize() method, which is virtual, they appear to behave as virtual methods.


Question on constraint Overriding :

Can we override constraints of base class in extended class, by defining a new constraint with the same name in extended class.

In the code below, there are two constraint in "base" class for variable "a" & "b".

In "extended" class which is extended from base, I defined two more constraint which are in conflict with the constraint in base class. For variable "a" constraint I used the same name as in base class, and for "b" I used a different name.



When I randomized the extended class object, I expected randomization should fail for both the constraint in extended class. But the randomization only fail for the conflicting constraint with different name in base and extended class.
module junk () ;
   class base;
      rand bit [15:0] a,b;
      
      function new();
      endfunction // new
      
      constraint ct_a {a inside {[0:9]};} 
      constraint ct_b {b inside {[10:19]};}
    endclass // base
   
   class extended extends base;
      function new();
      endfunction // new

      constraint ct_a       {a inside {[10:19]};}
      constraint ct_b_new   {b inside {[0:9]};}
   endclass // extended
   
   initial begin
      extended extended_obj;
      extended_obj = new();

      if(!extended_obj.randomize()) $display("Randomization Failed");
   end
endmodule // junk


Answer :
1. That's expected as per LRM. With same names, you are "overriding" the base constraint and hence is not conflicting.

2. if u use the same name in extended class that means you are overriding that constraint in the derived class. so the constraint in the base class no more work for the extended class. so for 'a' there is no conflict and the constraint is easily overwritten in extended class.

Note : here we are randomizing the object of extended class

where as for 'b' both the constraints are working so conflicts occurs in that case.



Monday, September 4, 2017

uvm_phases and flow - Interview Presparation

From the starting of simulation till the end of the simulation:

Why Phases Concept : 
1. In order to have a consistent Testbench flow, UVM introduces “Phases” to synchronize major functional steps a simulation runs through.
2. These steps are sequential in nature which are executed in the following order:

Build Phases:
Where the Testbench is constructed, connected and configured.
Run-time Phases:
Stimulus generation & time-consuming simulation takes place here.
Clean up Phases:
Here the Test results are collected and reported.

We’ll see more details of these 3 Phases in the upcoming section of this post.

1. We know that UVM environment is built of static components those are derived from the UVM base class i.e. uvm_component which contains a number of virtual methods. 
2. These virtual methods support the UVM Phasing mechanism,
3. So UVM phasing mechanism is only for uvm_components
4. Hence a verification component can be developed in isolation since there is an established understanding of what is expected to happen in each of the execution phases.



Diagram 1: UVM Phases

Here we can see 3 groups of Phases which are briefly described as well.
Build Phases group contains 3 sub-phases
Run Phases group contains 13 sub-phases
Cleanup Phases group comprises of 4 sub-phases
How UVM Phasing is triggered?:
1. To start a UVM Testbench, the run_test() method has to be called from the static part of the Testbench. 
2. It is usually called from within an initial block in the top level module of the Testbench.
// Top level Testbench 
module module top_tb; 
// UVM start up: 
initial begin 
uvm_config_db #(virtual bus_if)::set(null, "*", "BUS_vif" , BUS); 
run_test("bidirect_bus_test"); 
end 
endmodule: top_tb 
3. Once the run_test() method is called, it constructs the root component of the UVM environment 
4. then triggers/initiates the UVM Phasing process. 
5. The run_test() method can be passed with a string argument
6.  In the above code argument is “bidirect_bus_test”, to define the default type name which is used as the root node of the Testbench Hierarchy.
7. In addition, run_test() method also checks for a command line plusarg called UVM_TESTNAME and uses that plusarg string to lookup a factory registered uvm_component to override any default type name.
8. Hence to execute the “bidirect_bus_test” using command line plusarg, we’ve to use the following command line:
% <simulator executable> +UVM_TESTNAME=bidirect_bus_test
9. about uvm_test_top and uvm_root (to be updated)


What each of UVM Phase Performs?:
Lets detail out each of the UVM Phase/Sub-Phase with respect to the activities being performed during their execution:
1) Build Phase:
The build phases are executed at the start of the UVM Testbench simulation and their overall purpose is to construct, configure and connect the Testbench component hierarchy. 
All the build phase methods are functions and therefore execute in zero simulation time.

build:
i) Once the UVM Testbench root node component is constructed, the build phase starts to execute. 
ii) It constructs the testbench component hierarchy in a top-down manner. 
iii) During the build phase, uvm_components are indirectly constructed using the UVM factory.

connect:i) The connect phase is used to make TLM connections between components or to assign handles to testbench resources. 
ii) It has to occur after the build method so that Testbench component hierarchy could be in place and it works from the bottom-up of the hierarchy upwards.

end_of_elaboration:
i) The end_of_elaboration phase is used to make any final adjustments to the structure, configuration or connectivity of the Testbench before simulation starts. 
ii) Its implementation can assume that the Testbench component hierarchy and inter-connectivity is in place. This phase executes bottom up.

start_of_simulation:The start_of_simulation phase is a function which occurs before the time consuming part (run-phase) of the testbench begins. It is intended to be used for displaying banners; Testbench topology; or configuration information. It is called in bottom up order.

2) Run Phase:
i) The UVM Testbench stimulus is generated and executed during the run time phases. 
ii) Run phase was present in OVM as well but additional other phases were added to UVM to give finer run-time granularity for tests, scoreboard and other components.
iii) The run phase occurs after the start_of_simulation phase and is used for the stimulus generation and checking activities of the Testbench. 
iv) The run phase is implemented as a task, and all uvm_component run tasks are executed in parallel. 
v) Transactors such as driver and monitor will nearly always use this phase.

pre_reset:
pre_reset phase starts at the same time as the run phase. Its purpose is to take care of any activity that should occur before the reset. E.g. waiting for a power signal to go active.
reset:
As the name indicates, reset phase is especially for DUT or Interface specific reset behaviour. This phase would be used to generate reset to put the DUT/Interface into a default state.
post_reset:
This phase is intended for any activity required just after the reset phase.


pre_configure:
This phase is intended for anything that is required to prepare for the DUT configuration process after the DUT is out of reset.
configure:
configure phase is used to put the DUT into a known state before the stimulus could be applied to the DUT. For example – programming the control registers of the device for a particular test scenario.
post_configure:
This phase is intended to wait for the effect of the configuration to propagate through the DUT.
pre_main:pre_main is used to ensure that all the components needed to generate the stimulus are ready to do so.
main:
the main phase is where the stimulus specified by the Test case is generated and applied to the DUT. It completes in two conditions: One is the stimulus gets exhausted and another is when a timeout occurs. Sequences are started in this phase to generate the stimulus.
post_main:
Used for any final act after the main phase.
pre_shutdown: This phase acts as a buffer to apply any stimulus before the shutdown phase starts.
shutdown:
The shutdown phase is to ensure that the effect of stimulus generated during the main phase has propagated through the DUT and that the resultant data has drained away. It might also be used to execute the time-consuming sequences that read status registers.
post_shutdown:
post_shutdown is intended for any final activity before exiting the run phase. After this, UVM Testbench starts the cleanup phase.

3) Clean up Phase:
The cleanup phases are used to extract information from Scoreboards and Functional Coverage Monitors to determine whether the test case has passed and/or reached its coverage goals. The cleanup phases are implemented as functions and therefore take zero time to execute. They work from the bottom to the top of the component hierarchy.

extract:
The extract phase is used to retrieve and process information from Scoreboards and Functional Coverage Monitors. This may include the calculation of statistical information used by the report phase. This phase is usually used by Analysis side components.
check:
This phase is also used by the Analysis Components. This phase is used to check if the DUT behaved correctly and to find any error that may have occurred during the stimulus execution.
report:
The report phase is used to display the results of the simulation to the standard output or to write the results to file. This phase is usually used by Analysis Components.
final:
The final phase is used to complete any other outstanding actions that the Testbench has not already completed.

So these are all the different phases through which a Standard UVM Testbench runs through to generate a reset, doing configuration, stimulus generation & performing simulation and finally report generation.
so these were all different phases a UVM static component like Driver or Monitor etc. & dynamic component like Sequences goes through during life time of UVM Simulation.

//more about dynamic and static components (to be updated)






Short Notes :
1. build - Depending on configuration and factory settings, create and configure additional component hierarchies.
2. connect - Connect ports, exports, and implementations (imps), TLM ports connection
3. end_of_elaboration - Perform final configuration, topology, connection,
and other integrity checks.
4. start_of_simulation - Do pre-run activities such as printing banners, pre-loading memories, etc.
5. run - Most verification is done in this time-consuming phase. May fork other processes. Phase ends when global_stop_request is called explicitly or using phase drop objection mechanism
i) Time-consuming phase, so we can use task here
ii) run tasks are executed in parallel
iii) 12 sub-phases added in parallel with run_phase
iv) driver and monitor use run_phase for sure
6. extract - Collect information from the run in preparation for checking
7. check - Check simulation results against expected outcome.
8. report - Report simulation results.

uvm_phase is a base class which defines everything about the phase like behavior, state or context.

uvm_void > uvm_object > uvm_phase (class hierarchy)

Constructor : new, get_phase_type


UVM flow :
  1. We call run_test in tb_top, which calls the run_test task of the uvm_root class.
  2. The uvm_root calls the m_run_phases task of the uvm_phase class.
  3. For each phase, the execute_phase task is called.
  4. If the phase is a top-down or bottom-up phase, exec_func is called for each component.
  5. For example, the exec_func calls the build_phase function of each component.
  6. If the phase is a task phase, exec_task is called for each component.
  7. For example, the exec_task calls the main_phase task of each component.
  8. The uvm_phase checks if any objections are raised by the components. The phase_done is the uvm_objection object that the uvm_phase keeps track of the number of objections with. When we called phase.raise_objection() from inside the run_phase of the test phase_done.raise_objection() is called in the uvm_phase under the hood.
  9. If no objection is raised, all the processes started by the exec_task are killed. In other words, unless an objection is raised, the phase is immediately killed!
  10. The steps 3 to 9 repeat until all phases are executed.
check for more details :
http://cluelogic.com/2014/08/uvm-tutorial-for-candy-lovers-phasing/



Thanks!  feedback/suggestions/edit_suggestions are most welcome

source of info: http://www.learnuvmverification.com/index.php/2016/04/29/uvm-phasing and uvm class reference manual and my understanding.




Monday, August 28, 2017

uvm_factory


1. What is uvm_factory?
 uvm_factory is a class that manufacture (create) uvm_component and object during run time.


2. Why use it?
ability to modify the types and no of objects that make up the testbench hierarchy.


3. Factory_Registration items :
  • An uvm_component_registry wrapper, typedef-ed to type_id.
  • A static id to get the type_id.
  • A function to get the type_name.
4. Only one instance of the factory is present in a given simulation (termed a singleton)


5. Register the class type to the factory using macros:
`uvm_component_utils //for component
`uvm_object_utils // for stimulus and sequences

above 2 macros are used to register components and objects in the factory:
i) declares typedef of wrapper type named type_id
ii) defines get_type and get_type_name function


6. Factory registration of parametrized class:
`uvm_component_param_utils //components
`uvm_object_param_utils //stimulus and sequence

Example:
class write_xtn #(Type T = int) extends uvm_sequence_item;
`uvm_object_param_utils (write xtn #(T))
endclass


class bus_wr_driver #(Type T= int, width W=32) extends uvm_driver;
`uvm_component_param_utils (bus_wr_driver) #(T W))
endclass



7. Constructor Defaults
  • uvm_component and uvm_objects constructors are virtual methods
  • the defaults are different for components and objects

8. Constructor Defaults for a component

class my_component extends uvm_component;
function new (string name = "my_component", uvm_component parent = null)
super.new (name, parent);
endfunction


9. Constructor Defaults for an object

class my_item extends uvm_sequence_item
function new(string name = "my_item");
super.new(name);
endfunction



10. Creating Components:
  • During the build phase using the top-down approach.
  • Using the create method of the uvm_component_registry.

Virtual function uvm_object create (String name = "", uvm_component, parent )




11. Creating Components in the build phase

Class bus_wr_agent extends uvm_components;
bus_wr_driver drvh ;
function build_phase (uvm_phase phase);
super.build_phase (uvm_phase phase);
drvh = bus_wr_driver :: type_id :: create ("drvh", this);
....
endfunction
endclass



12. Note :
do not use new() to allocate the memory, use create()
drvh = new (drvh, this) //no to this

WHY:-  when you do new to create an object, you will be restricted with that type of object, it is highly desirable to change the type of the object being constructed without having to modify the existing code

13. uvm_factory has two kind of registry :
classtype_registry - whenever we register something it goes to classtype_registry
override registry


14.  uvm_factory provides four different methods to override a particular instance or all instances of a particular class. 
i) set_inst_override_by_type  - when we want to overwrite all the instance of a class 

ii) set_inst_override_by_name - when we want to override all the instance of a data type or method or variable


i) set_type_override_by_type : A convenience function for uvm_factory::set_type_override_by_type, this method registers a factory override for components and objects created at this level of hierarchy or below.


ii) set_inst_override_by_type : A convenience function for uvm_factory::set_inst_override_by_type, this method registers a factory override for components and objects created at this level of hierarchy or below
factory.set_inst_override_by_type(B::get_type(), B_override::get_type(), "path2.b2"); 

iii) set_inst_override_by_type configure factory to create an object of override type when request made to create an object for original type using context that matches the full_inst_path string argument.

iv) set_type_override_by_type configure factory to create an object of override type when request made to create an object for original type.



15. Question: how to get a handle to the UVM factory so as to use a function such as set_type_override_by_name().


An instance named factory is automatically created internally in UVM. You can use it directly. Directly use factory.set_type_override_by_name("original_type_name","override_type_name");

16. It uses the concept of polymorphism.



















Monday, August 14, 2017

Difference between implication (->) and ##0 in SVA


First thing that you have to check is syntax of single implication operator that is a |-> b.

In SystemVerilog assertion, there are two expressions.
a ##0 b
a |-> b

Actually, it looks like a similar in expressions. First of this expression is checking a is asserted(1) and after 0 clock cycle b is asserted(1) or not. Second expression is checking b is (on)asserted when a is asserted(1) then on same posedge b is asserted(1) or not.

Now, practically when verification engineers wrote this kind of assertions they take care of following things.
a ##0 b: In this expression, if a is not asserted then it shows failure.
When a is asserted(1) and on same time stamp b is not asserted then also shows failure.

a |-> b: In this expression, if a is asserted and b is not asserted then it will show a failure.
If a is not asserted then it is not going to check whether b is asserted or not. This behaviour is different than a ##0 b.

If you apply different inputs data then you can see that expression a ##0 b will give you more failure than a |-> b. Reason for same is already explained above.

One more thing to note down is "The implication construct can be used only with property definitions. It cannot be used in sequences."


Source: stack overflow

Friday, July 21, 2017

Working with GIT : Basic Commands

What is GIT :
  1. Git is a version control system (VCS) for tracking changes in computer files and coordinating work on those files among multiple people. 
  2. It is primarily used for source code management in software development, but it can be used to keep track of changes in any set of files 
  3. Git was created by Linus Torvalds in 2005 for development of the Linux kernel, with other kernel developers contributing to its initial development. Its current maintainer since 2005 is Junio Hamano. 
  4. As with most other distributed version control systems, and unlike most client–server systems, every Git directory on every computer is a full-fledged repository with complete history and full version tracking abilities, independent of network access or a central server. 
  5. Like the Linux kernel, Git is free software distributed under the terms of the GNU General Public License version 2. 



Basic Commands :

  1. git clone <repo path> Clone a repository into a new directory 
  2. git status  - Show the working tree status like file a is modified and file b is newly added. 
  3. git add <file name> - Add file contents to the index 
  4. git commit -m “message1” - Record changes to the repository 
  5. git pull – Fetch from and integrate with another repository or a local branch (fetch + merge)   Git pull is useful when you are working on your local branch and you want to merge your changes with the latest central repo.                                                                                       Note1: Before using git pull, always commit your changes 1st so that it may merge with central repo.                                                                                                                                       Note2: Before using git commit we need to use git add. 
  6. git checkout <file A> – it will revert your all changes of file A in local branch 
  7. git blame <file A> - it will show all the modification done to file A with the person name , time and line no. It helps to migrate changes done by a particular person in file A, to another file or project. 



Sunday, June 4, 2017

Assertion

1. An Assertion specifies the behaviour of the system.
2. It validates the behaviour of design 
3. In addition, assertion can be used to provide functional coverage and generate input stimulus for validation


The advantage of assertion:
1. Improving observability 
2. reduce the debug time 
3. bugs can be found earlier and more isolated 
4. can interact with C function



types of assertion:
1.Immediate 
2. concurrent 


Immediate                                                                concurrent                            

based on simulation event                                       based on a clock cycle 
used without property keyword                                used with property keyword
placed in procedure block definition                        placed in procedural blocks, modules, interfaces or program                                                                                     definition

i) Immediate assertions are useful for combinational expression, similar to if else statement but with assertion control.
ii) Assertions are non-synthesizable
iii) Assertions can be written in design and TB both but in design, while synthesising need to remove so use `define


Difference between assert and cover :

assert: if you want scenario to be hold true then you write an assertion.
cover : Whether scenario ever happened in your simulation or not.


|-> implication operator



sequence s;
    @(posedge clk) a ##1 b;
  endsequence
 
  property p;
    a |-> s;
  endproperty
 
  assert property (p);
  cover property (p);

Monday, March 20, 2017

X Propagation


1. Hardware description languages such as SystemVerilog use the symbol 'X' to describe any unknown logic value.
2. If a simulator is unable to decide whether a logic value should be a '1', '0', or 'Z' for high impedance, it will assign an X. This causes problems for two reasons. The first is that an X may be converted inadvertently(accidently) to a 'known' state by overly optimistic simulation code. The second is that gate simulators can generate excess X values because they generally apply more pessimistic rules.

3. The situation is not helped by the traditional use of the X to express 'don't-care' conditions for the purposes of synthesis, as well as for an unknown state in simulation.

X states can propagate through a simulation, multiplying uncertainty and potentially hiding bugs.

This has become a bigger issue in recent years because of the use of power-gating architectures to save energy. In this design approach, when the logic is powered down, it no longer provides a reliable signal to downstream logic, which itself may not have been designed to cope properly. This propagates errors through the chip when the blocks move between power states. However, any logic block that has not been properly reset may also generate X values.
Over-optimistic simulation

For example, a simulator will apply an X to any memory location that has not been initialized. Reset logic is expensive, particularly in terms of routing overhead, so it will rarely be feasible to apply a reset to every memory element at restart. Logic that has been designed with uninitialized memories and a weak reset strategy may be prone to more undiscovered bugs due to X propagation.

A common source of unwanted X optimism is when downstream logic states are assigned using 'if-then-else' or 'case' statements. Because the X state will not satisfy the logic test, the block will be assigned the default case. This may convert the X to a 'known' value or propagate it further into the simulation, masking a bug.

X pessimism can happen when signals converge, for example in a multiplexor. The simulator has to assign the X value to the output if presented with an X on an input that is not overridden by other known signals feeding into the block.
Simulation tweaks

There are a number of ways of dealing with X propagation. One is to analyze the waveform generated by a simulator – many simulators color-code these signals to make them easier to pick out. However, this involves painstaking manual inspection and design insight to work out whether the X is dealt with correctly or not.

Some simulators can be set up to generate random values in place of Xs, on the basis that differences in behaviour with otherwise identical input vectors should point to X propagation issues. However, the errors caused by X propagation can be subtle and only turn up in rare cases, which may not be encountered during most simulation runs. Another possibility is more exhaustive simulation.

The 'xprop' simulation technology employed by recent versions of Synopsys' VCS will replace every X it encounters with both a 0 and 1 to calculate all possible values, and then merge them to decide which value should be driven to the output. VCS employs a number of merge techniques to reflect different expectations, including a pessimistic approach more akin to gate-level simulation, and a more hardware-like scenario in which any output that cannot be merged to a known value is converted to an X.

The CVC simulator from Tachyon-DA takes the approach of changing default Verilog semantics to a situation in which it works on the assumption that any X should be treated as a 0, 1 or X.
X prevention

On the basis that prevention is better than cure, Mike Turpin's seminal 2003 SNUG Boston paper "The dangers of living with an X" contained a number of recommendations for writing HDL that is more likely to avoid X propagation, as well as advice on verification techniques:


"For one-hot logic on a critical path, write the RTL directly in a sum-of-products form (rather than case) and add a one-hot assertion checker.

"Avoid using if-statements, as they optimistically interpret Xs. Instead use ternary (that is, conditional ?) operators or priority-encoded case statements.
"For case statements, cover all reachable 2-state values with case-items and always add a default (but only use it to assign Xs, to avoid X-optimism)."

However, for complex control logic, it can be difficult to be sure that these coding technique lead to an X accurate, rather than X optimistic or X pessimistic, design.
X detection

Some of these issues can be detected by linting tools such as Ascent Lint. Cadence Design Systems is working on a combination of formal techniques that will yield what the company currently calls "super linting", and which will form part of a range of verification 'apps'.

Source : Internet 

Ethernet and more

Ethernet is a protocol under IEEE 802.33 standard User Datagram Protocol (UDP) UDP is a connectionless transport protocol. I...