Uvm data flow and handshaking

I am learning UVM and this is a test program I wrote. So in the uvm_drv, there is a infinity blocking loop asking data from sequence. In sequence class, anything between “start_item” and “finish_item” will be passed to driver? How does the handshaking exactly happen here?

When I compile this code, I got an error message saying:


UVM_INFO top.sv(162) @ 0: reporter [top] I’m alive
UVM_INFO @ 0: reporter [RNTST] Running test test1…
UVM_INFO top.sv(111) @ 0: uvm_test_top.e.a [agent] starting sequence
UVM_INFO top.sv(53) @ 0: uvm_test_top.e.a.s [seqencer] sequencer body
UVM_INFO top.sv(73) @ 0: uvm_test_top.e.a.d [drv] I am in run phase
UVM_INFO top.sv(76) @ 0: uvm_test_top.e.a.d [drv] I am in forever loop
UVM_INFO top.sv(34) @ 0: uvm_test_top.e.a.s@@trans [sequence] sequence body
dst=054097bd, crc=7e261e9c
UVM_FATAL @ 0: uvm_test_top.e.a.s [s] send_request failed to cast sequence item

— UVM Report catcher Summary —

How should I make it correct? Thanks a lot.


  1 // include package
  2 `include "uvm_macros.svh"
  3 
  4 package usr_pkg;
  5 
  6   import uvm_pkg::*;
  8   class pkt extends uvm_sequence_item;
  9     rand int dst;
 10     rand int crc;
 11 
 12     function new (string name ="pkt");
 13       super.new(name);
 14     endfunction
 15 
 16     `uvm_object_utils(pkt)
 17   endclass

 20   class trans extends uvm_sequence #(pkt);
 21     pkt p;
 22 
 23     function new (string name = "trans");
 24       super.new("trans");
 25     endfunction
 26 
 27     `uvm_object_utils (trans)
 28 
 29     task body();
 30 
 31       pkt p = pkt::type_id::create("p");
 32 
 33       start_item(p);
 34       `uvm_info ("sequence", "sequence body", UVM_MEDIUM);
 35       if (!(p.randomize())) `uvm_info ("sequence", "bad randomization", UVM_MEDIUM);
 36       $display ("dst=%h, crc=%h",p.dst, p.crc);
 37       finish_item(p);
 38     endtask
 39 
 40   endclass

 43   class sqr extends uvm_sequencer #(trans);
 44     `uvm_component_utils (sqr)
 45 
 46     trans t;
 47 
 48     function new (string name, uvm_component parent);
 49        super.new(name, parent);
 50     endfunction
 51 
 52     task run_phase(uvm_phase phase);
 53       `uvm_info ("seqencer", "sequencer body", UVM_MEDIUM);
 54     endtask
 55 
 56   endclass
 57 
 58 
 59   class drv extends uvm_driver #(trans);
 60     `uvm_component_utils (drv)
 61 
 62     trans t;
 63 
 64     function new (string name, uvm_component parent);
 65       super.new(name, parent);
 66     endfunction
 67 
 68     function void build_phase(uvm_phase phase);
 69       super.build_phase (phase);
 70     endfunction
 71 
 72     task run_phase (uvm_phase phase);
 73       `uvm_info ("drv", "I am in run phase", UVM_MEDIUM);
 74 
 75       forever begin
 76         `uvm_info ("drv", "I am in forever loop", UVM_MEDIUM);
 77         seq_item_port.get_next_item(t);
 78         `uvm_info ("drv", "ph", UVM_MEDIUM);
 79         seq_item_port.item_done();
 80       end
 81 
 82     endtask
 83   endclass

 86   class agnt extends uvm_agent;
 87     `uvm_component_utils (agnt)
 88 
 89     trans t;
 90     sqr s;
 91     drv d;
 92 
 93     function new (string name, uvm_component parent);
 94        super.new(name, parent);
 95     endfunction
 96 
 97     function void build_phase (uvm_phase phase);
 98        super.build_phase(phase);
 99        s = sqr::type_id::create ("s", this);
100        d = drv::type_id::create ("d", this);
101     endfunction
102 
103     function void connect_phase (uvm_phase phase);
104        super.connect_phase(phase);
105        d.seq_item_port.connect (s.seq_item_export);
106     endfunction
107 
108     task run_phase(uvm_phase phase);
109        t=trans::type_id::create("t");
110        phase.raise_objection(this, "starting");
111        `uvm_info ("agent", "starting sequence", UVM_MEDIUM);
112        t.start(s);
113        #1000;
114        `uvm_info ("agent", "ending sequence", UVM_MEDIUM);
115     
116        phase.drop_objection(this, "ending");
117     endtask
118 
119   endclass

122   class env extends uvm_env;
123     `uvm_component_utils(env)
124     agnt a;
125 
126     function new (string name, uvm_component parent);
127       super.new (name, parent);
128     endfunction
129 
130     function void build_phase(uvm_phase phase);
131       super.build_phase (phase);
132       a=agnt::type_id::create("a", this);
133     endfunction
134 
135   endclass
136 
137   class test1 extends uvm_test;
138     `uvm_component_utils(test1)
139     env e;
140 
141     function new (string name, uvm_component parent);
142       super.new (name, parent);
143     endfunction
144 
145     function void build_phase(uvm_phase phase);
146       super.build_phase (phase);
147       e=env::type_id::create("e", this);
148     endfunction
149 
150   endclass
151 
152 
153 endpackage
154 
155 
156 module top ();
157 
158   import uvm_pkg::*;
159   import usr_pkg::*;
160 
161   initial begin
162     `uvm_info ("top", "I'm alive", UVM_MEDIUM);
163     run_test();
164   end
165 
166 endmodule


In reply to ningyangverificationacademy:

You are misunderstanding sequence and transaction.
The sequencer and driver should be declared as:


class sqr extends uvm_sequencer #(pkt);
...
endclass

class drv extends uvm_driver #(pkt);
...
endclass

In reply to An Pham:

Thanks a lot. That solves my problem, and I am starting to make sense how things work in UVM

In reply to ningyangverificationacademy:

If you want to understand how the hand-shaking between driver and sequencer works, you could find it inside the UVM cookbook or this website:
http://cluelogic.com/2012/11/uvm-tutorial-for-candy-lovers-sequence-item-port/