This the code of the subscriber:
class spi_functional_coverage extends uvm_subscriber #(spi_seq_item);
`uvm_component_utils(spi_functional_coverage)
typedef enum bit [1:0] {A8=0,A16=1,A24=2,A0=3} addr_size_t;
typedef enum bit [1:0] {D8=0,D16=1,D32=2} data_size_t;
typedef enum bit {RD=0,WR=1} access_t;
typedef enum bit [2:0] {B1=0,B2=1,B4=2,B8=3,B16=4,B32=5,B64=6,UNDEF=7} burst_t;
addr_size_t address;
data_size_t data;
access_t wnr;
covergroup spi_cmd_cov;
ADDR: coverpoint address {
bins A8 = {A8};
bins A16 = {A16};
bins A24 = {A24};
}
DATA: coverpoint data {
bins D8 = {D8};
bins D16 = {D16};
bins D32 = {D32};
}
TYP: coverpoint wnr {
bins RD = {RD};
bins WR = {WR};
}
COV_CROSS: cross DATA, ADDR, TYP;
endgroup: spi_cmd_cov
extern function new(string name = "spi_functional_coverage", uvm_component parent = null);
extern function void write(T t);
endclass: spi_functional_coverage
function spi_functional_coverage::new(string name = "spi_functional_coverage", uvm_component parent = null);
super.new(name, parent);
spi_cmd_cov = new();
endfunction
function void spi_functional_coverage::write(T t);
string S;
foreach(t.pedge_mosi[j])
S = {S,$sformatf(" %0h",t.pedge_mosi[j])};
`uvm_info("SPI_FUNC_COV",S, UVM_LOW)
$cast(address,t.pedge_mosi[0][7:6]);
$cast(data,t.pedge_mosi[0][5:4]);
$cast(wnr,t.pedge_mosi[0][0]);
spi_cmd_cov.sample();
endfunction: write
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
This is the monitor:
class spi_monitor extends uvm_component;
// UVM Factory Registration Macro
//
`uvm_component_utils(spi_monitor);
// Virtual Interface
virtual spi_if SPI;
//------------------------------------------
// Data Members
//------------------------------------------
//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(spi_seq_item) ap;
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
extern function new(string name = "spi_monitor", uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
extern function void report_phase(uvm_phase phase);
endclass: spi_monitor
function spi_monitor::new(string name = "spi_monitor", uvm_component parent = null);
super.new(name, parent);
endfunction
function void spi_monitor::build_phase(uvm_phase phase);
ap = new("ap", this);
endfunction: build_phase
task spi_monitor::run_phase(uvm_phase phase);
spi_seq_item item;
logic [7:0] pedge_mosi_int;
logic [7:0] pedge_miso_int;
string S;
item = spi_seq_item::type_id::create("item");
while(SPI.CSN === 1'bx) begin
#1ns;
end
forever begin
item.p = 0;
item.pedge_mosi = '{};
item.pedge_miso = '{};
S = "";
fork
begin
@(negedge SPI.CSN);
forever
begin
pedge_mosi_int=0;
pedge_miso_int=0;
for(int i=7; i>=0; i--)
begin
@(posedge SPI.SCLK);
pedge_mosi_int[i] = SPI.MOSI;
pedge_miso_int[i] = SPI.MISO;
item.p++;
end
item.pedge_mosi.push_back(pedge_mosi_int);
item.pedge_miso.push_back(pedge_miso_int);
end
end
begin
@(posedge SPI.CSN);
end
join_any
disable fork;
foreach(item.pedge_mosi[j])
S = {S,$sformatf(" %0h",item.pedge_mosi[j])};
`uvm_info("SPI_MONITOR",S, UVM_LOW)
ap.write(item);
end
endtask: run_phase
Please note that this is not a complete example, I was just playing with this example and I got stuck with the issue that I have described.