I am trying to develop AXI master sequence but i am facing a problem when i am trying to get the responses for outstanding transaction. Below mentioned are more details with code.
class axi4_if_random_sequence #(
int ADDR_WIDTH = 32,
int DATA_WIDTH = 64,
int ID_WIDTH = 8
)
extends axi4_if_sequence_base #(
.ADDR_WIDTH(ADDR_WIDTH),
.DATA_WIDTH(DATA_WIDTH),
.ID_WIDTH(ID_WIDTH)
);
`uvm_object_param_utils( axi4_if_random_sequence #(
ADDR_WIDTH,
DATA_WIDTH,
ID_WIDTH
))
// pragma uvmf custom class_item_additional begin
//To keep the axi transaction
rand axi4_if_transaction_req_t item;
//To indicate if this transaction is outstanding or not
rand bit is_outstanding;
//To indicate completion of the sequence
bit sequence_done=1'b0;
// pragma uvmf custom class_item_additional end
//*****************************************************************
function new(string name = "");
super.new(name);
item = axi4_if_transaction_req_t::type_id::create("item");
endfunction: new
// ****************************************************************************
// TASK : post_body()
virtual task post_body();
super.post_body();
if(is_outstanding) begin
fork
begin
$display("Time:%t, m_seq_id:%0d, axi_id:%0h", $realtime, req.get_transaction_id(), req.axi_id);
get_response(rsp, req.get_transaction_id());
// New rsp received. Indicate to sequence using event.
sequence_done = 1'b1;
// Display the received response transaction
`uvm_info("SEQ", {"New response transaction:",rsp.convert2string()}, UVM_MEDIUM)
end
join_none
end
else begin
get_response(rsp, req.get_transaction_id());
// New rsp received. Indicate to sequence using event.
sequence_done = 1'b1;
// Display the received response transaction
`uvm_info("SEQ", {"New response transaction:",rsp.convert2string()}, UVM_MEDIUM)
end
endtask
// ****************************************************************************
// TASK : body()
// This task is automatically executed when this sequence is started using the
// start(sequencerHandle) task.
//
task body();
req=item;
start_item(req);
finish_item(req);
`uvm_info("SEQ", {"Request:",req.convert2string()},UVM_MEDIUM)
endtask
endclass: axi4_if_random_sequence
If “is_outstanding” is 1 then i treat the AXI transaction as outstanding transaction and it is sent to the sequencer and then i invoke the “get_response(rsp, req.get_transaction_id());” in a fork join_none assuming the transaction will be completed at a later time and the response will be returned by the driver and then using flag “sequence_done = 1’b1;” to indicate that the sequence is complete.
But when i start say suppose 10 such sequences with “is_outstanding == 1” from my testcase i could see that the driver is returning the responses at correct timestamps when the write transaction is completely handled using prints/waveform but the “get_response(rsp, req.get_transaction_id());” never unblocks and hence the test assumes the sequence is never complete and hangs. Also when i start 10 such sequences with “is_outstanding == 0” then everything seems to work okay. So i am not suspecting the logic in the driver code and i am suspicious in the sequence code.
Below is the main_phase of the testcase:
task ta_new_axi_vip::main_phase(uvm_phase phase);
int num_wr_txn=10, num_rd_txn=10;
axi4_if_random_sequence#(.ADDR_WIDTH(32), .DATA_WIDTH(128), .ID_WIDTH(4)) axi_wr_seq[] = new[num_wr_txn];
axi4_if_random_sequence#(.ADDR_WIDTH(32), .DATA_WIDTH(128), .ID_WIDTH(4)) axi_rd_seq[] = new[num_rd_txn];
foreach(axi_wr_seq[i])
axi_wr_seq[i]= axi4_if_random_sequence #(.ADDR_WIDTH(32), .DATA_WIDTH(128), .ID_WIDTH(4))::type_id::create($sformatf("axi_wr_seq_%0d", i));
foreach(axi_rd_seq[i])
axi_rd_seq[i]= axi4_if_random_sequence #(.ADDR_WIDTH(32), .DATA_WIDTH(128), .ID_WIDTH(4))::type_id::create($sformatf("axi_rd_seq_%0d", i));
super.main_phase(phase);
phase.raise_objection(this);
//Start the axi write sequence
foreach(axi_wr_seq[i]) begin
void'(axi_wr_seq[i].randomize() with {item.axi_addr=='h100*i;
item.axi_op == AXI_WR;
item.axi_burst_type == AXI_INCR;
item.axi_burst_len == 8;
item.axi_size_in_bytes == 16;
is_outstanding == 1;});
axi_wr_seq[i].start(drv_env_cfg.axi4_memory_initiator_cfg.sequencer);
end
//Wait for all the sequence to complete
forever begin
bit all_seq_done=1;
foreach(axi_wr_seq[i])
all_seq_done &= axi_wr_seq[i].sequence_done;
if(!all_seq_done)
repeat(100) @(posedge drv_env.vif.CLK_CFG);
else
break;
end
phase.drop_objection(this);
endtask : main_phase