Jump to content
Sign in to follow this  
Khushi

monitor output is delayed due to run_phase ordering

Recommended Posts

Hi Guys

I am very new to UVM and trying to play around with a small example(see below). In this example what I am observing that the following sequence(at each posedge)

- first monitor run_phase is executed

- rtl is executed

- driver is executed

due to this, I get the following output

UVM_INFO example.sv(112) @ 10: uvm_test_top.m_env.m_agent.m_monitor [monitor] out = 0x0
in=x
UVM_INFO example.sv(42) @ 10: uvm_test_top.m_env.m_agent.m_data_sequencer@@m_data_sequence.m_data_item [data_item] in = 0xd, out = 0x0
UVM_INFO example.sv(112) @ 30: uvm_test_top.m_env.m_agent.m_monitor [monitor] out = 0x0
in=d
UVM_INFO example.sv(42) @ 30: uvm_test_top.m_env.m_agent.m_data_sequencer@@m_data_sequence.m_data_item [data_item] in = 0xa, out = 0x2
UVM_INFO example.sv(112) @ 50: uvm_test_top.m_env.m_agent.m_monitor [monitor] out = 0x1a
in=a
UVM_INFO example.sv(42) @ 50: uvm_test_top.m_env.m_agent.m_data_sequencer@@m_data_sequence.m_data_item [data_item] in = 0x4, out = 0x6
UVM_INFO example.sv(112) @ 70: uvm_test_top.m_env.m_agent.m_monitor [monitor] out = 0x14
in=4
UVM_INFO example.sv(42) @ 70: uvm_test_top.m_env.m_agent.m_data_sequencer@@m_data_sequence.m_data_item [data_item] in = 0xc, out = 0xc

But I want the following order(at each posedge)

- driver run_phase

- rtl

- monitor run phase

so that monitor display correct output.

How I can achieve this. Or is there some other way to get the correct output.

Here is the complete code

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

module dut(
  input            clk,
  input [3:0]      in,
  output reg [4:0] out
);

  always @ (posedge clk)
    begin
      $display("in=%h",in);  
      out <= 2*in;
    end

endmodule

interface dut_if (input clk);
    logic [3:0] in;
    logic [4:0] out;
endinterface    

module dut_wrapper(dut_if _if);
    dut dut0(.clk   (_if.clk),
             .in    (_if.in),
             .out   (_if.out));
endmodule   

class data_item extends uvm_sequence_item;

   `uvm_object_utils(data_item)
    rand bit  [3:0] in;
    rand bit [4:0] out;

    constraint c_in {in >=0;in<=15;}

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

    virtual function void display ();
         `uvm_info (get_type_name (), $sformatf ("in = 0x%0h, out = 0x%0h", in,out), UVM_LOW);
    endfunction

endclass

class data_sequence extends uvm_sequence;
    `uvm_object_utils(data_sequence)
    data_item m_data_item;

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

    virtual task body();
        m_data_item = data_item::type_id::create("m_data_item");
        repeat (4) begin
            start_item(m_data_item);
            assert(m_data_item.randomize())
            finish_item(m_data_item);
        end
    endtask
endclass

class driver extends uvm_driver#(data_item);
    `uvm_component_utils(driver)

    data_item m_data_item;
    virtual dut_if m_dut_if;
    
    function new(string name,uvm_component parent);
        super.new(name,parent);
    endfunction

    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        assert(uvm_config_db #(virtual dut_if) :: get (this, "", "m_dut_if", m_dut_if));
    endfunction
    
    task run_phase(uvm_phase phase);
        forever begin
            @(posedge m_dut_if.clk);
            seq_item_port.get_next_item (m_data_item);
            m_dut_if.in = m_data_item.in;
            m_data_item.display();
            seq_item_port.item_done();
        end
    endtask

endclass

class monitor extends uvm_monitor;
    `uvm_component_utils(monitor)
     virtual dut_if m_dut_if;
     uvm_analysis_port #(data_item)  item_collected_port;
     data_item m_data_item;
     function new(string name, uvm_component parent);
        super.new(name, parent);
        item_collected_port = new ("item_collected_port", this);
    endfunction

    virtual function void build_phase (uvm_phase phase);
         super.build_phase (phase);
         assert(uvm_config_db #(virtual dut_if) :: get (this, "", "m_dut_if", m_dut_if));
    endfunction

    task run_phase(uvm_phase phase);
        super.run_phase(phase);
        m_data_item = data_item::type_id::create ("m_data_item", this);
        forever @(posedge m_dut_if.clk) begin
            m_data_item.out = m_dut_if.out;
            `uvm_info (get_type_name (), $sformatf ("out = 0x%0h", m_data_item.out), UVM_LOW);
            //item_collected_port.write (m_data_item);
        end
    endtask
endclass

class agent extends uvm_agent;
    `uvm_component_utils(agent)
    driver m_driver;
    data_sequence m_data_sequence;
    uvm_sequencer#(data_item) m_data_sequencer;
    monitor m_monitor;
    
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        m_driver = driver::type_id::create("m_driver",this);
        m_data_sequence = data_sequence::type_id::create("m_data_sequence",this);
        m_data_sequencer = uvm_sequencer#(data_item)::type_id::create("m_data_sequencer",this);
        m_monitor = monitor::type_id::create ("m_monitor", this);
    endfunction

    virtual function void connect_phase (uvm_phase phase);
       super.connect_phase (phase);
       m_driver.seq_item_port.connect (m_data_sequencer.seq_item_export);
    endfunction


endclass

class env extends uvm_env;
    `uvm_component_utils(env)
    agent m_agent;
    
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction

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

endclass    

class my_test extends uvm_test;
    `uvm_component_utils(my_test)

    env m_env;
    virtual dut_if m_dut_if;

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

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        m_env = env::type_id::create("m_env",this);
        assert(uvm_config_db #(virtual dut_if) :: get (this, "", "dut_if", m_dut_if));
        uvm_config_db #(virtual dut_if) :: set (this, "*", "m_dut_if", m_dut_if);
    endfunction   

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

   task run_phase(uvm_phase phase);
       phase.raise_objection(this);
       m_env.m_agent.m_data_sequence.start(m_env.m_agent.m_data_sequencer);
       phase.drop_objection(this);
   endtask

  endclass

module top;
    bit clk;
    always #10 clk <= ~clk;

    dut_if m_dut_if(clk);
    dut_wrapper m_dut_wrapper(._if(m_dut_if));


    initial begin
        uvm_config_db #(virtual dut_if)::set (null, "uvm_test_top", "dut_if", m_dut_if);
        run_test("my_test");
    end
endmodule  

 

 

Share this post


Link to post
Share on other sites

based on your defined data_item, your monitor implementation is incorrect.

the monitor shall sample the sample the in signal and than sample the corresponding out signal, give the encapsulation the two value in a data item, send it out.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×