31 class axi_driver :
public uvm_driver <axi_seq_item> {
public:
44 new (
string name=
"axi_driver", uvm_component parent=null);
63 super.new(name, parent);
68 super.build_phase(phase);
70 vif = axi_if_abstract::type_id::create(
"vif",
this);
77 super.connect_phase(phase);
106 seq_item_port.get(item);
108 uvm_info(this.get_type_name(),
150 int wait_clks_before_next_aw;
153 vif.set_awvalid(0b0);
155 vif.wait_for_not_in_reset();
161 uvm_info(
"axi_driver::write_address",
168 vif.wait_for_clks(.cnt(1));
171 if (vif.get_awready_awvalid == 0b1) {
177 wait_clks_before_next_aw=$urandom_range(maxval,minval);
180 if (wait_clks_before_next_aw==0) {
184 uvm_info(
"axi_driver::write_address",
198 vif.write_aw(.s(v), .valid(0b1));
206 vif.write_aw(.s(v), .valid(0b0));
209 if (wait_clks_before_next_aw > 0) {
210 vif.wait_for_clks(.cnt(wait_clks_before_next_aw-1));
244 int wait_clks_before_next_w;
251 int valid_assert_bit;
253 int clks_without_wvalid_or_wready;
265 for (
int i=0;i <item.
len;i++) {
266 item.
valid[i]=$random;
272 for (
int i=0;i <j;i++) {
273 item.
valid[i] = $random;
274 if (item.
valid[i] == 0b1) {
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),
291 validcntr_max=item.
valid.size();
296 .burst_length(item.
len)) + 1;
298 clks_without_wvalid_or_wready=0;
299 uvm_info(
"axi_driver::write_data",
306 vif.wait_for_clks(.cnt(1));
311 if (vif.get_wready()==0b1 && vif.get_wvalid() == 10b1) {
315 uvm_info(
"axi_driver::write_data",
316 $sformatf(
"beat_cntr:%0d beat_cntr_max: %0d", beat_cntr, beat_cntr_max),
320 if (beat_cntr >= beat_cntr_max) {
327 wait_clks_before_next_w=$urandom_range(maxval,minval);
330 if (wait_clks_before_next_w==0) {
334 uvm_info(
"axi_driver::write_data",
342 for (
int i=0;i <item.
len;i++) {
343 item.
valid[i]=$random;
349 for (
int i=0;i <j;i++) {
350 item.
valid[i] = $random;
351 if (item.
valid[i] == 0b1) {
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),
367 validcntr_max=item.
valid.size();
372 .burst_length(item.
len)) + 1;
373 clks_without_wvalid_or_wready=0;
387 if (vif.get_wready()==0b0 && vif.get_wvalid() == 10b0) {
388 clks_without_wvalid_or_wready++;
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),
397 clks_without_wvalid_or_wready=0;
403 uvm_info(this.get_type_name(),
404 $sformatf(
"Calling get_beat_N_data: %s",
409 .data_bus_bytes(vif.get_data_bus_width()/8),
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];
426 if (vif.get_wready()==0b1 && vif.get_wvalid() == 10b1) {
428 uvm_info(this.get_type_name(),
429 $sformatf(
"debuga validcntr=%0d",validcntr),
433 uvm_info(this.get_type_name(),
434 $sformatf(
"debugb validcntr=%0d",validcntr),
436 }
else if (vif.get_wvalid() == 0b0) {
438 uvm_info(this.get_type_name(),
439 $sformatf(
"debugc validcntr=%0d",validcntr),
443 if (validcntr >= validcntr_max) {
460 if (wait_clks_before_next_w > 0) {
461 vif.wait_for_clks(.cnt(wait_clks_before_next_w-1));
494 vif.wait_for_write_response(.s(s));
497 seq_item_port.put(item);
525 int wait_clks_before_next_ar;
528 vif.set_arvalid(0b0);
530 vif.wait_for_not_in_reset();
536 uvm_info(
"axi_driver::read_address",
543 vif.wait_for_clks(.cnt(1));
546 if (vif.get_arready_arvalid == 0b1) {
552 wait_clks_before_next_ar=$urandom_range(maxval,minval);
555 if (wait_clks_before_next_ar==0) {
570 vif.write_ar(.s(v), .valid(0b1));
579 vif.write_ar(.s(v), .valid(0b0));
582 if (wait_clks_before_next_ar > 0) {
583 vif.wait_for_clks(.cnt(wait_clks_before_next_ar-1));
622 uvm_info(this.get_type_name(),
623 "========> wait_for_read_data()",
626 vif.wait_for_read_data(.s(r_s));
627 uvm_info(this.get_type_name(),
"wait_for_read_data - DONE", UVM_HIGH)
638 $cast(cloned_item, item.clone());
639 cloned_item.set_id_info(item);
642 cloned_item.
data =
new[cloned_item.
len];
647 .burst_length (cloned_item.
len)) + 1;
653 while (item != null && r_q.size() > 0) {
658 .burst_length (cloned_item.
len),
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),
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);
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]);
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];
690 if (beat_cntr >= beat_cntr_max) {
692 seq_item_port.put(cloned_item);
task write_address()
Write Address channel thread.
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
void connect_phase(uvm_phase phase)
Nothing to connect so doesn't actually do anything except call parent connect phase.
string convert2string()
Convert item'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
mailbox< axi_seq_item > writeresponse_mbx
Logic to act as an AXI master for all 5 channels.
new(string name="axi_driver", uvm_component parent=null)
Constructor.
mailbox< axi_seq_item > readaddress_mbx
task write_response()
Write Response channel thread.
Extremely simple memory model with just write() and read() methods.
logic< C_AXI_ID_WIDTH-1:0 > bid
logic< C_AXI_ID_WIDTH-1:0 > awid
logic< C_AXI_DATA_WIDTH/8-1:0 > wstrb
This packed struct is used to send read data channel information between the DUT and TB...
This packed struct is used to send write address channel information between the DUT and TB...
logic< C_AXI_DATA_WIDTH-1:0 > wdata
rand bit< 31:0 > rready_toggle_pattern
mailbox< axi_seq_item > writeaddress_mbx
logic< C_AXI_DATA_WIDTH-1:0 > rdata
byte clks_without_wvalid_or_wready_max
rand bit< ADDR_WIDTH-1:0 > addr
logic< C_AXI_ID_WIDTH-1:0 > arid
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.
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.
void build_phase(uvm_phase phase)
Creates the virtual interface.
uvm_component_utils(axi_driver) axi_if_abstract vif
task read_address()
Read Address channel thread.
bit axi_incompatible_wvalid_toggling_mode
rand bit< 31:0 > bready_toggle_pattern
logic< C_AXI_ADDR_WIDTH-1:0 > araddr
rand byte min_clks_between_w_transfers
logic< C_AXI_ADDR_WIDTH-1:0 > awaddr
axi_agent_config m_config
This packed struct is used to send write data channel information between the DUT and TB...
mailbox< axi_seq_item > writedata_mbx
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
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.
This packed struct is used to send write response channel information between the DUT and TB...
Configuration object for an axi_agent.
task read_data()
monitors Read Data channel and sends out TLM pkt
rand logic< 1:0 > burst_type
rand byte min_clks_between_ar_transfers
mailbox< axi_seq_item > readdata_mbx
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...