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 tlast;
logic tready; logic tready;
//------------------------------------------------------------ initial begin // Default values
// Clocking block для Testbench (Driver/Monitor) tdata = 'x;
// Защищает от Race Conditions в симуляции tvalid = 1'b0;
//------------------------------------------------------------ tlast = 1'b0;
tready = 1'b0;
end
// Master Clocking Block (для отправки данных из TB)
clocking drv_cb @(posedge clk); clocking drv_cb @(posedge clk);
default input #1step output #100ps; default input #1step output #100ps;
output tdata, tvalid, tlast; output tdata, tvalid, tlast;
input tready; input tready;
endclocking 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); clocking mon_cb @(posedge clk);
default input #1step; default input #1step;
input tdata, tvalid, tlast, tready; input tdata, tvalid, tlast, tready;
endclocking endclocking
//------------------------------------------------------------ modport master (output tdata, tvalid, tlast, input tready);
// Modports для автоматического подключения одной строчкой modport slave (input tdata, tvalid, tlast, output tready);
//------------------------------------------------------------
modport master (
output tdata, tvalid, tlast,
input tready
);
modport slave ( // Модпорт для тестбенча с тасками
input tdata, tvalid, tlast,
output tready
);
// Modport для тестбенча (чтобы работать через функции)
modport tb ( modport tb (
clocking drv_cb, 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 endinterface
`endif // AXIS_INTERFACE_SVH `endif // AXIS_INTERFACE_SVH`

View File

@ -149,99 +149,37 @@ module reflectometer_tb;
//------------------------------------------------------------ //------------------------------------------------------------
// Таски для тестирования // Таски для тестирования
//------------------------------------------------------------ //------------------------------------------------------------
task automatic dut_soft_reset(virtual axis_if#(8).tb vif);
// AXI-S таски logic [7:0] tx_packet[];
task automatic axis_send_packet( tx_packet = '{8'h0f};
virtual axis_if.tb vif, vif.master_send(tx_packet);
logic [7:0] payload[]
);
int packet_size = payload.size();
if (packet_size == 0) begin
$display("[WARNING] -axis_send_packet- Попытка отправить пустой пакет.");
return;
end
foreach (payload[i]) begin
$display("%1", payload[i]);
// vif.drv_cb.tdata <= payload[i];
// vif.drv_cb.tvalid <= 1'b1;
// vif.drv_cb.tlast <= (i == packet_size - 1); // tlast активен только на последнем байте
// // Шагаем на следующий фронт клока, чтобы симулятор применил выходы
// @(vif.drv_cb);
// // Ждем на последующих фронтах, пока tready не станет равен 1.
// while (vif.drv_cb.tready !== 1'b1) begin
// @(vif.drv_cb);
// end
end
// Снимаем валидность на следующем дельта-цикле
vif.drv_cb.tvalid <= 1'b0;
vif.drv_cb.tlast <= 1'b0;
vif.drv_cb.tdata <= '0;
endtask endtask
task automatic dut_soft_reset(); task automatic dut_start(virtual axis_if#(8).tb vif);
logic [7:0] cmd[] = '{8'b00001111}; logic [7:0] tx_packet[];
axis_send_packet( tx_packet = '{8'hf0};
.vif(axis_control_if.tb), vif.master_send(tx_packet);
.payload(cmd)
);
endtask endtask
task automatic dut_start();
logic [7:0] cmd[] = '{8'b11110000};
axis_send_packet(
.vif(axis_control_if.tb),
.payload(cmd)
);
endtask
task automatic dut_send_system_config( task automatic dut_send_system_config(
virtual axis_if#(8).tb vif,
input logic [31:0] pulse_width, input logic [31:0] pulse_width,
input logic [31:0] pulse_period, input logic [31:0] pulse_period,
input logic [15:0] pulse_num, input logic [15:0] pulse_num,
input logic [13:0] pulse_height, input logic [13:0] pulse_height, // achtung! p_height strictly must have 14 bits of width
input logic [31:0] pulse_period_adc input logic [31:0] pulse_period_adc
); );
// Выделяем 17 байт: 1 байт команды + 16 байт регистров // Создаем временный фиксированный массив и упаковываем всё одной строкой
logic [7:0] full_packet[17]; logic [7:0] tx_packet[];
// 1. Сначала пишем команду в нулевой байт пакета tx_packet = '{
full_packet[0] = 8'b10001000; // Твоя команда set_data 8'h88, // Команда
pulse_width[7:0], pulse_width[15:8], pulse_width[23:16], pulse_width[31:24],
pulse_period[7:0], pulse_period[15:8], pulse_period[23:16], pulse_period[31:24],
pulse_num[7:0], pulse_num[15:8], pulse_height[7:0], 8'({2'b00, pulse_height[13:8]}),
pulse_period_adc[7:0], pulse_period_adc[15:8], pulse_period_adc[23:16], pulse_period_adc[31:24]
};
// 2. Упаковываем регистр pulse_width [31:0] (байты 1..4) vif.master_send(tx_packet);
full_packet[1] = pulse_width[7:0];
full_packet[2] = pulse_width[15:8];
full_packet[3] = pulse_width[23:16];
full_packet[4] = pulse_width[31:24];
// 3. Упаковываем регистр pulse_period [63:32] (байты 5..8)
full_packet[5] = pulse_period[7:0];
full_packet[6] = pulse_period[15:8];
full_packet[7] = pulse_period[23:16];
full_packet[8] = pulse_period[31:24];
// 4. Упаковываем регистр pulse_num [79:64] (байты 9..10)
full_packet[9] = pulse_num[7:0];
full_packet[10] = pulse_num[15:8];
// 5. Упаковываем регистр pulse_height [79+dac_width:80] (байты 11..12)
full_packet[11] = pulse_height[7:0];
full_packet[12] = {2'b00, pulse_height[13:8]}; // дополняем до честного байта
// 6. Упаковываем регистр pulse_period_adc [127:96] (байты 13..16)
full_packet[13] = pulse_period_adc[7:0];
full_packet[14] = pulse_period_adc[15:8];
full_packet[15] = pulse_period_adc[23:16];
full_packet[16] = pulse_period_adc[31:24];
axis_send_packet(
.vif(axis_control_if.tb),
.payload(full_packet)
);
endtask endtask
// Таски сбора и обработки статистики // Таски сбора и обработки статистики
@ -251,6 +189,9 @@ module reflectometer_tb;
// ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ // ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ
//------------------------------------------------------------ //------------------------------------------------------------
initial begin initial begin
automatic virtual axis_if.tb control_vif = axis_control_if.tb;
automatic virtual axis_if.tb accumulator_vif = axis_accumulator_if.tb;
$display("[TB] Tests start"); $display("[TB] Tests start");
// Инициализация // Инициализация
@ -259,16 +200,20 @@ module reflectometer_tb;
rst_n = 1; rst_n = 1;
wait(mmcm_locked === 1'b1); wait(mmcm_locked === 1'b1);
#10; #10;
$display("[TB] MMCM locked");
dut_soft_reset(); dut_soft_reset(control_vif);
// dut_send_system_config( #100;
// .pulse_width(32'd350), dut_send_system_config(
// .pulse_period(32'd1250), .vif(control_vif),
// .pulse_num(16'd10), .pulse_width(32'd350),
// .pulse_height(14'd14000), // 0V .pulse_period(32'd1250),
// .pulse_period_adc(32'd650) .pulse_num(16'd10),
// ); .pulse_height(14'd14000), // 0V
// dut_start(); .pulse_period_adc(32'd650)
);
#100;
dut_start(control_vif);
$display("[TB] ALL PASSED"); $display("[TB] ALL PASSED");
$finish; $finish;