130 lines
4.4 KiB
Systemverilog
130 lines
4.4 KiB
Systemverilog
`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`
|