Files
reflectometer_fpga_project/designs/reflectometer_base/reflectometer_tb.sv

277 lines
10 KiB
Systemverilog
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

`timescale 1ns / 1ps
`include "interfaces.svh"
module reflectometer_tb;
//------------------------------------------------------------
// Параметры
//------------------------------------------------------------
localparam int unsigned DAC_DATA_WIDTH = 14;
localparam int unsigned ADC_DATA_WIDTH = 12;
localparam LOGIC_ZERO_LEVEL = 0; // DAC -5V for logic zero
localparam VOLTAGE_ZERO_LEVEL = 2**(DAC_DATA_WIDTH-1); // DAC 0V for logic zero
localparam PACK_FACTOR = 1; // not used in TB
localparam PROCESS_MODE = 0; // 0 - uint, 1 - int
localparam ACCUM_WIDTH = 32; // accumulator number bit witdth
localparam N_MAX = 4096; // max value of windows to average by experiments
localparam WINDOW_SIZE = 65; // fixed subwindow size to average by time
localparam PACKET_SIZE = 1024; // bytes per UDP packet
localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "true"
localparam CLK_ETH_PHY_PERIOD = 8.000; // 125 MHz
localparam CLK_REF_PERIOD = 5.000; // 200 MHz
//------------------------------------------------------------
// Тактовые сигналы и сброс
//------------------------------------------------------------
logic clk_ref = 1'b0; // 200 MHz
logic clk_eth_phy = 1'b0; // common for RX & TX
logic rst_n = 1'b0;
//------------------------------------------------------------
// Управление и конфиг
//------------------------------------------------------------
//------------------------------------------------------------
// Входы
//------------------------------------------------------------
//------------------------------------------------------------
// Выходы
//------------------------------------------------------------
wire mmcm_locked;
//------------------------------------------------------------
// Внутренние сигналы тестбенча
//------------------------------------------------------------
// AXI-S интерфейс для управления
axis_if axis_control_if (
.clk(clk_eth_phy),
.rst_n(rst_n)
);
// AXI-S интерфейс для данных
axis_if axis_accumulator_if (
.clk(clk_eth_phy),
.rst_n(rst_n)
);
// DAC интерфейс
wire clk_dac;
wire dac_wrt;
wire [DAC_DATA_WIDTH-1:0] dac_data;
// ADC интерфейс
wire clk_adc;
wire adc_otr = 1'b0;
wire [ADC_DATA_WIDTH-1:0] adc_data = '0;
// Интерфейс хендшейка с MAC-PHY
wire send_request;
logic request_ready = 1'b0;
// Сигналы ЦАП и АЦП
real signal_voltage;
//------------------------------------------------------------
// Virtual DAC
//------------------------------------------------------------
virtual_dac_model #( // default voltage range is +/- 5V
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
) virtual_dac (
.clk_i(clk_dac),
.wrt_i(dac_wrt),
.data_i(dac_data),
.voltage_o(signal_voltage)
);
//------------------------------------------------------------
// Virtual ADC
//------------------------------------------------------------
virtual_adc_model #( // default voltage range is +/- 5V
.ADC_DATA_WIDTH(ADC_DATA_WIDTH)
) virtual_adc (
.clk_i(clk_adc),
.voltage_i(signal_voltage),
.otr_o(adc_otr),
.data_o(adc_data)
);
//------------------------------------------------------------
// Statistics monitor
//------------------------------------------------------------
//------------------------------------------------------------
// Config handler
//------------------------------------------------------------
//------------------------------------------------------------
// DUT
//------------------------------------------------------------
reflectometer_top #(
.DAC_DATA_WIDTH(DAC_DATA_WIDTH),
.ADC_DATA_WIDTH(ADC_DATA_WIDTH),
.PACK_FACTOR(PACK_FACTOR),
.PROCESS_MODE(PROCESS_MODE),
.ZERO_LEVEL(ZERO_LEVEL),
.ACCUM_WIDTH(ACCUM_WIDTH),
.N_MAX(N_MAX),
.WINDOW_SIZE(WINDOW_SIZE),
.PACKET_SIZE(PACKET_SIZE)
) DUT (
.clk_in(clk_ref),
.rst_n(rst_n),
.locked(mmcm_locked),
// Accumulator AXI-S bus
.clk_axis_accumulator(clk_eth_phy), // GMII PHY RX clock
.axis_accumulator(axis_accumulator_if.master),
// Control AXI-S bus
.clk_axis_control(clk_eth_phy), // GMII PHY TX clock
.axis_control(axis_control_if.slave),
// RTL-MAC handshake
.request_ready(request_ready),
.send_request(send_request),
// DAC
.dac_clk_o(clk_dac),
.dac_data(dac_data),
.dac_wrt(dac_wrt),
// ADC
.adc_clk_o(clk_adc),
.adc_data(adc_data),
.adc_otr(adc_otr)
);
//------------------------------------------------------------
// Тактовые сигналы
//------------------------------------------------------------
initial begin
forever #(CLK_REF_PERIOD/2) clk_ref = ~clk_ref;
end
initial begin
forever #(CLK_ETH_PHY_PERIOD/2) clk_eth_phy = ~clk_eth_phy;
end
//------------------------------------------------------------
// Таски для тестирования
//------------------------------------------------------------
// AXI-S таски
task automatic axis_send_packet(
virtual axis_if.tb vif,
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
task automatic dut_soft_reset();
logic [7:0] cmd[] = '{8'b00001111};
axis_send_packet(
.vif(axis_control_if.tb),
.payload(cmd)
);
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(
input logic [31:0] pulse_width,
input logic [31:0] pulse_period,
input logic [15:0] pulse_num,
input logic [13:0] pulse_height,
input logic [31:0] pulse_period_adc
);
// Выделяем 17 байт: 1 байт команды + 16 байт регистров
logic [7:0] full_packet[17];
// 1. Сначала пишем команду в нулевой байт пакета
full_packet[0] = 8'b10001000; // Твоя команда set_data
// 2. Упаковываем регистр pulse_width [31:0] (байты 1..4)
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
// Таски сбора и обработки статистики
//------------------------------------------------------------
// ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ
//------------------------------------------------------------
initial begin
$display("[TB] Tests start");
// Инициализация
rst_n = 0;
#100;
rst_n = 1;
wait(mmcm_locked === 1'b1);
#10;
dut_soft_reset();
// dut_send_system_config(
// .pulse_width(32'd350),
// .pulse_period(32'd1250),
// .pulse_num(16'd10),
// .pulse_height(14'd14000), // 0V
// .pulse_period_adc(32'd650)
// );
// dut_start();
$display("[TB] ALL PASSED");
$finish;
end
endmodule