uvm_sequence - EDA Playground
Warning! This exercise has been opened in another tab; autosave has been disabled. Close this tab or refresh to reactivate.

 Languages & Libraries

 Tools & Simulators

 Examples

205


386
 
1
`include "uvm_macros.svh"
2
3
package my_pkg;
4
5
  timeunit 1ns;
6
  timeprecision 1ns;
7
8
  import uvm_pkg::*;
9
  
10
  `define FALSE 0
11
  `define TRUE 1
12
  typedef enum { read, write } dir_t;
13
14
// Define a uvm_sequence_item
15
class my_seq_item extends uvm_sequence_item;
16
  rand bit [31:0] data;
17
  rand bit [9:0] addr;
18
  rand dir_t dir;
19
  
20
  function new (string name = "");
21
    super.new(name);
22
  endfunction
23
24
  function string convert2string;
25
    return $sformatf("addr = %0d, data = %0d, dir = %s", addr, data, dir);
26
  endfunction
27
28
  // Register sequence item with the factory and add the
29
  // field automation macros
30
  `uvm_object_utils_begin( my_seq_item )
31
    `uvm_field_int( data, UVM_ALL_ON )
32
    `uvm_field_int( addr, UVM_ALL_ON )
33
    `uvm_field_enum( dir_t, dir, UVM_ALL_ON )
34
  `uvm_object_utils_end
35
  
36
endclass : my_seq_item
37
38
39
class my_other_seq extends uvm_sequence #(my_seq_item);
40
  `uvm_object_utils ( my_other_seq )
41
42
  rand bit ctrl_flag;
43
  
44
  function new ( string name = "my_seq");
45
    super.new (name);
46
  endfunction : new
47
48
  virtual task body();
49
    `uvm_info ( get_name(), "Starting  my_other_seq ...", UVM_NONE )
50
    `uvm_do( req )
51
    `uvm_info ( get_name(), $sformatf("ctrl_flag = %0d, addr = %0d, data = %0d", ctrl_flag, req.addr, req.data), UVM_MEDIUM )
52
  endtask : body
53
54
endclass : my_other_seq
55
56
57
// Create a sequence that uses the sequence item
58
class my_seq extends uvm_sequence #(my_seq_item);
59
  `uvm_object_utils ( my_seq )
60
61
  // my_seq_item req; // built-in sequence item
62
  my_other_seq subseq; // A nested subsequence
63
64
  // Define a constructor
65
  function new ( string name = "my_seq");
66
    super.new (name);
67
  endfunction : new
68
69
  // Define the sequence functionality in the body() using macros
70
  virtual task body();
71
    `uvm_info ( get_name(), "Starting the sequence ...", UVM_NONE )
72
73
    // Use the do action macros on the sequence item
74
    `uvm_do_with( req,{ addr > 10'h0ff; dir == read; } )
75
76
    // Invoke a nested subsequence
77
    `uvm_do_with( subseq, { ctrl_flag == `TRUE; } )
78
79
  endtask : body
80
81
endclass : my_seq
82
  
83
84
// Equivalent sequence that uses start_item() and finish_item()
85
class my_seq_alt extends uvm_sequence #(my_seq_item);
86
  `uvm_object_utils ( my_seq_alt )
87
  `uvm_declare_p_sequencer(uvm_sequencer #(my_seq_item))
88
89
  my_other_seq subseq; // A nested subsequence
90
  
91
  function new ( string name = "my_seq_alt");
92
    super.new (name);
93
  endfunction : new
94
95
  virtual task body();
96
    `uvm_info ( get_name(), "Starting my_seq_alt ...", UVM_NONE )
97
98
    // Generate a sequence item
99
    req = my_seq_item::type_id::create("req");
100
    start_item(req);
101
    randomize(req) with { req.addr > 10'h0ff; req.dir == read; };
102
    finish_item(req);
103
    
104
    // Invoke a nested subsequence
105
    subseq = my_other_seq::type_id::create("subseq");
106
    subseq.start(p_sequencer);
107
108
  endtask : body
109
110
endclass : my_seq_alt
111
112
113
typedef uvm_sequencer #(my_seq_item) my_sequencer_t;
114
115
116
class my_driver_t extends uvm_driver #(my_seq_item);
117
  `uvm_component_utils(my_driver_t)
118
119
  virtual dut_if dut_vi;
120
  uvm_event local_ev1;
121
122
  function new (string name, uvm_component parent);
123
    super.new(name, parent);
124
  endfunction : new
125
126
  function void build_phase(uvm_phase phase);
127
    if (!uvm_config_db#(uvm_event)::get(this,"","sync_ev1",local_ev1))
128
      `uvm_fatal(get_type_name(), "my_driver's local_ev1 not configured")
129
  endfunction : build_phase
130
131
  task run_phase(uvm_phase phase);
132
    int i = 0;
133
    forever
134
    begin
135
      // Pull the next stimulus item from the sequencer
136
      //seq_item_port.get(req);
137
      seq_item_port.get_next_item(req);
138
      i++;
139
      
140
      // Raise objection - busy     
141
      phase.raise_objection(this);
142
143
      // Wiggle pins of DUT
144
      @(posedge dut_vi.clock);
145
      dut_vi.addr = req.addr;
146
      dut_vi.data = req.data;
147
148
      `uvm_info(get_type_name(), $sformatf("Driving transaction # %0d", i), UVM_MEDIUM)
149
      `uvm_info(get_type_name(), req.convert2string(), UVM_MEDIUM)
150
      
151
      // Drop objection - idle       
152
      phase.drop_objection(this);
153
      
154
      seq_item_port.item_done();
155
      local_ev1.trigger();
156
    end
157
  endtask: run_phase
158
159
endclass: my_driver_t
160
161
162
class my_monitor_t extends uvm_monitor;
163
  `uvm_component_utils(my_monitor_t)
164
165
  uvm_analysis_port #(my_seq_item) ap;
166
167
  // Virtual interface variable points to the interface
168
  virtual dut_if mi;
169
  uvm_event local_ev1;
170
171
  function new(string name, uvm_component parent);
172
    super.new(name, parent);
173
  endfunction : new
174
175
  function void build_phase(uvm_phase phase);
176
    ap = new("ap", this);
177
    if (!uvm_config_db#(uvm_event)::get(this,"","sync_ev1",local_ev1))
178
      `uvm_fatal(get_type_name(), "my_monitor's local_ev1 not configured")
179
  endfunction : build_phase
180
181
  task run_phase(uvm_phase phase);
182
    my_seq_item tr;
183
    tr = my_seq_item::type_id::create();
184
185
    assert (mi != null) else
186
      `uvm_fatal(get_type_name(), "my_monitor virtual interface is null")
187
      
188
    forever
189
    begin
190
      @(posedge mi.clock);
191
      local_ev1.wait_ptrigger();
192
      tr.addr = mi.addr;
193
      tr.data = mi.data;
194
195
      `uvm_info(get_type_name(), tr.convert2string(), UVM_MEDIUM)
196
197
      // Send the transaction to the analysis port
198
      ap.write(tr);
199
    end
200
  endtask: run_phase
201
202
endclass: my_monitor_t
203
204
205
class my_agent_t extends uvm_agent;
206
`uvm_component_utils(my_agent_t)
207
  
208
  my_sequencer_t m_sequencer;
209
  my_driver_t   m_driver;
210
  my_monitor_t  m_monitor;
211
  
212
  uvm_analysis_port #(my_seq_item) ap;
213
  
214
  virtual dut_if v_dut_if;
215
216
  function new(string name, uvm_component parent);
217
    super.new(name, parent);
218
  endfunction : new
219
  
220
  virtual function void build_phase(uvm_phase phase);
221
    super.build_phase(phase);
222
    m_monitor  = my_monitor_t::type_id::create("m_monitor", this);
223
    ap = new("ap", this);
224
    if ( get_is_active() == UVM_ACTIVE ) begin
225
      m_sequencer = my_sequencer_t::type_id::create("m_sequencer", this);
226
      m_driver    = my_driver_t   ::type_id::create("m_driver", this);
227
    end
228
  endfunction: build_phase
229
230
  virtual function void connect_phase(uvm_phase phase);
231
    m_monitor.ap.connect(ap);
232
    // code to connect monitor’s virtual interface
233
    if (uvm_config_db#(virtual dut_if)::get(this, "", "dut_if", v_dut_if))
234
      begin
235
        m_monitor.mi = v_dut_if;
236
    
237
        if ( get_is_active() == UVM_ACTIVE ) begin
238
          m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
239
          // code to connect driver’s virtual interface
240
          m_driver.dut_vi = v_dut_if;
241
        end
242
      end
243
    else
244
      `uvm_fatal(get_type_name(), "my_agent's virtual interface not configured")
245
246
  endfunction: connect_phase
247
248
endclass: my_agent_t
249
250
251
class my_subscriber_t extends uvm_subscriber #(my_seq_item);
252
  `uvm_component_utils(my_subscriber_t)
253
254
  uvm_report_object my_report = new("my_subscriber");
255
256
  function new(string name, uvm_component parent);
257
    super.new(name, parent);
258
  endfunction : new
259
260
  function void write(input my_seq_item t);
261
//  `uvm_info        (get_type_name(), t.convert2string(), UVM_MEDIUM)             // uvm_test_top.m_env.m_subscriber [my_subscriber_t]
262
    `uvm_info_context(get_type_name(), t.convert2string(), UVM_MEDIUM, my_report)  // my_subscriber [my_subscriber_t]
263
  endfunction : write
264
265
endclass : my_subscriber_t
266
267
268
class env extends uvm_env;
269
`uvm_component_utils(env)
270
271
my_agent_t       m_agent;
272
my_subscriber_t  m_subscriber;
273
uvm_event        sync_ev1;
274
275
function new (string name, uvm_component parent);
276
  super.new(name, parent);
277
endfunction
278
279
function void build_phase(uvm_phase phase);
280
  m_agent      = my_agent_t     ::type_id::create("m_agent", this);
281
  m_subscriber = my_subscriber_t::type_id::create("m_subscriber", this);
282
  sync_ev1 = new();
283
  uvm_config_db #(uvm_event)::set(this,"*","sync_ev1",sync_ev1);
284
endfunction: build_phase
285
286
function void connect_phase(uvm_phase phase);
287
  m_agent.ap.connect(m_subscriber.analysis_export);
288
endfunction: connect_phase  
289
290
endclass: env
291
292
293
class test extends uvm_test;
294
`uvm_component_utils(test)
295
296
  env  m_env;
297
  
298
  function new (string name, uvm_component parent);
299
    super.new(name, parent);
300
  endfunction : new
301
302
  function void build_phase(uvm_phase phase);
303
    m_env = env::type_id::create("m_env", this);
304
  endfunction : build_phase
305
306
  task run_phase(uvm_phase phase);
307
    uvm_objection objection;
308
    uvm_component comp;
309
    my_sequencer_t seqr;
310
311
    my_seq seq;
312
    seq = my_seq::type_id::create();
313
314
    // Do not propagate objections up the hierarchy (always done prior to UVM 1.2)      
315
    objection = phase.get_objection();
316
    objection.set_propagate_mode(0);
317
318
//     seq.starting_phase = phase; // UVM-1.1
319
    seq.set_starting_phase(phase); // UVM-1.2
320
    
321
    // Raise objection - busy     
322
    phase.raise_objection(this);
323
324
    if( !seq.randomize() ) 
325
      `uvm_error(get_type_name(), "Randomize failed")
326
327
      comp = uvm_top.find("*.m_sequencer");
328
      $cast(seqr, comp);
329
      seq.start( seqr );
330
331
    // Drop objection - idle       
332
    phase.drop_objection(this);
333
334
  endtask: run_phase
335
336
endclass: test
337
338
endpackage: my_pkg
339
340
341
interface dut_if;
342
343
  import my_pkg::*;
344
345
  logic clock;
346
  bit [31:0] data;
347
  bit [9:0] addr;
348
  dir_t dir;
349
350
endinterface
351
352
353
module top;
354
355
  timeunit 1ns;
356
  timeprecision 1ns;
357
358
  import uvm_pkg::*;
359
  import my_pkg::*;
360
361
  dut_if  dut_if1();
362
  DUT     dut1 ( .dif(dut_if1) );
363
364
  // Clock generator
365
  initial begin
366
    dut_if1.clock = 0;
367
    forever #5 dut_if1.clock = ~dut_if1.clock;
368
  end
369
370
initial begin
371
  uvm_config_db #(virtual dut_if)::set(null, "*", "dut_if", dut_if1);
372
373
  uvm_top.enable_print_topology = 1;
374
  uvm_top.finish_on_completion = 1;
375
  uvm_top.set_timeout(1ms);
376
  uvm_top.run_test("test");
377
end
378
379
initial begin
380
// Dump waves
381
  $dumpfile("dump.vcd");
382
  $dumpvars(0, top);
383
end
384
385
endmodule : top
386
10
 
1
module DUT(dut_if dif);
2
  timeunit 1ns;
3
  timeprecision 1ns;
4
5
  always @(posedge dif.clock)
6
  begin
7
  end
8
  
9
endmodule
10
210 views and 0 likes     
 
Another complete UVM example for uvm_sequence topic.
REFERENCED

Another complete UVM example for uvm_sequence topic.

REFERENCED

480:0