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