upd:
fix axi-stream interface definition; successful TB DUT launch
This commit is contained in:
@ -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`
|
||||
Reference in New Issue
Block a user