`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 //------------------------------------------------------------ // Таски для тестирования //------------------------------------------------------------ task automatic dut_soft_reset(virtual axis_if#(8).tb vif); logic [7:0] tx_packet[]; tx_packet = '{8'h0f}; vif.master_send(tx_packet); endtask task automatic dut_start(virtual axis_if#(8).tb vif); logic [7:0] tx_packet[]; tx_packet = '{8'hf0}; vif.master_send(tx_packet); endtask task automatic dut_send_system_config( virtual axis_if#(8).tb vif, input logic [31:0] pulse_width, input logic [31:0] pulse_period, input logic [15:0] pulse_num, input logic [13:0] pulse_height, // achtung! p_height strictly must have 14 bits of width input logic [31:0] pulse_period_adc ); // Создаем временный фиксированный массив и упаковываем всё одной строкой logic [7:0] tx_packet[]; tx_packet = '{ 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] }; vif.master_send(tx_packet); endtask // Таски сбора и обработки статистики //------------------------------------------------------------ // ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ //------------------------------------------------------------ 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"); // Инициализация rst_n = 0; #100; rst_n = 1; wait(mmcm_locked === 1'b1); #10; $display("[TB] MMCM locked"); dut_soft_reset(control_vif); #100; dut_send_system_config( .vif(control_vif), .pulse_width(32'd350), .pulse_period(32'd1250), .pulse_num(16'd10), .pulse_height(14'd14000), // 0V .pulse_period_adc(32'd650) ); #100; dut_start(control_vif); $display("[TB] ALL PASSED"); $finish; end endmodule