Missing Last Read Burst in Simulation

Hello everyone, not sure if this is a valid question for this forum but I will ask anyway. If you think I should ask somewhere else, let me know.

I have a testcase for an image_reader module that reads data out of DDR via a MM axi-full interface, and outputs that data on a axi-stream interface. We are using this VIP to simulate ddr and to simulate the axi read and writes:
https://docs.xilinx.com/v/u/en-US/ds940-zynq-vip

I am prefilling the DDR with a raw video file that is 160x120. There are 4 frames and each frame is stored in a different DDR buffer. I am using backdoor access to fill DDR at the start of the testcase. I can dump the contents back to a another file and I can verify the data is correct, so I am fairly confident in that part.

My testcase reads the data out of the PS doing bursts with a size of 16 transactions. My issue is that the very last burst never arrives. I get 599 bursts and the 600th burst never gets read out. On the address lines, I can see that the last address is correctly received by the PS, but it never asserts RVALID data for that address. The assert statement error message I am getting is:

ncsim: *W,WARSEV (/tools/Xilinx/Vivado/2018.2/data/xilinx_vip/hdl/axi_vip_axi4pc.sv,1623): (time 213765 NS).
tb_fpga.a0_fpga_zynq.processing_system7_0.inst.S_AXI_GP0.slave.IF.PC
XILINX_RECS_CONTINUOUS_RTRANSFERS_MAX_WAIT: RVALID should be asserted within MAXWAITS cycles of AR Command being accepted.

The SystemVerilog code for the testcase is below. Any advice on debugging this is appreciated!


// Local Parameters
localparam BUFF0_ADDR       = 32'h2E000000;
localparam BUFF1_ADDR       = 32'h2F000000;
localparam BUFF2_ADDR       = 32'h2A000000;
localparam BUFF3_ADDR       = 32'h2B000000;

//--------------------------------------------------------------------------------
// Testcase image_memory_read_GP
// Description: Reads a YUV 4:2:2 video from a file into PS VIP DDR
// then the image_reader_GP reads it out and it gets written
// to a file for comparison with the original file
//--------------------------------------------------------------------------------
task file_memory_read_GP(
    input [1024*8-1:0]  input_file_name,
    input [31:0]        i_frame_width,
    input [31:0]        i_frame_height,
    input [31:0]        num_frames,
    output              error
);
int input_file_handler;
int output_file_handler;
int frame_counter = 0;
string output_file_name = "DDR_video_dump.yuv";
string scrb_message;
logic [0:76800][31:0] video_data; //size  = i_frame_width*i_frame_height*num_frames
logic [31:0] status_reg;
logic [31:0] control_reg;
logic [31:0] frame_delay = 500; // number of clock cycles delay between frame reads
logic [1:0] num_buff;

begin
    $display("[%0t]: Starting GP_image_reader testcase", $time);

    if(num_frames <= 4) begin
        num_buff = 2'b11;
    end else begin
        num_buff = num_frames - 1;
    end

    // Read an input file into DDR
    input_file_handler = $fopen (input_file_name, "rb");
    if(input_file_handler == 0) begin
        $display("Failed to open file: %0s", input_file_name);
        error = 1;
        $stop;
    end

    // Fill 4 seperate buffers with 1 frame each:
    for(int frame_index = 0; frame_index < num_frames; frame_index++) begin // loop through all the frames
        for(int i = 0; i < (i_frame_width*i_frame_height/2 + 1); i++) begin // loop through all the pixels in the frame
            $fscanf(input_file_handler, "%u", video_data[frame_index*i_frame_width*i_frame_height + i]);
            case (frame_index)
                0: ps_vif.task_write_mem(video_data[frame_index*i_frame_width*i_frame_height + i], BUFF0_ADDR + i*4, 4);
                1: ps_vif.task_write_mem(video_data[frame_index*i_frame_width*i_frame_height + i], BUFF1_ADDR + i*4, 4);
                2: ps_vif.task_write_mem(video_data[frame_index*i_frame_width*i_frame_height + i], BUFF2_ADDR + i*4, 4);
                3: ps_vif.task_write_mem(video_data[frame_index*i_frame_width*i_frame_height + i], BUFF3_ADDR + i*4, 4);
                default: begin $display("frame_index error"); $stop; end
            endcase
        end
    end

    // Enable the GP Image Reader and set force_read bit:
    hdcs_tools.task_config_gp_rmem(BUFF0_ADDR, BUFF1_ADDR, BUFF2_ADDR, BUFF3_ADDR, 1'b1, 1'b1, num_buff, i_frame_width, i_frame_height);
    
    // set delay between frames
    this.ps_vif.task_write_data(`S_AXI_GP_READER_OFFSET, `GP_READER_FRAME_DELAY_OFFSET, frame_delay);

    // Dump M_AXI-Stream (YUV 16-bit) to file
    output_file_handler = $fopen(output_file_name, "wb");
    if(output_file_handler == 0) begin
        error = 1;
        $sformat(scrb_message, "Video output: Failed to open file: %0s", output_file_name);
        scrb.task_validate_result(!error, scrb_message);
    end else begin
        this.image_reader_gp_vif.M_AXIS_tready = 1'b1; // set the interface TREADY once the file is open
    end
    fork
        forever @(posedge this.image_reader_gp_vif.CLK) begin
            if (image_reader_gp_vif.M_AXIS_tready == 1'b1 && image_reader_gp_vif.M_AXIS_tvalid == 1'b1 && frame_counter < num_frames) begin
                $fwrite(output_file_handler, "%c%c", image_reader_gp_vif.M_AXIS_tdata[7:0], image_reader_gp_vif.M_AXIS_tdata[15:8]);
            end
        end
    join_none

    $display("[%0t]: Writing AXI-stream output to file and polling status register for frame_done flag...", $time);

    // Poll the status_reg for the frame_done bit:
    forever @(posedge this.image_reader_gp_vif.CLK) begin
        this.ps_vif.task_read_data(`S_AXI_GP_READER_OFFSET, 15*4, status_reg);
        if (status_reg[9] == 1) begin
            frame_counter = frame_counter + 1;
            $display("[%0t]: Frame %0d of %0d complete", $time, frame_counter, num_frames);
            // clear the frame_done bit:
            control_reg = 0;
            this.ps_vif.task_read_data(`S_AXI_GP_READER_OFFSET, 0*4, control_reg);
            control_reg[11] = 1; // this is a self clearing bit
            this.ps_vif.task_write_data(`S_AXI_GP_READER_OFFSET, 0*4, control_reg);
        end;
        if (frame_counter == num_frames) begin
            image_reader_gp_vif.M_AXIS_tready = 1'b0;
            // Disable the GP reader
            hdcs_tools.task_config_gp_rmem(BUFF0_ADDR, BUFF1_ADDR, BUFF2_ADDR, BUFF3_ADDR, 1'b0, 1'b0, num_buff, i_frame_width, i_frame_height);
            $fclose(output_file_handler);
            break;
        end
    end

    // Compare input and output files
    hdcs_tools.compare_video_files(error, input_file_name, output_file_name, num_frames, i_frame_width, i_frame_height);
    scrb.task_validate_result(!error, "INPUT AND OUTPUT VIDEO FILES MATCH");

    $display("[%0t]: Completed GP_image_reader testcase", $time);

end
endtask