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`
|