From 5b613191406b8a5038c881d2ea50b362be108314 Mon Sep 17 00:00:00 2001 From: otroubi Date: Tue, 4 Aug 2026 15:46:43 +0300 Subject: [PATCH] adding tests for further modification to the new reflectometer ip --- designs/full_new_reflectometer/tests/Makefile | 75 ---- .../tests/reflectometer_ip/Makefile | 60 +++ .../tests/reflectometer_ip/adc_model.sv | 59 +++ .../tests/reflectometer_ip/dac_model.sv | 58 +++ .../debug.xdc} | 6 +- .../tests/reflectometer_ip/interfaces.svh | 130 ++++++ .../reflectometer_ip/reflectometer_tb.sv | 373 ++++++++++++++++++ .../reflectometer_tb_behav.wcfg | 117 ++++++ .../tests/tb_reflectometer_and_dma_wrapper.sv | 282 ------------- .../tests/test_reflectometer_and_dma.py | 0 10 files changed, 801 insertions(+), 359 deletions(-) delete mode 100644 designs/full_new_reflectometer/tests/Makefile create mode 100644 designs/full_new_reflectometer/tests/reflectometer_ip/Makefile create mode 100644 designs/full_new_reflectometer/tests/reflectometer_ip/adc_model.sv create mode 100644 designs/full_new_reflectometer/tests/reflectometer_ip/dac_model.sv rename designs/full_new_reflectometer/tests/{test_timing.xdc => reflectometer_ip/debug.xdc} (50%) create mode 100644 designs/full_new_reflectometer/tests/reflectometer_ip/interfaces.svh create mode 100644 designs/full_new_reflectometer/tests/reflectometer_ip/reflectometer_tb.sv create mode 100644 designs/full_new_reflectometer/tests/reflectometer_ip/reflectometer_tb_behav.wcfg delete mode 100644 designs/full_new_reflectometer/tests/tb_reflectometer_and_dma_wrapper.sv delete mode 100644 designs/full_new_reflectometer/tests/test_reflectometer_and_dma.py diff --git a/designs/full_new_reflectometer/tests/Makefile b/designs/full_new_reflectometer/tests/Makefile deleted file mode 100644 index 9c40e0f..0000000 --- a/designs/full_new_reflectometer/tests/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -TOPLEVEL_LANG = verilog -SIM ?= verilator - -PWD := $(shell pwd) - -WRAP_DIR = $(PWD)/../src -RTL_CTRL_DIR = $(PWD)/../../controller_new/src -RTL_ACCUM_DIR = $(PWD)/../../accum/src -RTL_GENERATOR_DIR = $(PWD)/../../generator/src -RTL_SAMPLER_DIR = $(PWD)/../../sampler/src -RTL_ADC_DAC_MODELS_DIR = $(PWD)/../reflectometer_base -LIBS_DIR = $(PWD)/../../../external/rtl_libs - -#axi primitives -VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi_pkg.sv -VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi_if.sv -VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axis_if.sv -VERILOG_SOURCES += $(LIBS_DIR)/axi/axi_reg/axi4l_reg_map.sv - -#dma primitives -VERILOG_SOURCES += $(RTL_CTRL_DIR)/dma_reg_pkg.sv -VERILOG_SOURCES += $(LIBS_DIR)/external/verilog-axi/rtl/axi_dma_rd.v -VERILOG_SOURCES += $(LIBS_DIR)/external/verilog-axi/rtl/axi_dma_wr.v -VERILOG_SOURCES += $(LIBS_DIR)/external/verilog-axi/rtl/axi_dma.v -VERILOG_SOURCES += $(WRAP_DIR)/axi_dma_wrapper_if.sv - -# controller primitives -VERILOG_SOURCES += $(RTL_CTRL_DIR)/controller.sv -VERILOG_SOURCES += $(RTL_CTRL_DIR)/dma_controller.sv -VERILOG_SOURCES += $(RTL_CTRL_DIR)/shaper_axis_desc.sv -VERILOG_SOURCES += $(RTL_CTRL_DIR)/shaper_axis_status.sv -VERILOG_SOURCES += $(RTL_CTRL_DIR)/controller_wrapper_axil.sv -VERILOG_SOURCES += $(RTL_CTRL_DIR)/axi4l_reg_map_controller_pkg.sv -VERILOG_SOURCES += $(RTL_CTRL_DIR)/axis_defaults_helper.sv -VERILOG_SOURCES += $(RTL_CTRL_DIR)/axi4l_reg_map_controller.sv - -# accumulator primitives -VERILOG_SOURCES += $(RTL_ACCUM_DIR)/adder.sv -VERILOG_SOURCES += $(RTL_ACCUM_DIR)/accum.sv -VERILOG_SOURCES += $(RTL_ACCUM_DIR)/out_axis_fifo.sv -VERILOG_SOURCES += $(RTL_ACCUM_DIR)/accum_top.sv - -# generator primitives -VERILOG_SOURCES += $(RTL_GENERATOR_DIR)/generator.sv - -#sampler_primitives -VERILOG_SOURCES += $(RTL_SAMPLER_DIR)/sampler.sv - -# project primitives -VERILOG_SOURCES += $(WRAP_DIR)/reflectometer_ip.sv -VERILOG_SOURCES += $(WRAP_DIR)/reflectometer_and_dma_wrapper.sv - -# testbench primitives -VERILOG_SOURCES += $(RTL_ADC_DAC_MODELS_DIR)/adc_model.sv -VERILOG_SOURCES += $(RTL_ADC_DAC_MODELS_DIR)/dac_model.sv -VERILOG_SOURCES += $(PWD)/tb_reflectometer_and_dma_wrapper.sv - -TOPLEVEL = tb_reflectometer_and_dma_wrapper -MODULE = test_reflectometer_and_dma - - -ifeq ($(SIM),verilator) - EXTRA_ARGS += --trace --trace-structs - EXTRA_ARGS += -I$(LIBS_DIR)/axi/rtl/ - COMPILE_ARGS += -Wno-fatal - COMPILE_ARGS += -I$(LIBS_DIR)/axi/rtl/ - EXTRA_ARGS += --trace - EXTRA_ARGS += --trace-structs - EXTRA_ARGS += --public-flat-rw - EXTRA_ARGS += -Wno-fatal - EXTRA_ARGS += --timing -endif - - -include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/designs/full_new_reflectometer/tests/reflectometer_ip/Makefile b/designs/full_new_reflectometer/tests/reflectometer_ip/Makefile new file mode 100644 index 0000000..7ecf4a0 --- /dev/null +++ b/designs/full_new_reflectometer/tests/reflectometer_ip/Makefile @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: MIT +# +# Copyright (c) 2025 FPGA Ninja, LLC +# +# Authors: +# - Alex Forencich +# + +# FPGA settings +FPGA_PART = xc7a100tfgg484-2 +FPGA_TOP = reflectometer_top +FPGA_ARCH = artix7 +SIM_TOP = reflectometer_tb + +RTL_DIR = ../../rtl + + +include ../../scripts/vivado.mk + + +INC_FILES += interfaces.svh + +TB_FILES += reflectometer_tb.sv +SYN_FILES += reflectometer.sv +SYN_FILES += dac_model.sv +SYN_FILES += adc_model.sv +SYN_FILES += reflectometer_tb.sv +SYN_FILES += $(sort $(shell find ../../rtl -type f \( -name '*.v' -o -name '*.sv' \))) + +XCI_FILES = $(sort $(shell find ../../rtl/ethernet-udp/src -type f -name '*.xci')) +XCI_FILES += $(sort $(shell find ip/ -type f -name '*.xci')) + +XDC_FILES += ../../constraints/ax7102.xdc +XDC_FILES += debug.xdc + + + +program: $(PROJECT).bit + echo "open_hw_manager" > program.tcl + echo "connect_hw_server" >> program.tcl + echo "open_hw_target" >> program.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl + echo "set_property PROGRAM.FILE {$(PROJECT).bit} [current_hw_device]" >> program.tcl + echo "program_hw_devices [current_hw_device]" >> program.tcl + echo "exit" >> program.tcl + vivado -nojournal -nolog -mode batch -source program.tcl + +$(PROJECT).mcs $(PROJECT).prm: $(PROJECT).bit + echo "write_cfgmem -force -format mcs -size 16 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; diff --git a/designs/full_new_reflectometer/tests/reflectometer_ip/adc_model.sv b/designs/full_new_reflectometer/tests/reflectometer_ip/adc_model.sv new file mode 100644 index 0000000..dee6ef3 --- /dev/null +++ b/designs/full_new_reflectometer/tests/reflectometer_ip/adc_model.sv @@ -0,0 +1,59 @@ +// AN9238 virtual ADC model (1 port) + +module virtual_adc_model #( + parameter int unsigned ADC_DATA_WIDTH = 12, + + // Bipolar input range: +/- VOLTAGE_RANGE + parameter real VOLTAGE_RANGE = 1.0, + + // Analog input correction + parameter real VOLTAGE_GAIN = 0.2, + parameter real GROUND_BIAS = 0.0, + + // ADC timing parameters + parameter time CONVERSION_DELAY = 250ps +)( + input logic clk_i, + input real voltage_i, + + output logic otr_o, + output logic [ADC_DATA_WIDTH-1:0] data_o +); + + localparam int unsigned ZERO_CODE = (1 << (ADC_DATA_WIDTH - 1)); + localparam real VOLTAGE_STEP = (2 * VOLTAGE_RANGE) / real'((1 << ADC_DATA_WIDTH) - 1); + + real voltage_corrected; + + //------------------------------------------------------------ + // Convert analog voltage to ADC code + //------------------------------------------------------------ + function automatic logic [ADC_DATA_WIDTH-1:0] voltage_to_code( input real voltage ); + if (voltage <= -VOLTAGE_RANGE) return '0; + if (voltage >= VOLTAGE_RANGE) return {ADC_DATA_WIDTH{1'b1}}; + return $rtoi(voltage / VOLTAGE_STEP + real'((ZERO_CODE)) + 0.5); + endfunction + + function automatic logic range_check( input real voltage ); + real v_abs = (voltage < 0.0) ? -voltage : voltage; + return v_abs >= VOLTAGE_RANGE; + endfunction + + //------------------------------------------------------------ + // Initial state + //------------------------------------------------------------ + initial begin + data_o = ZERO_CODE; // 0V + otr_o = 0; + end + + //------------------------------------------------------------ + // Update analog output + //------------------------------------------------------------ + always @(posedge clk_i) begin + voltage_corrected = (voltage_i - GROUND_BIAS) * VOLTAGE_GAIN; + data_o <= #(CONVERSION_DELAY) voltage_to_code(voltage_corrected); + otr_o <= #(CONVERSION_DELAY) range_check(voltage_corrected); + end + +endmodule diff --git a/designs/full_new_reflectometer/tests/reflectometer_ip/dac_model.sv b/designs/full_new_reflectometer/tests/reflectometer_ip/dac_model.sv new file mode 100644 index 0000000..f830117 --- /dev/null +++ b/designs/full_new_reflectometer/tests/reflectometer_ip/dac_model.sv @@ -0,0 +1,58 @@ +// AN9767 model (1 port) + +module virtual_dac_model #( + parameter int unsigned DAC_DATA_WIDTH = 14, + + // Bipolar output range: +/- VOLTAGE_RANGE + parameter real VOLTAGE_RANGE = 5.0, + + // Analog output correction + parameter real VOLTAGE_GAIN = 1.0, + parameter real GROUND_BIAS = 0.0, + + // DAC timing parameters + parameter time TRANSMISSION_DELAY = 150ps, + parameter time CONVERSION_DELAY = 150ps +)( + input logic clk_i, + input logic wrt_i, + input logic [DAC_DATA_WIDTH-1:0] data_i, + + output real voltage_o +); + + localparam int unsigned ZERO_CODE = (1 << (DAC_DATA_WIDTH - 1)); + localparam real VOLTAGE_STEP = (2 * VOLTAGE_RANGE) / real'((1 << DAC_DATA_WIDTH) - 1); + + logic [DAC_DATA_WIDTH-1:0] dac_code; + + //------------------------------------------------------------ + // Convert DAC code to analog voltage + //------------------------------------------------------------ + function automatic real code_to_voltage( input logic [DAC_DATA_WIDTH-1:0] code); + return (int'(code) - int'(ZERO_CODE)) * VOLTAGE_STEP; + endfunction + + //------------------------------------------------------------ + // Initial state + //------------------------------------------------------------ + initial begin + dac_code = '0; + voltage_o = code_to_voltage('0) * VOLTAGE_GAIN + GROUND_BIAS; + end + + //------------------------------------------------------------ + // Latch new DAC code + //------------------------------------------------------------ + always @(posedge wrt_i) begin + dac_code <= #(TRANSMISSION_DELAY) data_i; + end + + //------------------------------------------------------------ + // Update analog output + //------------------------------------------------------------ + always @(posedge clk_i) begin + voltage_o <= #(CONVERSION_DELAY) code_to_voltage(dac_code) * VOLTAGE_GAIN + GROUND_BIAS; + end + +endmodule diff --git a/designs/full_new_reflectometer/tests/test_timing.xdc b/designs/full_new_reflectometer/tests/reflectometer_ip/debug.xdc similarity index 50% rename from designs/full_new_reflectometer/tests/test_timing.xdc rename to designs/full_new_reflectometer/tests/reflectometer_ip/debug.xdc index 12725ca..d408385 100644 --- a/designs/full_new_reflectometer/tests/test_timing.xdc +++ b/designs/full_new_reflectometer/tests/reflectometer_ip/debug.xdc @@ -1,7 +1,9 @@ # Primary clocks -create_clock -name ref_clock -period 5.000 [get_ports ctrl_clk] +create_clock -name ref_clock -period 5.000 [get_ports clk_in] +create_clock -name phy_rx_clock -period 8.000 [get_ports clk_m_axis] +create_clock -name phy_tx_clock -period 8.000 [get_ports clk_s_axis] set clk_125_name [get_clocks -of_objects [get_pins generator_inst/clk_dac_125]] -set clk_65_name [get_clocks -of_objects [get_pins accumulator_top_inst/clk_adc_65]] +set clk_65_name [get_clocks -of_objects [get_pins accumulator_top_dut/clk_adc_65]] set_clock_groups -asynchronous -group $clk_125_name -group $clk_65_name \ No newline at end of file diff --git a/designs/full_new_reflectometer/tests/reflectometer_ip/interfaces.svh b/designs/full_new_reflectometer/tests/reflectometer_ip/interfaces.svh new file mode 100644 index 0000000..8f0c4aa --- /dev/null +++ b/designs/full_new_reflectometer/tests/reflectometer_ip/interfaces.svh @@ -0,0 +1,130 @@ +`ifndef AXIS_INTERFACE_SVH +`define AXIS_INTERFACE_SVH + +interface axis_if #( + parameter int DATA_WIDTH = 8 +)( + input logic clk, + input logic rst_n +); + + // Сигналы шины AXI-Stream + logic [DATA_WIDTH-1:0] tdata; + logic tvalid; + logic tlast; + logic tready; + + 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 + + modport master (output tdata, tvalid, tlast, input tready); + modport slave (input tdata, tvalid, tlast, output tready); + + // Модпорт для тестбенча с тасками + modport tb ( + clocking drv_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` \ No newline at end of file diff --git a/designs/full_new_reflectometer/tests/reflectometer_ip/reflectometer_tb.sv b/designs/full_new_reflectometer/tests/reflectometer_ip/reflectometer_tb.sv new file mode 100644 index 0000000..1d1cbd9 --- /dev/null +++ b/designs/full_new_reflectometer/tests/reflectometer_ip/reflectometer_tb.sv @@ -0,0 +1,373 @@ +`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. Current accumulator don't support signed sum + localparam ACCUM_WIDTH = 32; // accumulator number bit witdth + localparam N_MAX = 4096; // max value of windows to average by experiments + localparam PACKET_SIZE = 1024; // bytes per UDP packet + + localparam int REQUEST_TIMEOUT = 3 * PACKET_SIZE; // timeout for packet receiving from accumulator + + localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "voltage" + + localparam CLK_ETH_PHY_PERIOD = 8.000; // 125 MHz + localparam CLK_REF_PERIOD = 5.000; // 200 MHz + + //------------------------------------------------------------ + // Глобальные перменные + //------------------------------------------------------------ + int unsigned WINDOW_SIZE = 65; // fixed subwindow size to average by time + + //------------------------------------------------------------ + // Тактовые сигналы и сброс + //------------------------------------------------------------ + logic clk_ref = 1'b0; // 200 MHz + logic clk_eth_phy = 1'b0; // common for RX & TX + logic rst_n = 1'b0; + + //------------------------------------------------------------ + // Управление и конфиг DUT + //------------------------------------------------------------ + logic [31:0] window_size; + // AXI-S интерфейс для управления + axis_if axis_control_if ( + .clk(clk_eth_phy), + .rst_n(rst_n) + ); + + //------------------------------------------------------------ + // Входы DUT + //------------------------------------------------------------ + // ADC интерфейс + wire clk_adc; + wire adc_otr; + wire [ADC_DATA_WIDTH-1:0] adc_data; + + //------------------------------------------------------------ + // Выходы + //------------------------------------------------------------ + // Статусы + wire mmcm_locked; + wire workflow_done; + wire processing_done; + // DAC интерфейс + wire clk_dac; + wire dac_wrt; + wire [DAC_DATA_WIDTH-1:0] dac_data; + // AXI-S интерфейс для данных + axis_if axis_accumulator_if ( + .clk(clk_eth_phy), + .rst_n(rst_n) + ); + //------------------------------------------------------------ + // Внутренние сигналы тестбенча + //------------------------------------------------------------ + // Интерфейс хендшейка с MAC-PHY + wire send_request; + logic request_ready; + // Сигнал между ЦАП и АЦП + real signal_voltage; + + //------------------------------------------------------------ + // Virtual DAC + //------------------------------------------------------------ + virtual_dac_model #( // default voltage range is +/- 5V + .DAC_DATA_WIDTH(DAC_DATA_WIDTH) + // ,.VOLTAGE_GAIN(2) + ) 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 processing + //------------------------------------------------------------ + + //------------------------------------------------------------ + // 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), + .PACKET_SIZE(PACKET_SIZE) + ) DUT ( + .clk_in(clk_ref), + .rst_n(rst_n), + + // Status + .locked(mmcm_locked), + .workflow_done(workflow_done), + .processing_done(processing_done), + + // 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), + .window_size(window_size), // direct signal crutch (old controller) + + // 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) + ); + assign window_size = WINDOW_SIZE; + + //------------------------------------------------------------ + // Тактовые сигналы + //------------------------------------------------------------ + 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-Stream + 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, + input logic [31:0] window_size + ); + // Создаем временный фиксированный массив и упаковываем всё одной строкой + logic [7:0] tx_packet[]; + + // Ахтунг, 14-битный ЦАП захардкожен + if (DAC_DATA_WIDTH != 14) + $display("[WARNING] -dut_send_system_config- Default pulse height (DAC bitwidth) is equal to 14. Be aware, controller packet structure is coded for 14 bits"); + + 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); + + // TODO remove for new controller + WINDOW_SIZE = window_size; + endtask + + // Таски сбора статистики + task automatic dut_read_output( + virtual axis_if#(8).tb vif, + input int sample_num, + input bit randomize_recv_delays, + output int output_data[] + ); + logic [7:0] rx_packet[]; + logic [ACCUM_WIDTH-1:0] data_packet[]; + int numbers_per_packet = PACKET_SIZE/(ACCUM_WIDTH/8); + int packet_num = $ceil(real'(sample_num / WINDOW_SIZE) / real'(numbers_per_packet)); + int timeout_flag = 0; + int packet_counter = 0; + + if (sample_num % WINDOW_SIZE) begin + $display("[ERROR] -dut_read_output- Sample_num must be multiple of WINDOW_SIZE: %0d %% %0d = %0d", sample_num, WINDOW_SIZE, sample_num % WINDOW_SIZE); + $finish; + end + + data_packet = new[numbers_per_packet]; + output_data = new[numbers_per_packet * packet_num]; + + // count send_request pulses (equal to number of packets) + fork + begin : packet_counter_proc + forever begin + @(posedge clk_eth_phy); + if(send_request === 1) + packet_counter++; + end + end + join_none + + // Wait until reflectometer done sampling and averaging + wait(processing_done == 1); + + // recv loop + // если число пакетов превышает заложенное предрассчитанное значение -- ошибка + fork : recv_loop_proc + begin + // packet recv loop + forever begin + if (packet_counter > packet_num) begin + $display("[ERROR] -dut_read_output- Packet overflow detected. Number of data packets exceeds expected amount of packets"); + $finish; + end + + if (randomize_recv_delays) + repeat($urandom_range(0, 500)) @(posedge clk_eth_phy); + + timeout_flag = 0; + fork : receive_packet_timeout + begin + request_ready = 1; + vif.slave_recv(rx_packet); + request_ready = 0; + end + begin + repeat(REQUEST_TIMEOUT) @(posedge clk_eth_phy); + timeout_flag = 1; + end + join_any + + disable receive_packet_timeout; + if (timeout_flag) begin + $display("[ERROR] -dut_read_output- Timeout detected when receiving packet"); + $finish; + end + + if (rx_packet.size() != PACKET_SIZE) begin + $display("[ERROR] -dut_read_output- Wrong packet size received: %0d bytes received, %0d bytes expected", rx_packet.size(), PACKET_SIZE); + $finish; + end + + // unpack values + data_packet = {<< byte {rx_packet}}; + data_packet = {<< ACCUM_WIDTH {data_packet}}; + + // copy and convert values + for (int j = 0; j < data_packet.size(); j++) begin + output_data[(packet_counter-1) * data_packet.size() + j] = int'(data_packet[j]); + end + + end + end + begin + // IP workflow completion event + wait(workflow_done == 1); + end + join_any + + disable recv_loop_proc; + disable packet_counter_proc; + + if (packet_counter != packet_num) begin + $display("[ERROR] -dut_read_output- Wrong number of packets received: %0d received, %0d expected", packet_counter, packet_num); + $finish; + end + + endtask + + // Основная таска типового теста + // todo + + //------------------------------------------------------------ + // ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ + //------------------------------------------------------------ + initial begin + int output_data[]; + + automatic virtual axis_if.tb control_vif = axis_control_if.tb; + automatic virtual axis_if.tb accumulator_vif = axis_accumulator_if.tb; + + $display("[TB] DUT initializaton"); + // Инициализация + request_ready = 0; + rst_n = 0; + #100; + rst_n = 1; + wait(mmcm_locked === 1'b1); + #150; + $display("[TB] MMCM locked"); + + dut_soft_reset(control_vif); + #100; + + // Тесты + $display("[TB] Tests start"); + dut_send_system_config( + .vif(control_vif), + .pulse_width(32'd123), + .pulse_period(32'd5000), + .pulse_num(16'd1), + .pulse_height(14'd15000), // 0V + .pulse_period_adc(32'd2600), + .window_size(1) + ); + #100; + dut_start(control_vif); + + dut_read_output( + .vif(accumulator_vif), + .sample_num(2600), + .randomize_recv_delays(0), + .output_data(output_data) + ); + #1000; + + $display("Received %0d numbers", output_data.size()); + for (int i = 0; i < output_data.size(); i++) begin + $write("%0d ", output_data[i]); + end + $display(""); + + $display("[TB] ALL PASSED"); + $finish; + end +endmodule diff --git a/designs/full_new_reflectometer/tests/reflectometer_ip/reflectometer_tb_behav.wcfg b/designs/full_new_reflectometer/tests/reflectometer_ip/reflectometer_tb_behav.wcfg new file mode 100644 index 0000000..b1841ec --- /dev/null +++ b/designs/full_new_reflectometer/tests/reflectometer_ip/reflectometer_tb_behav.wcfg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + rst_n + rst_n + + + mmcm_locked + mmcm_locked + + + Signal + label + + dac_data[13:0] + dac_data[13:0] + + + signal_voltage + signal_voltage + + + adc_data[11:0] + adc_data[11:0] + + + adc_otr + adc_otr + + + + send_request + send_request + + + request_ready + request_ready + + + Controller + label + + + clk + clk + + + rst_n + rst_n + + + tdata[7:0] + tdata[7:0] + + + tvalid + tvalid + + + tlast + tlast + + + tready + tready + + + + Accumulator + label + + + clk + clk + + + rst_n + rst_n + + + tdata[7:0] + tdata[7:0] + + + tvalid + tvalid + + + tlast + tlast + + + tready + tready + + + diff --git a/designs/full_new_reflectometer/tests/tb_reflectometer_and_dma_wrapper.sv b/designs/full_new_reflectometer/tests/tb_reflectometer_and_dma_wrapper.sv deleted file mode 100644 index 98bf458..0000000 --- a/designs/full_new_reflectometer/tests/tb_reflectometer_and_dma_wrapper.sv +++ /dev/null @@ -1,282 +0,0 @@ -import dma_reg_pkg::*; -`timescale 1 ns / 1 ns - -module tb_reflectometer_and_dma_wrapper -#( - // parameters for base reflectometer works - parameter int unsigned DAC_DATA_WIDTH = 14, - parameter int unsigned ADC_DATA_WIDTH = 12, - parameter int unsigned PACK_FACTOR = 1, - parameter int unsigned PROCESS_MODE = 0, - parameter int unsigned ZERO_LEVEL = 8192, - parameter int unsigned ACCUM_WIDTH = 32, - parameter int unsigned N_MAX = 4096, - parameter int unsigned PACKET_SIZE = 1024, - parameter int unsigned RD_FIFO_WIDTH = 32, - - // parameters for DMA and interfaces - parameter int unsigned ADDR_W = 16, - parameter int unsigned DATA_W = 32, - parameter int unsigned USER_W = 1, - - parameter int unsigned DAC_DATA_WIDTH = 12, - - parameter int unsigned AXI_DATA_WIDTH = 32, - - parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8, - parameter int unsigned AXI_ID_WIDTH = 8, - parameter int unsigned AXI_USER_WIDTH = 1, - parameter int unsigned AXI_MAX_BURST_LEN = 16, - - parameter int unsigned AXIS_DATA_WIDTH = AXI_DATA_WIDTH, - parameter int unsigned AXIS_KEEP_ENABLE = AXIS_DATA_WIDTH > 8, - parameter int unsigned AXIS_KEEP_WIDTH = AXIS_DATA_WIDTH / 8, - parameter int unsigned AXIS_LAST_ENABLE = 1, - parameter int unsigned AXIS_ID_ENABLE = 1, - parameter int unsigned AXIS_DEST_ENABLE = 0, - parameter int unsigned AXIS_USER_ENABLE = 1, - - parameter int unsigned ENABLE_SG = 0, - parameter int unsigned ENABLE_UNALIGNED = 0, - - parameter int unsigned PIPELINE_OUTPUT = 0 -) -( - input logic ctrl_clk, - input logic rst_n, - output wire locked, - - input logic [ADDR_W-1:0] s_axil_awaddr, - input logic [2:0] s_axil_awprot, - input logic s_axil_awvalid, - output logic s_axil_awready, - - input logic [DATA_W-1:0] s_axil_wdata, - input logic [DATA_W/8-1:0] s_axil_wstrb, - input logic s_axil_wvalid, - output logic s_axil_wready, - - output logic [1:0] s_axil_bresp, - output logic s_axil_bvalid, - input logic s_axil_bready, - - input logic [ADDR_W-1:0] s_axil_araddr, - input logic [2:0] s_axil_arprot, - input logic s_axil_arvalid, - output logic s_axil_arready, - - output logic [DATA_W-1:0] s_axil_rdata, - output logic [1:0] s_axil_rresp, - output logic s_axil_rvalid, - input logic s_axil_rready, - - output wire [AXIS_DATA_WIDTH-1:0] m_axis_read_data_tdata, - output wire [AXIS_KEEP_WIDTH-1:0] m_axis_read_data_tkeep, - output wire m_axis_read_data_tvalid, - input wire m_axis_read_data_tready, - output wire m_axis_read_data_tlast, - output wire [AXIS_ID_WIDTH-1:0] m_axis_read_data_tid, - output wire [AXIS_DEST_WIDTH-1:0] m_axis_read_data_tdest, - output wire [AXIS_USER_WIDTH-1:0] m_axis_read_data_tuser, - - output wire [AXI_ID_WIDTH-1:0] m_axi_awid, - output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr, - output wire [7:0] m_axi_awlen, - output wire [2:0] m_axi_awsize, - output wire [1:0] m_axi_awburst, - output wire m_axi_awlock, - output wire [3:0] m_axi_awcache, - output wire [2:0] m_axi_awprot, - output wire m_axi_awvalid, - input wire m_axi_awready, - output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata, - output wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb, - output wire m_axi_wlast, - output wire m_axi_wvalid, - input wire m_axi_wready, - input wire [AXI_ID_WIDTH-1:0] m_axi_bid, - input wire [1:0] m_axi_bresp, - input wire m_axi_bvalid, - output wire m_axi_bready, - output wire [AXI_ID_WIDTH-1:0] m_axi_arid, - output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr, - output wire [7:0] m_axi_arlen, - output wire [2:0] m_axi_arsize, - output wire [1:0] m_axi_arburst, - output wire m_axi_arlock, - output wire [3:0] m_axi_arcache, - output wire [2:0] m_axi_arprot, - output wire m_axi_arvalid, - input wire m_axi_arready, - input wire [AXI_ID_WIDTH-1:0] m_axi_rid, - input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata, - input wire [1:0] m_axi_rresp, - input wire m_axi_rlast, - input wire m_axi_rvalid, - output wire m_axi_rready - -); - - logic rst_n; - assign rst_n = ~rst; - - // --------------------------------------------------------------------------- - // AXI-Lite flat -> axi4l_if - // --------------------------------------------------------------------------- - - axi4l_if #( - .ADDR_W(ADDR_W), - .DATA_W(DATA_W), - .USER_W(USER_W) - ) axil_bus ( - .aclk(ctrl_clk), - .aresetn(rst_n) - ); - - axi4l_flat_to_if #( - .ADDR_W(ADDR_W), - .DATA_W(DATA_W), - .USER_W(USER_W) - ) u_axil_flat_to_if ( - .s_axil_awaddr (s_axil_awaddr), - .s_axil_awprot (s_axil_awprot), - .s_axil_awvalid(s_axil_awvalid), - .s_axil_awready(s_axil_awready), - - .s_axil_wdata (s_axil_wdata), - .s_axil_wstrb (s_axil_wstrb), - .s_axil_wvalid (s_axil_wvalid), - .s_axil_wready (s_axil_wready), - - .s_axil_bresp (s_axil_bresp), - .s_axil_bvalid (s_axil_bvalid), - .s_axil_bready (s_axil_bready), - - .s_axil_araddr (s_axil_araddr), - .s_axil_arprot (s_axil_arprot), - .s_axil_arvalid(s_axil_arvalid), - .s_axil_arready(s_axil_arready), - - .s_axil_rdata (s_axil_rdata), - .s_axil_rresp (s_axil_rresp), - .s_axil_rvalid (s_axil_rvalid), - .s_axil_rready (s_axil_rready), - - .m_axil(axil_bus) - ); - - // --------------------------------------------------------------------------- - // AXIS interfaces for the updated controller_wrapper_axil - // --------------------------------------------------------------------------- - -// AXIS READ DATA DMA MASTER output - axis_if #( - .DATA_W (AXIS_DATA_WIDTH), - .KEEP_W (AXIS_KEEP_WIDTH), - .ID_W (AXIS_ID_WIDTH), - .DEST_W (AXIS_DEST_WIDTH), - .USER_W (AXIS_USER_WIDTH) - ) read_data ( - .aclk(ctrl_clk), - .aresetn(rst_n) - ); - -logic [AXIS_KEEP_WIDTH-1:0] unused_read_tstrb; - -axis_if_to_flat #( - .DATA_W (AXIS_DATA_WIDTH), - .KEEP_W (AXIS_KEEP_WIDTH), - .ID_W (AXIS_ID_WIDTH), - .DEST_W (AXIS_DEST_WIDTH), - .USER_W (AXIS_USER_WIDTH) -) u_read_data_if_to_flat ( - .s_axis(read_data), - - .m_axis_tdata (m_axis_read_data_tdata), - .m_axis_tkeep (m_axis_read_data_tkeep), - .m_axis_tstrb (unused_read_tstrb), - .m_axis_tlast (m_axis_read_data_tlast), - .m_axis_tid (m_axis_read_data_tid), - .m_axis_tdest (m_axis_read_data_tdest), - .m_axis_tuser (m_axis_read_data_tuser), - .m_axis_tvalid(m_axis_read_data_tvalid), - .m_axis_tready(m_axis_read_data_tready) -); - - // Интерфейс хендшейка с MAC-PHY - wire send_request; - logic request_ready; - // Сигнал между ЦАП и АЦП - real signal_voltage; - - // ADC интерфейс - wire clk_adc; - wire adc_otr; - wire [ADC_DATA_WIDTH-1:0] adc_data; - - 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) - ); - - // DAC интерфейс - wire clk_dac; - wire dac_wrt; - wire [DAC_DATA_WIDTH-1:0] dac_data; - - virtual_dac_model #( // default voltage range is +/- 5V - .DAC_DATA_WIDTH(DAC_DATA_WIDTH) - // ,.VOLTAGE_GAIN(2) - ) virtual_dac ( - .clk_i(clk_dac), - .wrt_i(dac_wrt), - .data_i(dac_data), - .voltage_o(signal_voltage) - ); - - reflectometer_and_dma_wrapper #( - .DAC_DATA_WIDTH(DAC_DATA_WIDTH), - .ADC_DATA_WIDTH(ADC_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), - .PACKET_SIZE(PACKET_SIZE), - .RD_FIFO_WIDTH(RD_FIFO_WIDTH), - - .AXI_DATA_WIDTH(AXI_DATA_WIDTH), - .AXI_STRB_WIDTH(AXI_STRB_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH), - .AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN), - .AXIS_DATA_WIDTH(AXIS_DATA_WIDTH), - .AXIS_KEEP_ENABLE(AXIS_KEEP_ENABLE), - .AXIS_KEEP_WIDTH(AXIS_KEEP_WIDTH), - .AXIS_LAST_ENABLE(AXIS_LAST_ENABLE), - .AXIS_ID_ENABLE(AXIS_ID_ENABLE), - .AXIS_DEST_ENABLE(AXIS_DEST_ENABLE), - .AXIS_USER_ENABLE(AXIS_USER_ENABLE), - .ENABLE_SG(ENABLE_SG), - .ENABLE_UNALIGNED(ENABLE_UNALIGNED) - ) reflectometer_and_dma_wrapper_dut ( - .ctrl_clk(ctrl_clk), - .rst_n(rst_n), - .locked(locked), - .s_axil(axil_bus), - .m_axi(m_axi), - .m_axis_read_data(read_data), - - .dac_clk_o(clk_dac), - .dac_data(dac_data), - .dac_wrt(dac_wrt), - .adc_clk_o(clk_adc), - .adc_data(adc_data), - .adc_otr(adc_otr) - ); - -endmodule \ No newline at end of file diff --git a/designs/full_new_reflectometer/tests/test_reflectometer_and_dma.py b/designs/full_new_reflectometer/tests/test_reflectometer_and_dma.py deleted file mode 100644 index e69de29..0000000