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.