fix axi-stream interface definition;
successful TB DUT launch
This commit is contained in:
Zer0Nu11
2026-07-16 19:33:51 +03:00
parent d80f5ff31f
commit 71b825ef2c
2 changed files with 136 additions and 114 deletions

View File

@ -14,40 +14,117 @@ interface axis_if #(
logic tlast;
logic tready;
//------------------------------------------------------------
// Clocking block для Testbench (Driver/Monitor)
// Защищает от Race Conditions в симуляции
//------------------------------------------------------------
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
//------------------------------------------------------------
// Modports для автоматического подключения одной строчкой
//------------------------------------------------------------
modport master (
output tdata, tvalid, tlast,
input tready
);
modport slave (
input tdata, tvalid, tlast,
output tready
);
// Modport для тестбенча (чтобы работать через функции)
modport master (output tdata, tvalid, tlast, input tready);
modport slave (input tdata, tvalid, tlast, output tready);
// Модпорт для тестбенча с тасками
modport tb (
clocking drv_cb,
clocking mon_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
`endif // AXIS_INTERFACE_SVH`