Query about seq_item_port.get_next_item (req);

I am trying to learn UVM by writing a wishbone master.
My test finishes without executing “seq_item_port.get_next_item (req);” and consequently “get_and_drive()” in the driver class.
The test case does not hang; it just doesn’t do anything that is coded in the driver class.
How do I fix this?
Thanks!


class wb_driver extends uvm_driver #(wb_transaction);

    protected virtual wb_if vif;

    `uvm_component_utils (wb_driver)

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

    function void build_phase (uvm_phase phase);

        super.build_phase(phase);
        if(!uvm_config_db#(virtual wb_if)::get(this, "", "vif", vif))
            `uvm_fatal("NOVIF",{"virtual interface must be set for: ",                            get_full_name(),".vif"});

    endfunction: build_phase

    virtual task run_phase (uvm_phase phase);
        get_and_drive ();
    endtask : run_phase

    // get_and_drive
    virtual protected task get_and_drive ();
		@ (posedge vif.arst);
        @ (posedge vif.ref_clk);
	forever begin
            seq_item_port.get_next_item (req);
            drive_transfer (req);
            seq_item_port.item_done ();
        end
    endtask : get_and_drive

	// drive_transfer
    virtual protected task drive_transfer (wb_transaction trans);
        // write
        if (trans.we == 1) begin
            @ (posedge vif.ref_clk);
	        vif.we 		<= 1'b1;
	        vif.adr 	<= trans.adr;
	        vif.cyc 	<= 1'b1;
	        vif.stb 	<= 1'b1;
	        vif.dout 	<= trans.dout;
            @ (posedge vif.ref_clk);
	        while (vif.ack == 0) @ (posedge vif.ref_clk)
	        vif.we 		<= 1'bx;
	        vif.adr 	<= 'hx;
	        vif.cyc 	<= 1'b0;
	        vif.stb 	<= 1'bx;
	        vif.dout 	<= 'hx;
	    end 
        // read
	    else if (trans.we == 0) begin
          @ (posedge vif.ref_clk);
	        vif.we 		<= 1'b0;
	        vif.adr 	<= trans.adr;
	        vif.cyc 	<= 1'b1;
	        vif.stb 	<= 1'b1;
            @ (posedge vif.ref_clk);
	        while (vif.ack == 0) @ (posedge vif.ref_clk)
	        vif.we 		<= 1'bx;
	        vif.adr 	<= 'hx;
	        vif.cyc 	<= 1'b0;
	        vif.stb 	<= 1'bx;
	        vif.dout 	<= 'hx;
	        trans.din 		<= vif.din;
	    end
    endtask : drive_transfer

endclass: wb_driver
class wb_sequencer extends uvm_sequencer# (wb_transaction);

    `uvm_component_utils (wb_sequencer)

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

endclass: wb_sequencer
class wb_transaction extends uvm_sequence_item;

    `uvm_object_utils (wb_transaction)

    typedef enum {READ=1, WRITE=0} read_write_enum;
    rand read_write_enum read_write;
    rand bit [7:0] adr;
    rand bit [7:0] dout;
    rand bit [7:0] sel;
    rand bit cyc;
    rand bit stb;
    rand bit we;
    bit [7:0] din;
    bit  ack;
    bit  err;
    bit  rty;

    constraint we_c 
    { 
        (read_write == WRITE) -> (we == 1);
	    (read_write == READ)  -> (we == 0);
    }

    // constructor
    function new (string name = "wb_transaction");
        super.new (name);
	    sel = 0;
    endfunction: new

    function void do_copy (uvm_object rhs);
 
        wb_transaction rhs_;
 
        if (!$cast(rhs_, rhs)) begin
            uvm_report_error("do_copy:", "Cast failed");
            return;
        end

        super.do_copy (rhs);

        read_write 	= rhs_.read_write ;
        adr 	= rhs_.adr;
        dout 	= rhs_.dout;
        sel 	= rhs_.sel;
        cyc 	= rhs_.cyc;
        stb 	= rhs_.stb;
        we 		= rhs_.we;
        din 	= rhs_.din;
        ack 	= rhs_.ack;
        err 	= rhs_.err;
        rty 	= rhs_.rty;
     
    endfunction: do_copy

    function bit do_compare (uvm_object rhs, uvm_comparer comparer);

        wb_transaction rhs_;
 
        if(!$cast(rhs_, rhs)) begin
            return 0;
        end 

		if (!super.do_compare (rhs, comparer)) begin
	    	return 0;
		end

    endfunction: do_compare

    function string convert2string ();
        string s;
 
        s = super.convert2string();
        $sformat(s, "%s\n read_write \t%0d\n adr \t%0h\n dout \t%0h\n din \t%0h\n we \t%0h\n cyc \t%0h\n stb \t%0h\n", s, read_write, adr, dout, din, we, cyc, stb);
        return s;
    endfunction: convert2string

    function void do_print (uvm_printer printer);
        if (printer.knobs.sprint == 0) begin
            $display (convert2string());
        end
        else begin
            printer.m_string = convert2string();
        end 
    endfunction: do_print

endclass: wb_transaction
`ifndef WB_TB_SV
`define WB_TB_SV

`include "wb_seq_lib.sv"

class wb_tb extends uvm_env;

    `uvm_component_utils (wb_tb)

    wb_env wb_env0;

    function new (string name, uvm_component parent=null);
      super.new (name, parent);
    endfunction : new

    virtual function void build_phase (uvm_phase phase);
        super.build_phase (phase);
        wb_env0 = wb_env::type_id::create ("wb_env0", this);
    endfunction : build_phase

endclass : wb_tb

`endif
`include "wb_tb.sv"

class wb_base_test extends uvm_test;

    `uvm_component_utils (wb_base_test)

    wb_tb wb_tb0;
    uvm_table_printer printer;

    function new (string name = "wb_base_test",                                   uvm_component parent=null);
        super.new (name,parent);
    endfunction : new

    virtual function void build_phase (uvm_phase phase);
        super.build_phase (phase);

        uvm_config_db#(int)::set(this, "*", "recording_detail", UVM_FULL);
        wb_tb0 = wb_tb::type_id::create("wb_tb0", this);

        printer = new ();
        printer.knobs.depth = 3;
    endfunction : build_phase

    function void end_of_elaboration_phase (uvm_phase phase);
        `uvm_info(get_type_name(),
        $psprintf ("Printing the test topology :\n%s", this.sprint(printer)), UVM_LOW)
    endfunction : end_of_elaboration_phase

    task run_phase (uvm_phase phase);
	    super.run_phase(phase);
    endtask : run_phase

endclass : wb_base_test

class test_write extends wb_base_test;

    `uvm_component_utils (test_write)

    function new (string name = "test_write", uvm_component parent=null);
        super.new (name,parent);
    endfunction : new

    virtual function void build_phase (uvm_phase phase);
		uvm_config_db# (uvm_object_wrapper)::set(this,                            "wb_tb0.wb_env0.sequencer.run_phase",                                         "default_sequence",                                                       write_seq::type_id::get());

        super.build_phase (phase);
    endfunction : build_phase

   local bit once = 1;
   task main_phase(uvm_phase phase);
      if (once) begin
         once = 0;
         phase.raise_objection (this);
		 #1us;
         phase.drop_objection (this);
      end
   endtask

endclass : test_write
virtual class wb_base_sequence extends uvm_sequence #(wb_transaction);

    function new (string name="wb_base_seq");
        super.new (name);
    endfunction
  
    virtual task pre_body ();
        if (starting_phase!=null) begin
            `uvm_info(get_type_name(),
		            $sformatf("%s pre_body() raising %s objection", 
			        get_sequence_path(),
			        starting_phase.get_name()), UVM_MEDIUM);

            starting_phase.raise_objection(this);
		end
    endtask

    virtual task post_body ();
        if (starting_phase!=null) begin
            `uvm_info(get_type_name(),
		            $sformatf("%s post_body() dropping %s objection", 
			        get_sequence_path(),
			        starting_phase.get_name()), UVM_MEDIUM);

            starting_phase.drop_objection(this);
    end
    endtask
  
endclass: wb_base_sequence

class write_seq extends wb_base_sequence;

    function new (string name="write_seq");
        super.new (name);
    endfunction

    `uvm_object_utils (write_seq)
    
    virtual task body ();
        repeat (1) begin
            //`uvm_create (req)
            //`uvm_rand_send_with (req, {req.we == 1;})
            `uvm_do_with(req, {req.we == 1;})
  	    end
    endtask

endclass: write_seq
package wb_pkg;

   import uvm_pkg::*;

`include "uvm_macros.svh"

   typedef uvm_config_db#(virtual wb_if) wb_vif_config;
   typedef virtual wb_if wb_vif;

`include "wb_transaction.sv"

`include "wb_sequencer.sv"
`include "wb_driver.sv"
`include "wb_agent.sv"

`include "wb_env.sv"

endpackage: wb_pkg
interface wb_if;

 logic ref_clk;
 logic rst;
 logic[2:0] adr;
 logic[7:0] din;
 logic[7:0] dout;
 logic      cyc;
 logic      stb;
 logic      we;
 logic[7:0] sel;
 logic      ack;
 logic      inta;

 logic arst;

endinterface: wb_if
class wb_env extends uvm_env;

    `uvm_component_utils (wb_env)

    wb_agent wb_agent0;

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

    function void build_phase (uvm_phase phase);

        string inst_name;
        super.build_phase (phase);
        wb_agent0 = wb_agent::type_id::create (inst_name, this);

    endfunction : build_phase

endclass: wb_env
class wb_agent extends uvm_agent;

    protected uvm_active_passive_enum is_active = UVM_ACTIVE;

    `uvm_component_utils (wb_agent)

    wb_driver driver;
    wb_sequencer sequencer;

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

    function void build_phase (uvm_phase phase);
        super.build_phase (phase);
        if (get_is_active() == UVM_ACTIVE) begin
            sequencer = wb_sequencer::type_id::create("sequencer", this);
            driver    = wb_driver::type_id::create("driver", this);
        end
    endfunction: build_phase

    function void connect_phase (uvm_phase phase);
        if (is_active == UVM_ACTIVE) begin
            driver.seq_item_port.connect (sequencer.seq_item_export);
        end
    endfunction : connect_phase

endclass : wb_agent
`include "wb_pkg.sv"
`include "i2c_master_top.v"
`include "i2c_if.sv"
`include "wb_if.sv"

module i2c_tb_top; 
  import uvm_pkg::*;
  import wb_pkg::*;
  `include "wb_test_lib.sv"

  wb_if vif();
  i2c_if i2c_if0(vif.ref_clk);

i2c_master_top i2c_top (

	// wishbone interface
	.wb_clk_i 	(vif.ref_clk),
	.wb_rst_i 	(1'b0),
	.arst_i 	(vif.arst),
	.wb_adr_i 	(vif.adr[2:0]),
	.wb_dat_i 	(vif.dout [7:0]),
	.wb_dat_o 	(vif.din [7:0]),
	.wb_we_i 	(vif.we),
	.wb_stb_i 	(vif.stb),
	.wb_cyc_i 	(vif.cyc),
	.wb_ack_o 	(vif.ack),
	.wb_inta_o 	(vif.inta),

	// i2c signals
	.scl_pad_i 	    (i2c_if0.scl),
	.scl_pad_o 	    (i2c_if0.scl0_o),
	.scl_padoen_o 	(i2c_if0.scl0_oen),
	.sda_pad_i 	    (i2c_if0.sda),
	.sda_pad_o 	    (i2c_if0.sda0_o),
	.sda_padoen_o 	(i2c_if0.sda0_oen)
);

initial begin
    uvm_config_db#(virtual wb_if)::set(uvm_root::get(), "*", "vif", vif);
    run_test ();
end

initial begin
    vif.ref_clk <= 1'b1;
    vif.arst <= 1'b1;
    vif.we <= 1'b0;
    vif.cyc <= 1'b0;
    vif.stb <= 1'b0;
    vif.dout <= 8'h0;
    vif.adr <= 3'h0;
    #20;
    vif.arst = 1'b0;
    @(posedge vif.ref_clk);
    vif.arst = 1'b1;
end

always 
    #50 vif.ref_clk <= ~vif.ref_clk;

initial begin
      $vcdpluson (0, i2c_tb_top);
end

endmodule

I don’t see anywhere in your code where you start any sequences.

For instance, in the run_phase() of your write_test you need some code like this:

task run_phase(uvm_phase phase); seq = ::type_id::create("seq");

phase.raise_objection(this);
seq.start(wb_tb0.wb_env0.wb_agent0.sequencer);
phase.drop_objection(this);
endtask: run_phase

Hi mperyer,
Thanks!