AXI muckbucket
axi_driver.svh
Go to the documentation of this file.
1 //
3 // Copyright (C) 2017, Matt Dew @ Dew Technologies, LLC
4 //
5 // This program is free software (logic verification): you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public License (LGPL)
7 // as published by the Free Software Foundation, either version 3 of the License,
8 // or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 // for more details.
14 //
15 // License: LGPL, v3, as defined and found on www.gnu.org,
16 // http://www.gnu.org/licenses/lgpl.html
17 //
18 //
19 // Author's intent: If you use this AXI verification code and find or fix bugs
20 // or make improvements, then share those fixes or improvements.
21 // If you use this in a bigger project, I don't care about,
22 // or want, any changes or code outside this block.
23 // Example: If you use this in an SoC simulation/testbench
24 // I don't want, or care about, your SoC or other blocks.
25 // I just care about the enhancements to these AXI files.
26 // That's why I have choosen the LGPL instead of the GPL.
28 
31 class axi_driver : public uvm_driver <axi_seq_item> { public:
33 
34  axi_if_abstract vif;
37 
38  mailbox <axi_seq_item> writeaddress_mbx = new(0); //unbounded mailboxes
39  mailbox <axi_seq_item> writedata_mbx = new(0);
40  mailbox <axi_seq_item> writeresponse_mbx = new(0);
41  mailbox <axi_seq_item> readaddress_mbx = new(0);
42  mailbox <axi_seq_item> readdata_mbx = new(0);
43 
44  new (string name="axi_driver", uvm_component parent=null);
45 
46  void build_phase (uvm_phase phase);
47  void connect_phase (uvm_phase phase);
48  task run_phase (uvm_phase phase);
49 
50  task write_address ();
51  task write_data ();
52  task write_response ();
53  task read_address ();
54  task read_data ();
55 
56 
57 };
58 
62  axi_driver::new (string name = "axi_driver", uvm_component parent = null) {
63  super.new(name, parent);
64 }
65 
67  void axi_driver::build_phase (uvm_phase phase) {
68  super.build_phase(phase);
69 
70  vif = axi_if_abstract::type_id::create("vif", this);
71 }
72 
76  void axi_driver::connect_phase (uvm_phase phase) {
77  super.connect_phase(phase);
78 }
79 
80 
91 task axi_driver::run_phase(uvm_phase phase) {
92 
93  axi_seq_item item;
94 
95  fork
96  write_address();
97  write_data();
99  read_address();
100  read_data();
101  join_none
102 
103 
104  forever {
105 
106  seq_item_port.get(item);
107 
108  uvm_info(this.get_type_name(),
109  $sformatf("Item: %s", item.convert2string()),
110  UVM_INFO)
111 
112  case (item.cmd) {
114  writeaddress_mbx.put(item);
115  }
117  readaddress_mbx.put(item);
118  }
119 
120  }
121 
122  } // forever
123 
124 }
125 
126 
139 
140  axi_seq_item item=null;
142 
143  bit <ADDR_WIDTH-1:0> aligned_addr;
144 
145  bit <7:0> wdata [];
146  bit wstrb [];
147 
148  int minval;
149  int maxval;
150  int wait_clks_before_next_aw;
151 
152 
153  vif.set_awvalid(0b0);
154 
155  vif.wait_for_not_in_reset();
156 
157  forever {
158 
159  if (item == null) {
160  writeaddress_mbx.get(item);
161  uvm_info("axi_driver::write_address",
162  $sformatf("Item: %s", item.convert2string()),
163  UVM_HIGH)
164 
165  axi_uvm_pkg::aw_from_class(.t(item), .v(v));
166  }
167 
168  vif.wait_for_clks(.cnt(1));
169 
170  // if done with this xfer (write address is only one clock, done with valid & ready
171  if (vif.get_awready_awvalid == 0b1) {
172  writedata_mbx.put(item);
173  item=null;
174 
177  wait_clks_before_next_aw=$urandom_range(maxval,minval);
178 
179  // Check if delay wanted
180  if (wait_clks_before_next_aw==0) {
181  // if not, check if there's another item
182 
183  if (writeaddress_mbx.try_get(item)) {
184  uvm_info("axi_driver::write_address",
185  $sformatf("Item: %s", item.convert2string()),
186  UVM_HIGH)
187 
188  axi_uvm_pkg::aw_from_class(.t(item), .v(v));
189  }
190  }
191  }
192  // Initialize values <-no need
193 
194  // Update values <- No need in write address (only one clk per)
195 
196  // Write out
197  if (item != null) {
198  vif.write_aw(.s(v), .valid(0b1));
199  } else {// if (item != null)
200 
201  // No item for next clock, so close out bus
202  v.awaddr = 0x0;
203  v.awid = 0x0;
204  v.awsize = 0x0;
205  v.awburst = 0x0;
206  vif.write_aw(.s(v), .valid(0b0));
207 
208 
209  if (wait_clks_before_next_aw > 0) {
210  vif.wait_for_clks(.cnt(wait_clks_before_next_aw-1)); // -1 because another wait
211  // // at beginning of loop
212  }
213  }
214 
215 
216  } // forever
217 
218 }
219 
234  axi_seq_item item=null;
236 
237  bit <7:0> wdata[];
238  bit wstrb[];
239 
240  int n=0;
241 
242  int minval;
243  int maxval;
244  int wait_clks_before_next_w;
245  int beat_cntr=0;
246  int beat_cntr_max;
247  int validcntr;
248  int validcntr_max;
249  int j;
250  int valid_asserts;
251  int valid_assert_bit;
252 
253  int clks_without_wvalid_or_wready;
254 
255  vif.set_wvalid(0b0);
256  forever {
257 
258  if (item == null) {
259  writedata_mbx.get(item);
260 
261  if (m_config.wvalid.size > 0) {
262  item.valid=new[m_config.wvalid.size](m_config.wvalid);
263  } else {
264  item.valid=new[item.len];
265  for (int i=0;i <item.len;i++) {
266  item.valid[i]=$random;
267  }
268  }
269 
270  valid_asserts = 0;
271  j=item.valid.size();
272  for (int i=0;i <j;i++) {
273  item.valid[i] = $random;
274  if (item.valid[i] == 0b1) {
275  valid_asserts++;
276  }
277  }
278 
279 
280  // valid must be asserted at least once to avoid never sending data.
281  if (valid_asserts==0) {
282  valid_assert_bit=$urandom_range(j-1,0);
283  item.valid[valid_assert_bit] = 0b1;
284  uvm_info("axi_driver::write_data",
285  $sformatf("All zeros. Settin bit %0d to 1", valid_assert_bit),
286  UVM_HIGH)
287  }
288 
289 
290  validcntr=0;
291  validcntr_max=item.valid.size();
292 
293  beat_cntr=0;
294  beat_cntr_max=axi_pkg::calculate_axlen(.addr(item.addr),
295  .burst_size(item.burst_size),
296  .burst_length(item.len)) + 1;
297 
298  clks_without_wvalid_or_wready=0;
299  uvm_info("axi_driver::write_data",
300  $sformatf("Item: %s", item.convert2string()),
301  UVM_HIGH)
302 
303  }
304 
305 
306  vif.wait_for_clks(.cnt(1));
307 
308 
309  // Check if done with this transfer
310 
311  if (vif.get_wready()==0b1 && vif.get_wvalid() == 10b1) {
312 
313  beat_cntr++;
314 
315  uvm_info("axi_driver::write_data",
316  $sformatf("beat_cntr:%0d beat_cntr_max: %0d", beat_cntr, beat_cntr_max),
317  UVM_HIGH)
318 
319 
320  if (beat_cntr >= beat_cntr_max) {
321  writeresponse_mbx.put(item);
322  item = null;
323 
324 
327  wait_clks_before_next_w=$urandom_range(maxval,minval);
328 
329  // Check if delay wanted
330  if (wait_clks_before_next_w==0) {
331  // if not, check if there's another item
332 
333  if (writedata_mbx.try_get(item)) {
334  uvm_info("axi_driver::write_data",
335  $sformatf("Item: %s", item.convert2string()),
336  UVM_HIGH)
337 
338  if (m_config.wvalid.size > 0) {
339  item.valid=new[m_config.wvalid.size](m_config.wvalid);
340  } else {
341  item.valid=new[item.len];
342  for (int i=0;i <item.len;i++) {
343  item.valid[i]=$random;
344  }
345  }
346 
347  valid_asserts = 0;
348  j=item.valid.size();
349  for (int i=0;i <j;i++) {
350  item.valid[i] = $random;
351  if (item.valid[i] == 0b1) {
352  valid_asserts++;
353  }
354  }
355 
356 
357  // valid must be asserted at least once to avoid never sending data.
358  if (valid_asserts==0) {
359  valid_assert_bit=$urandom_range(j-1,0);
360  item.valid[valid_assert_bit] = 0b1;
361  uvm_info("axi_driver::write_data",
362  $sformatf("All zeros. Settin bit %0d to 1", valid_assert_bit),
363  UVM_HIGH)
364  }
365 
366  validcntr=0;
367  validcntr_max=item.valid.size();
368 
369  beat_cntr=0;
370  beat_cntr_max=axi_pkg::calculate_axlen(.addr(item.addr),
371  .burst_size(item.burst_size),
372  .burst_length(item.len)) + 1;
373  clks_without_wvalid_or_wready=0;
374  }
375 
376  }
377  }
378  } // (vif.get_wready()==1'b1 && vif.get_wvalid() == 1'b1)
379 
380 
381  // Update values
382  if (item != null) {
383  // if too long withoutsending any data, then add an extra valid.
384  // it is entirely possible for ready and valid to not have overlap,
385  // which will hang the sim. Add additional valids to counteract.
386  // \Todo: Need to report all this to help with reproducing bugs
387  if (vif.get_wready()==0b0 && vif.get_wvalid() == 10b0) {
388  clks_without_wvalid_or_wready++;
389  if (clks_without_wvalid_or_wready > m_config.clks_without_wvalid_or_wready_max) {
390  j=item.valid.size();
391 
392  valid_assert_bit=$urandom_range(j-1,0);
393  item.valid[valid_assert_bit] = 0b1;
394  uvm_info("axi_driver::write_data",
395  $sformatf("%0d clocks without ready/valid overlap. Setting another valid[], bit %0d, to 1", clks_without_wvalid_or_wready, valid_assert_bit),
396  UVM_INFO)
397  clks_without_wvalid_or_wready=0;
398  }
399  }
400 
401  s.wvalid = item.valid[validcntr]; // 1'b1;
402 
403  uvm_info(this.get_type_name(),
404  $sformatf("Calling get_beat_N_data: %s",
405  item.convert2string()),
406  UVM_HIGH)
407 
408  item.get_beat_N_data(.beat_cnt(beat_cntr),
409  .data_bus_bytes(vif.get_data_bus_width()/8),
410  .data(wdata),
411  .wstrb(wstrb),
412  .wlast(s.wlast));
413 
414  for (int x=0;x <vif.get_data_bus_width()/8;x++) {
415  s.wdata[x*8+:8] = wdata[x];
416  s.wstrb[x] = wstrb[x];
417  }
418 
419  // Write out
420  vif.write_w(.s(s));
421 
422 
423  // if invalid-toggling-mode is enabled, then allow deasserting valid
424  // before ready asserts.
425  // Default is to stay asserted, and only allow deasssertion after ready asserts.
426  if (vif.get_wready()==0b1 && vif.get_wvalid() == 10b1) {
427  validcntr++;
428  uvm_info(this.get_type_name(),
429  $sformatf("debuga validcntr=%0d",validcntr),
430  UVM_HIGH)
432  validcntr++;
433  uvm_info(this.get_type_name(),
434  $sformatf("debugb validcntr=%0d",validcntr),
435  UVM_HIGH)
436  } else if (vif.get_wvalid() == 0b0) {
437  validcntr++;
438  uvm_info(this.get_type_name(),
439  $sformatf("debugc validcntr=%0d",validcntr),
440  UVM_HIGH)
441 
442  }
443  if (validcntr >= validcntr_max) {
444  validcntr=0;
445  }
446 
447 
448  } // (item != null)
449 
450  // No item for next clock, so close out bus
451  if (item == null) {
452  s.wvalid = 0b0;
453  s.wlast = 0b0;
454  s.wdata = 0x0;
455  // s.wid = 'h0; AXI3 only
456  s.wstrb = 0x0;
457 
458  vif.write_w(.s(s));
459 
460  if (wait_clks_before_next_w > 0) {
461  vif.wait_for_clks(.cnt(wait_clks_before_next_w-1));
462  // -1 because another wait
463  // at beginning of loop
464  }
465  } // if (item == null
466  } // forever
467 }
468 
469 
470 
471 
480 
481  axi_seq_item item;
483 
484  vif.enable_bready_toggle_pattern(m_config.bready_toggle_pattern);
485 
486  // \todo: Ch to be like others. wait for write_resonse, add to quque, then
487  // process.
488  // // need timeout on get ???
489 
490  forever {
491  writeresponse_mbx.get(item);
492 
493  item.cmd = e_WRITE_RESPONSE;
494  vif.wait_for_write_response(.s(s));
495  item.bid = s.bid;
496  item.bresp = s.bresp;
497  seq_item_port.put(item);
498 
499 
500  }
501 }
502 
503 
516 
517  axi_seq_item item=null;
519 
520  bit <ADDR_WIDTH-1:0> aligned_addr;
521 
522 
523  int minval;
524  int maxval;
525  int wait_clks_before_next_ar;
526 
527 
528  vif.set_arvalid(0b0);
529 
530  vif.wait_for_not_in_reset();
531 
532  forever {
533 
534  if (item == null) {
535  readaddress_mbx.get(item);
536  uvm_info("axi_driver::read_address",
537  $sformatf("Item: %s", item.convert2string()),
538  UVM_HIGH)
539 
540  axi_uvm_pkg::ar_from_class(.t(item), .v(v));
541  }
542 
543  vif.wait_for_clks(.cnt(1));
544 
545  // if done with this xfer (write address is only one clock, done with valid & ready
546  if (vif.get_arready_arvalid == 0b1) {
547  readdata_mbx.put(item);
548  item=null;
549 
552  wait_clks_before_next_ar=$urandom_range(maxval,minval);
553 
554  // Check if delay wanted
555  if (wait_clks_before_next_ar==0) {
556  // if not, check if there's another item
557 
558  if (readaddress_mbx.try_get(item)) {
559 
560  axi_uvm_pkg::ar_from_class(.t(item), .v(v));
561  }
562  }
563  }
564  // Initialize values <-no need
565 
566  // Update values <- No need in write address (only one clk per)
567 
568  // Write out
569  if (item != null) {
570  vif.write_ar(.s(v), .valid(0b1));
571  } else {// if (item != null)
572 
573  // No item for next clock, so close out bus
574  // if (item == null) begin
575  v.araddr = 0x0;
576  v.arid = 0x0;
577  v.arsize = 0x0;
578  v.arburst = 0x0;
579  vif.write_ar(.s(v), .valid(0b0));
580  // end
581 
582  if (wait_clks_before_next_ar > 0) {
583  vif.wait_for_clks(.cnt(wait_clks_before_next_ar-1)); // -1 because another wait
584  // // at beginning of loop
585  }
586  }
587 
588 
589  } // forever
590 }
591 
592 
606 
609  axi_seq_item item=null;
610  axi_seq_item cloned_item=null;
611  bit <ADDR_WIDTH-1:0> read_addr;
612  int beat_cntr=0;
613  int beat_cntr_max=0;
614  int Lower_Byte_Lane;
615  int Upper_Byte_Lane;
616  int offset;
617  string msg_s;
618 
619  vif.enable_rready_toggle_pattern(.pattern(m_config.rready_toggle_pattern));
620 
621  forever {
622  uvm_info(this.get_type_name(),
623  "========> wait_for_read_data()",
624  UVM_HIGH)
625 
626  vif.wait_for_read_data(.s(r_s));
627  uvm_info(this.get_type_name(), "wait_for_read_data - DONE", UVM_HIGH)
628 
629  // Can we just queue the data no matter what and
630  // if the addresshasn'tarrived, we don't sit and poll continuosly
631  // for and address.
632  // What happens if we don't get an address until after wlast?
633  r_q.push_back(r_s);
634 
635  if (item == null) {
636  if (readdata_mbx.num() > 0) {
637  readdata_mbx.get(item);
638  $cast(cloned_item, item.clone());
639  cloned_item.set_id_info(item);
640 
641  cloned_item.cmd=e_READ_DATA;
642  cloned_item.data = new[cloned_item.len];
643 
644  beat_cntr=0;
645  beat_cntr_max=axi_pkg::calculate_axlen(.addr (cloned_item.addr),
646  .burst_size (cloned_item.burst_size),
647  .burst_length (cloned_item.len)) + 1;
648  } // if .num > 0
649  } // if item == null
650 
651  // if anything in data queue, write it out
652  if (item != null) {
653  while (item != null && r_q.size() > 0) {
654 
655  r_s=r_q.pop_front();
656  axi_pkg::get_beat_N_byte_lanes(.addr (cloned_item.addr),
657  .burst_size (cloned_item.burst_size),
658  .burst_length (cloned_item.len),
659  .burst_type (cloned_item.burst_type),
660  .beat_cnt (beat_cntr),
661  .data_bus_bytes (vif.get_data_bus_width()/8),
662  .Lower_Byte_Lane (Lower_Byte_Lane),
663  .Upper_Byte_Lane (Upper_Byte_Lane),
664  .offset (offset));
665 
666  msg_s="";
667  $sformat(msg_s, "%s beat_cntr:%0d", msg_s, beat_cntr);
668  $sformat(msg_s, "%s beat_cntr_max:%0d", msg_s, beat_cntr_max);
669  $sformat(msg_s, "%s data_bus_bytes:%0d", msg_s, vif.get_data_bus_width()/8);
670  $sformat(msg_s, "%s Lower_Byte_Lane:%0d", msg_s, Lower_Byte_Lane);
671  $sformat(msg_s, "%s Upper_Byte_Lane:%0d", msg_s, Upper_Byte_Lane);
672  $sformat(msg_s, "%s offset:%0d", msg_s, offset);
673 
674  // `uvm_info("driver::read_data", msg_s, UVM_INFO)
675 
676  msg_s="data: 0x";
677  for (int z=(vif.get_data_bus_width()/8)-1;z>=0;z--) {
678  $sformat(msg_s, "%s%02x", msg_s, r_s.rdata[z*8+:8]);
679  }
680  // `uvm_info("driver::read_data", msg_s, UVM_INFO)
681 
682  for (int z=Lower_Byte_Lane;z <=Upper_Byte_Lane;z++) {
683  if (offset < cloned_item.len) {
684  cloned_item.data[offset++] = r_s.rdata[z*8+:8];
685  }
686  }
687 
688  beat_cntr++;
689  // if (r_s.rlast == 1'b1) begin // @Todo: count, dont rely on wlast?
690  if (beat_cntr >= beat_cntr_max) {
691  // ap.write(cloned_item);
692  seq_item_port.put(cloned_item);
693  item=null;
694  beat_cntr=0;
695  } // if .wlast == 1
696  } // while
697  }// if
698  } // forever
699 
700 }
701 
702 
task write_address()
Write Address channel thread.
Definition: axi_driver.svh:138
rand cmd_t cmd
rand bit< 7:0 > data[]
logic< ID_WIDTH-1:0 > bid
bit< C_AXI_LEN_WIDTH-1:0 > calculate_axlen(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input bit< 2:0 > burst_size, input shortint burst_length)
calculate awlen or arlen
Definition: axi_pkg.sv:320
void connect_phase(uvm_phase phase)
Nothing to connect so doesn&#39;t actually do anything except call parent connect phase.
Definition: axi_driver.svh:76
rand int len
string convert2string()
Convert item&#39;s variable into one printable string.
automatic void ar_from_class(ref axi_seq_item t, output axi_seq_item_ar_vector_s v)
take values from an axi_seq_item and stuff into a axi_seq_item_ar_vector_s
Definition: axi_uvm_pkg.sv:193
mailbox< axi_seq_item > writeresponse_mbx
Definition: axi_driver.svh:40
Logic to act as an AXI master for all 5 channels.
Definition: axi_driver.svh:31
new(string name="axi_driver", uvm_component parent=null)
Constructor.
Definition: axi_driver.svh:62
logic< 1:0 > arburst
Definition: axi_pkg.sv:185
mailbox< axi_seq_item > readaddress_mbx
Definition: axi_driver.svh:41
task write_response()
Write Response channel thread.
Definition: axi_driver.svh:479
Extremely simple memory model with just write() and read() methods.
Definition: memory.svh:32
logic< C_AXI_ID_WIDTH-1:0 > bid
Definition: axi_pkg.sv:163
logic< C_AXI_ID_WIDTH-1:0 > awid
Definition: axi_pkg.sv:114
logic< 2:0 > arsize
Definition: axi_pkg.sv:184
logic< C_AXI_DATA_WIDTH/8-1:0 > wstrb
Definition: axi_pkg.sv:143
This packed struct is used to send read data channel information between the DUT and TB...
Definition: axi_pkg.sv:205
memory m_memory
Definition: axi_driver.svh:36
This packed struct is used to send write address channel information between the DUT and TB...
Definition: axi_pkg.sv:113
logic< 1:0 > bresp
Definition: axi_pkg.sv:164
logic< 2:0 > awsize
Definition: axi_pkg.sv:119
logic< C_AXI_DATA_WIDTH-1:0 > wdata
Definition: axi_pkg.sv:142
rand bit< 31:0 > rready_toggle_pattern
mailbox< axi_seq_item > writeaddress_mbx
Definition: axi_driver.svh:38
logic< C_AXI_DATA_WIDTH-1:0 > rdata
Definition: axi_pkg.sv:206
byte clks_without_wvalid_or_wready_max
rand bit< ADDR_WIDTH-1:0 > addr
logic< C_AXI_ID_WIDTH-1:0 > arid
Definition: axi_pkg.sv:179
abstract base class for polymorphic interface class (axi_if_concrete) for AXI UVM environment ...
rand byte min_clks_between_aw_transfers
rand byte max_clks_between_aw_transfers
rand byte max_clks_between_w_transfers
task run_phase(uvm_phase phase)
Launches channel driver threads and then acts as a dispatcher.
Definition: axi_driver.svh:91
rand logic< 2:0 > burst_size
void get_beat_N_data(input int beat_cnt, input int data_bus_bytes, ref bit< 7:0 > data[], ref bit wstrb[], output bit wlast)
return beat values for write data and read data channels
task write_data()
Write Data channel thread.
Definition: axi_driver.svh:233
void build_phase(uvm_phase phase)
Creates the virtual interface.
Definition: axi_driver.svh:67
uvm_component_utils(axi_driver) axi_if_abstract vif
task read_address()
Read Address channel thread.
Definition: axi_driver.svh:515
bit axi_incompatible_wvalid_toggling_mode
rand bit< 31:0 > bready_toggle_pattern
logic< C_AXI_ADDR_WIDTH-1:0 > araddr
Definition: axi_pkg.sv:180
rand bit valid[]
rand byte min_clks_between_w_transfers
logic< C_AXI_ADDR_WIDTH-1:0 > awaddr
Definition: axi_pkg.sv:115
axi_agent_config m_config
Definition: axi_driver.svh:35
This packed struct is used to send write data channel information between the DUT and TB...
Definition: axi_pkg.sv:141
mailbox< axi_seq_item > writedata_mbx
Definition: axi_driver.svh:39
void get_beat_N_byte_lanes(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input bit< 2:0 > burst_size, input shortint burst_length, input bit< 1:0 > burst_type, input int beat_cnt, input int data_bus_bytes, output int Lower_Byte_Lane, output int Upper_Byte_Lane, output int offset)
return byte lanes that contain valid data
Definition: axi_pkg.sv:538
automatic void aw_from_class(ref axi_seq_item t, output axi_seq_item_aw_vector_s v)
Pull values out of axi_seq_item and stuff into a axi_seq_item_aw_vector_s.
Definition: axi_uvm_pkg.sv:94
This packed struct is used to send write response channel information between the DUT and TB...
Definition: axi_pkg.sv:162
Configuration object for an axi_agent.
logic< 1:0 > bresp
logic< 1:0 > awburst
Definition: axi_pkg.sv:120
task read_data()
monitors Read Data channel and sends out TLM pkt
Definition: axi_driver.svh:605
rand logic< 1:0 > burst_type
rand byte min_clks_between_ar_transfers
mailbox< axi_seq_item > readdata_mbx
Definition: axi_driver.svh:42
contains all data and functions related to axi and usage
rand byte max_clks_between_ar_transfers
This packed struct is used to send read address channel information between the DUT and TB...
Definition: axi_pkg.sv:178
localparam ADDR_WIDTH
Definition: axi_uvm_pkg.sv:39