diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/hdllib.cfg b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/hdllib.cfg new file mode 100644 index 0000000000000000000000000000000000000000..728eb3310d317b9891f2131dd22635378182690c --- /dev/null +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/hdllib.cfg @@ -0,0 +1,132 @@ +hdl_lib_name = lofar2_unb2c_sdp_station_bf_ring +hdl_library_clause_name = lofar2_unb2c_sdp_station_bf_ring_lib +hdl_lib_uses_synth = common mm technology unb2c_board lofar2_unb2c_sdp_station +hdl_lib_uses_sim = eth +hdl_lib_technology = ip_arria10_e2sg + + synth_files = + lofar2_unb2c_sdp_station_bf_ring.vhd + +test_bench_files = + tb_lofar2_unb2c_sdp_station_bf_ring.vhd + +regression_test_vhdl = + tb_lofar2_unb2c_sdp_station_bf_ring.vhd + +[modelsim_project_file] +modelsim_copy_files = + ../../src/data data + $RADIOHDL_WORK/libraries/dsp/filter/src/hex data # FIR filter coefficients + # Overwrite bf weights with sim data + ../../tb/data data + +[quartus_project_file] +synth_top_level_entity = + +quartus_copy_files = + # Note: path $RADIOHDL_WORK is equivalent to relative path ../../../../../../ + ../../quartus . + ../../src/data data + $RADIOHDL_WORK/libraries/dsp/filter/src/hex data # FIR filter coefficients + +quartus_qsf_files = + $RADIOHDL_WORK/boards/uniboard2c/libraries/unb2c_board/quartus/unb2c_board.qsf + +# use lofar2_unb2c_sdp_station.sdc instead because BCK_REF_CLK is 200MHz, not 644.33MHz. +quartus_sdc_files = + ../../quartus/lofar2_unb2c_sdp_station.sdc + #$RADIOHDL_WORK/boards/uniboard2c/libraries/unb2c_board/quartus/unb2c_board.sdc + +quartus_tcl_files = + lofar2_unb2c_sdp_station_bf_ring_pins.tcl + +quartus_vhdl_files = + +quartus_qip_files = + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station_bf_ring/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station.qip + +quartus_ip_files = + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_avs_common_mm_0.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_avs_common_mm_1.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_avs_eth_0.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_clk_0.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_cpu_0.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_jesd204b.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_jtag_uart_0.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_onchip_memory2_0.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_pio_jesd_ctrl.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_pio_pps.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_pio_system_info.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_pio_wdi.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_bf_weights.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_diag_data_buffer_bsn.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_equalizer_gains.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_fil_coefs.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_scrap.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_ss_ss_wide.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_st_bst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_st_histogram.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_st_sst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_st_xsq.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_ram_wg.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_aduh_monitor.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bf_scale.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_align_v2_bf.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_align_v2_xsub.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_input.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_aligned_bf.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_aligned_xsub.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_beamlet_output.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_bst_offload.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_ring_rx_bf.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_ring_rx_xst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_ring_tx_bf.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_ring_tx_xst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_rx_align_bf.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_rx_align_xsub.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_sst_offload.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_monitor_v2_xst_offload.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_scheduler.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_source_v2.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_bsn_sync_scheduler_xsub.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_crosslets_info.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_diag_data_buffer_bsn.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dp_block_validate_bsn_at_sync_bf.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dp_block_validate_bsn_at_sync_xst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dp_block_validate_err_bf.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dp_block_validate_err_xst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dpmm_ctrl.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dpmm_data.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dp_selector.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dp_shiftram.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_dp_xonoff.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_epcs.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_fpga_temp_sens.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_fpga_voltage_sens.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_hdr_dat.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_mmdp_ctrl.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_mmdp_data.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_nof_crosslets.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_nw_10gbe_eth10g.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_nw_10gbe_mac.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_remu.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_ring_info.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_ring_lane_info_bf.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_ring_lane_info_xst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_sdp_info.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_si.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_stat_enable_bst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_stat_enable_sst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_stat_enable_xst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_stat_hdr_dat_bst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_stat_hdr_dat_sst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_stat_hdr_dat_xst.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_tr_10gbe_eth10g.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_tr_10gbe_mac.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_wdi.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_reg_wg.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_rom_system_info.ip + $RADIOHDL_BUILD_DIR/unb2c/quartus/lofar2_unb2c_sdp_station/ip/qsys_lofar2_unb2c_sdp_station/qsys_lofar2_unb2c_sdp_station_timer_0.ip + +nios2_app_userflags = -DCOMPILE_FOR_GEN2_UNB2 + diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/lofar2_unb2c_sdp_station_bf_ring.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/lofar2_unb2c_sdp_station_bf_ring.vhd new file mode 100644 index 0000000000000000000000000000000000000000..e9e12923f78e08e5ae5f69ab6e74167a3c863a92 --- /dev/null +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/lofar2_unb2c_sdp_station_bf_ring.vhd @@ -0,0 +1,170 @@ +------------------------------------------------------------------------------- +-- +-- 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 : R. van der Walle +-- Purpose: +-- Wrapper for Lofar2 SDP Station beamformer design +-- Description: +-- Unb2c version for lab testing +-- Contains complete AIT input stage with 12 ADC streams, FSUB and BF + + +LIBRARY IEEE, common_lib, unb2c_board_lib, technology_lib, diag_lib, dp_lib, tech_jesd204b_lib, lofar2_unb2c_sdp_station_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE technology_lib.technology_pkg.ALL; +USE unb2c_board_lib.unb2c_board_pkg.ALL; +USE diag_lib.diag_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; + +ENTITY lofar2_unb2c_sdp_station_bf IS + GENERIC ( + g_design_name : STRING := "lofar2_unb2c_sdp_station_bf"; + g_design_note : STRING := "Lofar2 SDP station beamformer design"; + g_sim : BOOLEAN := FALSE; --Overridden by TB + g_sim_unb_nr : NATURAL := 0; + g_sim_node_nr : NATURAL := 0; + g_stamp_date : NATURAL := 0; -- Date (YYYYMMDD) -- set by QSF + g_stamp_time : NATURAL := 0; -- Time (HHMMSS) -- set by QSF + g_revision_id : STRING := "" -- revision ID -- set by QSF + ); + PORT ( + -- GENERAL + CLK : IN STD_LOGIC; -- System Clock + PPS : IN STD_LOGIC; -- System Sync + WDI : OUT STD_LOGIC; -- Watchdog Clear + INTA : INOUT STD_LOGIC; -- FPGA interconnect line + INTB : INOUT STD_LOGIC; -- FPGA interconnect line + + -- Others + VERSION : IN STD_LOGIC_VECTOR(c_unb2c_board_aux.version_w-1 DOWNTO 0); + ID : IN STD_LOGIC_VECTOR(c_unb2c_board_aux.id_w-1 DOWNTO 0); + TESTIO : INOUT STD_LOGIC_VECTOR(c_unb2c_board_aux.testio_w-1 DOWNTO 0); + + -- 1GbE Control Interface + ETH_CLK : IN STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0); + ETH_SGIN : IN STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0); + ETH_SGOUT : OUT STD_LOGIC_VECTOR(c_unb2c_board_nof_eth-1 DOWNTO 0); + + -- Transceiver clocks + SA_CLK : IN STD_LOGIC := '0'; -- Clock 10GbE front (qsfp) and ring lines + + -- front transceivers QSFP0 for Ring. + QSFP_0_RX : IN STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 downto 0) := (OTHERS=>'0'); + QSFP_0_TX : OUT STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 downto 0); + + + -- front transceivers + QSFP_1_RX : IN STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 DOWNTO 0) := (OTHERS=>'0'); + QSFP_1_TX : OUT STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 DOWNTO 0); + + -- LEDs + QSFP_LED : OUT STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp_nof_leds-1 DOWNTO 0); + + -- ring transceivers + RING_0_RX : IN STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 DOWNTO 0) := (OTHERS => '0'); -- Using qsfp bus width also for ring interfaces + RING_0_TX : OUT STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 DOWNTO 0); + RING_1_RX : IN STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 DOWNTO 0) := (OTHERS=>'0'); + RING_1_TX : OUT STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 DOWNTO 0); + + + -- back transceivers (note only 12 are used in unb2c) + BCK_RX : IN STD_LOGIC_VECTOR(c_unb2c_board_nof_tr_jesd204b-1 DOWNTO 0); -- c_unb2c_board_nof_tr_jesd204b = c_sdp_S_pn = 12 + BCK_REF_CLK : IN STD_LOGIC; -- Use as JESD204B_REFCLK + + -- jesd204b syncronization signals (4 syncs) + JESD204B_SYSREF : IN STD_LOGIC; + JESD204B_SYNC_N : OUT STD_LOGIC_VECTOR(c_unb2c_board_nof_sync_jesd204b-1 DOWNTO 0) -- c_unb2c_board_nof_sync_jesd204b = c_sdp_N_sync_jesd = 4 + ); +END lofar2_unb2c_sdp_station_bf; + +ARCHITECTURE str OF lofar2_unb2c_sdp_station_bf IS + + SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR((c_unb2c_board_tr_jesd204b.bus_w*c_unb2c_board_tr_jesd204b.nof_bus)-1 DOWNTO 0); + SIGNAL jesd204b_sync_n_arr : STD_LOGIC_VECTOR(c_unb2c_board_nof_sync_jesd204b-1 DOWNTO 0); + SIGNAL JESD204B_REFCLK : STD_LOGIC; + + +BEGIN + + -- Mapping between JESD signal names and UNB2B pin/schematic names + JESD204B_REFCLK <= BCK_REF_CLK; + JESD204B_SERIAL_DATA <= BCK_RX; + JESD204B_SYNC_N(c_unb2c_board_nof_sync_jesd204b-1 DOWNTO 0) <= jesd204b_sync_n_arr(c_unb2c_board_nof_sync_jesd204b-1 DOWNTO 0); + + u_revision : ENTITY lofar2_unb2c_sdp_station_lib.lofar2_unb2c_sdp_station + GENERIC MAP ( + g_design_name => g_design_name, + g_design_note => g_design_note, + g_sim => g_sim, + g_sim_unb_nr => g_sim_unb_nr, + g_sim_node_nr => g_sim_node_nr, + g_stamp_date => g_stamp_date, + g_stamp_time => g_stamp_time, + g_revision_id => g_revision_id + ) + PORT MAP ( + -- GENERAL + CLK => CLK, + PPS => PPS, + WDI => WDI, + INTA => INTA, + INTB => INTB, + + -- Others + VERSION => VERSION, + ID => ID, + TESTIO => TESTIO, + + -- 1GbE Control Interface + ETH_clk => ETH_clk, + ETH_SGIN => ETH_SGIN, + ETH_SGOUT => ETH_SGOUT, + + -- Transceiver clocks + SA_CLK => SA_CLK, + + -- front transceivers QSFP0 for Ring. + QSFP_0_RX => QSFP_0_RX, + QSFP_0_TX => QSFP_0_TX, + + -- front transceivers QSFP1 for 10GbE output to CEP. + QSFP_1_RX => QSFP_1_RX, + QSFP_1_TX => QSFP_1_TX, + -- LEDs + QSFP_LED => QSFP_LED, + + -- ring transceivers + RING_0_RX => RING_0_RX, + RING_0_TX => RING_0_TX, + RING_1_RX => RING_1_RX, + RING_1_TX => RING_1_TX, + + -- 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_arr + ); +END str; diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/lofar2_unb2c_sdp_station_bf_ring_pins.tcl b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/lofar2_unb2c_sdp_station_bf_ring_pins.tcl new file mode 100644 index 0000000000000000000000000000000000000000..fbaf7c6ca74ab8b72e3a3555b42428fd3fea1573 --- /dev/null +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/lofar2_unb2c_sdp_station_bf_ring_pins.tcl @@ -0,0 +1,25 @@ +############################################################################### +# +# Copyright (C) 2022 +# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################### +source $::env(RADIOHDL_WORK)/applications/lofar2/designs/lofar2_unb2c_sdp_station/quartus/lofar2_unb2c_sdp_station_pins.tcl +source $::env(RADIOHDL_WORK)/applications/lofar2/designs/lofar2_unb2c_sdp_station/quartus/lofar2_unb2c_sdp_station_beamlets_pins.tcl +source $::env(RADIOHDL_WORK)/applications/lofar2/designs/lofar2_unb2c_sdp_station/quartus/lofar2_unb2c_sdp_station_ring_pins.tcl + + diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd new file mode 100644 index 0000000000000000000000000000000000000000..d1efebdef031e01550a6d3853bfcfaa6b94f3f10 --- /dev/null +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd @@ -0,0 +1,1421 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- 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: R. van der Walle (original), E. Kooistra (updates) +-- Purpose: Self-checking testbench for simulating lofar2_unb2c_sdp_station_bf_ring +-- using WG data. +-- +-- Description: +-- This tb is a balance between verification coverage and keeping it simple: +-- - Use only one signal input (g_sp). Put same remnant WG signal on the +-- other signal inputs. +-- - Use different BF weight for the two beamlet polarizations (g_bf_x_gain, +-- g_bf_x_phase and g_bf_y_phase, g_bf_y_phase) of signal input g_sp. +-- Using different BF weights for the N_pol_bf = 2 BF polarizations allows +-- verification of the dual polarization beamlet. +-- - Use same remnant BF weight for the other S_pn - 1 = 11 signal inputs. +-- The remnant signal inputs and BF weights allow verifying the BF sum if +-- they are not 0. Using the same settings for all remnant SP simplyfies +-- the tb, while still testing the BF sum. +-- - Select one beamlet for the subband (g_beamlet). Selecting one beamlet +-- other than the default beamlet for the subband is sufficient to verify +-- the beamlet subband select. +-- - Use same stimuli for both beamsets. +-- +-- MM control actions: +-- +-- 1) Enable calc mode for WG on signal input (si) g_sp via reg_diag_wg with: +-- g_subband = 102 --> 102 * f_sub = 19.921875 MHz +-- g_sp_ampl = 1.0 --> 1.0 yield WG ampl = 2**13 +-- g_sp_phase --> subband phase +-- Use g_sp_remnant_ampl = 0.1 and g_sp_remnant_phase = 0.0 for the other +-- S_pn-1 = 11 signal inputs, than g_sp, that are not used in the BF. +-- +-- 2) Read current BSN from reg_bsn_scheduler_wg and write +-- reg_bsn_scheduler_wg to trigger start of WG at BSN. +-- +-- 3) Read and verify subband statistics (SST) for g_sp. This also reads the +-- SST of the other signal input of the WPFB that processes g_sp. +-- +-- 4) Select subband g_subband for beamlets in g_beamlet +-- +-- 5) Apply BF weight to g_beamlet X beam and Y beam, so for example if g_sp +-- = 3, then w_x3 = g_bf_x_gain/phase and w_y3 = = g_bf_x_gain/phase. The +-- other BF weights are 0. +-- +-- WG BF BF +-- si weight weight +-- X Y +-- 0 -----> * w_x0 ..+ +-- \--------------|----> * w_y0 ..+ +-- 1 -----> * w_x1 ..+ | +-- \--------------|----> * w_y1 ..+ +-- 2 -----> * w_x2 ..+ | +-- \--------------|----> * w_y2 ..+ +-- 3 -----> * w_x3 ..+ | +-- \--------------|----> * w_y3 ..+ +-- 4 -----> * w_x4 ..+ | +-- \--------------|----> * w_y4 ..+ +-- 5 -----> * w_x5 ..+ | +-- \--------------|----> * w_y5 ..+ +-- 6 -----> * w_x6 ..+ | +-- \--------------|----> * w_y6 ..+ +-- 7 -----> * w_x7 ..+ | +-- \--------------|----> * w_y7 ..+ +-- 8 -----> * w_x8 ..+ | +-- \--------------|----> * w_y8 ..+ +-- 9 -----> * w_x9 ..+ | +-- \--------------|----> * w_y9 ..+ +-- 10 -----> * w_x10 ..+ | +-- \--------------|----> * w_y10 ..+ +-- 11 -----> * w_x11 ..+ | +-- \--------------|----> * w_y11 ..+ +-- | | +-- \----------------|---> beamlet_x +-- \--> beamlet_y +-- +-- +-- 6) Read and verify beamlet statistics (BST) +-- View sp_sst in Wave window +-- View bst_x_arr, bst_y_arr in Wave window +-- +-- 7) Verify 10GbE output header and output payload for g_beamlet. +-- View rx_beamlet_sosi +-- View rx_beamlet_cnt (in analog format) +-- +-- Remark: +-- . The c_wg_phase_offset and c_subband_phase_offset are used to tune the WG +-- phase reference to 0.0 degrees at the start (sop) +-- +-- Usage: +-- > as 7 # default +-- > as 12 # for detailed debugging +-- # Manually add missing signal +-- > add wave -position insertpoint \ +-- sim:/tb_lofar2_unb2c_sdp_station_bf_ring/sp_ssts_arr2 \ +-- sim:/tb_lofar2_unb2c_sdp_station_bf_ring/bsts_arr2 +-- > run -a +-- Takes about 40 m when g_read_all_* = FALSE +-- Takes about 1h 5 m when g_read_all_* = TRUE +-- +------------------------------------------------------------------------------- +LIBRARY IEEE, common_lib, unb2c_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib, lofar2_unb2c_sdp_station_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.math_real.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.common_field_pkg.ALL; +USE common_lib.common_network_layers_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 unb2c_board_lib.unb2c_board_pkg.ALL; +USE lofar2_sdp_lib.sdp_pkg.ALL; +USE lofar2_sdp_lib.tb_sdp_pkg.ALL; +USE tech_pll_lib.tech_pll_component_pkg.ALL; + +ENTITY tb_lofar2_unb2c_sdp_station_bf_ring IS + GENERIC ( + g_sp : NATURAL := 3; -- WG signal path (SP) index in range(S_pn = 12) + g_sp_ampl : REAL := 0.5; -- WG normalized amplitude + g_sp_phase : REAL := -110.0; -- WG phase in degrees = subband phase + g_sp_remnant_ampl : REAL := 0.1; -- WG normalized amplitude for remnant sp + g_sp_remnant_phase : REAL := 15.0; -- WG phase in degrees for remnant sp + g_subband : NATURAL := 102; -- select g_subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz + g_beamlet : NATURAL := 10; -- map g_subband to g_beamlet index in beamset in range(c_sdp_S_sub_bf = 488) + g_beamlet_scale : REAL := 1.0 / 2.0**9; -- g_beamlet output scale factor + g_bf_x_gain : REAL := 0.7; -- g_beamlet X BF weight normalized gain for g_sp + g_bf_y_gain : REAL := 0.6; -- g_beamlet Y BF weight normalized gain for g_sp + g_bf_x_phase : REAL := 30.0; -- g_beamlet X BF weight phase rotation in degrees for g_sp + g_bf_y_phase : REAL := 40.0; -- g_beamlet Y BF weight phase rotation in degrees for g_sp + g_bf_remnant_x_gain : REAL := 0.05; -- g_beamlet X BF weight normalized gain for remnant sp + g_bf_remnant_y_gain : REAL := 0.04; -- g_beamlet Y BF weight normalized gain for remnant sp + g_bf_remnant_x_phase : REAL := 170.0; -- g_beamlet X BF weight phase rotation in degrees for g_sp + g_bf_remnant_y_phase : REAL := -135.0; -- g_beamlet Y BF weight phase rotation in degrees for g_sp + g_read_all_SST : BOOLEAN := FALSE; -- when FALSE only read SST for g_subband, to save sim time + g_read_all_BST : BOOLEAN := FALSE -- when FALSE only read BST for g_beamlet, to save sim time + ); +END tb_lofar2_unb2c_sdp_station_bf_ring; + +ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS + + CONSTANT c_sim : BOOLEAN := TRUE; + CONSTANT c_unb_nr : NATURAL := 0; -- UniBoard 0 + CONSTANT c_node_nr : NATURAL := 0; + CONSTANT c_nof_rn : NATURAL := 2; + CONSTANT c_gn_index : NATURAL := c_unb_nr * 4 + c_nof_rn-1; -- end node GN + CONSTANT c_init_bsn : NATURAL := 17; -- some recognizable value >= 0 + CONSTANT c_nof_lanes : NATURAL := c_sdp_N_beamsets; + + CONSTANT c_id : STD_LOGIC_VECTOR(7 DOWNTO 0) := TO_UVEC(c_gn_index, 8); + CONSTANT c_version : STD_LOGIC_VECTOR(1 DOWNTO 0) := "00"; + CONSTANT c_fw_version : t_unb2c_board_fw_version := (1, 0); + + CONSTANT c_mac_15_0 : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(c_unb_nr + ((c_nof_rn-1) / c_quad), 8) & TO_UVEC((c_nof_rn-1) MOD c_quad, 8); + CONSTANT c_ip_15_0 : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(c_unb_nr + ((c_nof_rn-1) / c_quad), 8) & TO_UVEC(((c_nof_rn-1) MOD c_quad) +1, 8); -- +1 to avoid IP = *.*.*.0 + + CONSTANT c_eth_clk_period : TIME := 8 ns; -- 125 MHz XO on UniBoard + CONSTANT c_ext_clk_period : TIME := 5 ns; + CONSTANT c_mm_clk_period : TIME := 10 ns; -- 100 MHz internal mm_clk + CONSTANT c_bck_ref_clk_period : TIME := 5 ns; + CONSTANT c_sa_clk_period : TIME := tech_pll_clk_644_period; -- 644MHz + + CONSTANT c_tb_clk_period : TIME := 100 ps; -- use fast tb_clk to speed up M&C + + CONSTANT c_nof_block_per_sync : NATURAL := 16; + 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_wpfb_sim : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync); + CONSTANT c_stat_data_sz : NATURAL := c_wpfb_sim.stat_data_sz; -- = 2 + + CONSTANT c_stat_percentage : REAL := 0.05; -- +-percentage margin that actual value may differ from expected value + CONSTANT c_stat_lo_factor : REAL := 1.0 - c_stat_percentage; -- lower boundary + CONSTANT c_stat_hi_factor : REAL := 1.0 + c_stat_percentage; -- higher boundary + + CONSTANT c_nof_beamlets_per_data : NATURAL := 2; -- 2 dual pol beamlets (= XY, XY) per 64b data word + + CONSTANT c_beamlet_output_delta : INTEGER := 2; -- +-delta margin + + -- header fields + CONSTANT c_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := c_sdp_cep_eth_dst_mac; -- 00074306C700 = DOP36-eth0 + CONSTANT c_cep_ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0) := c_sdp_cep_ip_dst_addr; -- C0A80001 = '192.168.0.1' = DOP36-eth0 + CONSTANT c_cep_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := c_sdp_cep_udp_dst_port; -- 5000 + + CONSTANT c_cep_eth_src_mac : STD_LOGIC_VECTOR(47 DOWNTO 0) := c_sdp_cep_eth_src_mac_47_16 & c_mac_15_0; -- x"00228608"; -- 47:16, 15:8 = backplane, 7:0 = node + CONSTANT c_cep_ip_src_addr : STD_LOGIC_VECTOR(31 DOWNTO 0) := c_sdp_cep_ip_src_addr_31_16 & c_ip_15_0; -- C0A80001 = '192.168.0.1' = DOP36-eth0 + CONSTANT c_cep_udp_src_port : STD_LOGIC_VECTOR(15 DOWNTO 0) := c_sdp_cep_udp_src_port_15_8 & c_id; -- D0 & c_id + + CONSTANT c_exp_ip_header_checksum : NATURAL := 16#5BDD#; -- value obtained from rx_sdp_cep_header.ip.header_checksum in wave window for c_nof_rn = 2. + + CONSTANT c_exp_beamlet_scale : NATURAL := NATURAL(g_beamlet_scale * REAL(c_sdp_unit_beamlet_scale)); -- c_sdp_unit_beamlet_scale = 2**15; + + CONSTANT c_exp_sdp_info : t_sdp_info := ( + TO_UVEC(601, 16), -- station_id + '0', -- antenna_band_index + x"7FFFFFFF", -- observation_id, use > 0 to avoid Warning: (vsim-151) NUMERIC_STD.TO_INTEGER: Value -2 is not in bounds of subtype NATURAL. + b"01", -- nyquist_zone_index, 0 = first, 1 = second, 2 = third + '1', -- f_adc, 0 = 160 MHz, 1 = 200 MHz + '0', -- fsub_type, 0 = critically sampled, 1 = oversampled + '0', -- beam_repositioning_flag + x"1400" -- block_period = 5120 + ); + + -- 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 + -- .ampl + CONSTANT c_wg_ampl_full_scale : NATURAL := 2**(c_sdp_W_adc-1); -- full scale (FS) of WG, will just cause clipping of +FS to +FS-1 + CONSTANT c_wg_ampl_lsb : REAL := c_diag_wg_ampl_unit / REAL(c_wg_ampl_full_scale); -- amplitude in number of LSbit resolution steps + CONSTANT c_wg_ampl : NATURAL := NATURAL(g_sp_ampl * REAL(c_wg_ampl_full_scale)); -- in number of lsb + CONSTANT c_wg_remnant_ampl : NATURAL := NATURAL(g_sp_remnant_ampl * REAL(c_wg_ampl_full_scale)); -- in number of lsb + CONSTANT c_exp_sp_power : REAL := REAL(c_wg_ampl**2) / 2.0; + CONSTANT c_exp_sp_ast : REAL := c_exp_sp_power * REAL(c_nof_clk_per_sync); + -- . phase + CONSTANT c_subband_freq : REAL := REAL(g_subband) / REAL(c_sdp_N_fft); -- normalized by fs = f_adc = 200 MHz = dp_clk rate + CONSTANT c_wg_latency : INTEGER := c_diag_wg_latency - 0; -- -0 to account for BSN scheduler start trigger latency + CONSTANT c_wg_phase_offset : REAL := 360.0 * REAL(c_wg_latency) * c_subband_freq; -- c_diag_wg_latency is in dp_clk cycles + CONSTANT c_wg_phase : REAL := g_sp_phase + c_wg_phase_offset; -- WG phase in degrees + CONSTANT c_wg_remnant_phase : REAL := g_sp_remnant_phase + c_wg_phase_offset; -- WG phase in degrees + -- . freq + CONSTANT c_wg_subband_freq_unit : REAL := c_diag_wg_freq_unit/REAL(c_sdp_N_fft); -- subband freq = Fs/1024 = 200 MSps/1024 = 195312.5 Hz sinus + + -- WPFB + CONSTANT c_pol_index : NATURAL := g_sp MOD c_sdp_Q_fft; + CONSTANT c_pfb_index : NATURAL := g_sp / c_sdp_Q_fft; -- only read used WPFB unit out of range(c_sdp_P_pfb = 6) + CONSTANT c_subband_phase_offset : REAL := -90.0; -- WG with zero phase sinus yields subband with -90 degrees phase (negative Im, zero Re) + CONSTANT c_subband_weight_gain : REAL := 1.0; -- use default unit subband weights + CONSTANT c_subband_weight_phase : REAL := 0.0; -- use default unit subband weights + CONSTANT c_exp_subband_phase : REAL := g_sp_phase + c_subband_phase_offset + c_subband_weight_phase; + CONSTANT c_exp_subband_ampl : REAL := REAL(c_wg_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio * c_subband_weight_gain; + CONSTANT c_exp_subband_power : REAL := c_exp_subband_ampl**2.0; -- complex signal ampl, so no divide by 2 + CONSTANT c_exp_subband_sst : REAL := c_exp_subband_power * REAL(c_nof_block_per_sync); + + CONSTANT c_exp_remnant_subband_phase : REAL := g_sp_remnant_phase + c_subband_phase_offset + c_subband_weight_phase; + CONSTANT c_exp_remnant_subband_ampl : REAL := REAL(c_wg_remnant_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio * c_subband_weight_gain; + + TYPE t_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL; + TYPE t_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_sub-1); -- 512 + TYPE t_slv_64_beamlets_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_beamlets_sdp-1); -- 2*488 = 976 + + -- BF X-pol and Y-pol + -- . select + CONSTANT c_exp_beamlet_x_index : NATURAL := g_beamlet * c_sdp_N_pol_bf; -- X index in beamset 0 + CONSTANT c_exp_beamlet_y_index : NATURAL := g_beamlet * c_sdp_N_pol_bf + 1; -- Y index in beamset 0 + -- . Beamlet weights for selected g_sp + CONSTANT c_bf_x_weight_re : INTEGER := INTEGER(COMPLEX_RE(g_bf_x_gain * REAL(c_sdp_unit_bf_weight), g_bf_x_phase)); + CONSTANT c_bf_x_weight_im : INTEGER := INTEGER(COMPLEX_IM(g_bf_x_gain * REAL(c_sdp_unit_bf_weight), g_bf_x_phase)); + CONSTANT c_bf_y_weight_re : INTEGER := INTEGER(COMPLEX_RE(g_bf_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_y_phase)); + CONSTANT c_bf_y_weight_im : INTEGER := INTEGER(COMPLEX_IM(g_bf_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_y_phase)); + CONSTANT c_bf_remnant_x_weight_re : INTEGER := INTEGER(COMPLEX_RE(g_bf_remnant_x_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_x_phase)); + CONSTANT c_bf_remnant_x_weight_im : INTEGER := INTEGER(COMPLEX_IM(g_bf_remnant_x_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_x_phase)); + CONSTANT c_bf_remnant_y_weight_re : INTEGER := INTEGER(COMPLEX_RE(g_bf_remnant_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_y_phase)); + CONSTANT c_bf_remnant_y_weight_im : INTEGER := INTEGER(COMPLEX_IM(g_bf_remnant_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_y_phase)); + + -- Model the SDP beamformer for one g_sp and S_pn-1 = 11 remnant signal inputs + FUNCTION bf_calculate_expected_beamlet(sp_subband_ampl, sp_subband_phase, sp_bf_gain, sp_bf_phase, + rem_subband_ampl, rem_subband_phase, rem_bf_gain, rem_bf_phase : REAL) RETURN t_real_arr IS -- 0:3 = ampl, phase, re, im + CONSTANT c_nof_rem : REAL := REAL(c_nof_rn * c_sdp_S_pn - 1); -- BF for one g_sp and N_rn * S_PN - 1 remnant signal inputs + VARIABLE v_sp_ampl, v_sp_phase, v_sp_re, v_sp_im : REAL; + VARIABLE v_rem_ampl, v_rem_phase, v_rem_re, v_rem_im : REAL; + VARIABLE v_sum_ampl, v_sum_phase, v_sum_re, v_sum_im : REAL; + VARIABLE v_tuple : t_real_arr(0 TO 3); + BEGIN + v_sp_ampl := sp_subband_ampl * sp_bf_gain; + v_sp_phase := sp_subband_phase + sp_bf_phase; + v_sp_re := COMPLEX_RE(v_sp_ampl, v_sp_phase); + v_sp_im := COMPLEX_IM(v_sp_ampl, v_sp_phase); + v_rem_ampl := rem_subband_ampl * rem_bf_gain; + v_rem_phase := rem_subband_phase + rem_bf_phase; + v_rem_re := COMPLEX_RE(v_rem_ampl, v_rem_phase); + v_rem_im := COMPLEX_IM(v_rem_ampl, v_rem_phase); + v_sum_re := v_sp_re + c_nof_rem * v_rem_re; -- BF sum re + v_sum_im := v_sp_im + c_nof_rem * v_rem_im; -- BF sum im + v_sum_ampl := COMPLEX_RADIUS(v_sum_re, v_sum_im); + v_sum_phase := COMPLEX_PHASE(v_sum_re, v_sum_im); + v_tuple := (0 => v_sum_ampl, 1 => v_sum_phase, 2 => v_sum_re, 3 => v_sum_im); + RETURN v_tuple; + END; + + -- . Beamlet internal + CONSTANT c_exp_beamlet_x_tuple : t_real_arr(0 TO 3) := bf_calculate_expected_beamlet( + c_exp_subband_ampl, c_exp_subband_phase, g_bf_x_gain, g_bf_x_phase, + c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_x_gain, g_bf_remnant_x_phase); + CONSTANT c_exp_beamlet_x_ampl : REAL := c_exp_beamlet_x_tuple(0); + CONSTANT c_exp_beamlet_x_phase : REAL := c_exp_beamlet_x_tuple(1); + CONSTANT c_exp_beamlet_x_re : REAL := c_exp_beamlet_x_tuple(2); + CONSTANT c_exp_beamlet_x_im : REAL := c_exp_beamlet_x_tuple(3); + + CONSTANT c_exp_beamlet_y_tuple : t_real_arr(0 TO 3) := bf_calculate_expected_beamlet( + c_exp_subband_ampl, c_exp_subband_phase, g_bf_y_gain, g_bf_y_phase, + c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_y_gain, g_bf_remnant_y_phase); + CONSTANT c_exp_beamlet_y_ampl : REAL := c_exp_beamlet_y_tuple(0); + CONSTANT c_exp_beamlet_y_phase : REAL := c_exp_beamlet_y_tuple(1); + CONSTANT c_exp_beamlet_y_re : REAL := c_exp_beamlet_y_tuple(2); + CONSTANT c_exp_beamlet_y_im : REAL := c_exp_beamlet_y_tuple(3); + -- . BST + CONSTANT c_exp_beamlet_x_power : REAL := c_exp_beamlet_x_ampl**2.0; -- complex signal ampl, so no divide by 2 + CONSTANT c_exp_beamlet_x_bst : REAL := c_exp_beamlet_x_power * REAL(c_nof_block_per_sync); + CONSTANT c_exp_beamlet_y_power : REAL := c_exp_beamlet_y_ampl**2.0; -- complex signal ampl, so no divide by 2 + CONSTANT c_exp_beamlet_y_bst : REAL := c_exp_beamlet_y_power * REAL(c_nof_block_per_sync); + -- . Beamlet output + CONSTANT c_exp_beamlet_x_output_ampl : REAL := c_exp_beamlet_x_ampl * g_beamlet_scale; + CONSTANT c_exp_beamlet_x_output_phase : REAL := c_exp_beamlet_x_phase; + CONSTANT c_exp_beamlet_x_output_re : REAL := c_exp_beamlet_x_re * g_beamlet_scale; + CONSTANT c_exp_beamlet_x_output_im : REAL := c_exp_beamlet_x_im * g_beamlet_scale; + CONSTANT c_exp_beamlet_y_output_ampl : REAL := c_exp_beamlet_y_ampl * g_beamlet_scale; + CONSTANT c_exp_beamlet_y_output_phase : REAL := c_exp_beamlet_y_phase; + CONSTANT c_exp_beamlet_y_output_re : REAL := c_exp_beamlet_y_re * g_beamlet_scale; + CONSTANT c_exp_beamlet_y_output_im : REAL := c_exp_beamlet_y_im * g_beamlet_scale; + + -- MM + -- . Address widths of a single MM instance + -- . c_sdp_S_pn = 12 instances + CONSTANT c_addr_w_reg_diag_wg : NATURAL := 2; + -- . c_sdp_N_beamsets = 2 instances + CONSTANT c_addr_w_ram_ss_ss_wide : NATURAL := ceil_log2(c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft); + CONSTANT c_addr_w_ram_bf_weights : NATURAL := ceil_log2(c_sdp_N_pol_bf * c_sdp_P_pfb * c_sdp_S_sub_bf * c_sdp_Q_fft); + CONSTANT c_addr_w_reg_bf_scale : NATURAL := 1; + CONSTANT c_addr_w_reg_hdr_dat : NATURAL := ceil_log2(field_nof_words(c_sdp_cep_hdr_field_arr, c_word_w)); + CONSTANT c_addr_w_reg_dp_xonoff : NATURAL := 1; + CONSTANT c_addr_w_ram_st_bst : NATURAL := ceil_log2(c_sdp_S_sub_bf*c_sdp_N_pol_bf*c_stat_data_sz); + -- . Address spans of a single MM instance + -- . c_sdp_S_pn = 12 instances + CONSTANT c_mm_span_reg_diag_wg : NATURAL := 2**c_addr_w_reg_diag_wg; + -- . c_sdp_N_beamsets = 2 instances + CONSTANT c_mm_span_ram_ss_ss_wide : NATURAL := 2**c_addr_w_ram_ss_ss_wide; + CONSTANT c_mm_span_ram_bf_weights : NATURAL := 2**c_addr_w_ram_bf_weights; + CONSTANT c_mm_span_reg_bf_scale : NATURAL := 2**c_addr_w_reg_bf_scale; + CONSTANT c_mm_span_reg_hdr_dat : NATURAL := 2**c_addr_w_reg_hdr_dat; + CONSTANT c_mm_span_reg_dp_xonoff : NATURAL := 2**c_addr_w_reg_dp_xonoff; + CONSTANT c_mm_span_ram_st_bst : NATURAL := 2**c_addr_w_ram_st_bst; + + 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_ram_equalizer_gains : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_EQUALIZER_GAINS"; + CONSTANT c_mm_file_reg_dp_selector : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_SELECTOR"; + CONSTANT c_mm_file_ram_st_sst : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_SST"; + CONSTANT c_mm_file_ram_st_bst : STRING := mmf_unb_file_prefix(c_unb_nr + ((c_nof_rn-1) / c_quad), (c_nof_rn-1) MOD c_quad) & "RAM_ST_BST"; --end RN + CONSTANT c_mm_file_reg_dp_xonoff : STRING := mmf_unb_file_prefix(c_unb_nr + ((c_nof_rn-1) / c_quad), (c_nof_rn-1) MOD c_quad) & "REG_DP_XONOFF"; --end RN + CONSTANT c_mm_file_ram_ss_ss_wide : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_SS_SS_WIDE"; + CONSTANT c_mm_file_ram_bf_weights : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_BF_WEIGHTS"; + CONSTANT c_mm_file_reg_bf_scale : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BF_SCALE"; + CONSTANT c_mm_file_reg_sdp_info : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_SDP_INFO"; + CONSTANT c_mm_file_reg_hdr_dat : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_HDR_DAT"; -- c_sdp_N_beamsets = 2 beamsets + + -- Tb + SIGNAL stimuli_done : STD_LOGIC := '0'; + SIGNAL tb_almost_end : STD_LOGIC := '0'; + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL tb_clk : STD_LOGIC := '0'; + SIGNAL rd_data : STD_LOGIC_VECTOR(c_32-1 DOWNTO 0); + + SIGNAL dest_rst : STD_LOGIC := '1'; -- use separate destination rst for Rx 10GbE in tb + SIGNAL pps_rst : STD_LOGIC := '1'; -- use separate reset to release the PPS generator + SIGNAL gen_pps : STD_LOGIC := '0'; + + SIGNAL in_sync : STD_LOGIC := '0'; + SIGNAL in_sync_cnt : NATURAL := 0; + SIGNAL test_sync_cnt : INTEGER := 0; + + -- MM + SIGNAL rd_sdp_info : t_sdp_info := c_sdp_info_rst; + SIGNAL rd_beamlet_scale : STD_LOGIC_VECTOR(15 DOWNTO 0); + SIGNAL rd_cep_eth_dst_mac : STD_LOGIC_VECTOR(47 DOWNTO 0); + SIGNAL rd_cep_ip_dst_addr : STD_LOGIC_VECTOR(31 DOWNTO 0); + SIGNAL rd_cep_udp_dst_port : STD_LOGIC_VECTOR(15 DOWNTO 0); + + -- WG + SIGNAL current_bsn_wg : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); + + -- FSUB + -- . Read sp_ssts_arr2 = SST for one WPFB unit that processes g_sp + SIGNAL sp_ssts_arr2 : t_slv_64_subbands_arr(c_sdp_N_pol-1 DOWNTO 0); -- [pol][sub], for X,Y pair of A, B + SIGNAL sp_sst : REAL := 0.0; + SIGNAL stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0); + + -- . Selector + SIGNAL sst_weighted_subbands_flag : STD_LOGIC; + + -- . Subband equalizer + SIGNAL sp_subband_weight_re : INTEGER := 0; + SIGNAL sp_subband_weight_im : INTEGER := 0; + SIGNAL sp_subband_weight_gain : REAL := 0.0; + SIGNAL sp_subband_weight_phase : REAL := 0.0; + + -- BF + -- . beamlet subband selection + SIGNAL sp_subband_select : NATURAL := 0; + SIGNAL sp_subband_select_arr : t_natural_arr(0 TO c_sdp_S_sub_bf * c_sdp_N_pol-1) := (OTHERS => 0); -- Q_fft = N_pol = 2 + + -- . beamlet X-pol + SIGNAL sp_bf_x_weights_re_arr : t_integer_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_x_weights_im_arr : t_integer_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_x_weights_gain_arr : t_real_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); + SIGNAL sp_bf_x_weights_phase_arr : t_real_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); + -- . beamlet Y-pol + SIGNAL sp_bf_y_weights_re_arr : t_integer_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_y_weights_im_arr : t_integer_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0); + SIGNAL sp_bf_y_weights_gain_arr : t_real_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); + SIGNAL sp_bf_y_weights_phase_arr : t_real_arr(0 TO c_nof_rn * c_sdp_S_pn-1) := (OTHERS => 0.0); + + -- . BST + SIGNAL bsts_arr2 : t_slv_64_beamlets_arr(c_sdp_N_pol_bf-1 DOWNTO 0); -- [pol_bf][blet] + SIGNAL bst_x_arr : t_real_arr(0 TO c_sdp_N_beamsets-1) := (OTHERS => 0.0); -- [bset] for BF X pol + SIGNAL bst_y_arr : t_real_arr(0 TO c_sdp_N_beamsets-1) := (OTHERS => 0.0); -- [bset] for BF Y pol + + -- CEP model + -- . 10GbE + SIGNAL tr_10GbE_src_out : t_dp_sosi; + SIGNAL tr_10GbE_src_in : t_dp_siso; + SIGNAL tr_ref_clk_312 : STD_LOGIC := '0'; + SIGNAL tr_ref_clk_156 : STD_LOGIC := '0'; + SIGNAL tr_ref_rst_156 : STD_LOGIC := '0'; + + -- . dp_offload_rx + SIGNAL rx_hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL rx_hdr_dat_miso : t_mem_miso; + + SIGNAL rx_hdr_fields_out : STD_LOGIC_VECTOR(1023 DOWNTO 0); + SIGNAL rx_hdr_fields_raw : STD_LOGIC_VECTOR(1023 DOWNTO 0) := (OTHERS => '0'); + + -- Beamlets packets header + SIGNAL rx_sdp_cep_header : t_sdp_cep_header; + SIGNAL exp_sdp_cep_header : t_sdp_cep_header; + SIGNAL exp_dp_bsn : NATURAL; + + -- Beamlets packets data + SIGNAL rx_beamlet_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0); -- 64 bit + SIGNAL rx_beamlet_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL rx_beamlet_sop_cnt : NATURAL := 0; + SIGNAL rx_beamlet_eop_cnt : NATURAL := 0; + + SIGNAL rx_beamlet_arr_re : t_slv_8_arr(c_sdp_cep_nof_blocks_per_packet-1 DOWNTO 0); -- [3:0] + SIGNAL rx_beamlet_arr_im : t_slv_8_arr(c_sdp_cep_nof_blocks_per_packet-1 DOWNTO 0); -- [3:0] + SIGNAL rx_beamlet_cnt : NATURAL; + SIGNAL rx_beamlet_valid : STD_LOGIC; + + SIGNAL rx_beamlet_list_re : t_slv_8_arr(c_sdp_cep_nof_beamlets_per_block * c_sdp_N_pol_bf-1 DOWNTO 0); -- [488 * 2-1:0] = [975:0] + SIGNAL rx_beamlet_list_im : t_slv_8_arr(c_sdp_cep_nof_beamlets_per_block * c_sdp_N_pol_bf-1 DOWNTO 0); -- [488 * 2-1:0] = [975: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); + + SIGNAL SA_CLK : STD_LOGIC := '1'; + SIGNAL i_QSFP_0_TX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_QSFP_0_RX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_RING_0_TX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_RING_0_RX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_RING_1_TX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_RING_1_RX : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '0')); + SIGNAL i_QSFP_1_lpbk : t_unb2c_board_qsfp_bus_2arr(c_nof_rn -1 DOWNTO 0) := (OTHERS => (OTHERS => '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); + +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) + SA_CLK <= NOT SA_CLK AFTER c_sa_clk_period/2; -- Serial Gigabit IO sa clock (644 MHz) + dest_rst <= '0' AFTER c_ext_clk_period * 10; + + INTA <= 'H'; -- pull up + INTB <= 'H'; -- pull up + + ------------------------------------------------------------------------------ + -- External PPS + ------------------------------------------------------------------------------ + proc_common_gen_pulse(5, c_pps_period, '1', pps_rst, ext_clk, gen_pps); + jesd204b_sysref <= gen_pps; + ext_pps <= gen_pps; + + ------------------------------------------------------------------------------ + -- DUT + ------------------------------------------------------------------------------ + gen_dut : FOR RN IN 0 TO c_nof_rn -1 GENERATE + u_lofar_unb2c_sdp_station_bf : ENTITY lofar2_unb2c_sdp_station_lib.lofar2_unb2c_sdp_station + GENERIC MAP ( + g_design_name => "lofar2_unb2c_sdp_station_bf_ring", + g_design_note => "", + g_sim => c_sim, + g_sim_unb_nr => c_unb_nr + (RN / c_quad), + g_sim_node_nr => RN MOD c_quad, + g_wpfb => c_wpfb_sim, + g_bsn_nof_clk_per_sync => c_nof_clk_per_sync, + g_scope_selected_subband => g_subband + ) + PORT MAP ( + -- GENERAL + CLK => ext_clk, + PPS => ext_pps, + WDI => WDI, + INTA => INTA, + INTB => INTB, + + -- Others + VERSION => c_version, + ID => ( TO_UVEC(RN / c_quad, c_unb2c_board_nof_uniboard_w) & TO_UVEC(RN MOD c_quad, c_unb2c_board_nof_chip_w) ), + TESTIO => open, + + -- 1GbE Control Interface + ETH_CLK => eth_clk, + ETH_SGIN => eth_rxp, + ETH_SGOUT => eth_txp, + + -- Transceiver clocks + SA_CLK => SA_CLK, + -- front transceivers for ring + QSFP_0_RX => i_QSFP_0_RX(RN), + QSFP_0_TX => i_QSFP_0_TX(RN), + + -- ring transceivers + RING_0_RX => i_RING_0_RX(RN), + RING_0_TX => i_RING_0_TX(RN), + RING_1_RX => i_RING_1_RX(RN), + RING_1_TX => i_RING_1_TX(RN), + + -- front transceivers for CEP + QSFP_1_RX => i_QSFP_1_lpbk(RN), + QSFP_1_TX => i_QSFP_1_lpbk(RN), + + -- 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 + ); + END GENERATE; + + -- Ring connections + gen_ring : FOR I IN 0 TO c_nof_rn -2 GENERATE + -- Connect consecutive nodes with RING interfaces (PCB) + i_RING_0_RX(I+1) <= i_RING_1_TX(I); + i_RING_1_RX(I) <= i_RING_0_TX(I+1); + END GENERATE; + + -- Connect first and last nodes with QSFP interface. + i_QSFP_0_RX(0) <= i_QSFP_0_TX(c_nof_rn-1); + i_QSFP_0_RX(c_nof_rn-1) <= i_QSFP_0_TX(0); + + + + ------------------------------------------------------------------------------ + -- CEP model + ------------------------------------------------------------------------------ + u_unb2_board_clk644_pll : ENTITY tech_pll_lib.tech_pll_xgmii_mac_clocks + PORT MAP ( + refclk_644 => SA_CLK, + rst_in => dest_rst, + clk_156 => tr_ref_clk_156, + clk_312 => tr_ref_clk_312, + rst_156 => tr_ref_rst_156, + rst_312 => OPEN + ); + + u_tr_10GbE: ENTITY tr_10GbE_lib.tr_10GbE + GENERIC MAP ( + g_sim => TRUE, + g_sim_level => 1, + g_nof_macs => 1, + g_use_mdio => FALSE + ) + PORT MAP ( + -- Transceiver PLL reference clock + tr_ref_clk_644 => SA_CLK, + tr_ref_clk_312 => tr_ref_clk_312, -- 312.5 MHz for 10GBASE-R + tr_ref_clk_156 => tr_ref_clk_156, -- 156.25 MHz for 10GBASE-R or for XAUI + tr_ref_rst_156 => tr_ref_rst_156, -- for 10GBASE-R or for XAUI + + -- MM interface + mm_rst => dest_rst, + mm_clk => tb_clk, + + -- DP interface + dp_rst => dest_rst, + dp_clk => ext_clk, + + serial_rx_arr(0) => i_QSFP_1_lpbk(c_nof_rn-1)(0), -- Last RN must be used as end node. + + src_out_arr(0) => tr_10GbE_src_out, + src_in_arr(0) => tr_10GbE_src_in + ); + + + u_rx : ENTITY dp_lib.dp_offload_rx + GENERIC MAP ( + g_nof_streams => 1, + g_data_w => c_longword_w, + g_symbol_w => c_octet_w, + g_hdr_field_arr => c_sdp_cep_hdr_field_arr, + g_remove_crc => FALSE, + g_crc_nof_words => 0 + ) + PORT MAP ( + mm_rst => dest_rst, + mm_clk => tb_clk, + + dp_rst => dest_rst, + dp_clk => ext_clk, + + reg_hdr_dat_mosi => rx_hdr_dat_mosi, + reg_hdr_dat_miso => rx_hdr_dat_miso, + + snk_in_arr(0) => tr_10GbE_src_out, + snk_out_arr(0) => tr_10GbE_src_in, + + src_out_arr(0) => rx_beamlet_sosi, + + hdr_fields_out_arr(0) => rx_hdr_fields_out, + hdr_fields_raw_arr(0) => rx_hdr_fields_raw + ); + + ------------------------------------------------------------------------------ + -- 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_bsn : NATURAL; + VARIABLE v_sp_sst : REAL := 0.0; + VARIABLE v_bst : REAL := 0.0; + VARIABLE v_data_lo, v_data_hi : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + VARIABLE v_stat_data : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0); + VARIABLE v_len, v_span, v_offset, v_addr, v_sel : NATURAL; -- address ranges, indices + VARIABLE v_W, v_P, v_PB, v_S, v_A, v_B, v_G : NATURAL; -- array indicies + VARIABLE v_re, v_im, v_weight : INTEGER; + VARIABLE v_re_exp, v_im_exp : REAL := 0.0; + BEGIN + -- Wait for DUT power up after reset + WAIT FOR 1 us; + + print_str(""); + print_str("WG:"); + print_str(". c_wg_ampl = " & int_to_str(c_wg_ampl)); + print_str(". c_exp_sp_power = " & real_to_str(c_exp_sp_power, 20, 1)); + print_str(". c_exp_sp_ast = " & real_to_str(c_exp_sp_ast, 20, 1)); + + print_str(""); + print_str("Subband weight:"); + print_str(". sp_subband_weight_gain = " & real_to_str(sp_subband_weight_gain, 20, 6)); + print_str(". sp_subband_weight_phase = " & real_to_str(sp_subband_weight_phase, 20, 6)); + + print_str(""); + print_str("SST results:"); + print_str(". sst_weighted_subbands_flag = " & sl_to_str(sst_weighted_subbands_flag)); + print_str(""); + print_str(". c_exp_subband_ampl = " & int_to_str(NATURAL(c_exp_subband_ampl))); + print_str(". c_exp_subband_power = " & real_to_str(c_exp_subband_power, 20, 1)); + print_str(". c_exp_subband_sst = " & real_to_str(c_exp_subband_sst, 20, 1)); + print_str(""); + print_str(". sp_sst = " & real_to_str(sp_sst, 20, 1)); + print_str(". sp_sst / c_exp_subband_sst = " & real_to_str(sp_sst / c_exp_subband_sst, 20, 6)); + + print_str(""); + print_str("BST results:"); + print_str(". c_exp_beamlet_x_ampl = " & int_to_str(NATURAL(c_exp_beamlet_x_ampl))); + print_str(". c_exp_beamlet_x_power = " & real_to_str(c_exp_beamlet_x_power, 20, 1)); + print_str(". c_exp_beamlet_x_bst = " & real_to_str(c_exp_beamlet_x_bst, 20, 1)); + print_str(""); + print_str(". c_exp_beamlet_y_ampl = " & int_to_str(NATURAL(c_exp_beamlet_y_ampl))); + print_str(". c_exp_beamlet_y_power = " & real_to_str(c_exp_beamlet_y_power, 20, 1)); + print_str(". c_exp_beamlet_y_bst = " & real_to_str(c_exp_beamlet_y_bst, 20, 1)); + print_str(""); + + ---------------------------------------------------------------------------- + -- Set and check SDP info + ---------------------------------------------------------------------------- + -- TYPE t_sdp_info IS RECORD + -- 7 station_id : STD_LOGIC_VECTOR(15 DOWNTO 0); + -- 6 antenna_band_index : STD_LOGIC; + -- 5 observation_id : STD_LOGIC_VECTOR(31 DOWNTO 0); + -- 4 nyquist_zone_index : STD_LOGIC_VECTOR(1 DOWNTO 0); + -- 3 f_adc : STD_LOGIC; + -- 2 fsub_type : STD_LOGIC; + -- 1 beam_repositioning_flag : STD_LOGIC; + -- 0 block_period : STD_LOGIC_VECTOR(15 DOWNTO 0); + -- END RECORD; + -- . Write + + + FOR RN IN 0 TO c_nof_rn-1 LOOP + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 7, TO_UINT(c_exp_sdp_info.station_id), tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 6, TO_UINT(slv(c_exp_sdp_info.antenna_band_index)), tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 5, TO_UINT(c_exp_sdp_info.observation_id), tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 4, TO_UINT(c_exp_sdp_info.nyquist_zone_index), tb_clk); + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), tb_clk); + -- . Read + mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 3, rd_data, tb_clk); rd_sdp_info.f_adc <= rd_data(0); + mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 2, rd_data, tb_clk); rd_sdp_info.fsub_type <= rd_data(0); + mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO", 0, rd_data, tb_clk); rd_sdp_info.block_period <= rd_data(15 DOWNTO 0); + END LOOP; + + proc_common_wait_some_cycles(tb_clk, 1); + -- . Verify read + ASSERT c_exp_sdp_info.f_adc = rd_sdp_info.f_adc REPORT "Wrong MM read SDP info f_adc" SEVERITY ERROR; + ASSERT c_exp_sdp_info.fsub_type = rd_sdp_info.fsub_type REPORT "Wrong MM read SDP info fsub_type" SEVERITY ERROR; + ASSERT c_exp_sdp_info.block_period = rd_sdp_info.block_period REPORT "Wrong MM read SDP info block_period" SEVERITY ERROR; + + ------------------------------------------------------------------------------ + ---- Set and check BF per beamset + ------------------------------------------------------------------------------ + FOR bset IN 0 TO c_sdp_N_beamsets-1 LOOP + -- MM beamlet_scale + -- . write + v_offset := bset * c_mm_span_reg_bf_scale; + FOR RN IN 0 TO c_nof_rn-1 LOOP + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BF_SCALE", v_offset + 0, c_exp_beamlet_scale, tb_clk); + END LOOP; + proc_common_wait_cross_clock_domain_latency(c_mm_clk_period, c_ext_clk_period); + + -- . readback + mmf_mm_bus_rd(c_mm_file_reg_bf_scale, v_offset + 0, rd_data, tb_clk); + rd_beamlet_scale <= rd_data(15 DOWNTO 0); + proc_common_wait_some_cycles(tb_clk, 1); + ASSERT TO_UINT(rd_beamlet_scale) = c_exp_beamlet_scale REPORT "Wrong MM read beamlet_scale for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR; + + -- CEP beamlet output header + -- c_sdp_cep_hdr_field_arr : t_common_field_arr(c_sdp_cep_nof_hdr_fields-1 DOWNTO 0) := ( + -- 40 "eth_dst_mac" ), "RW", 48, field_default(c_sdp_cep_eth_dst_mac) ), + -- 38 "eth_src_mac" ), "RW", 48, field_default(0) ), + -- 37 "eth_type" ), "RW", 16, field_default(x"0800") ), + -- + -- 36 "ip_version" ), "RW", 4, field_default(4) ), + -- 35 "ip_header_length" ), "RW", 4, field_default(5) ), + -- 34 "ip_services" ), "RW", 8, field_default(0) ), + -- 33 "ip_total_length" ), "RW", 16, field_default(c_sdp_cep_ip_total_length) ), + -- 32 "ip_identification" ), "RW", 16, field_default(0) ), + -- 31 "ip_flags" ), "RW", 3, field_default(2) ), + -- 30 "ip_fragment_offset" ), "RW", 13, field_default(0) ), + -- 29 "ip_time_to_live" ), "RW", 8, field_default(127) ), + -- 28 "ip_protocol" ), "RW", 8, field_default(17) ), + -- 27 "ip_header_checksum" ), "RW", 16, field_default(0) ), + -- 26 "ip_src_addr" ), "RW", 32, field_default(0) ), + -- 25 "ip_dst_addr" ), "RW", 32, field_default(c_sdp_cep_ip_dst_addr) ), + -- + -- 24 "udp_src_port" ), "RW", 16, field_default(0) ), + -- 23 "udp_dst_port" ), "RW", 16, field_default(c_sdp_cep_udp_dst_port) ), + -- 22 "udp_total_length" ), "RW", 16, field_default(c_sdp_cep_udp_total_length) ), + -- 21 "udp_checksum" ), "RW", 16, field_default(0) ), + -- + -- 20 "sdp_marker" ), "RW", 8, field_default(c_sdp_marker_beamlets) ), + -- 19 "sdp_version_id" ), "RW", 8, field_default(c_sdp_cep_version_id) ), + -- 18 "sdp_observation_id" ), "RW", 32, field_default(0) ), + -- 17 "sdp_station_id" ), "RW", 16, field_default(0) ), + -- + -- 16 "sdp_source_info_antenna_band_id" ), "RW", 1, field_default(0) ), + -- 15 "sdp_source_info_nyquist_zone_id" ), "RW", 2, field_default(0) ), + -- 14 "sdp_source_info_f_adc" ), "RW", 1, field_default(0) ), + -- 13 "sdp_source_info_fsub_type" ), "RW", 1, field_default(0) ), + -- 12 "sdp_source_info_payload_error" ), "RW", 1, field_default(0) ), + -- 11 "sdp_source_info_repositioning_flag" ), "RW", 1, field_default(0) ), + -- 10 "sdp_source_info_beamlet_width" ), "RW", 4, field_default(c_sdp_W_beamlet) ), + -- 9 "sdp_source_info_gn_id" ), "RW", 5, field_default(0) ), + -- + -- 7 "sdp_reserved" ), "RW", 40, field_default(0) ), + -- 6 "sdp_beamlet_scale" ), "RW", 16, field_default(c_sdp_beamlet_scale_default) ), + -- 5 "sdp_beamlet_index" ), "RW", 16, field_default(0) ), + -- 4 "sdp_nof_blocks_per_packet" ), "RW", 8, field_default(c_sdp_cep_nof_blocks_per_packet) ), + -- 3 "sdp_nof_beamlets_per_block" ), "RW", 16, field_default(c_sdp_cep_nof_beamlets_per_block) ), + -- 2 "sdp_block_period" ), "RW", 16, field_default(c_sdp_block_period) ), + -- + -- 0 "dp_bsn" ), "RW", 64, field_default(0) ) + -- ); + + v_offset := bset * c_mm_span_reg_hdr_dat; + -- . Use defaults, so no need to write + -- . Read + mmf_mm_bus_rd(c_mm_file_reg_hdr_dat, v_offset + 41, rd_data, tb_clk); rd_cep_eth_dst_mac(47 DOWNTO 32) <= rd_data(15 DOWNTO 0); + mmf_mm_bus_rd(c_mm_file_reg_hdr_dat, v_offset + 40, rd_data, tb_clk); rd_cep_eth_dst_mac(31 DOWNTO 0) <= rd_data; + mmf_mm_bus_rd(c_mm_file_reg_hdr_dat, v_offset + 25, rd_data, tb_clk); rd_cep_ip_dst_addr <= rd_data; + mmf_mm_bus_rd(c_mm_file_reg_hdr_dat, v_offset + 23, rd_data, tb_clk); rd_cep_udp_dst_port <= rd_data(15 DOWNTO 0); + proc_common_wait_some_cycles(tb_clk, 1); + + -- verify read + ASSERT rd_cep_eth_dst_mac = c_sdp_cep_eth_dst_mac REPORT "Wrong MM read rd_cep_eth_dst_mac for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR; -- 00074306C700 = DOP36-eth0 + ASSERT rd_cep_ip_dst_addr = c_sdp_cep_ip_dst_addr REPORT "Wrong MM read rd_cep_ip_dst_addr for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR; -- C0A80001 = '192.168.0.1' = DOP36-eth0 + ASSERT rd_cep_udp_dst_port = c_sdp_cep_udp_dst_port REPORT "Wrong MM read rd_cep_udp_dst_port for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR; -- 5000 + + ---------------------------------------------------------------------------- + -- Enable beamlet UDP offload off end node (dp_xonoff) + ---------------------------------------------------------------------------- + v_offset := bset * c_mm_span_reg_dp_xonoff; + mmf_mm_bus_wr(c_mm_file_reg_dp_xonoff, v_offset + 0, 1, tb_clk); + END LOOP; + + ---------------------------------------------------------------------------- + -- Enable BS + ---------------------------------------------------------------------------- + FOR RN IN 0 TO c_nof_rn-1 LOOP + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SOURCE_V2", 2, c_init_bsn, tb_clk); -- Init BSN + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SOURCE_V2", 3, 0, tb_clk); -- Write high part a + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SOURCE_V2", 1, c_nof_clk_per_sync, tb_clk); -- nof_block_per_syn + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SOURCE_V2", 0, 16#00000003#, tb_clk); -- Enable BS at PPS + END LOOP; + + -- Release PPS pulser, to get first PPS now and to start BSN source + WAIT FOR 1 us; + pps_rst <= '0'; + + ---------------------------------------------------------------------------- + -- Ring config + ---------------------------------------------------------------------------- + -- Write ring configuration to all nodes. + FOR RN IN 0 TO c_nof_rn-1 LOOP + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_INFO", 2, c_nof_rn, tb_clk); -- N_rn + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_INFO", 3, 0, tb_clk); -- O_rn + END LOOP; + + -- Start node specific settings + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr, 0) & "REG_RING_INFO", 0, 1, tb_clk); -- use_ring_to_previous_rn = 1 + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr, 0) & "REG_RING_INFO", 1, 0, tb_clk); -- use_ring_to_next_rn = 0 + + -- End node specific settings + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + ((c_nof_rn-1) / c_quad), (c_nof_rn-1) MOD c_quad) & "REG_RING_INFO", 0, 0, tb_clk); -- use_ring_to_previous_rn = 0 + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + ((c_nof_rn-1) / c_quad), (c_nof_rn-1) MOD c_quad) & "REG_RING_INFO", 1, 1, tb_clk); -- use_ring_to_next_rn = 1 + + -- Access scheme 1. Each RN uses and sends them along the ring. + FOR RN IN 0 TO c_nof_rn-1 LOOP + FOR I IN 0 TO c_nof_lanes-1 LOOP + IF RN = c_nof_rn-1 THEN + -- End RN, so set transport_nof_hops to 0. + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_LANE_INFO_BF", I*2+1, 0, tb_clk); + ELSE + -- Set transport_nof_hops to 1 on all nodes. + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_LANE_INFO_BF", I*2+1, 1, tb_clk); + END IF; + END LOOP; + END LOOP; + + ---------------------------------------------------------------------------- + -- Enable and start 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] + -- . Put wanted signal on g_sp input and remnant signal on the other inputs + FOR RN IN 0 TO c_nof_rn-1 LOOP + FOR I IN 0 TO c_sdp_S_pn-1 LOOP + IF RN * c_sdp_S_pn + I = g_sp THEN + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 1, INTEGER(c_wg_phase * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 2, INTEGER(REAL(g_subband) * c_wg_subband_freq_unit), tb_clk); -- freq + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 3, INTEGER(REAL(c_wg_ampl) * c_wg_ampl_lsb), tb_clk); -- ampl + ELSE + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 0, 1024*2**16 + 1, tb_clk); -- nof_samples, mode calc + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 1, INTEGER(c_wg_remnant_phase * c_diag_wg_phase_unit), tb_clk); -- phase offset in degrees + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 2, INTEGER(REAL(g_subband) * c_wg_subband_freq_unit), tb_clk); -- freq + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_WG", I*4 + 3, INTEGER(REAL(c_wg_remnant_ampl) * c_wg_ampl_lsb), tb_clk); -- ampl + END IF; + END LOOP; + END LOOP; + + + -- 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; + + FOR RN IN 0 TO c_nof_rn-1 LOOP + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SCHEDULER", 0, c_bsn_start_wg, tb_clk); -- first write low then high part + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BSN_SCHEDULER", 1, 0, tb_clk); -- assume v_bsn < 2**31-1 + END LOOP; + + ---------------------------------------------------------------------------- + -- Read weighted subband selector + ---------------------------------------------------------------------------- + mmf_mm_bus_rd(c_mm_file_reg_dp_selector, 0, rd_data, tb_clk); + sst_weighted_subbands_flag <= NOT rd_data(0); + proc_common_wait_some_cycles(tb_clk, 1); + + ---------------------------------------------------------------------------- + -- Subband weight + ---------------------------------------------------------------------------- + + -- . MM format: (cint16)RAM_EQUALIZER_GAINS[S_pn/Q_fft]_[Q_fft][N_sub] = [S_pn][N_sub] + v_addr := g_sp * c_sdp_N_sub + g_subband; + -- . read + mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains, v_addr, rd_data, tb_clk); + v_re := unpack_complex_re(rd_data, c_sdp_W_sub_weight); + v_im := unpack_complex_im(rd_data, c_sdp_W_sub_weight); + sp_subband_weight_re <= v_re; + sp_subband_weight_im <= v_im; + sp_subband_weight_gain <= COMPLEX_RADIUS(v_re, v_im) / REAL(c_sdp_unit_sub_weight); + sp_subband_weight_phase <= COMPLEX_PHASE(v_re, v_im); + + -- No need to write subband weight, because default it is unit weight + + ---------------------------------------------------------------------------- + -- Subband select to map subband to beamlet + ---------------------------------------------------------------------------- + -- . MM format: (uint16)RAM_SS_SS_WIDE[N_beamsets][A_pn]_[S_sub_bf][Q_fft], Q_fft = N_pol = 2 + + -- . write selection, only for g_beamlet to save sim time + v_span := true_log_pow2(c_sdp_N_pol * c_sdp_S_sub_bf); -- = 1024 + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + -- Same selection for both beamsets + -- Select beamlet g_beamlet to subband g_subband + FOR A IN 0 TO c_sdp_A_pn-1 LOOP + -- Same selection to all SP + FOR P IN 0 TO c_sdp_N_pol-1 LOOP + v_addr := P + g_beamlet * c_sdp_N_pol + A * v_span + U * c_mm_span_ram_ss_ss_wide; + v_sel := P + g_subband * c_sdp_N_pol; + FOR RN IN 0 TO c_nof_rn-1 LOOP + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "RAM_SS_SS_WIDE", v_addr, v_sel, tb_clk); + END LOOP; + END LOOP; + END LOOP; + END LOOP; + + -- . read back selection for g_sp = c_pfb_index * c_sdp_N_pol + c_pol_index + v_P := c_pol_index; + v_A := c_pfb_index; + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + -- Same selection for both beamsets, so fine to use only one sp_subband_select_arr() + FOR B IN 0 TO c_sdp_S_sub_bf-1 LOOP + -- Same selection for all SP, so fine to only read subband selection for g_sp + v_addr := v_P + B * c_sdp_N_pol + v_A * v_span + U * c_mm_span_ram_ss_ss_wide; + mmf_mm_bus_rd(c_mm_file_ram_ss_ss_wide, v_addr, rd_data, tb_clk); + v_sel := (TO_UINT(rd_data) - v_P) / c_sdp_N_pol; + sp_subband_select_arr(B) <= v_sel; + sp_subband_select <= v_sel; -- for time series view in Wave window + END LOOP; + END LOOP; + proc_common_wait_some_cycles(tb_clk, 1); + proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window + + ---------------------------------------------------------------------------- + -- Write beamlet weight for g_beamlet in S_sub_bf + ---------------------------------------------------------------------------- + -- . MM format: (cint16)RAM_BF_WEIGHTS[N_beamsets][N_pol_bf][A_pn]_[N_pol][S_sub_bf] + + -- . write BF weights, only for g_beamlet to save sim time + v_span := true_log_pow2(c_sdp_N_pol * c_sdp_S_sub_bf); -- = 1024 + FOR RN IN 0 TO c_nof_rn-1 LOOP + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + -- Same BF weights for both beamsets + FOR PB IN 0 TO c_sdp_N_pol_bf-1 LOOP + -- Same BF weights for both beamlet polarizations + FOR A IN 0 TO c_sdp_A_pn-1 LOOP + FOR P IN 0 TO c_sdp_N_pol-1 LOOP + v_S := RN * c_sdp_S_pn + A * c_sdp_N_pol + P; + IF v_S = g_sp THEN + -- use generic BF weight for g_sp in g_beamlet + IF PB = 0 THEN + v_weight := pack_complex(re => c_bf_x_weight_re, im => c_bf_x_weight_im, w => c_sdp_W_bf_weight); + ELSE + v_weight := pack_complex(re => c_bf_y_weight_re, im => c_bf_y_weight_im, w => c_sdp_W_bf_weight); + END IF; + ELSE + -- use the remnant BF weights for the other SP + IF PB = 0 THEN + v_weight := pack_complex(re => c_bf_remnant_x_weight_re, im => c_bf_remnant_x_weight_im, w => c_sdp_W_bf_weight); + ELSE + v_weight := pack_complex(re => c_bf_remnant_y_weight_re, im => c_bf_remnant_y_weight_im, w => c_sdp_W_bf_weight); + END IF; + END IF; + v_addr := g_beamlet; -- beamlet index + v_addr := v_addr + P * c_sdp_S_sub_bf; -- antenna input polarization address offset + v_addr := v_addr + A * v_span; -- antenna input address offset + v_addr := v_addr + PB * c_sdp_A_pn * v_span; -- beamlet polarization address offset + v_addr := v_addr + U * c_mm_span_ram_bf_weights; -- beamset address offset + mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "RAM_BF_WEIGHTS", v_addr, v_weight, tb_clk); + END LOOP; + END LOOP; + END LOOP; + END LOOP; + END LOOP; + + -- . read back BF weights for g_beamlet in S_sub_bf + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + FOR PB IN 0 TO c_sdp_N_pol_bf-1 LOOP + FOR A IN 0 TO c_sdp_A_pn-1 LOOP + FOR P IN 0 TO c_sdp_N_pol-1 LOOP + v_addr := g_beamlet; -- beamlet index + v_addr := v_addr + P * c_sdp_S_sub_bf; -- antenna input polarization address offset + v_addr := v_addr + A * v_span; -- antenna input address offset + v_addr := v_addr + PB * c_sdp_A_pn * v_span; -- beamlet polarization address offset + v_addr := v_addr + U * c_mm_span_ram_bf_weights; -- beamset address offset + mmf_mm_bus_rd(c_mm_file_ram_bf_weights, v_addr, rd_data, tb_clk); + v_re := unpack_complex_re(rd_data, c_sdp_W_bf_weight); + v_im := unpack_complex_im(rd_data, c_sdp_W_bf_weight); + -- same BF weights for both beamsets and both beamlet polarizations, + -- so fine to use only one sp_bf_x_weights_*_arr() + v_S := A * c_sdp_N_pol + P; + IF PB = 0 THEN + sp_bf_x_weights_re_arr(v_S) <= v_re; + sp_bf_x_weights_im_arr(v_S) <= v_im; + sp_bf_x_weights_gain_arr(v_S) <= COMPLEX_RADIUS(v_re, v_im) / REAL(c_sdp_unit_bf_weight); + sp_bf_x_weights_phase_arr(v_S) <= COMPLEX_PHASE(v_re, v_im); + ELSE + sp_bf_y_weights_re_arr(v_S) <= v_re; + sp_bf_y_weights_im_arr(v_S) <= v_im; + sp_bf_y_weights_gain_arr(v_S) <= COMPLEX_RADIUS(v_re, v_im) / REAL(c_sdp_unit_bf_weight); + sp_bf_y_weights_phase_arr(v_S) <= COMPLEX_PHASE(v_re, v_im); + END IF; + END LOOP; + END LOOP; + END LOOP; + END LOOP; + proc_common_wait_some_cycles(tb_clk, 1); + proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window + + ---------------------------------------------------------------------------- + -- 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*3, -- this is the wait until condition + c_sdp_T_sub, tb_clk); + + -- Stimuli done, now verify results at end of test + stimuli_done <= '1'; + + --------------------------------------------------------------------------- + -- Read subband statistics + --------------------------------------------------------------------------- + -- . the subband statistics are c_stat_data_sz = 2 word power values. + -- . there are c_sdp_S_pn = 12 signal inputs A, B, C, D, E, F, G, H, I, J, K, L + -- . there are c_sdp_N_sub = 512 subbands per signal input (SI, = signal path, SP) + -- . one complex WPFB can process two real inputs A, B, so there are c_sdp_P_pfb = 6 WPFB units, + -- but only read for the 1 WPFB unit of the selected g_sp, to save sim time + -- . the outputs for A, B are time multiplexed, c_sdp_Q_fft = 2, assume that they + -- correspond to the c_sdp_N_pol = 2 signal polarizations + -- . the subbands are output alternately so A0 B0 A1 B1 ... A511 B511 for input A, B + -- . the subband statistics multiple WPFB units appear in order in the ram_st_sst address map + -- . the subband statistics are stored first lo word 0 then hi word 1 + v_len := c_sdp_N_sub * c_sdp_N_pol * c_stat_data_sz; -- 2048 = 512 * 2 * 64/32 + v_span := true_log_pow2(v_len); -- = 2048 + FOR I IN 0 TO v_len-1 LOOP + v_W := I MOD c_stat_data_sz; -- 0, 1 per statistics word, word index + v_P := (I / c_stat_data_sz) MOD c_sdp_N_pol; -- 0, 1 per SP pol, polarization index + v_B := I / (c_sdp_N_pol * c_stat_data_sz); -- subband index, range(N_sub = 512) per dual pol + v_addr := I + c_pfb_index * v_span; -- MM address + -- Only read SST for g_subband for dual pol SP, to save sim time + IF g_read_all_SST = TRUE OR v_B = g_subband THEN + IF v_W=0 THEN + -- low part + mmf_mm_bus_rd(c_mm_file_ram_st_sst, v_addr, rd_data, tb_clk); + v_data_lo := rd_data; + ELSE + -- high part + mmf_mm_bus_rd(c_mm_file_ram_st_sst, v_addr, rd_data, tb_clk); + v_data_hi := rd_data; + v_stat_data := v_data_hi & v_data_lo; + + sp_ssts_arr2(v_P)(v_B) <= v_stat_data; + stat_data <= v_stat_data; -- for time series view in Wave window + END IF; + END IF; + END LOOP; + proc_common_wait_some_cycles(tb_clk, 1); + + -- Subband power of g_subband in g_sp + sp_sst <= TO_UREAL(sp_ssts_arr2(c_pol_index)(g_subband)); + proc_common_wait_some_cycles(tb_clk, 1); + proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window + + --------------------------------------------------------------------------- + -- Read beamlet statistics from end node + --------------------------------------------------------------------------- + -- . the beamlet statistics are c_stat_data_sz = 2 word power values. + -- . there are c_sdp_S_sub_bf = 488 dual pol beamlets per beamset + -- . the beamlets are output alternately so X0 Y0 X1 Y1 ... X487 Y487 for polarizations X, Y + -- . the beamlet statistics for multiple beamsets appear in order in the ram_st_bst address map + -- . the beamlet statistics are stored first lo word 0 then hi word 1 + v_len := c_sdp_S_sub_bf * c_sdp_N_pol_bf * c_stat_data_sz; -- = 1952 = 488 * 2 * 64/32 + v_span := true_log_pow2(v_len); -- = 2048 + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + FOR I IN 0 TO v_len-1 LOOP + v_W := I MOD c_stat_data_sz; -- 0, 1 per statistics word, word index + v_PB := (I / c_stat_data_sz) MOD c_sdp_N_pol_bf; -- 0, 1 per BF pol, polarization index + v_B := I / (c_sdp_N_pol_bf * c_stat_data_sz); -- beamlet index in beamset, range(S_sub_bf = 488) per dual pol + v_G := v_B + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp) + v_addr := I + U * v_span; -- MM address + --Only read BST for g_beamlet and dual pol_bf 0 and 1 and for both beamsets, to save sim time + IF g_read_all_BST = TRUE OR v_B = g_beamlet THEN + IF v_W = 0 THEN + -- low part + mmf_mm_bus_rd(c_mm_file_ram_st_bst, v_addr, rd_data, tb_clk); + v_data_lo := rd_data; + ELSE + -- high part + mmf_mm_bus_rd(c_mm_file_ram_st_bst, v_addr, rd_data, tb_clk); + v_data_hi := rd_data; + v_stat_data := v_data_hi & v_data_lo; + + bsts_arr2(v_PB)(v_G) <= v_stat_data; + stat_data <= v_stat_data; -- for time series view in Wave window + END IF; + END IF; + END LOOP; + END LOOP; + proc_common_wait_some_cycles(tb_clk, 1); + + -- Beamlet power of g_beamlet X and Y, same for both beamsets + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + v_G := g_beamlet + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp) + bst_x_arr(U) <= TO_UREAL(bsts_arr2(0)(v_G)); -- X pol beamlet + bst_y_arr(U) <= TO_UREAL(bsts_arr2(1)(v_G)); -- Y pol beamlet + END LOOP; + proc_common_wait_some_cycles(tb_clk, 1); + proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window + + --------------------------------------------------------------------------- + -- Log WG, subband and beamlet statistics + --------------------------------------------------------------------------- + + print_str(""); + print_str("WG:"); + print_str(". c_wg_ampl = " & int_to_str(c_wg_ampl)); + print_str(". c_exp_sp_power = " & real_to_str(c_exp_sp_power, 20, 1)); + print_str(". c_exp_sp_ast = " & real_to_str(c_exp_sp_ast, 20, 1)); + + print_str(""); + print_str("Subband weight:"); + print_str(". sp_subband_weight_gain = " & real_to_str(sp_subband_weight_gain, 20, 6)); + print_str(". sp_subband_weight_phase = " & real_to_str(sp_subband_weight_phase, 20, 6)); + + print_str(""); + print_str("SST results:"); + print_str(". sst_weighted_subbands_flag = " & sl_to_str(sst_weighted_subbands_flag)); + print_str(""); + print_str(". c_exp_subband_ampl = " & int_to_str(NATURAL(c_exp_subband_ampl))); + print_str(". c_exp_subband_power = " & real_to_str(c_exp_subband_power, 20, 1)); + print_str(". c_exp_subband_sst = " & real_to_str(c_exp_subband_sst, 20, 1)); + print_str(""); + print_str(". sp_sst = " & real_to_str(sp_sst, 20, 1)); + print_str(". sp_sst / c_exp_subband_sst = " & real_to_str(sp_sst / c_exp_subband_sst, 20, 6)); + + print_str(""); + print_str("BST results:"); + print_str(". c_exp_beamlet_x_ampl = " & int_to_str(NATURAL(c_exp_beamlet_x_ampl))); + print_str(". c_exp_beamlet_x_power = " & real_to_str(c_exp_beamlet_x_power, 20, 1)); + print_str(". c_exp_beamlet_x_bst = " & real_to_str(c_exp_beamlet_x_bst, 20, 1)); + print_str(""); + print_str(". c_exp_beamlet_y_ampl = " & int_to_str(NATURAL(c_exp_beamlet_y_ampl))); + print_str(". c_exp_beamlet_y_power = " & real_to_str(c_exp_beamlet_y_power, 20, 1)); + print_str(". c_exp_beamlet_y_bst = " & real_to_str(c_exp_beamlet_y_bst, 20, 1)); + print_str(""); + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + v_G := g_beamlet + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp) + print_str(". bst_x_arr(" & INTEGER'IMAGE(v_G) & ") = " & real_to_str(bst_x_arr(U), 20, 1)); + print_str(". bst_y_arr(" & INTEGER'IMAGE(v_G) & ") = " & real_to_str(bst_y_arr(U), 20, 1)); + END LOOP; + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + v_G := g_beamlet + U * c_sdp_S_sub_bf; -- global beamlet index, range(c_sdp_N_beamlets_sdp) + print_str(". bst_x_arr(" & INTEGER'IMAGE(v_G) & ") / c_exp_beamlet_x_bst = " & real_to_str(bst_x_arr(U) / c_exp_beamlet_x_bst, 20, 6)); + print_str(". bst_y_arr(" & INTEGER'IMAGE(v_G) & ") / c_exp_beamlet_y_bst = " & real_to_str(bst_y_arr(U) / c_exp_beamlet_y_bst, 20, 6)); + END LOOP; + + print_str(""); + print_str("Beamlet output:"); + print_str(". rd_beamlet_scale = " & int_to_str(TO_UINT(rd_beamlet_scale))); + print_str(". c_exp_beamlet_scale = " & int_to_str(c_exp_beamlet_scale)); + print_str(""); + print_str(". c_exp_beamlet_x_output_ampl = " & int_to_str(NATURAL(c_exp_beamlet_x_output_ampl))); + print_str(". c_exp_beamlet_x_output_phase = " & int_to_str(INTEGER(c_exp_beamlet_x_output_phase))); + print_str(". c_exp_beamlet_x_output_re = " & int_to_str(INTEGER(c_exp_beamlet_x_output_re))); + print_str(". c_exp_beamlet_x_output_im = " & int_to_str(INTEGER(c_exp_beamlet_x_output_im))); + print_str(""); + print_str(". c_exp_beamlet_y_output_ampl = " & int_to_str(NATURAL(c_exp_beamlet_y_output_ampl))); + print_str(". c_exp_beamlet_y_output_phase = " & int_to_str(INTEGER(c_exp_beamlet_y_output_phase))); + print_str(". c_exp_beamlet_y_output_re = " & int_to_str(INTEGER(c_exp_beamlet_y_output_re))); + print_str(". c_exp_beamlet_y_output_im = " & int_to_str(INTEGER(c_exp_beamlet_y_output_im))); + + --------------------------------------------------------------------------- + -- Verify SST + --------------------------------------------------------------------------- + -- verify expected subband power based on WG power + ASSERT sp_sst > c_stat_lo_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR; + ASSERT sp_sst < c_stat_hi_factor * c_exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR; + + --------------------------------------------------------------------------- + -- Verify BST + --------------------------------------------------------------------------- + -- verify expected beamlet power based on WG power and BF weigths + FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP + -- X-pol + ASSERT bst_x_arr(U) < c_stat_hi_factor * c_exp_beamlet_x_bst REPORT "Wrong beamlet X power in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR; + ASSERT bst_x_arr(U) > c_stat_lo_factor * c_exp_beamlet_x_bst REPORT "Wrong beamlet X power in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR; + -- Y-pol + ASSERT bst_y_arr(U) > c_stat_lo_factor * c_exp_beamlet_y_bst REPORT "Wrong beamlet Y power in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR; + ASSERT bst_y_arr(U) < c_stat_hi_factor * c_exp_beamlet_y_bst REPORT "Wrong beamlet Y power in beamset " & NATURAL'IMAGE(U) SEVERITY ERROR; + END LOOP; + + --------------------------------------------------------------------------- + -- Verify beamlet output in 10GbE UDP offload + --------------------------------------------------------------------------- + -- X-pol + v_re := TO_SINT(rx_beamlet_list_re(c_exp_beamlet_x_index)); v_re_exp := c_exp_beamlet_x_output_re; + v_im := TO_SINT(rx_beamlet_list_im(c_exp_beamlet_x_index)); v_im_exp := c_exp_beamlet_x_output_im; + ASSERT v_re > INTEGER(v_re_exp) - c_beamlet_output_delta REPORT "Wrong beamlet X output (re) " & INTEGER'IMAGE(v_re) & " != " & REAL'IMAGE(v_re_exp) SEVERITY ERROR; + ASSERT v_re < INTEGER(v_re_exp) + c_beamlet_output_delta REPORT "Wrong beamlet X output (re) " & INTEGER'IMAGE(v_re) & " != " & REAL'IMAGE(v_re_exp) SEVERITY ERROR; + ASSERT v_im > INTEGER(v_im_exp) - c_beamlet_output_delta REPORT "Wrong beamlet X output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR; + ASSERT v_im < INTEGER(v_im_exp) + c_beamlet_output_delta REPORT "Wrong beamlet X output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR; + -- Y-pol + v_re := TO_SINT(rx_beamlet_list_re(c_exp_beamlet_y_index)); v_re_exp := c_exp_beamlet_y_output_re; + v_im := TO_SINT(rx_beamlet_list_im(c_exp_beamlet_y_index)); v_im_exp := c_exp_beamlet_y_output_im; + ASSERT v_re > INTEGER(v_re_exp) - c_beamlet_output_delta REPORT "Wrong beamlet Y output (re) " & INTEGER'IMAGE(v_re) & " != " & REAL'IMAGE(v_re_exp) SEVERITY ERROR; + ASSERT v_re < INTEGER(v_re_exp) + c_beamlet_output_delta REPORT "Wrong beamlet Y output (re) " & INTEGER'IMAGE(v_re) & " != " & REAL'IMAGE(v_re_exp) SEVERITY ERROR; + ASSERT v_im > INTEGER(v_im_exp) - c_beamlet_output_delta REPORT "Wrong beamlet Y output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR; + ASSERT v_im < INTEGER(v_im_exp) + c_beamlet_output_delta REPORT "Wrong beamlet Y output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR; + + --------------------------------------------------------------------------- + -- End Simulation + --------------------------------------------------------------------------- + tb_almost_end <= '1'; + proc_common_wait_some_cycles(ext_clk, 100); -- delay for ease of view in Wave window + proc_common_stop_simulation(TRUE, ext_clk, tb_almost_end, tb_end); + WAIT; + END PROCESS; + + ----------------------------------------------------------------------------- + -- Verify beamlet offload packet header + ----------------------------------------------------------------------------- + + -- Counters to time expected exp_sdp_cep_header fields per offload packet + p_test_counters : PROCESS(ext_clk) + BEGIN + IF rising_edge(ext_clk) THEN + -- Count rx_beamlet_sosi packets + IF rx_beamlet_sosi.sop = '1' THEN + rx_beamlet_sop_cnt <= rx_beamlet_sop_cnt + 1; -- early count + END IF; + IF rx_beamlet_sosi.eop = '1' THEN + rx_beamlet_eop_cnt <= rx_beamlet_eop_cnt + 1; -- after count + END IF; + END IF; + END PROCESS; + + -- Count sync intervals using in_sosi.sync, because there is no rx_beamlet_sosi.sync + in_sync_cnt <= in_sync_cnt + 1 WHEN rising_edge(ext_clk) AND in_sync = '1'; + test_sync_cnt <= in_sync_cnt - 1; -- optionally adjust to fit rx_beamlet_sosi + + -- Prepare exp_sdp_cep_header before rx_beamlet_sosi.eop, so that + -- p_exp_sdp_cep_header can verify it at rx_beamlet_sosi.eop. + + p_exp_sdp_cep_header : PROCESS(exp_dp_bsn) + BEGIN + -- eth header + exp_sdp_cep_header.eth.dst_mac <= c_cep_eth_dst_mac; + exp_sdp_cep_header.eth.src_mac <= c_cep_eth_src_mac; + exp_sdp_cep_header.eth.eth_type <= x"0800"; + + -- ip header + exp_sdp_cep_header.ip.version <= TO_UVEC( 4, c_network_ip_version_w); + exp_sdp_cep_header.ip.header_length <= TO_UVEC( 5, c_network_ip_header_length_w); + exp_sdp_cep_header.ip.services <= TO_UVEC( 0, c_network_ip_services_w); + exp_sdp_cep_header.ip.total_length <= c_sdp_cep_ip_total_length; -- 7868, see ICD STAT-CEP + exp_sdp_cep_header.ip.identification <= TO_UVEC( 0, c_network_ip_identification_w); + exp_sdp_cep_header.ip.flags <= TO_UVEC( 2, c_network_ip_flags_w); + exp_sdp_cep_header.ip.fragment_offset <= TO_UVEC( 0, c_network_ip_fragment_offset_w); + exp_sdp_cep_header.ip.time_to_live <= TO_UVEC( 127, c_network_ip_time_to_live_w); + exp_sdp_cep_header.ip.protocol <= TO_UVEC( 17, c_network_ip_protocol_w); + exp_sdp_cep_header.ip.header_checksum <= TO_UVEC( c_exp_ip_header_checksum, c_network_ip_header_checksum_w); + exp_sdp_cep_header.ip.src_ip_addr <= c_cep_ip_src_addr; -- c_network_ip_addr_w + exp_sdp_cep_header.ip.dst_ip_addr <= c_cep_ip_dst_addr; -- c_network_ip_addr_w + + -- udp header + exp_sdp_cep_header.udp.src_port <= c_cep_udp_src_port; + exp_sdp_cep_header.udp.dst_port <= c_cep_udp_dst_port; + exp_sdp_cep_header.udp.total_length <= c_sdp_cep_udp_total_length; -- 7848, see ICD STAT-CEP + exp_sdp_cep_header.udp.checksum <= TO_UVEC( 0, c_network_udp_checksum_w); + + -- app header + exp_sdp_cep_header.app.sdp_marker <= TO_UVEC(c_sdp_marker_beamlets, 8); -- 98 = x"62" = 'b' + exp_sdp_cep_header.app.sdp_version_id <= TO_UVEC(c_sdp_cep_version_id, 8); -- 5 + exp_sdp_cep_header.app.sdp_observation_id <= c_exp_sdp_info.observation_id; + exp_sdp_cep_header.app.sdp_station_id <= c_exp_sdp_info.station_id; + + exp_sdp_cep_header.app.sdp_source_info_antenna_band_id <= slv(c_exp_sdp_info.antenna_band_index); + exp_sdp_cep_header.app.sdp_source_info_nyquist_zone_id <= c_exp_sdp_info.nyquist_zone_index; + exp_sdp_cep_header.app.sdp_source_info_f_adc <= slv(c_exp_sdp_info.f_adc); + exp_sdp_cep_header.app.sdp_source_info_fsub_type <= slv(c_exp_sdp_info.fsub_type); + exp_sdp_cep_header.app.sdp_source_info_payload_error <= TO_UVEC(0, 1); + exp_sdp_cep_header.app.sdp_source_info_repositioning_flag <= slv(c_exp_sdp_info.beam_repositioning_flag); + exp_sdp_cep_header.app.sdp_source_info_beamlet_width <= TO_UVEC(c_sdp_W_beamlet, 4); + exp_sdp_cep_header.app.sdp_source_info_gn_id <= TO_UVEC(c_gn_index, 5); + + exp_sdp_cep_header.app.sdp_reserved <= TO_UVEC( 0, 40); + exp_sdp_cep_header.app.sdp_beamlet_scale <= TO_UVEC( c_exp_beamlet_scale, 16); + exp_sdp_cep_header.app.sdp_beamlet_index <= TO_UVEC( 0, 16); -- depends on bset + exp_sdp_cep_header.app.sdp_nof_blocks_per_packet <= TO_UVEC( c_sdp_cep_nof_blocks_per_packet, 8); + exp_sdp_cep_header.app.sdp_nof_beamlets_per_block <= TO_UVEC(c_sdp_cep_nof_beamlets_per_block, 16); + exp_sdp_cep_header.app.sdp_block_period <= c_exp_sdp_info.block_period; + + exp_sdp_cep_header.app.dp_bsn <= TO_UVEC(exp_dp_bsn, 64); -- depends on bset and time + END PROCESS; + + rx_sdp_cep_header <= func_sdp_map_cep_header(rx_hdr_fields_raw); + + p_verify_cep_header : PROCESS + VARIABLE v_bool : BOOLEAN; + BEGIN + WAIT UNTIL rising_edge(ext_clk); + + -- Prepare exp_sdp_cep_header at sop, so that it can be verified at eop + IF rx_beamlet_sosi.sop = '1' THEN + -- Expected BSN increments by c_sdp_cep_nof_blocks_per_packet = 4 blocks per packet + IF rx_beamlet_sop_cnt MOD c_sdp_N_beamsets = 0 THEN + exp_dp_bsn <= c_init_bsn + (rx_beamlet_sop_cnt / c_sdp_N_beamsets) * c_sdp_cep_nof_blocks_per_packet; + END IF; + END IF; + + -- Verify header at eop + -- . The expected beamlet_index 0 or S_sub_bf = 488 depends on beamset 0 + -- or 1, but the order in which the packets arrive is undetermined. + -- Therefore accept any beamlet_index MOD c_sdp_S_sub_bf = 0 as correct + -- in func_sdp_verify_cep_header(). + IF rx_beamlet_sosi.eop = '1' THEN + v_bool := func_sdp_verify_cep_header(rx_sdp_cep_header, exp_sdp_cep_header); + END IF; + END PROCESS; + + ----------------------------------------------------------------------------- + -- CEP Read Rx 10GbE Stream + ----------------------------------------------------------------------------- + -- Show received beamlets from 10GbE stream in Wave Window + -- . The packet header is 9.25 longwords wide. The dp_offload_rx has stripped + -- the header and has realigned the payload at a longword boundary. + -- . expect c_nof_block_per_sync / c_sdp_cep_nof_blocks_per_packet * + -- c_sdp_N_beamsets = 16 / 4 * 2 = 4 * 2 = 8 packets per sync interval + -- . expect c_sdp_cep_nof_beamlets_per_block = c_sdp_S_sub_bf = 488 dual pol + -- and complex beamlets per packet, so 2 dual pol beamlets/64b data word. + -- . Beamlets array is stored big endian in the data, so X index 0 first in + -- MSByte of rx_beamlet_sosi.data. + p_rx_cep_beamlets : PROCESS + BEGIN + rx_beamlet_cnt <= 0; + rx_beamlet_valid <= '0'; + -- Wait until start of a beamlet packet, capture only first block in packet + proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.sop); + -- c_nof_beamlets_per_data = 2 dual pol beamlets (= XY, XY) per 64b data word + FOR I IN 0 TO (c_sdp_cep_nof_blocks_per_packet * c_sdp_cep_nof_beamlets_per_block / c_nof_beamlets_per_data)-1 LOOP + proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.valid); + rx_beamlet_valid <= '1'; + -- Capture rx beamlets per longword in rx_beamlet_arr, for time series view in Wave window + rx_beamlet_arr_re(0) <= rx_beamlet_sosi.data(55 DOWNTO 48); -- X + rx_beamlet_arr_im(0) <= rx_beamlet_sosi.data(63 DOWNTO 56); + rx_beamlet_arr_re(1) <= rx_beamlet_sosi.data(39 DOWNTO 32); -- Y + rx_beamlet_arr_im(1) <= rx_beamlet_sosi.data(47 DOWNTO 40); + rx_beamlet_arr_re(2) <= rx_beamlet_sosi.data(23 DOWNTO 16); -- X + rx_beamlet_arr_im(2) <= rx_beamlet_sosi.data(31 DOWNTO 24); + rx_beamlet_arr_re(3) <= rx_beamlet_sosi.data( 7 DOWNTO 0); -- Y + rx_beamlet_arr_im(3) <= rx_beamlet_sosi.data(15 DOWNTO 8); + IF I < c_sdp_cep_nof_beamlets_per_block / c_nof_beamlets_per_data THEN + -- Only capture the first beamlets block of each packet in rx_beamlet_list + rx_beamlet_list_re(I*4 + 0) <= rx_beamlet_sosi.data(55 DOWNTO 48); -- X + rx_beamlet_list_im(I*4 + 0) <= rx_beamlet_sosi.data(63 DOWNTO 56); + rx_beamlet_list_re(I*4 + 1) <= rx_beamlet_sosi.data(39 DOWNTO 32); -- Y + rx_beamlet_list_im(I*4 + 1) <= rx_beamlet_sosi.data(47 DOWNTO 40); + rx_beamlet_list_re(I*4 + 2) <= rx_beamlet_sosi.data(23 DOWNTO 16); -- X + rx_beamlet_list_im(I*4 + 2) <= rx_beamlet_sosi.data(31 DOWNTO 24); + rx_beamlet_list_re(I*4 + 3) <= rx_beamlet_sosi.data( 7 DOWNTO 0); -- Y + rx_beamlet_list_im(I*4 + 3) <= rx_beamlet_sosi.data(15 DOWNTO 8); + END IF; + proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.valid); + -- Use at least one WAIT instead of proc_common_wait_some_cycles() to + -- avoid Modelsim warning: (vcom-1090) Possible infinite loop: Process + -- contains no WAIT statement. + WAIT UNTIL rising_edge(ext_clk); + rx_beamlet_valid <= '0'; + rx_beamlet_cnt <= (rx_beamlet_cnt + c_nof_beamlets_per_data) MOD c_sdp_cep_nof_beamlets_per_block; -- 4 blocks/packet + END LOOP; + END PROCESS; + + -- To view the 64 bit 10GbE offload data more easily in the Wave window + rx_beamlet_data <= rx_beamlet_sosi.data(c_longword_w-1 DOWNTO 0); +END tb; diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/src/vhdl/lofar2_unb2c_sdp_station_pkg.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/src/vhdl/lofar2_unb2c_sdp_station_pkg.vhd index 1cf8f2d16ef84f2aaa5a4cb31ae35ef44100b90c..6b2c624be0d2f18fcfb606db9899c77b122124f4 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/src/vhdl/lofar2_unb2c_sdp_station_pkg.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/src/vhdl/lofar2_unb2c_sdp_station_pkg.vhd @@ -43,6 +43,7 @@ PACKAGE lofar2_unb2c_sdp_station_pkg IS CONSTANT c_ait : t_lofar2_unb2c_sdp_station_config := (FALSE, FALSE, FALSE, FALSE, FALSE, 0); CONSTANT c_fsub : t_lofar2_unb2c_sdp_station_config := (FALSE, TRUE, FALSE, FALSE, FALSE, 0); CONSTANT c_bf : t_lofar2_unb2c_sdp_station_config := (FALSE, TRUE, TRUE, FALSE, FALSE, 0); + CONSTANT c_bf_ring : t_lofar2_unb2c_sdp_station_config := (FALSE, TRUE, TRUE, FALSE, TRUE, 0); CONSTANT c_xsub_one : t_lofar2_unb2c_sdp_station_config := (FALSE, TRUE, FALSE, TRUE, FALSE, 1); CONSTANT c_xsub_ring : t_lofar2_unb2c_sdp_station_config := (FALSE, TRUE, FALSE, TRUE, TRUE, 9); CONSTANT c_full : t_lofar2_unb2c_sdp_station_config := (FALSE, TRUE, TRUE, TRUE, TRUE, 9); @@ -61,6 +62,7 @@ PACKAGE BODY lofar2_unb2c_sdp_station_pkg IS IF g_design_name = "lofar2_unb2c_sdp_station_adc" THEN RETURN c_ait; ELSIF g_design_name = "lofar2_unb2c_sdp_station_fsub" THEN RETURN c_fsub; ELSIF g_design_name = "lofar2_unb2c_sdp_station_bf" THEN RETURN c_bf; + ELSIF g_design_name = "lofar2_unb2c_sdp_station_bf_ring" THEN RETURN c_bf_ring; ELSIF g_design_name = "lofar2_unb2c_sdp_station_xsub_one" THEN RETURN c_xsub_one; ELSIF g_design_name = "lofar2_unb2c_sdp_station_xsub_ring" THEN RETURN c_xsub_ring; ELSE RETURN c_full; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd index 652c2b7f64bc7bbfd615eaf7681352958514b383..f8bcfb7bae2ff567addead29e994ee10bfdb4296 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd @@ -383,7 +383,8 @@ ARCHITECTURE str OF sdp_station IS CONSTANT c_addr_w_reg_bsn_monitor_v2_rx_align_bf : NATURAL := ceil_log2(c_dual) + c_sdp_reg_bsn_monitor_v2_addr_w; CONSTANT c_addr_w_reg_bsn_monitor_v2_ring_rx_bf : NATURAL := ceil_log2(c_sdp_N_pn_max) + c_sdp_reg_bsn_monitor_v2_addr_w; CONSTANT c_addr_w_reg_bsn_monitor_v2_ring_tx_bf : NATURAL := ceil_log2(c_sdp_N_pn_max) + c_sdp_reg_bsn_monitor_v2_addr_w; - + CONSTANT c_addr_w_reg_ring_lane_info_bf : NATURAL := 1; + -- Read only sdp_info values CONSTANT c_f_adc : STD_LOGIC := '1'; -- '0' => 160M, '1' => 200M CONSTANT c_fsub_type : STD_LOGIC := '0'; -- '0' => critical sampled PFB, '1' => oversampled PFB @@ -1172,7 +1173,7 @@ BEGIN u_mem_mux_reg_ring_lane_info_bf : ENTITY common_lib.common_mem_mux GENERIC MAP ( g_nof_mosi => c_sdp_N_beamsets, - g_mult_addr_w => c_sdp_reg_ring_lane_info_addr_w + g_mult_addr_w => c_addr_w_reg_ring_lane_info_bf ) PORT MAP ( mosi => reg_ring_lane_info_bf_copi,