diff --git a/designs/reflectometer_base/Makefile b/designs/reflectometer_base/Makefile index 1c3fe92..caa7662 100644 --- a/designs/reflectometer_base/Makefile +++ b/designs/reflectometer_base/Makefile @@ -17,6 +17,7 @@ RTL_DIR = ../../rtl include ../../scripts/vivado.mk SYN_FILES += reflectometer.sv +SYN_FILES += tb_reflectometer.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')) diff --git a/designs/reflectometer_base/tb_reflectometer.sv b/designs/reflectometer_base/tb_reflectometer.sv new file mode 100644 index 0000000..02d9c00 --- /dev/null +++ b/designs/reflectometer_base/tb_reflectometer.sv @@ -0,0 +1,139 @@ +`timescale 1ns / 1ps + +module tb_reflectometer; + + // parameters + localparam int unsigned DAC_DATA_WIDTH = 14; + localparam int unsigned ADC_DATA_WIDTH = 12; + localparam PACK_FACTOR = 1; // not used in TB + localparam PROCESS_MODE = 0; // 0 - uint, 1 - int + localparam ZERO_LEVEL = 8192; // DAC zero voltage representation (2^14 / 2) + 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 + + // DUT signals + logic clk200, clk_eth_phy_tx, clk_eth_phy_rx; + logic rst_n; + wire [3:0] status_leds; // [ None, dac_start, m_axis_valid, clk_wiz_locked ] + + wire dac_clk, dac_en; + wire [DAC_DATA_WIDTH-1:0] dac_data; + wire adc_clk; + logic adc_otr; + logic [ADC_DATA_WIDTH-1:0] adc_data; + + wire [7:0] s_axis_tx_tdata; + wire s_axis_tx_tvalid; + logic s_axis_tx_tready; + wire s_axis_tx_tlast; + + logic phy_ready; + wire accum_tx_start; + logic [7:0] m_axis_rx_tdata; + logic m_axis_rx_tvalid; + logic m_axis_rx_tlast; + wire m_axis_rx_tready; + + // 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 ( + .sys_clk(clk200), // main clk 200 mhz + .rst_n(rst_n), // rst_n + .led(status_leds), // indication [3:0] + .gmii_rx_clk(clk_eth_phy_rx), // ext. clk from PHY + .gmii_tx_clk(clk_eth_phy_tx), // ext. clk from PHY + // accumulated data stream + .s_axis_tx_tdata(s_axis_tx_tdata), + .s_axis_tx_tvalid(s_axis_tx_tvalid), + .s_axis_tx_tready(s_axis_tx_tready), + .s_axis_tx_tlast(s_axis_tx_tlast), + // controller data stream + .m_axis_rx_tdata(m_axis_rx_tdata), + .m_axis_rx_tvalid(m_axis_rx_tvalid), + .m_axis_rx_tlast(m_axis_rx_tlast), + .m_axis_rx_tready(m_axis_rx_tready), + + .req_ready(phy_ready), // AXI-stream requester ready + .send_req(accum_tx_start), // AXI-stream start transmit + .p2_clk(dac_clk), // DAC clk + .p2_data(dac_data), // DAC [DAC_DATA_WIDTH-1:0] data + .p2_wrt(dac_en), // DAC write enable + .ch2_clk(adc_clk), // ADC clk + .ch2_data(adc_data), // ADC [ADC_DATA_WIDTH-1:0] data + .ch2_otr(adc_otr) // ADC signal out-of-range + ); + + // clocks + initial begin + // 200 MHz + clk200 = 1'b0; + forever #2.5 clk200 = ~clk200; + end + initial begin + // 125 MHz + clk_eth_phy_tx = 1'b0; + forever #4 clk_eth_phy_tx = ~clk_eth_phy_tx; + end + initial begin + // 125 MHz + clk_eth_phy_rx = 1'b0; + forever #4 clk_eth_phy_rx = ~clk_eth_phy_rx; + end + + // ADC input noise simulation + always @(posedge adc_clk or negedge rst_n) begin + if (!rst_n) begin + adc_data <= '0; + end else begin + adc_data <= $urandom() & ((1 << ADC_DATA_WIDTH) - 1); + end + end + assign adc_otr = 1'b0; + + // some helpers for controller axis + + // GAME PLAN + // 1. setup reflectometer + // 2. create some reference signal with noise + virtual ADC + // 3. setup m_axis endpoint for controller to start reflectometer (create multiple tasks) + // 4. setup s_axis endpoint for data gathering and plotting + // 5. check standalone reflectometer + // 6. add reference signal averaging loop throw generator pulse posedge detection + // 7. visual comparision of reference VS reflectometer + // 8. add statistics for signal comparision (MSE/RMSE) + + // main TB + initial begin + // setup + rst_n = 1'b0; + s_axis_tx_tready = 1'b0; + m_axis_rx_tdata = 1'b0; + m_axis_rx_tvalid = 1'b0; + m_axis_rx_tlast = 1'b0; + phy_ready = 1'b0; + + // startup + #100; + rst_n = 1'b1; + wait(DUT.clk_wiz_ctrl_inst.locked == 1'b1); + #20; + $display("=== clocks ready / wiz. locked ==="); + #40; + + + + $display("=== ALL BASIC TESTS PASSED ==="); + $finish; + end +endmodule \ No newline at end of file