Error message : can not find the member in the class

Hi all
i am a beginner in uvm. please correct me if the testbench is wrong or there is better solution
the error message is (Error-[MFNF] Member not found
driver.sv,
“this.req.”
Could not find member ‘addr’ in class ‘uvm_sequence_item’ ) while running vcs

i am confused with the error, because addr is defined in the class mem_seq_item.

here is my code.

class mem_seq_item extends uvm_sequence_item;
  //data and control fields
  rand bit [3:0] addr;
  rand bit       wr_en;
  rand bit       rd_en;
  rand bit [7:0] wdata;
       bit [7:0] rdata;
   
  //Utility and Field macros,
  `uvm_object_utils_begin(mem_seq_item)
    `uvm_field_int(addr,UVM_ALL_ON)
    `uvm_field_int(wr_en,UVM_ALL_ON)
    `uvm_field_int(rd_en,UVM_ALL_ON)
    `uvm_field_int(wdata,UVM_ALL_ON)
  `uvm_object_utils_end
   
  //Constructor
  function new(string name = "mem_seq_item");
    super.new(name);
  endfunction
   
  //constaint, to generate any one among write and read
  constraint wr_rd_c { wr_en != rd_en; };
   
endclass


class mem_sequencer extends uvm_sequencer#(mem_seq_item);
 
  `uvm_component_utils(mem_sequencer)
 
  //constructor
  function new(string name, uvm_component parent);
    super.new(name,parent);
  endfunction
   
endclass


Calling of build phase




class mem_sequence extends uvm_sequence#(mem_seq_item);
   
  `uvm_object_utils(mem_sequence )
  //`uvm_sequence_utils(mem_sequence,mem_sequencer)
   
  //Constructor
  function new(string name = "mem_sequence");
    super.new(name);
  endfunction
   
//   virtual function void build_phase(uvm_phase phase)
//   
//       req = mem_seq_item::type_id::create("req");
//   
//   endfunction
   
   
  virtual task body();
 
   req = mem_seq_item::type_id::create("req");
   // wait_for_grant();
    req.randomize();
    send_request(req);
  //  wait_for_item_done();
 
  endtask
   
endclass



`define DRIV_IF pointer_to_interface.DRIVER.driver_cb
class mem_driver extends uvm_driver;
   `uvm_component_utils(mem_driver);

 virtual mem_if pointer_to_interface;
   
 function new (string name, uvm_component parent);
      super.new(name,parent);

 endfunction : new

 virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    
	if(!uvm_config_db #(virtual mem_if)::get(null, "*","pointer_to_interface", pointer_to_interface))
        $fatal("Failed to get BFM");
		
 endfunction : build_phase
   
   
   
   
 task run_phase(uvm_phase phase);

      phase.raise_objection(this);
    forever begin
        seq_item_port.get_next_item(req);
      drive();
        seq_item_port.item_done();
    end

      phase.drop_objection(this);
 endtask : run_phase

   
  virtual task drive();
    `DRIV_IF.wr_en <= 0;
    `DRIV_IF.rd_en <= 0;
    @(posedge pointer_to_interface.DRIVER.clk);
        `DRIV_IF.addr <= req.addr;
   
     if(req.wr_en) begin
        `DRIV_IF.wr_en <= req.wr_en;
        `DRIV_IF.wdata <= req.wdata;
        @(posedge vif.DRIVER.clk);
      end
    if(req.rd_en) begin
        `DRIV_IF.rd_en <= req.rd_en;
        @(posedge vif.DRIVER.clk);
        `DRIV_IF.rd_en <= 0;
        @(posedge vif.DRIVER.clk);
        req.rdata = `DRIV_IF.rdata;
      end
    
  endtask : drive
  
endclass
   






class mem_agent extends uvm_agent;
  //declaring agent components
  mem_driver    driver;
  mem_sequencer sequencer;
  //mem_monitor   monitor;
 
  // UVM automation macros for general components
  `uvm_component_utils(mem_agent)
 
  // constructor
  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new
 
  // build_phase
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
 
      driver = mem_driver::type_id::create("driver", this);
      sequencer = mem_sequencer::type_id::create("sequencer", this);

 
  endfunction : build_phase
 
  // connect_phase
  function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      driver.seq_item_port.connect(sequencer.seq_item_export);

  endfunction : connect_phase
 
endclass : mem_agent












class mem_model_test extends uvm_test;
 
  `uvm_component_utils(mem_model_test)
 
  mem_agent agent;
  mem_sequence  seq;
 
  function new(string name = "mem_model_test",uvm_component parent=null);
    super.new(name,parent);
  endfunction : new
 
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
 
    agent = mem_agent::type_id::create("agent", this);
    seq = mem_sequence::type_id::create("seq",this);
  endfunction : build_phase
 
  task run_phase(uvm_phase phase);
  phase.raise_objection(this);
 // seq.start(env.mem_agnt.sequencer);
    phase.drop_objection(this);
  endtask : run_phase
 
endclass : mem_model_test

interface mem_if(input logic clk,reset);
  
  //---------------------------------------
  //declaring the signals
  //---------------------------------------
  logic [1:0] addr;
  logic wr_en;
  logic rd_en;
  logic [7:0] wdata;
  logic [7:0] rdata;
  
  //---------------------------------------
  //driver clocking block
  //---------------------------------------
  clocking driver_cb @(posedge clk);
    default input #1 output #1;
    output addr;
    output wr_en;
    output rd_en;
    output wdata;
    input  rdata;  
  endclocking
  
  //---------------------------------------
  //monitor clocking block
  //---------------------------------------
  clocking monitor_cb @(posedge clk);
    default input #1 output #1;
    input addr;
    input wr_en;
    input rd_en;
    input wdata;
    input rdata;  
  endclocking
  
  //---------------------------------------
  //driver modport
  //---------------------------------------
  modport DRIVER  (clocking driver_cb,input clk,reset);
  
  //---------------------------------------
  //monitor modport  
  //---------------------------------------
  modport MONITOR (clocking monitor_cb,input clk,reset);
  
endinterface


module memory
  #( parameter ADDR_WIDTH = 2,
     parameter DATA_WIDTH = 8 ) (
    input clk,
    input reset,
    
    //control signals
    input [ADDR_WIDTH-1:0]  addr,
    input                   wr_en,
    input                   rd_en,
    
    //data signals
    input  [DATA_WIDTH-1:0] wdata,
    output [DATA_WIDTH-1:0] rdata
  ); 
  
  reg [DATA_WIDTH-1:0] rdata;
  
  //Memory
  reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH];

  //Reset 
  always @(posedge reset) 
    for(int i=0;i<2**ADDR_WIDTH;i++) mem[i]=8'hFF;
   
  // Write data to Memory
  always @(posedge clk) 
    if (wr_en)    mem[addr] <= wdata;

  // Read data from memory
  always @(posedge clk)
    if (rd_en) rdata <= mem[addr];

endmodule


module tbench_top;

  //---------------------------------------
  //clock and reset signal declaration
  //---------------------------------------
  bit clk;
  bit reset;
  
  //---------------------------------------
  //clock generation
  //---------------------------------------
  always #5 clk = ~clk;
  
  //---------------------------------------
  //reset Generation
  //---------------------------------------
  initial begin
    reset = 1;
    #5 reset =0;
  end
  
  //---------------------------------------
  //interface instance
  //---------------------------------------
  mem_if intf(clk,reset);
  
  //---------------------------------------
  //DUT instance
  //---------------------------------------
  memory DUT (
    .clk(intf.clk),
    .reset(intf.reset),
    .addr(intf.addr),
    .wr_en(intf.wr_en),
    .rd_en(intf.rd_en),
    .wdata(intf.wdata),
    .rdata(intf.rdata)
   );
  
  //---------------------------------------
  //passing the interface handle to lower heirarchy using set method 
  //and enabling the wave dump
  //---------------------------------------
  initial begin 
    uvm_config_db#(virtual mem_if)::set(uvm_root::get(),"*","pointer_to_interface",intf);
    //enable wave dump
    //$dumpfile("dump.vcd"); 
   // $dumpvars;
  end
  
  //---------------------------------------
  //calling test
  //---------------------------------------
  initial begin 
    run_test();
  end
  
endmodule


In reply to peter:

Your problem is you extended uvm_driver without specifying a parameter (mem_seq_item) for REQ.

In reply to dave_59:

In reply to peter:
Your problem is you extended uvm_driver without specifying a parameter (mem_seq_item) for REQ.

Thanks Dave, i fixed the code. it worked! But , addr ,wr_en, rd_en, wdata ,rdata are unknown,
i used req.randomize() in body task. why the addr,wr_en, rd_en, wdata ,rdata can not be randomized?
Here is new driver code


 `define DRIV_IF pointer_to_interface.DRIVER.driver_cb
class mem_driver extends uvm_driver #(mem_seq_item);
   `uvm_component_utils(mem_driver);

 virtual mem_if pointer_to_interface;
   
 function new (string name, uvm_component parent);
      super.new(name,parent);

 endfunction : new

 virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    
	if(!uvm_config_db #(virtual mem_if)::get(null, "*","pointer_to_interface", pointer_to_interface))
        $fatal("Failed to get BFM");
		
 endfunction : build_phase
   

 task run_phase(uvm_phase phase);

      phase.raise_objection(this);
    forever begin
        seq_item_port.get_next_item(req);
      drive();
        seq_item_port.item_done();
    end

      phase.drop_objection(this);
 endtask : run_phase

   
  virtual task drive();
    `DRIV_IF.wr_en <= 0;
    `DRIV_IF.rd_en <= 0;
    @(posedge pointer_to_interface.DRIVER.clk);
        `DRIV_IF.addr <= req.addr;
      if(req.wr_en) begin
        `DRIV_IF.wr_en <= req.wr_en;
        `DRIV_IF.wdata <= req.wdata;

    @(posedge pointer_to_interface.DRIVER.clk);
      //end
    if(req.rd_en) begin
        `DRIV_IF.rd_en <= req.rd_en;
    @(posedge pointer_to_interface.DRIVER.clk);
       `DRIV_IF.rd_en <= 0;
    @(posedge pointer_to_interface.DRIVER.clk);
        req.rdata = `DRIV_IF.rdata;
      end   
  endtask : drive  
endclass

In reply to peter:

Are you sure

seq_item_port.get_next_item(req);

is completing, i.e. get a req?

Could you please show your sequence code?
BTW the connection to the virtual interface should be made in the connect_phase.

In reply to chr_sue:

In reply to peter:
Are you sure

seq_item_port.get_next_item(req);

is completing, i.e. get a req?
Could you please show your sequence code?
BTW the connection to the virtual interface should be made in the connect_phase.

Hi chr_sue. why virtual interface should be made in the connect_phase? thanks!
here is sequence code

 
class mem_sequence extends uvm_sequence#(mem_seq_item);
 
  `uvm_object_utils(mem_sequence )
  //`uvm_sequence_utils(mem_sequence,mem_sequencer)
 
  //Constructor
  function new(string name = "mem_sequence");
    super.new(name);
  endfunction
 

 
  virtual task body();
 
   req = mem_seq_item::type_id::create("req");
   // wait_for_grant();
    req.randomize();
    send_request(req);
  //  wait_for_item_done();
 
  endtask
 
endclass

In reply to peter:

Your body task is incomplete. It should look like this:

 virtual task body();
   req = mem_seq_item::type_id::create("req");
   start_item(req);
   void'(req.randomize());
   finish_item(req); 
  endtask

In reply to chr_sue:

Hi ,
i find that task body() is not executed, so req is always null . But, why my task body is not executed?

In reply to peter:
It looks like you did not implement the interface between your driver and the sequencer correctly. Did you modify the body task as I was proposing?

In reply to chr_sue:

In reply to peter:
It looks like you did not implement the interface between your driver and the sequencer correctly. Did you modify the body task as I was proposing?

Yes , i modified the body task which you suggest. But , it did not work
the addr ,wr_en,rd_en etc still are unknown.
I dont know why The task body is not executed
here is task body code

 
 virtual task body();
   mem_seq_item  req;
   req = mem_seq_item::type_id::create("req");
   start_item(req);
   req.randomize();
   finish_item(req); 
  endtask

Thanks

@peter:

when you say "the addr ,wr_en,rd_en etc still are unknown. ", is it for every clock? only when driver drives it? always? did you print the req in the “drive” task?

also , please always make sure you use the same clocking block clk , which you are using to drive the signals.
try updating the “drive” task to this.

  virtual task drive();
    `DRIV_IF.wr_en <= 0;
    `DRIV_IF.rd_en <= 0;
    @(`DRIV_IF);
        `DRIV_IF.addr <= req.addr;
      if(req.wr_en) begin
        `DRIV_IF.wr_en <= req.wr_en;
        `DRIV_IF.wdata <= req.wdata;
      end
    @(`DRIV_IF);
      //end
    if(req.rd_en) begin
        `DRIV_IF.rd_en <= req.rd_en;
    @(`DRIV_IF);
       `DRIV_IF.rd_en <= 0;
    @(`DRIV_IF);
        req.rdata = `DRIV_IF.rdata;
      end   
  endtask : drive  

In reply to peter:

  1. Did you start your sequence in your test with specific sequencer?
  2. In driver, raise/drop objection for a forever loop is terrible. I wonder how your simulation finish?

In reply to chris_le:

i set break point in task body(). i found that task body() never be executed. i think the problem is not related to driver. i am confused that why the body() is not executed
can anyone give some suggestions?
Thanks!!

In reply to peter:

Did you check #1 that I suggested? Did you start your sequence in your test?
Check again the line:


seq.start(env.mem_agnt.sequencer);

Please make sure you have the line above in your test, the body method is executed once you start the sequence correctly.

One more thing, as I mentioned in #2, dont use raise/drop objection in run_phase of driver where you have forever loop. I dont think your test will finish with your implementation.
The objection should be raised/dropped in your test only where you start the sequence.

In reply to peter:

In reply to chris_le:
i set break point in task body(). i found that task body() never be executed. i think the problem is not related to driver. i am confused that why the body() is not executed
can anyone give some suggestions?
Thanks!!

I’d recommend to clean-up your driver code. The task drive is never working. You are using very different names for your virtual interface.
There is the problem with your code. And also in your design you have weaknesses.
Your simulator should point you these places.

In reply to chr_sue:

Yes, i use seq.start() in run_phase in uvm_test.Now, the task body() works.
But , the driver seems has some problems.
here is my modified driver and interface 's code. there is compiler error related to @(posedge `DRIV_IF);
I am still finding the reason

interface mem_if(input logic clk,reset);
 

  logic [1:0] addr;
  logic wr_en;
  logic rd_en;
  logic [7:0] wdata;
  logic [7:0] rdata;
 
  //---------------------------------------
  //driver clocking block
  //---------------------------------------
  clocking driver_cb @(posedge clk);
    default input #1 output #1;
    output addr;
    output wr_en;
    output rd_en;
    output wdata;
    input  rdata;  
  endclocking
 

  //---------------------------------------
  //driver modport
  //---------------------------------------
  //modport DRIVER  (clocking driver_cb,input clk,reset);


endinterface

 `define DRIV_IF pointer_to_interface.driver_cb
class mem_driver extends uvm_driver #(mem_seq_item);
   `uvm_component_utils(mem_driver);
 
 virtual mem_if pointer_to_interface;
 
 function new (string name, uvm_component parent);
      super.new(name,parent);
 
 endfunction : new
 
 virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
 
	if(!uvm_config_db #(virtual mem_if)::get(null, "*","pointer_to_interface", pointer_to_interface))
        $fatal("Failed to get BFM");
 
 endfunction : build_phase
 
 
 task run_phase(uvm_phase phase);
 
      phase.raise_objection(this);
    forever begin
        seq_item_port.get_next_item(req);
      drive();
        seq_item_port.item_done();
    end
 
      phase.drop_objection(this);
 endtask : run_phase

  virtual task drive();
    `DRIV_IF.wr_en <= 0;
    `DRIV_IF.rd_en <= 0;
    @(posedge `DRIV_IF);
        `DRIV_IF.addr <= req.addr;
      if(req.wr_en) begin
        `DRIV_IF.wr_en <= req.wr_en;
        `DRIV_IF.wdata <= req.wdata;
      end
    @(posedge `DRIV_IF);  
      if(req.rd_en) begin
        `DRIV_IF.rd_en <= req.rd_en;
    @(posedge `DRIV_IF);
       `DRIV_IF.rd_en <= 0;
    @(posedge `DRIV_IF);
        req.rdata = `DRIV_IF.rdata;
     end  
  endtask : drive 
 endclass

In reply to peter:

the clocking block already has the cloking event as posedge clk , so you don’t need to state
@(posedge DRIV_IF), @(DRIV_IF) ← is the right way to ask for the posedge event.

its that simple.