Issue with register write coverage (sample and sample_value)

Hi All,

I am facing a issue, where when I am writing to a register, the coverage bin for write is getting hit for initialized value, but not for the actual value written. To explain more:

My register class looks like this:

class er_pcie_line_rate_i14_t extends uvm_reg;
   rand uvm_reg_field pad26;   // 
   rand uvm_reg_field value;   // 

   virtual function void build();
      pad26 = uvm_reg_field::type_id::create("pad26");
      pad26.configure(this, 26, 6, "RW", 1, `UVM_REG_DATA_WIDTH'h0000000, 1, 1, 0); // Default value is "n/a", set to 0 and disable.
      value = uvm_reg_field::type_id::create("value");
      value.configure(this, 6, 0, "RW", 0, `UVM_REG_DATA_WIDTH'h00, 1, 1, 1);
      wr_cg.set_inst_name($sformatf("%s.wcov", get_full_name()));
      rd_cg.set_inst_name($sformatf("%s.rcov", get_full_name()));
   endfunction

   covergroup wr_cg; // Fields with default value = "n/a" is removed from cover group.
      option.per_instance=1;
      value : coverpoint value.value[5:0] {
          option.auto_bin_max = 4; // Cover group restricted to 4 bins
      }
   endgroup

   covergroup rd_cg; // Fields with default value = "n/a" is removed from cover group.
      option.per_instance=1;
      value : coverpoint value.value[5:0] {
          option.auto_bin_max = 4; // Cover group restricted to 4 bins
      }
   endgroup

   protected virtual function void sample(uvm_reg_data_t data, uvm_reg_data_t byte_en, bit is_read, uvm_reg_map map);
      super.sample(data, byte_en, is_read, map);
      if(!is_read) wr_cg.sample();
      if(is_read) rd_cg.sample();
   endfunction

   `uvm_register_cb(er_pcie_line_rate_i14_t, uvm_reg_cbs)
   `uvm_set_super_type(er_pcie_line_rate_i14_t, uvm_reg)
   `uvm_object_utils(er_pci_line_rate_i14_t)

   function new(input string name="er_pci_line_rate_i14_t");
      super.new(name, 32, build_coverage(UVM_CVR_FIELD_VALS));
      wr_cg=new;
      rd_cg=new;
   endfunction
endclass : er_pcie_line_rate_i14_t

The number of bins getting created are 4 and bins are as follows:

                       auto[0:15]
                       auto[16:31]
                       auto[32:47]
                       auto[48:63]

The initial value of register is 0 for which the WRITE bin auto[0:15] is getting hit, but around 15000ns, I am writing to this register with value 1B for which the WRITE bin auto[16:31] is not getting hit.

The register model is automatically generated and I believe, whenever WRITE will happen, the bin should get hit, which is not happening in my case.

I tried register.sample_value() after register write, but WRITE bin is still un-hit.

Please suggest me, what can be done?

In reply to kmishra:

You are showing only the definitions but not how do you execute your sequence and calling the sample method. The issue might be there.

In reply to chr_sue:

In reply to kmishra:
You are showing only the definitions but not how do you execute your sequence and calling the sample method. The issue might be there.

This is the code of do_block function of my register sequence. Also, my register sequence is extended from “uvm_reg_frontdoor”

protected virtual task do_block(uvm_reg_block blk);
      uvm_status_e               status;
      uvm_reg_data_t             value;
      uvm_reg_data_t             read_value;
      uvm_reg                    regs[$];
      uvm_reg_addr_t             addr_value;
     
      blk.get_registers(regs, UVM_NO_HIER);
      
      foreach (regs[i]) begin //{
        value = 32'h0;
        if (regs[i].get_rights == "RW") begin//{
          if (regs[i].get_address >= 32'h4800 && regs[i].get_address <= 32'h4820) begin
            value='1;
          end
          else if(regs[i].get_address >= 32'h4c00 && regs[i].get_address <= 32'h4c38) begin
            value='1;
          end
          rw.kind     = UVM_WRITE;
          rw.addr     = regs[i].get_address();

         `uvm_create_on(l2_seq, sequencer)
               
          l2_seq.mid            = 'b1;
          l2_seq.crs            = RW_CRS;
          l2_seq.ud             = 'b0;
          l2_seq.addr           = rw.addr[23:0];
          l2_seq.wr             = WRITE_L2;
          l2_seq.p_len          = 5'h4;
          l2_seq.initial_delay  = 0;

          if (rw.kind == UVM_WRITE) begin
            l2_seq.manual_data_mode = 1              ; // need it so l2_seq doesn't generate req_payload randomly
            l2_seq.req_payload      = new[4]         ;
            l2_seq.req_payload[3]   = value[7:0] ;   // Payload;
            l2_seq.req_payload[2]   = value[15:8] ;
            l2_seq.req_payload[1]   = value[23:16] ;
            l2_seq.req_payload[0]   = value[31:24] ;
          end
          fork
              l2_seq.start(sequencer);
          join_none
          #0;
        end//}
      end //}

      begin
        uvm_reg_block blks[$];
        
        blk.get_blocks(blks);
        foreach (blks[i]) begin
           do_block(blks[i]);
        end
      end
endtask: do_block


Please let me know, if additional details needed.

In reply to kmishra:

You need to call the sample method you have defined. But I do not see this. Then you’ll not see real functional coverage.

In reply to chr_sue:

In reply to kmishra:
You need to call the sample method you have defined. But I do not see this. Then you’ll not see real functional coverage.

Thanks much, I tried that but still bins for write are not hitting. I need to figure out exact place to call sample function. Thanks much appreciate your response.