Search code examples
system-veriloguvmfunction-coverage

functional_coverage not showing proper result


I have developed a simple uvm testbench to verify a simple adder. I have used functional coverage to monitor the coverage as well. The adder is 8 bit with inputs a and b and the output is c, which is 9 bits.

I have developed the transaction with 8 bits rand logic for a and b. In sequence, I have run that with repeat(100) and it will randomize and drives a and b to the DUT. The best case for functional coverage for this scenario is (100/256)*100% i.e around 40% assuming that no value will be repeated. I sample the coverage in my scoreboard and get the coverage result in env.

Here are my code snippets

// monitor class
  covergroup cg;
    a : coverpoint sb_item.a;
    b : coverpoint sb_item.b;
  endgroup
  ...
  function void write(input input_seq_item i);
    sb_item = i;
    if(sb_item.c == sb_item.a + sb_item.b)
      begin
        `uvm_info("SB","OK!",UVM_LOW)
        cg.sample();
      end
      else
        `uvm_error("SB",$sformatf("ERROR! %b + %b = %b", sb_item.a, sb_item.b, sb_item.c), UVM_LOW)
  endfunction

  // env class
  ...
  task run_phase(uvm_phase phase);
    sb.cg.stop();
    phase.raise_objection(this);
    sb.cg.start();
    seq.start(sqr);
    phase.drop_objection(this);
    sb.cg.stop();
    `uvm_info("env",$sformatf("The coverage collected is %f",sb.cg.a.get_coverage()),UVM_LOW);
  endtask
  ...

When I run the code, I get coverage of around 81. Results shown below

# KERNEL: UVM_INFO /home/runner/monitor.sv(56) @ 996: uvm_test_top.env.sb [SB] OK!
# KERNEL: UVM_INFO /home/runner/env.sv(34) @ 996: uvm_test_top.env [env] The coverage collected is 85.937500
# KERNEL: UVM_INFO /home/build/vlib1/vlib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 996: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
# KERNEL: UVM_INFO /home/build/vlib1/vlib/uvm-1.2/src/base/uvm_report_server.svh(855) @ 996: reporter [UVM/REPORT/SERVER] 
# KERNEL: --- UVM Report Summary ---
# KERNEL: 
# KERNEL: ** Report counts by severity
# KERNEL: UVM_INFO :  204
# KERNEL: UVM_WARNING :    0
# KERNEL: UVM_ERROR :    0
# KERNEL: UVM_FATAL :    0
# KERNEL: ** Report counts by id
# KERNEL: [Driver]   100
# KERNEL: [RNTST]     1
# KERNEL: [SB]   100
# KERNEL: [TEST_DONE]     1
# KERNEL: [UVM/RELNOTES]     1
# KERNEL: [env]     1
# KERNEL: 
# RUNTIME: Info: RUNTIME_0068 uvm_root.svh (521): $finish called.
# KERNEL: Time: 996 ns,  Iteration: 61,  Instance: /top,  Process: @INITIAL#14_0@.
# KERNEL: stopped at time: 996 ns
# VSIM: Simulation has finished. There are no more test vectors to simulate.
exit
# FCOVER: Covergroup Coverage data has been saved to "fcover.acdb" database.
# VSIM: Simulation has finished.

Can anyone explain what mistake I am doing here? Is the coverage cumulative over all runs?


Solution

  • Whether the coverage is cumulative over all runs depends on what you're analyzing. I'm guessing you're analyzing only one simulation, though. Your calculation is correct, the maximum coverage you could get per test is about 40% (basically 40% per each coverpoint, averaged together), but that's highly unlikely to reach.

    What you also need to look at (aside from the percentage) is what bins are actually getting created. I don't think you're getting a bin for each value of a or b, but that some of them might be clumped up together (i.e. a in [ 0..3 ] would be one bin and so on, leaving you with 256/4 bins instead of 256). Each coverpoint has an option called auto_bin_max, whose default value is 64. if you set this to 256 or explicitly declare a (range) bin for each value that a or b could take, you'll get a coverage percentage you'd expect.

    As a side note, you typically don't create a coverage bin for every value of a data item, since this doesn't really make sense. In a typical device there are so many values the data items could take that you can't verify them all. What you would do, however is declare bins for more "interesting" situations. In your case, interesting values are 0, 8'hff and anything in between. What's also particularly interesting is crossing a and b and checking the combinations, especially the case where a and b are both 8'hff (as that's where your result would overflow on 8 bits and output a carry.