Connecting DUT and TB using interface without modports

In reply to cgales:

It does not work as I expect.
I added tasks into interfaces responsible for interaction with DUT.

In master interface there is a task send_data that takes an input buffer and sends it to the DUT:

import com_tb_package::*;
 
interface com_tb_int_in #(
    parameter TDATA_WIDTH   = 32,
    parameter TUSER_WIDTH   = 32
)
(
    input logic ACLK,
    input logic ARESETN
);
 
    logic                   S_AXIS_TVALID = 0;
    logic                   S_AXIS_TREADY;
    logic                   S_AXIS_TLAST = 0;
    logic [TDATA_WIDTH-1:0] S_AXIS_TDATA;
    logic [TUSER_WIDTH-1:0] S_AXIS_TUSER;
 
    clocking cb @(posedge ACLK);
        input   S_AXIS_TREADY;
        output  S_AXIS_TVALID;
        output  S_AXIS_TLAST;
        output  S_AXIS_TDATA;
        output  S_AXIS_TUSER;
    endclocking
 
    task automatic send_data (const ref c_data_buffer #(TDATA_WIDTH, TUSER_WIDTH) data_buffer, input logic random_tvalid = 0);
        int i = 0;
 
        assert (data_buffer.size() > 0)
        else begin
            $error("Data buffer is empty. Exitting task");
            return;
        end
 
        while (i <= data_buffer.size() - 1) begin
 
            if ( (random_tvalid && $urandom_range(1, 0) == 1) || !random_tvalid ) begin
 
                cb.S_AXIS_TVALID    <= 1'b1;
                cb.S_AXIS_TDATA     <= data_buffer.bus[i].tdata;
                cb.S_AXIS_TUSER     <= data_buffer.bus[i].tuser;
                cb.S_AXIS_TLAST     <= data_buffer.bus[i].tlast;
 
                if (cb.S_AXIS_TREADY) begin
                    i++;
                end
 
            end else begin
                cb.S_AXIS_TVALID <= 1'b0;
            end
 
            @ (cb);
 
        end
 
        cb.S_AXIS_TVALID <= 1'b0;
 
    endtask
 
endinterface

Slave interface has task get_data that receiving data from DUT until stop_event:

import com_tb_package::*;
 
interface com_tb_int_out #(
    parameter int TDATA_WIDTH = 32,
    parameter int TUSER_WIDTH = 32
)
(
    input logic ACLK,
    input logic ARESETN
);
 
    logic                       M_AXIS_TVALID;
    logic                       M_AXIS_TREADY = 0;
    logic                       M_AXIS_TLAST;
    logic [TDATA_WIDTH-1:0]     M_AXIS_TDATA;
    logic [TUSER_WIDTH-1:0]     M_AXIS_TUSER;
 
    clocking cb @(posedge ACLK);
        input   M_AXIS_TVALID;
        output  M_AXIS_TREADY;
        input   M_AXIS_TLAST;
        input   M_AXIS_TDATA;
        input   M_AXIS_TUSER;
    endclocking
 
    task automatic get_data (input event stop_e, c_data_buffer #(TDATA_WIDTH,TUSER_WIDTH) data_buffer, logic random_tready = 0);
        event push_backed_e;
 
        if (!random_tready) begin
            cb.M_AXIS_TREADY <= 1'b1;
        end
 
        fork begin
 
            fork
 
                begin
 
                    wait (stop_e.triggered);
 
                    wait (push_backed_e.triggered);
 
                end
 
                forever begin
 
                    @(cb);
 
                    if ( (random_tready && $urandom_range(1,0) == 1) || !random_tready) begin
                        cb.M_AXIS_TREADY <= 1'b1;
 
                        if (cb.M_AXIS_TVALID) begin
                            data_buffer.push_back(cb.M_AXIS_TDATA, cb.M_AXIS_TUSER, cb.M_AXIS_TLAST);
                        end
 
                    end else begin
                        cb.M_AXIS_TREADY <= 1'b0;
                    end
 
                    ->push_backed_e;
 
                end
 
            join_any
 
            disable fork;
 
        end join
 
        cb.M_AXIS_TREADY <= 1'b0;
 
    endtask
 
endinterface

DUT is simply generate S_AXIS_DATA_TREADY signal and M_AXIS_DATA_TVALID with counters on M_AXIS_DATA_TDATA and M_AXIS_DATA_TUSER buses:

module test_int (
    // Synchro signal and reset
    input  logic                ACLK,
    input  logic                ARESETN,
    // Interface S_AXIS_DATA
    input  logic                S_AXIS_DATA_TVALID,
    output logic                S_AXIS_DATA_TREADY,
    input  logic                S_AXIS_DATA_TLAST,
    input  logic [31:0]         S_AXIS_DATA_TDATA,
    input  logic [7:0]          S_AXIS_DATA_TUSER,
    // Interface M_AXIS_DATA
    output logic                M_AXIS_DATA_TVALID,
    input  logic                M_AXIS_DATA_TREADY,
    output logic                M_AXIS_DATA_TLAST,
    output logic [31:0]         M_AXIS_DATA_TDATA,
    output logic [7:0]          M_AXIS_DATA_TUSER
);
 
    // Constants
    localparam logic random_tready = 0;
    localparam logic random_tvalid = 0;
 
    // Delayed reset signal (active low)
    (* keep = "true" *) logic   aresetn_into = 1'b0;
 
    // Work signals
    logic [31:0] data_cnt;
    logic [7:0]  user_cnt;
 
    assign M_AXIS_DATA_TDATA = data_cnt;
    assign M_AXIS_DATA_TUSER = user_cnt;
 
    // Delay input ARESETN signal
    always_ff @(posedge ACLK) begin
        aresetn_into <= ARESETN;
    end
 
    //
    always_ff @(posedge ACLK) begin
        if (aresetn_into == 1'b0) begin
            S_AXIS_DATA_TREADY <= 1'b0;
            M_AXIS_DATA_TVALID <= 1'b0;
            data_cnt <= 0;
            user_cnt <= 1;
            M_AXIS_DATA_TLAST <= 0;
        end else begin
 
            if (random_tready && $urandom_range(1, 0) == 1 || !random_tready) begin
                S_AXIS_DATA_TREADY <= 1'b1;
            end else begin
                S_AXIS_DATA_TREADY <= 1'b0;
            end
 
            if (random_tvalid && $urandom_range(1, 0) == 1 || !random_tvalid) begin
                M_AXIS_DATA_TVALID <= 1'b1;
            end else begin
                M_AXIS_DATA_TVALID <= 1'b0;
            end
 
            if (M_AXIS_DATA_TVALID && M_AXIS_DATA_TREADY) begin
                data_cnt <= data_cnt + 1;
                user_cnt <= user_cnt + 1;
            end
 
 
        end
    end
 
endmodule

TB is

module test_int_tb (
    input  logic                ACLK,
    input  logic                ARESETN
);
 
    import com_tb_package::*;
 
    logic [31:0] data[100];
    logic [7:0]  user[100];
 
    event data_sended_e;
    event stop_receiving_e;
 
    // S_AXIS_DATA
    com_tb_int_in #(
        .TDATA_WIDTH                    (32),
        .TUSER_WIDTH                    (8)
    ) com_tb_int_in_data_inst (
        .ACLK                           (ACLK),
        .ARESETN                        (ARESETN)
    );
 
    // M_AXIS_DATA
    com_tb_int_out #(
        .TDATA_WIDTH                    (32),
        .TUSER_WIDTH                    (8)
    ) com_tb_int_out_inst (
        .ACLK                           (ACLK),
        .ARESETN                        (ARESETN)
    );
 
 
    // module test_int instantiation
    test_int test_int_inst (
        // Synchro signals and reset
        .ACLK                           (ACLK),
        .ARESETN                        (ARESETN),
        // Interface S_AXIS_DATA
        .S_AXIS_DATA_TVALID             (com_tb_int_in_data_inst.cb.S_AXIS_TVALID),
        .S_AXIS_DATA_TREADY             (com_tb_int_in_data_inst.cb.S_AXIS_TREADY),
        .S_AXIS_DATA_TLAST              (com_tb_int_in_data_inst.cb.S_AXIS_TLAST),
        .S_AXIS_DATA_TDATA              (com_tb_int_in_data_inst.cb.S_AXIS_TDATA),
        .S_AXIS_DATA_TUSER              (com_tb_int_in_data_inst.cb.S_AXIS_TUSER),
        // Interface M_AXIS_DATA
        .M_AXIS_DATA_TVALID             (com_tb_int_out_inst.cb.M_AXIS_TVALID),
        .M_AXIS_DATA_TLAST              (com_tb_int_out_inst.cb.M_AXIS_TLAST),
        .M_AXIS_DATA_TREADY             (com_tb_int_out_inst.cb.M_AXIS_TREADY),
        .M_AXIS_DATA_TDATA              (com_tb_int_out_inst.cb.M_AXIS_TDATA),
        .M_AXIS_DATA_TUSER              (com_tb_int_out_inst.cb.M_AXIS_TUSER)
    );
 
    // S_AXIS_DATA
    initial begin
        automatic c_data_buffer #(.TDATA_WIDTH (32), .TUSER_WIDTH (8)) s_data_buffer;
        automatic logic random_valid = 0;
 
        for (int i = 0; i <= $size(data) - 1; i++) begin
            data[i] = i;
        end
 
        for (int i = 0; i <= $size(user) - 1; i++) begin
            user[i] = i+1;
        end
 
        s_data_buffer = new;
 
        for (int i = 0; i <= 12; i++) begin
            if (i == 11) begin
                s_data_buffer.push_back(data[i], user[i], 1);
            end else begin
                s_data_buffer.push_back(data[i], user[i], 0);
            end
        end
 
        com_tb_int_in_data_inst.send_data(s_data_buffer, random_valid);
 
        ->data_sended_e;
 
    end
 
    // M_AXIS_DATA
    initial begin
        automatic c_data_buffer #(.TDATA_WIDTH (32), .TUSER_WIDTH (8)) m_data_buffer;
        automatic logic random_ready = 1;
 
        @ (posedge ARESETN);
 
        // start collecting data
        m_data_buffer = new;
 
        fork
 
            com_tb_int_out_inst.get_data(stop_receiving_e, m_data_buffer, random_ready);
 
            begin
 
                wait (data_sended_e.triggered);
 
                repeat (5) @ (posedge ACLK);
 
                ->stop_receiving_e;
 
            end
 
        join
 
        for (int i = 0; i <= m_data_buffer.size() - 1; i++) begin
 
            assert (m_data_buffer.bus[i].tdata == data[i])
            else begin
                $error("Data error! M_AXIS_DATA_TDATA = %8h, expected %8h, word %4d", m_data_buffer.bus[i].tdata, data[i], i);
            end
 
        end
 
        $stop;
 
 
    end
 
 
endmodule // test_int_tb

Send_data task in master interface is working, but get_data doesn’t: first words of cb.M_AXIS_TDATA and cb.M_AXIS_TUSER buses and cb.M_AXIS_TLAST signal is in X state.