• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Functional Verification
  3. How to use uvm_agent for sequencing

Stats

  • Locked Locked
  • Replies 4
  • Subscribers 65
  • Views 17310
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to use uvm_agent for sequencing

Sporadic Crash
Sporadic Crash over 7 years ago

Hi all,

based on the discussion in https://community.cadence.com/cadence_technology_forums/f/functional-verification/38665/run_phase-doesn-t-update-sv-interface-signals I have extended the testbench  with uvm_agent, but sequencing cannot be bound properly.

DUT interface, DUT and testbench are in the thread above. I am trying to test a very simple counter to learn UVM environment.

My UVM package looks like as follows.

I get the compilation error at Incisive 15.22.

ncvlog: *E,NOTCLM (tb_pkg.sv,120|52): seq_item_port is not a class item.
seq.start (m_env.m_seqr);

The problem is the "run_phase" function in uvm_test which complains that the object cannot be found. Where should I move the seq_item_port? To the agent or to the sequencer? And how?

Sorry this might be stupid question but I couldnt figure out how to do it, because on web most examples are simple so that there is no need to use uvm_agent.

Any help appreciated.


`include "uvm_macros.svh"

// www.youtube.com/watch
package my_pkg;

import uvm_pkg::*;

// Transaction (for constrain random value generation)

class my_transaction extends uvm_sequence_item;

`uvm_object_utils (my_transaction)

rand logic [7:0] load_val;
constraint c_load_val { load_val > 10 ; load_val < 20; }

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

function void do_copy (uvm_object rhs);
my_transaction tx;
$cast(tx, rhs);
load_val = tx.load_val;
endfunction

endclass : my_transaction

// Sequencer (to create sequences, to be called by the driver)

typedef uvm_sequencer #(my_transaction) my_sequencer;

class my_sequence extends uvm_sequence #(my_transaction);

`uvm_object_utils(my_sequence)

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

task body;
if (starting_phase != null)
starting_phase.raise_objection(this);

repeat (8)
begin
req = my_transaction::type_id::create("req");
start_item(req);
if (!req.randomize()) `uvm_error ("", "randomize failed");
finish_item (req);
end

if (starting_phase != null)
starting_phase.drop_objection(this);
endtask : body

endclass: my_sequence

// Driver

class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils (my_driver)

// this is the DUT interface, mostly instantiated in the driver
virtual dut_if dut_vi;

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

function void build_phase(uvm_phase phase);
if (! uvm_config_db #(virtual dut_if)::get(this, "", "dut_if", dut_vi))
`uvm_error ("", "uvm_config_db::get failed");

endfunction

task run_phase(uvm_phase phase);
forever
begin
seq_item_port.get_next_item(req);
@(posedge dut_vi.i_clk);
$display ("run_phase!!");
dut_vi.i_load_en <= '1;
// dut_vi.i_load_val <= $urandom;
dut_vi.i_load_val = req.load_val;
seq_item_port.item_done();
end
endtask

endclass: my_driver


// Agent

class my_agent extends uvm_agent;

my_sequencer m_seqr;
my_driver m_driv;

`uvm_component_utils(my_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);

if (get_is_active() == UVM_ACTIVE) begin
m_driv = my_driver::type_id::create("m_driv", this);
m_seqr = my_sequencer::type_id::create("m_seqr", this);
end
endfunction : build_phase

function void connect_phase(uvm_phase phase);
if (get_is_active() == UVM_ACTIVE) begin
m_driv.seq_item_port.connect(m_seqr.seq_item_port);
end
endfunction : connect_phase

endclass : my_agent


// Environment

class my_env extends uvm_env;
`uvm_component_utils (my_env)

// my_sequencer m_seqr;
// my_driver m_driv;
my_agent m_agt;


// Constructor - informs parent this class
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new

function void build_phase(uvm_phase phase);
// m_seqr = my_sequencer::type_id::create("m_seqr", this);
// m_driv = my_driver::type_id::create("m_driv", this);
m_agt = my_agent::type_id::create("m_agt", this);
endfunction : build_phase

// if connect_phase is empty, then no need to instantiate it :-)

// function void connect_phase(uvm_phase phase);
// m_driv.seq_item_port.connect(m_seqr.seq_item_export);
// endfunction : connect_phase

endclass


// driver is instantiated in the test
class my_test extends uvm_test;

`uvm_component_utils (my_test)

// decl member
my_env m_env;

// standard code for all components
// must it be a virtual function?
function new (string name, uvm_component parent);
super.new (name, parent);
endfunction

// Factory method call "create" in UVM is used
// we extend the functionality of m_env
function void build_phase(uvm_phase phase);
m_env = my_env::type_id::create("m_env", this);
endfunction

// only task phase (contains sim time)
task run_phase(uvm_phase phase);
/* // from now on the test is busy
phase.raise_objection(this);
// we consume some time
#200;
// one of 4 macros, others: `uvm_warning, `uvm_error, `uvm_fatal
// UVM_MEDIUM - verbosity level: UVM_INFO,
`uvm_info("", "Hello world", UVM_MEDIUM);
// I'm finished, test is over
phase.drop_objection(this); */
my_sequence seq;
seq = my_sequence::type_id::create("seq");
if(!seq.randomize() ) `uvm_error ("", "run_phase::seq.randomize failed");
seq.starting_phase = phase;
seq.start (m_env.m_seqr);
endtask

endclass: my_test

endpackage : my_pkg

  • Cancel
  • muffi
    muffi over 7 years ago

    I haven't run your example but I can see one mistake.

    m_driv.seq_item_port.connect(m_seqr.seq_item_port);

    should be:

    m_driv.seq_item_port.connect(m_seqr.seq_item_export);

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • tpylant
    tpylant over 7 years ago

    And seq.start (m_env.m_seqr); should be seq.start (m_env.m_agt.m_seqr);

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • tpylant
    tpylant over 7 years ago

    And seq.start (m_env.m_seqr); should be seq.start (m_env.m_agt.m_seqr);

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • Sporadic Crash
    Sporadic Crash over 7 years ago in reply to tpylant

    muffi and tpylant thank you for your help. I had 2 errors indeed. Fixed them, 

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information