`ifndef AXIS_INTERFACE_SVH `define AXIS_INTERFACE_SVH interface axis_if #( parameter int DATA_WIDTH = 8 )( input logic clk, input logic rst_n ); // Сигналы шины AXI-Stream logic [DATA_WIDTH-1:0] tdata; logic tvalid; logic tlast; logic tready; initial begin // Default values tdata = 'x; tvalid = 1'b0; tlast = 1'b0; tready = 1'b0; end // Master Clocking Block (для отправки данных из TB) clocking drv_cb @(posedge clk); default input #1step output #100ps; output tdata, tvalid, tlast; input tready; endclocking // Slave Clocking Block (для приема данных в TB с генерацией tready) clocking slv_cb @(posedge clk); default input #1step output #100ps; input tdata, tvalid, tlast; output tready; endclocking // Passive Monitor Clocking Block clocking mon_cb @(posedge clk); default input #1step; input tdata, tvalid, tlast, tready; endclocking modport master (output tdata, tvalid, tlast, input tready); modport slave (input tdata, tvalid, tlast, output tready); // Модпорт для тестбенча с тасками modport tb ( clocking drv_cb, clocking slv_cb, clocking mon_cb, import master_send, import slave_recv, import monitor_recv ); // Отправка пакета (Тестбенч выступает как Master) task automatic master_send(input logic [DATA_WIDTH-1:0] payload[]); if (payload.size() == 0) return; @(drv_cb); for (int i = 0; i < payload.size(); i++) begin drv_cb.tdata <= payload[i]; drv_cb.tvalid <= 1'b1; drv_cb.tlast <= (i == payload.size() - 1); forever begin // Ждем подтверждение от слейва пока не получим @(drv_cb); if (drv_cb.tready === 1'b1) begin break; end end end // Сбрасываем сигналы после отправки пакета drv_cb.tvalid <= 1'b0; drv_cb.tlast <= 1'b0; drv_cb.tdata <= 'x; endtask // Прием пакета (Тестбенч выступает как Slave и управляет tready). Не применять если есть реальный Slave (его tready опустится насильно) task automatic slave_recv(output logic [DATA_WIDTH-1:0] payload[]); logic [DATA_WIDTH-1:0] local_queue[$]; // Внутри таски очередь использовать можно slv_cb.tready <= 1'b1; // Показываем, что готовы принимать forever begin @(slv_cb); if (slv_cb.tvalid === 1'b1) begin local_queue.push_back(slv_cb.tdata); if (slv_cb.tlast === 1'b1) begin break; // Пакет закончился end end end slv_cb.tready <= 1'b0; // Снимаем готовность // Перекладываем из очереди в динамический массив payload = new[local_queue.size()](local_queue); endtask // Прием пакета (Тестбенч выступает как пассивный наблюдатель без tready) task automatic monitor_recv(output logic [DATA_WIDTH-1:0] payload[]); logic [DATA_WIDTH-1:0] local_queue[$]; // Внутри таски очередь использовать можно forever begin if (mon_cb.tready === 1'b1) begin break; // Дождались слейва end @(slv_cb); end forever begin @(mon_cb); if (mon_cb.tvalid === 1'b1) begin local_queue.push_back(mon_cb.tdata); if (mon_cb.tlast === 1'b1) begin break; // Пакет закончился end end end // Перекладываем из очереди в динамический массив payload = new[local_queue.size()](local_queue); endtask endinterface `endif // AXIS_INTERFACE_SVH`