Monitor not detected package at the correct time probably

Hi All ,

I am trying build some verification environment to an APB with transmit and receive unit.

I tried to capture my monitor at one point and the result is that my monitor behave like my driver.

I attached waves pictures, interface ,driver,item and monitor code…
Please pay attention that my monitor and driver task in the monitor(collect_item, send_to_dut).

waves



class apb_monitor extends uvm_monitor;

  // Collected Data handle
  apb_packet pkt;

  // Count packets collected
  int num_pkt_col;

  // analysis port for lab09*
  uvm_analysis_port#(apb_packet) item_collected_port;

  virtual interface apb_if vif;

  // component macro
  `uvm_component_utils_begin(apb_monitor)
    `uvm_field_int(num_pkt_col, UVM_ALL_ON)
  `uvm_component_utils_end

  // component constructor - required syntax for UVM automation and utilities
  function new (string name, uvm_component parent);
    super.new(name, parent);
    item_collected_port = new("item_collected_port",this);
  endfunction : new

  function void connect_phase(uvm_phase phase);
    if (!apb_vif_config::get(this, get_full_name(),"vif", vif))
      `uvm_error("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
  endfunction: connect_phase

  // UVM run() phase
  task run_phase(uvm_phase phase);
    // Look for packets after reset
    @(negedge vif.reset)
    @(posedge vif.reset)
    `uvm_info(get_type_name(), "Detected Reset Done", UVM_MEDIUM)
    forever begin 
      // Create collected packet instance
      pkt = apb_packet::type_id::create("pkt", this);

       fork
        // collect packet
        vif.collect_packet( pkt.paddr, pkt.pwdata, pkt.pwrite, pkt.prdata);
        // trigger transaction at start of packet
     //@(posedge vif.monstart) void'(begin_tr(pkt, "Monitor_APB_Packet"));
        void'(begin_tr(pkt, "Monitor_APB_Packet"));
      join

      // End transaction recording
      end_tr(pkt);
      `uvm_info(get_type_name(), $sformatf("Packet Collected :\n%s", pkt.sprint()), UVM_LOW)
      num_pkt_col++;
      item_collected_port.write(pkt);
    end
  endtask : run_phase

  // UVM report_phase
  function void report_phase(uvm_phase phase);
    `uvm_info(get_type_name(), $sformatf("Report: APB Monitor Collected %0d Packets", num_pkt_col), UVM_LOW)
  endfunction : report_phase

endclass : apb_monitor



interface apb_if (input clock, input reset );
timeunit 1ns;
timeprecision 100ps;

import uvm_pkg::*;
`include "uvm_macros.svh"

import apb_pkg::*;


  logic [3:0] paddr_if;
  logic psel_if;
  logic penable_if;
  logic pwrite_if;
  logic [31:0] pwdata_if;
  logic [31:0] prdata_if;


  // signal for transaction recording
 // bit monstart, drvstart;
  
  task apb_reset();
    @(negedge reset);
    paddr_if    <=  4'h0;
    psel_if     <= 1'b0;  
    penable_if  <= 1'b0;
    pwrite_if  <= 1'b0;
    pwdata_if  <= 32'b0;
    disable send_to_dut;
  endtask
  
  // Gets a packet and drive it into the DUT
  task send_to_dut(input bit [3:0]   paddr,
                         bit [31:0]  pwdata,
                         bit         pwrite);
                        // int packet_delay);
    // Wait for packet delay
    //repeat(packet_delay)
    @(posedge clock);
      `uvm_info("apb_if", "Send packets", UVM_LOW) 
       paddr_if <= paddr;
       pwrite_if <= pwrite;
       psel_if <= 1'b1; 
       pwdata_if <=  pwdata;

    @(posedge clock);
      penable_if <= 1'b1;

    @(posedge clock);
      psel_if <= 1'b0; 
      penable_if <= 1'b0;


  endtask : send_to_dut

  // Collect Packets
  task collect_packet(output bit [3:0]   paddr,
                         bit [31:0]      pwdata,
                         bit             pwrite,
                         bit [31:0]      prdata );
      
    @(posedge clock iff (penable_if && psel_if))
      // trigger for transaction recording
      `uvm_info("apb_if", "collect packets", UVM_LOW)
       pwrite = pwrite_if;

       if (pwrite_if == 1) begin
        pwdata = pwdata_if;
        paddr  = paddr_if;
       // prdata = 32'dx;;
       end
       else if(pwrite_if ==0)
        begin
          prdata = prdata_if;
         // pwdata = 32'bx;
        end
endtask : collect_packet
endinterface : apb_if



// using type parameterized driver which defines built-in yapp_packet handle req 
class apb_master_driver extends uvm_driver #(apb_packet);

  // Declare this property to count packets sent
  int num_sent;

  virtual interface apb_if vif;

  // component macro
  `uvm_component_utils_begin(apb_master_driver)
    `uvm_field_int(num_sent, UVM_ALL_ON)
  `uvm_component_utils_end

  // Constructor - required syntax for UVM automation and utilities
  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new

  function void connect_phase(uvm_phase phase);
    if (!apb_vif_config::get(this,"","vif", vif))
      `uvm_error("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
  endfunction: connect_phase

  // start_of_simulation 
  function void start_of_simulation_phase(uvm_phase phase);
    `uvm_info(get_type_name(), {"start of simulation for ", get_full_name()}, UVM_HIGH) 
  endfunction : start_of_simulation_phase

  // UVM run_phase
  task run_phase(uvm_phase phase);
    fork
      get_and_drive();
      reset_signals();
    join
  endtask : run_phase

  // Gets packets from the sequencer and passes them to the driver. 
  task get_and_drive();
    @(negedge vif.reset);
    @(posedge vif.reset);
    `uvm_info(get_type_name(), "Reset dropped", UVM_MEDIUM)
    forever begin
      // Get new item from the sequencer
      seq_item_port.get_next_item(req);

      `uvm_info(get_type_name(), $sformatf("Sending Packet :\n%s", req.sprint()), UVM_HIGH)
       
      fork
        // send packet
        begin
        vif.send_to_dut(req.paddr, req.pwdata,req.pwrite);//req.packet_delay);
        end
        // trigger transaction at start of packet (trigger signal from interface)
       // @(negedge vif.drvstart) void'(begin_tr(req, "Driver_APB_Packet"));
       void'(begin_tr(req, "Driver_APB_Packet"));

      join

      // End transaction recording
      end_tr(req);
      num_sent++;
      // Communicate item done to the sequencer
      seq_item_port.item_done();
    end
  endtask : get_and_drive

  // Reset all TX signals
  task reset_signals();
    forever 
     vif.apb_reset();
  endtask : reset_signals

  // UVM report_phase
  function void report_phase(uvm_phase phase);
    `uvm_info(get_type_name(), $sformatf("Report: APB TX driver sent %0d packets", num_sent), UVM_LOW)
  endfunction : report_phase
endclass : apb_master_driver

class apb_packet extends uvm_sequence_item;     

  // Physical Data
  rand bit [31:0]  pwdata;
  rand bit [3:0]  paddr;
  rand bit        pwrite ;
  bit   [31:0]  prdata;

 // rand int packet_delay;
 

  // UVM macros for built-in automation - These declarations enable automation
  // of the data_item fields 
  `uvm_object_utils_begin(apb_packet)
    `uvm_field_int(pwdata,          UVM_ALL_ON)
    `uvm_field_int(paddr,           UVM_ALL_ON)
    `uvm_field_int(pwrite,         UVM_ALL_ON)
    `uvm_field_int(prdata,         UVM_ALL_ON)
   // `uvm_field_int(packet_delay, UVM_ALL_ON | UVM_DEC | UVM_NOCOMPARE)
    `uvm_object_utils_end

  // Constructor - required syntax for UVM automation and utilities
  function new (string name = "apb_item");
    super.new(name);
  endfunction : new

    constraint default_addr{ paddr == 4'h8; }
   // constraint default_delay  { packet_delay >= 0; packet_delay < 20; }

  endclass: apb_packet








In reply to Tzvi_V:

It’s going to be hard to help you without seeing all the code necessary to run your example. It would also help to explain what is going wrong versus what you expected to see happen if it were executed correctly.

In reply to dave_59:

You can see at the image (in the link) that driver and monitor working on same time .
I want to collect my packet after the driver - on rising clock and with penable and psel is 1,
what didn’t happens unfortunately.

Also it seems that monitor trying to collect another packet (long “pkt” in image) and I dont want this .

I attaching the following code :

class apb_master_sequence_lib extends uvm_sequence#(apb_packet);

// Required macro for sequences automation
`uvm_object_utils(apb_master_sequence_lib)

// Constructor
function new(string name=“apb_master_sequence_lib”);
super.new(name);
// option in UVM1.2 to handle objections automatically
//set_automatic_phase_objection (1);
endfunction

task pre_body();
uvm_phase phase;
ifdef UVM_VERSION_1_2 // in UVM1.2, get starting phase from method phase = get_starting_phase(); else
phase = starting_phase;
endif if (phase != null) begin phase.raise_objection(this, get_type_name()); uvm_info(get_type_name(), “raise objection”, UVM_MEDIUM)
end
endtask : pre_body

task post_body();
uvm_phase phase;
ifdef UVM_VERSION_1_2 // in UVM1.2, get starting phase from method phase = get_starting_phase(); else
phase = starting_phase;
endif if (phase != null) begin phase.drop_objection(this, get_type_name()); uvm_info(get_type_name(), “drop objection”, UVM_MEDIUM)
end
endtask : post_body

endclass :apb_master_sequence_lib
//////////////////////////////////////////////

class apb_8_items extends apb_master_sequence_lib;
int ok;

// Required macro for sequences automation
`uvm_object_utils(apb_8_items)

// Constructor
function new(string name=“apb_8_items”);
super.new(name);
endfunction

// Sequence body definition
virtual task body();
uvm_info(get_type_name(), "Executing apb_8_items sequence", UVM_LOW) repeat(3) begin uvm_do_with(req,{req.pwrite == 1’b1;})
end
endtask

endclass : apb_8_items

class apb_master_sequencer extends uvm_sequencer #(apb_packet);

apb_packet packet;

`uvm_component_utils(apb_master_sequencer)

function new(string name, uvm_component parent);
super.new(name, parent); // important!!
endfunction

// start_of_simulation
function void start_of_simulation_phase(uvm_phase phase);
`uvm_info(get_type_name(), {"start of simulation for ", get_full_name()}, UVM_HIGH)
endfunction : start_of_simulation_phase

endclass : apb_master_sequencer

class apb_trans_env extends uvm_env;

// Components of the environment
apb_agent agent;

// component macro
`uvm_component_utils(apb_trans_env)

// component constructor
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new

// UVM build_phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent = apb_agent::type_id::create(“agent”, this);
endfunction : build_phase

// start_of_simulation
function void start_of_simulation_phase(uvm_phase phase);
`uvm_info(get_type_name(), {"start of simulation for ", get_full_name()}, UVM_HIGH)
endfunction : start_of_simulation_phase

endclass : apb_trans_env

class apb_agent extends uvm_agent;

// predeclared field inherited from uvm_agent determines whether an agent is active or passive.
// uvm_active_passive_enum is_active = UVM_ACTIVE; // This field determines whether an agent is active or passive.

apb_monitor monitor;
apb_master_sequencer sequencer;
apb_master_driver driver;

// component macro
uvm_component_utils_begin(apb_agent) uvm_field_enum(uvm_active_passive_enum, is_active, UVM_ALL_ON)
`uvm_component_utils_end

// Constructor - required syntax for UVM automation and utilities
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new

// UVM build_phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
monitor = apb_monitor::type_id::create(“monitor”, this);
if(is_active == UVM_ACTIVE) begin
sequencer = apb_master_sequencer::type_id::create(“sequencer”, this);
driver = apb_master_driver::type_id::create(“driver”, this);
end
endfunction : build_phase

// UVM connect_phase
function void connect_phase(uvm_phase phase);
if(is_active == UVM_ACTIVE)
// connect the driver to the sequencer
driver.seq_item_port.connect(sequencer.seq_item_export);
endfunction : connect_phase

// start_of_simulation
function void start_of_simulation_phase(uvm_phase phase);
`uvm_info(get_type_name(), {"start of simulation for ", get_full_name()}, UVM_HIGH)
endfunction : start_of_simulation_phase

// Assign the virtual interfaces of the agent’s children
function void assign_vi(virtual interface apb_if vif);
monitor.vif = vif;
if (is_active == UVM_ACTIVE)
driver.vif = vif;
endfunction : assign_vi

endclass : apb_agent

class base_test extends uvm_test;

// component macro
`uvm_component_utils(base_test)

// Components of the environment
router_tb tb;

// component constructor
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new

// UVM build_phase()
function void build_phase(uvm_phase phase);
uvm_config_int::set( this, “*”, “recording_detail”, 1);
super.build_phase(phase);
tb = router_tb::type_id::create(“tb”,this);
endfunction : build_phase

function void end_of_elaboration_phase(uvm_phase phase);
uvm_top.print_topology();
endfunction : end_of_elaboration_phase

function void start_of_simulation_phase(uvm_phase phase);
`uvm_info(get_type_name(), {"start of simulation for ", get_full_name()}, UVM_HIGH);
endfunction : start_of_simulation_phase

task run_phase(uvm_phase phase);
uvm_objection obj = phase.get_objection();
obj.set_drain_time(this, 200ns);
endtask : run_phase

function void check_phase(uvm_phase phase);
// configuration checker
check_config_usage();
endfunction

endclass : base_test

////////////////////////////////////////////
class short_packet_test extends base_test;

// component macro
`uvm_component_utils(short_packet_test)

// component constructor
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new

function void build_phase(uvm_phase phase);
// apb_item::type_id::set_type_override(short_yapp_packet::get_type());
uvm_config_wrapper::set(this, “tb.apb.agent.sequencer.run_phase”,
“default_sequence”,
apb_8_items ::get_type());
super.build_phase(phase);
endfunction : build_phase

endclass : short_packet_test

module hw_top;

// Clock and reset signals
//logic [31:0] clock_period;
// logic run_clock;
bit clock;
bit reset;

//reset Generation
initial begin
reset = 1;
#50 reset =0;
#50 reset =1;
end

//clock generation

always #10 clock = ~clock;

// YAPP Interface to the DUT
apb_if in0(clock, reset);

// CLKGEN module generates clock
//clkgen clkgen (
// .clock(clock ),
// .run_clock(1’b1),
// .clock_period(32’d10)
// );

//DUT instance, interface signals are connected to the DUT ports
apb_transceiver DUT (
.pclk(clock),
.presetn(reset),
.psel(in0.psel_if),
.penable(in0.penable_if),
.pwrite(in0.pwrite_if),
.paddr(in0.paddr_if),
.pwdata(in0.pwdata_if),
.prdata(in0.prdata_if),
.tx_data(),
.tx_valid(),
.tx_halt(1’b0),
.rx_data(),
.rx_valid(),
.rx_halt()
);

initial begin
//clock <= 0;

//reset <= 1'b1;
//@(negedge clock)
  //#1 reset <= 1'b0;
//@(negedge clock)
//  #1 reset <= 1'b1;

end

endmodule