Welcome ! This website will help YOU (recent graduates/professionals) learn verification languages like SystemVerilog and UVM. Register for free and access more content !
2 minutes reading time (451 words)

Using a custom sample function for functional coverage

custom-sample

The first way to sample covergroups is to specify an event like clock edge or an event handle that can be triggered from elsewhere in the testbench. The second way to sample covergroups is to explicitly call sample() at places where we want the variables to be sampled. The first method is usually preferred for repetitive sampling at regular event triggers. For example, we can sample the variables on every positive edge of the clock or whenever an event called "interrupt" happens. The best way to sample values at a set of specific places in the testbench is to call sample() method as required.

The default sample() method call does not accept any argument, and so the next obvious way to pass arguments to the covergroup is when it is instantiated like shown below.

 
class coverage;
  ...
  covergroup cg_abc (int low, int high);
    coverpoint x {
      bins range = {[low:high]};
    }
  endgroup
 
  function new ();
    cg_abc = new (12, 64);
  endfunction
endclass
 

There are a couple of limitations here. The argument values have to be provided during instantiation of the covergroup. A different covergroup instance is required that can accept a different set of values. And if the argument is a class object, then that object cannot be pointing to null when the covergroup is instantiated or else it gives out a null pointer error.

 
class coverage;
  covergroup cg_abc (data_obj obj);
    coverpoint obj.mode {
      bins range = {[3:'hB]};
    }
  endgroup
 
  function new ();
      data_obj obj;
    cg_abc = new (obj);
  endfunction
endclass
 
module tb;
  initial begin
    coverage m_cov = new();
    for (int i = 0; i < 10; i++) begin
      data_obj obj = new();
      obj.randomize();          // How do I assign obj to covergroup inst ?
      m_cov.cg_abc.sample();
    end
    $display ("Coverage : %0.2f %%", m_cov.cg_abc.get_coverage());
  end
endmodule
 

The above code will result in a NULL pointer error because the obj was never instantiated before it was passed to the covergroup.

Simulation Log
ncsim> run
ncsim: *E,TRNULLID: NULL pointer dereference.
          File: ./custom-sample.sv, line = 12, pos = 15
What works

The other way is to define a custom sample method that can accept arguments. So, different argument values can be provided to the sample method when that covergroup is sampled.

 
class coverage;
    covergroup cg_abc with function sample (data_obj obj);
    coverpoint obj.mode {
      bins range = {[3:'hB]};
    }
  endgroup
 
  function new ();
      data_obj obj;
      cg_abc = new();
  endfunction
endclass
 
module tb;
  initial begin
    coverage m_cov = new();
    for (int i = 0; i < 10; i++) begin
      data_obj obj = new();
      obj.randomize();
      m_cov.cg_abc.sample(obj);
    end
    $display ("Coverage : %0.2f %%", m_cov.cg_abc.get_coverage());
  end
endmodule
 
Simulation Log
ncsim> run
Coverage : 100.00 %
ncsim: *W,RNQUIE: Simulation is complete.
Overriding covergroups
HDL routines for error injection

Related Posts

 

Comments

No comments made yet. Be the first to submit a comment
Already Registered? Login Here
Guest
Tuesday, 14 August 2018

We use cookies to personalize content and ads, to provide social media features and to analyze our traffic. You consent to our cookies if you continue to use our website. To find out more about the cookies we use and how to delete them, see our privacy policy.

  I accept cookies from this site.
Agree
EU Cookie Directive plugin by www.channeldigital.co.uk