diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/hdllib.cfg b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/hdllib.cfg index 1b2814376d6cc37507ad76435846f6dbf15fbdd2..ae6e4816942e867c8ed21c7f6dcf59681e4a9987 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/hdllib.cfg +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/hdllib.cfg @@ -9,10 +9,11 @@ hdl_lib_technology = ip_arria10_e2sg test_bench_files = tb_lofar2_unb2c_sdp_station_adc.vhd + tb_lofar2_unb2c_sdp_station_adc_jesd.vhd regression_test_vhdl = tb_lofar2_unb2c_sdp_station_adc.vhd - + tb_lofar2_unb2c_sdp_station_adc_jesd.vhd [modelsim_project_file] modelsim_copy_files = diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/tb_lofar2_unb2c_sdp_station_adc_jesd.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/tb_lofar2_unb2c_sdp_station_adc_jesd.vhd new file mode 100644 index 0000000000000000000000000000000000000000..97d29420f39edcf091aeba0d2273c08023f86fb9 --- /dev/null +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/tb_lofar2_unb2c_sdp_station_adc_jesd.vhd @@ -0,0 +1,366 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2021 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- +-- Author: E. Kooistra, R. van der Walle +-- Purpose: Self-checking testbench for simulating restart of JESD interface +-- rx_clk domain input section in lofar2_unb2c_sdp_station_adc +-- +-- Description: +-- FOR I IN 0 TO c_nof_restarts LOOP +-- . Run WG and ADUH monitor similar as in tb_lofar2_unb2c_sdp_station_adc +-- . Reset the AIT rx_clk somain input section via PIO_JESD_CTRL +-- END LOOP +-- Issue: +-- For some unknown reason the rx_clk does not stop in sim after applying +-- reset via PIO_JESD_CTRL. +---- +-- Usage: +-- > as 7 # default +-- > as 15 # for detailed debugging of JESD204B IP +-- > run -a +-- +------------------------------------------------------------------------------- +LIBRARY IEEE, common_lib, unb2c_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib, lofar2_unb2c_sdp_station_lib, tech_jesd204b_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.MATH_REAL.ALL; +USE common_lib.common_pkg.ALL; +USE unb2c_board_lib.unb2c_board_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE common_lib.common_str_pkg.ALL; +USE mm_lib.mm_file_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE mm_lib.mm_file_unb_pkg.ALL; +USE diag_lib.diag_pkg.ALL; +USE wpfb_lib.wpfb_pkg.ALL; +USE lofar2_sdp_lib.sdp_pkg.ALL; +USE tech_jesd204b_lib.tech_jesd204b_pkg.ALL; + +ENTITY tb_lofar2_unb2c_sdp_station_adc_jesd IS +END tb_lofar2_unb2c_sdp_station_adc_jesd; + +ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_adc_jesd IS + + CONSTANT c_sim : BOOLEAN := TRUE; + CONSTANT c_unb_nr : NATURAL := 0; -- UniBoard 0 + CONSTANT c_node_nr : NATURAL := 0; + CONSTANT c_id : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000"; + CONSTANT c_version : STD_LOGIC_VECTOR(1 DOWNTO 0) := "00"; + CONSTANT c_fw_version : t_unb2c_board_fw_version := (1, 0); + CONSTANT c_init_bsn : NATURAL := 17; -- some recognizable value >= 0 + + CONSTANT c_eth_clk_period : TIME := 8 ns; -- 125 MHz XO on UniBoard + CONSTANT c_ext_clk_period : TIME := 5 ns; + CONSTANT c_bck_ref_clk_period : TIME := 5 ns; + + CONSTANT c_tb_clk_period : TIME := 100 ps; -- use fast tb_clk to speed up M&C + + CONSTANT c_nof_restarts : NATURAL := 1; + CONSTANT c_nof_block_per_sync : NATURAL := 7; -- use short interval to speed up simulation + CONSTANT c_nof_clk_per_sync : NATURAL := c_nof_block_per_sync*c_sdp_N_fft; + CONSTANT c_pps_period : NATURAL := c_nof_clk_per_sync; + + CONSTANT c_percentage : REAL := 0.05; -- percentage that actual value may differ from expected value, due to WG rounding + CONSTANT c_lo_factor : REAL := 1.0 - c_percentage; -- lower boundary + CONSTANT c_hi_factor : REAL := 1.0 + c_percentage; -- higher boundary + + -- WG + CONSTANT c_bsn_start_wg : NATURAL := c_init_bsn + 2; -- start WG at this BSN to instead of some BSN, to avoid mismatches in exact expected data values + CONSTANT c_ampl_sp_0 : NATURAL := c_sdp_FS_adc/2; -- = 0.5 * FS, so in number of lsb + CONSTANT c_wg_freq_offset : REAL := 0.0/11.0; -- in freq_unit + CONSTANT c_subband_sp_0 : REAL := 102.0; -- Select subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz + CONSTANT c_exp_wg_power_sp_0 : REAL := REAL(c_ampl_sp_0**2)/2.0 * REAL(c_nof_clk_per_sync); + + -- ADUH + CONSTANT c_mon_buffer_nof_samples : NATURAL := 512; --samples per stream + + -- MM + CONSTANT c_mm_file_reg_ppsh : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "PIO_PPS"; + CONSTANT c_mm_file_reg_bsn_source_v2 : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2"; + CONSTANT c_mm_file_reg_bsn_scheduler_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SCHEDULER"; + CONSTANT c_mm_file_reg_diag_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG"; + CONSTANT c_mm_file_reg_aduh_mon : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_ADUH_MONITOR"; + CONSTANT c_mm_file_jesd204b : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "JESD204B"; + CONSTANT c_mm_file_pio_jesd_ctrl : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "PIO_JESD_CTRL"; + + -- Tb + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL sim_done : STD_LOGIC := '0'; + SIGNAL tb_clk : STD_LOGIC := '0'; + SIGNAL rd_data : STD_LOGIC_VECTOR(c_32-1 DOWNTO 0); + + SIGNAL pps_rst : STD_LOGIC := '1'; + SIGNAL gen_pps : STD_LOGIC := '0'; + + -- WG + SIGNAL dbg_c_exp_wg_power_sp_0 : REAL := c_exp_wg_power_sp_0; + SIGNAL sp_samples : t_integer_arr(0 TO c_mon_buffer_nof_samples-1) := (OTHERS=>0); + SIGNAL sp_sample : INTEGER := 0; + SIGNAL sp_power_sum : STD_LOGIC_VECTOR(63 DOWNTO 0); + SIGNAL current_bsn_wg : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); + + -- DUT + SIGNAL ext_clk : STD_LOGIC := '0'; + SIGNAL ext_pps : STD_LOGIC := '0'; + + SIGNAL WDI : STD_LOGIC; + SIGNAL INTA : STD_LOGIC; + SIGNAL INTB : STD_LOGIC; + + SIGNAL eth_clk : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0) := (OTHERS => '0'); + SIGNAL eth_txp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0); + SIGNAL eth_rxp : STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 downto 0); + + -- back transceivers + SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 downto 0); + SIGNAL JESD204B_REFCLK : STD_LOGIC := '1'; + + -- jesd204b syncronization signals + SIGNAL jesd204b_sysref : STD_LOGIC; + SIGNAL jesd204b_sync_n : STD_LOGIC_VECTOR(c_sdp_N_sync_jesd-1 DOWNTO 0); + + -- jesd204b IP registers + SIGNAL reg_jesd204b_rx_err0 : STD_LOGIC_VECTOR(tech_jesd204b_field_rx_err0_w-1 DOWNTO 0); + SIGNAL reg_jesd204b_rx_err1 : STD_LOGIC_VECTOR(tech_jesd204b_field_rx_err1_w-1 DOWNTO 0); + SIGNAL reg_jesd204b_csr_rbd_count : STD_LOGIC_VECTOR(tech_jesd204b_field_csr_rbd_count_w-1 DOWNTO 0); + SIGNAL reg_jesd204b_csr_dev_syncn : STD_LOGIC_VECTOR(tech_jesd204b_field_csr_dev_syncn_w-1 DOWNTO 0); + + -- jesd204b ctrl register + SIGNAL pio_jesd_ctrl : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL pio_jesd_ctrl_enable : STD_LOGIC_VECTOR(c_sdp_jesd_ctrl_enable_w-1 DOWNTO 0); + SIGNAL pio_jesd_ctrl_reset : STD_LOGIC; + +BEGIN + + ---------------------------------------------------------------------------- + -- System setup + ---------------------------------------------------------------------------- + ext_clk <= NOT ext_clk AFTER c_ext_clk_period/2; -- External clock (200 MHz) + eth_clk(0) <= NOT eth_clk(0) AFTER c_eth_clk_period/2; -- Ethernet ref clock (125 MHz) + JESD204B_REFCLK <= NOT JESD204B_REFCLK AFTER c_bck_ref_clk_period/2; -- JESD sample clock (200MHz) + + INTA <= 'H'; -- pull up + INTB <= 'H'; -- pull up + + ------------------------------------------------------------------------------ + -- External PPS + ------------------------------------------------------------------------------ + proc_common_gen_pulse(10, c_pps_period, '1', pps_rst, ext_clk, gen_pps); + jesd204b_sysref <= gen_pps; + ext_pps <= gen_pps; + + ------------------------------------------------------------------------------ + -- DUT + ------------------------------------------------------------------------------ + u_lofar_unb2c_sdp_station_adc : ENTITY lofar2_unb2c_sdp_station_lib.lofar2_unb2c_sdp_station + GENERIC MAP ( + g_design_name => "lofar2_unb2c_sdp_station_adc", + g_design_note => "", + g_sim => c_sim, + g_sim_unb_nr => c_unb_nr, + g_sim_node_nr => c_node_nr, + g_bsn_nof_clk_per_sync => c_nof_clk_per_sync, + g_scope_selected_subband => NATURAL(c_subband_sp_0) + ) + PORT MAP ( + -- GENERAL + CLK => ext_clk, + PPS => ext_pps, + WDI => WDI, + INTA => INTA, + INTB => INTB, + + -- Others + VERSION => c_version, + ID => c_id, + TESTIO => open, + + -- 1GbE Control Interface + ETH_CLK => eth_clk, + ETH_SGIN => eth_rxp, + ETH_SGOUT => eth_txp, + + -- LEDs + QSFP_LED => open, + + -- back transceivers + JESD204B_SERIAL_DATA => JESD204B_SERIAL_DATA, + JESD204B_REFCLK => JESD204B_REFCLK, + + -- jesd204b syncronization signals + JESD204B_SYSREF => jesd204b_sysref, + JESD204B_SYNC_N => jesd204b_sync_n + ); + + ------------------------------------------------------------------------------ + -- MM slave accesses via file IO + ------------------------------------------------------------------------------ + tb_clk <= NOT tb_clk AFTER c_tb_clk_period/2; -- Testbench MM clock + + p_mm_stimuli : PROCESS + VARIABLE v_offset : NATURAL; + VARIABLE v_bsn : NATURAL; + VARIABLE v_sp_power_sum_0 : REAL; + VARIABLE v_sp_subband_power : REAL; + VARIABLE v_W, v_T, v_U, v_S, v_B : NATURAL; -- array indicies + BEGIN + FOR REP IN 0 TO c_nof_restarts LOOP + -- Wait for DUT power up after reset or after AIT rx_clk domain restart + WAIT FOR 1 us; + + ---------------------------------------------------------------------------- + -- Enable BS + ---------------------------------------------------------------------------- + mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 2, c_init_bsn, tb_clk); -- Init BSN + mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 3, 0, tb_clk); -- Write high part activates the init BSN + mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 1, c_nof_clk_per_sync, tb_clk); -- nof_block_per_sync + mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 0, 16#00000003#, tb_clk); -- Enable BS at PPS + + -- Release PPS pulser, to get first PPS now and to start BSN source + WAIT FOR 1 us; + pps_rst <= '0'; + + --------------------------------------------------------------------------- + -- Read JESD204B IP status per signal input + --------------------------------------------------------------------------- + -- Note: The IP sim model does not seem to support the mm_clk, so this + -- reads undefined values, see comment in ip_arria10_e2sg_jesd204b.vhd + FOR I IN 0 TO c_sdp_S_pn-1 LOOP + v_offset := I * tech_jesd204b_port_span; + mmf_mm_bus_rd(c_mm_file_jesd204b, v_offset + tech_jesd204b_field_rx_err0_adr, rd_data, tb_clk); + reg_jesd204b_rx_err0 <= rd_data(tech_jesd204b_field_rx_err0_hi DOWNTO tech_jesd204b_field_rx_err0_lo); + mmf_mm_bus_rd(c_mm_file_jesd204b, v_offset + tech_jesd204b_field_rx_err1_adr, rd_data, tb_clk); + reg_jesd204b_rx_err1 <= rd_data(tech_jesd204b_field_rx_err1_hi DOWNTO tech_jesd204b_field_rx_err1_lo); + mmf_mm_bus_rd(c_mm_file_jesd204b, v_offset + tech_jesd204b_field_csr_rbd_count_adr, rd_data, tb_clk); + reg_jesd204b_csr_rbd_count <= rd_data(tech_jesd204b_field_csr_rbd_count_hi DOWNTO tech_jesd204b_field_csr_rbd_count_lo); + mmf_mm_bus_rd(c_mm_file_jesd204b, v_offset + tech_jesd204b_field_csr_dev_syncn_adr, rd_data, tb_clk); + reg_jesd204b_csr_dev_syncn <= rd_data(tech_jesd204b_field_csr_dev_syncn_hi DOWNTO tech_jesd204b_field_csr_dev_syncn_lo); + proc_common_wait_some_cycles(tb_clk, 10); + END LOOP; + + --------------------------------------------------------------------------- + -- Read JESD_CTRL register + --------------------------------------------------------------------------- + -- Note: pio_jesd_ctrl_enable works in fact as disable, so '0' enables + -- signal input and '1' disables it, and read yields + -- pio_jesd_ctrl = 0. + mmf_mm_bus_rd(c_mm_file_pio_jesd_ctrl, 0, rd_data, tb_clk); + pio_jesd_ctrl <= rd_data; + pio_jesd_ctrl_enable <= rd_data(c_sdp_jesd_ctrl_enable_w-1 DOWNTO 0); + pio_jesd_ctrl_reset <= rd_data(c_sdp_jesd_ctrl_reset_bi); + + ---------------------------------------------------------------------------- + -- Enable WG + ---------------------------------------------------------------------------- + -- 0 : mode[7:0] --> off=0, calc=1, repeat=2, single=3) + -- nof_samples[31:16] --> <= c_ram_wg_size=1024 + -- 1 : phase[15:0] + -- 2 : freq[30:0] + -- 3 : ampl[16:0] + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 1, INTEGER( 0.0 * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 2, INTEGER((c_subband_sp_0 + c_wg_freq_offset) * c_sdp_wg_subband_freq_unit), tb_clk); -- freq + mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 3, INTEGER(REAL(c_ampl_sp_0) * c_sdp_wg_ampl_lsb), tb_clk); -- ampl + + -- Read current BSN + mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO 0), tb_clk); + mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 1, current_bsn_wg(63 DOWNTO 32), tb_clk); + proc_common_wait_some_cycles(tb_clk, 1); + + -- Write scheduler BSN to trigger start of WG at next block + v_bsn := TO_UINT(current_bsn_wg) + 2; + ASSERT v_bsn <= c_bsn_start_wg REPORT "Too late to start WG: " & int_to_str(v_bsn) & " > " & int_to_str(c_bsn_start_wg) SEVERITY ERROR; + v_bsn := c_bsn_start_wg; + mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 0, v_bsn, tb_clk); -- first write low then high part + mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 1, 0, tb_clk); -- assume v_bsn < 2**31-1 + + ---------------------------------------------------------------------------- + -- Wait for enough WG data and start of sync interval + ---------------------------------------------------------------------------- + mmf_mm_wait_until_value(c_mm_file_reg_bsn_scheduler_wg, 0, -- read BSN low + "UNSIGNED", rd_data, ">=", c_init_bsn + c_nof_block_per_sync*2, -- this is the wait until condition + c_sdp_T_sub, tb_clk); + + --------------------------------------------------------------------------- + -- Read ADUH monitor power sum + --------------------------------------------------------------------------- + mmf_mm_bus_rd(c_mm_file_reg_aduh_mon, 2, rd_data, tb_clk); -- read low part + sp_power_sum(31 DOWNTO 0) <= rd_data; + mmf_mm_bus_rd(c_mm_file_reg_aduh_mon, 3, rd_data, tb_clk); -- read high part + sp_power_sum(63 DOWNTO 32) <= rd_data; + proc_common_wait_some_cycles(tb_clk, 1); + + --------------------------------------------------------------------------- + -- Verify sp_power_sum + --------------------------------------------------------------------------- + -- Convert STD_LOGIC_VECTOR sp_power_sum to REAL + v_sp_power_sum_0 := REAL(REAL(TO_UINT(sp_power_sum(61 DOWNTO 30)))*REAL(2**30) + REAL(TO_UINT(sp_power_sum(29 DOWNTO 0)))); + + ASSERT v_sp_power_sum_0 > c_lo_factor * c_exp_wg_power_sp_0 REPORT "Wrong SP power for SP 0" SEVERITY ERROR; + ASSERT v_sp_power_sum_0 < c_hi_factor * c_exp_wg_power_sp_0 REPORT "Wrong SP power for SP 0" SEVERITY ERROR; + + ---------------------------------------------------------------------------- + -- Restart AIT + ---------------------------------------------------------------------------- + -- . Disable BSN source to allow rx_clk/dp_clk domain FIFO to empty + mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 0, 16#00000000#, tb_clk); + + -- . Wait until BSN source has finished last block, use ext_clk as 200 MHz equivalent for dp_clk, + -- and wait for > 1 block of c_sdp_N_fft samples + proc_common_wait_some_cycles(ext_clk, c_sdp_N_fft * 2); + + -- . Reset rx_clk domain via JESD_CTRL and read back + -- Note: Awkward way to set MSbit. Options are: + -- . Use directly 16#80000000# + -- . Use parameter c_sdp_jesd_ctrl_reset_bi = 31 and then INTEGER(-1* REAL(2**31)), + -- to avoid INTEGER overflow warning for +2**31 + --mmf_mm_bus_wr(c_mm_file_pio_jesd_ctrl, 0, INTEGER(-1.0 * 2.0**REAL(c_sdp_jesd_ctrl_reset_bi)), tb_clk); + mmf_mm_bus_wr(c_mm_file_pio_jesd_ctrl, 0, 16#80000000# + 2, tb_clk); + proc_common_wait_cross_clock_domain_latency(tb_clk, ext_clk); + mmf_mm_bus_rd(c_mm_file_pio_jesd_ctrl, 0, rd_data, tb_clk); + pio_jesd_ctrl <= rd_data; + pio_jesd_ctrl_enable <= rd_data(c_sdp_jesd_ctrl_enable_w-1 DOWNTO 0); + pio_jesd_ctrl_reset <= rd_data(c_sdp_jesd_ctrl_reset_bi); + + -- For some unknown reason the rx_clk does not stop + WAIT FOR 1 us; + + -- . Re-enable rx_clk domain via JESD_CTRL and read back + mmf_mm_bus_wr(c_mm_file_pio_jesd_ctrl, 0, 2, tb_clk); + proc_common_wait_cross_clock_domain_latency(tb_clk, ext_clk); + mmf_mm_bus_rd(c_mm_file_pio_jesd_ctrl, 0, rd_data, tb_clk); + pio_jesd_ctrl <= rd_data; + pio_jesd_ctrl_enable <= rd_data(c_sdp_jesd_ctrl_enable_w-1 DOWNTO 0); + pio_jesd_ctrl_reset <= rd_data(c_sdp_jesd_ctrl_reset_bi); + + END LOOP; + + --------------------------------------------------------------------------- + -- End Simulation + --------------------------------------------------------------------------- + sim_done <= '1'; + proc_common_wait_some_cycles(ext_clk, 100); + proc_common_stop_simulation(TRUE, ext_clk, sim_done, tb_end); + WAIT; + END PROCESS; + +END tb;