diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/lofar2_unb2b_sdp_station_pkg.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/lofar2_unb2b_sdp_station_pkg.vhd index 5f3c67cba2d45e3b1a17a1f40ee74994c39095fd..52ec178cdc50c135cc65498f1e64d0b1f22a1fb1 100644 --- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/lofar2_unb2b_sdp_station_pkg.vhd +++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/lofar2_unb2b_sdp_station_pkg.vhd @@ -36,7 +36,7 @@ package lofar2_unb2b_sdp_station_pkg is use_oversample : boolean; use_bf : boolean; use_bdo_transpose : boolean; - nof_bdo_destinations_max : natural; -- <= c_sdp_bdo_mm_nof_destinations_max + nof_bdo_destinations_max : natural; -- <= c_sdp_bdo_mm_nof_destinations_max = 32 in sdp_bdo_pkg.vhd use_xsub : boolean; use_ring : boolean; P_sq : natural; @@ -51,7 +51,7 @@ package lofar2_unb2b_sdp_station_pkg is constant c_xsub_one : t_lofar2_unb2b_sdp_station_config := (false, true, false, false, false, 1, true, false, 1); constant c_xsub_ring : t_lofar2_unb2b_sdp_station_config := (false, true, false, false, false, 1, true, true, 9); -- use c_full_wg for SDP regression test on Arts-unb2b - constant c_full_wg : t_lofar2_unb2b_sdp_station_config := (true, true, false, true, true, 32, true, true, 9); + constant c_full_wg : t_lofar2_unb2b_sdp_station_config := (true, true, false, true, true, 8, true, true, 9); constant c_full : t_lofar2_unb2b_sdp_station_config := (false, true, false, true, false, 1, true, true, 9); constant c_full_wg_os : t_lofar2_unb2b_sdp_station_config := (true, true, true, true, false, 1, true, true, 9); -- use c_full_os for SDP on LTS-unb2b of Disturb2 diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/tb_lofar2_unb2c_sdp_station_adc_jesd.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/tb_lofar2_unb2c_sdp_station_adc_jesd.vhd index 02130ecf7708d27b33d450f0218a278e92a10272..da2dc05893342fab45500bcf8bb0885a4d342fbb 100644 --- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/tb_lofar2_unb2c_sdp_station_adc_jesd.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_adc/tb_lofar2_unb2c_sdp_station_adc_jesd.vhd @@ -49,7 +49,9 @@ -- > as 16 # for detailed debugging of JESD204B IP -- > run -a -- --- View ait_sosi_arr, to see that only complete blocks are passed on. +-- View u_sdp_station/ait_sosi_arr, to see that only complete blocks are +-- passed on. If necessary also manually add missing other arrays like +-- u_sdp_station/u_ait/gen_rx_ait/u_rx_ait/st_sosi_arr -- ------------------------------------------------------------------------------- library IEEE, common_lib, unb2c_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib, lofar2_unb2c_sdp_station_lib, tech_jesd204b_lib; 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 6f3810e7995a00ec291322808662b30ce927f178..94dbd9c7b09e764cb54be56e9703194dac9172c8 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 @@ -36,7 +36,7 @@ package lofar2_unb2c_sdp_station_pkg is use_oversample : boolean; use_bf : boolean; use_bdo_transpose : boolean; - nof_bdo_destinations_max : natural; -- <= c_sdp_bdo_mm_nof_destinations_max + nof_bdo_destinations_max : natural; -- <= c_sdp_bdo_mm_nof_destinations_max = 32 in sdp_bdo_pkg.vhd use_xsub : boolean; use_ring : boolean; P_sq : natural; @@ -46,13 +46,13 @@ package lofar2_unb2c_sdp_station_pkg is constant c_fsub : t_lofar2_unb2c_sdp_station_config := (false, true, false, false, false, 1, false, false, 0); -- use c_bf on one node also to simulate bdo transpose -- use c_bf_ring with ring also to simulate bdo identity - constant c_bf : t_lofar2_unb2c_sdp_station_config := (false, true, false, true, true, 32, false, false, 0); + constant c_bf : t_lofar2_unb2c_sdp_station_config := (false, true, false, true, true, 8, false, false, 0); constant c_bf_ring : t_lofar2_unb2c_sdp_station_config := (false, true, false, true, false, 1, false, true, 0); constant c_xsub_one : t_lofar2_unb2c_sdp_station_config := (false, true, false, false, false, 1, true, false, 1); constant c_xsub_ring : t_lofar2_unb2c_sdp_station_config := (false, true, false, false, false, 1, true, true, 9); constant c_full_wg : t_lofar2_unb2c_sdp_station_config := (true, true, false, true, true, 1, true, true, 9); -- Use c_full for LOFAR2 Station SDP operations - constant c_full : t_lofar2_unb2c_sdp_station_config := (false, true, false, true, true, 32, true, true, 9); + constant c_full : t_lofar2_unb2c_sdp_station_config := (false, true, false, true, true, 8, true, true, 9); constant c_full_wg_os : t_lofar2_unb2c_sdp_station_config := (true, true, true, true, true, 1, true, true, 9); constant c_full_os : t_lofar2_unb2c_sdp_station_config := (false, true, true, true, true, 1, true, true, 9); diff --git a/applications/lofar2/libraries/sdp/hdllib.cfg b/applications/lofar2/libraries/sdp/hdllib.cfg index 24415a8291ea288a2f86dcf333670bffd4153ab7..6e7ad9ac344bfb31412ec917035554d5013d8ca7 100644 --- a/applications/lofar2/libraries/sdp/hdllib.cfg +++ b/applications/lofar2/libraries/sdp/hdllib.cfg @@ -7,6 +7,7 @@ hdl_lib_technology = synth_files = src/vhdl/sdp_pkg.vhd src/vhdl/sdp_scope.vhd + src/vhdl/sdp_adc_input_and_timing.vhd src/vhdl/sdp_subband_weights.vhd src/vhdl/sdp_subband_equalizer.vhd src/vhdl/sdp_bf_weights.vhd diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd index 107e1a05883b173a0ea9f423426ca1eb60511687..ba5ace7994c52065b2c62316717a2e6230e93370 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd @@ -37,7 +37,11 @@ use work.sdp_pkg.all; entity node_sdp_adc_input_and_timing is generic ( - g_no_jesd : boolean := false; + g_no_jesd : boolean := false; -- when false use Rx JESD204B and WG, else use only WG + -- When g_use_tech_jesd204b_v2 = false use tech_jesd204b with tech_jesd204b and FIFO in ait, + -- else use tech_jesd204b_v2 with FIFO in tech_jesd204b_v2 + g_use_tech_jesd204b_v2 : boolean := false; + g_no_st_histogram : boolean := true; -- when false use input histogram, else not to save block RAM g_buf_nof_data : natural := c_sdp_V_si_db; g_bsn_nof_clk_per_sync : natural := c_sdp_N_clk_per_sync; -- Default 200M, overide for short simulation g_sim : boolean := false @@ -117,449 +121,352 @@ architecture str of node_sdp_adc_input_and_timing is signal trigger_wg : std_logic; -- Frame parameters - constant c_bs_sync_timeout : natural := g_bsn_nof_clk_per_sync + g_bsn_nof_clk_per_sync / 10; -- +10% margin constant c_bs_bsn_w : natural := 64; -- > 51; constant c_bs_aux_w : natural := 2; - constant c_bs_block_size : natural := c_sdp_N_fft; -- =1024; constant c_dp_fifo_dc_size : natural := 64; + signal dp_sysref : std_logic; + -- JESD signals signal rx_clk : std_logic; -- formerly jesd204b_frame_clk signal rx_rst : std_logic; signal rx_sysref : std_logic; - signal rx_bsn_source_restart : std_logic; - signal rx_bsn_source_new_interval : std_logic; - signal rx_bsn_source_nof_clk_per_sync : std_logic_vector(c_word_w - 1 downto 0); - signal rx_aux : std_logic_vector(c_bs_aux_w - 1 downto 0); - signal dp_aux : std_logic_vector(c_bs_aux_w - 1 downto 0); + signal mm_rst_jesd : std_logic; + signal mm_jesd_ctrl_reg_wr : std_logic_vector(c_word_w - 1 downto 0); + signal mm_jesd_ctrl_reg_rd : std_logic_vector(c_word_w - 1 downto 0); + signal jesd204b_disable_arr : std_logic_vector(c_sdp_S_pn - 1 downto 0); + signal jesd204b_reset_request : std_logic := '0'; - -- Sosis and sosi arrays + -- AIT processing signal rx_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); signal dp_shiftram_snk_in_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); signal ant_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); signal bs_sosi : t_dp_sosi := c_dp_sosi_rst; + signal bs_sosi_valid : std_logic; signal wg_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); signal mux_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); signal nxt_mux_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); signal st_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); - signal mm_rst_jesd : std_logic; - signal mm_jesd_ctrl_reg_wr : std_logic_vector(c_word_w - 1 downto 0); - signal mm_jesd_ctrl_reg_rd : std_logic_vector(c_word_w - 1 downto 0); - signal jesd204b_disable_arr : std_logic_vector(c_sdp_S_pn - 1 downto 0); - signal jesd204b_reset_request : std_logic := '0'; + signal rx_bsn_source_restart : std_logic; + signal rx_bsn_source_new_interval : std_logic; + signal rx_bsn_source_nof_clk_per_sync : std_logic_vector(c_word_w - 1 downto 0); + signal rx_aux : std_logic_vector(c_bs_aux_w - 1 downto 0); + signal dp_aux : std_logic_vector(c_bs_aux_w - 1 downto 0); begin gen_no_jesd : if g_no_jesd = true generate - rx_clk <= dp_clk; - rx_rst <= dp_rst; - rx_sysref <= dp_pps; - end generate; - - -- The node AIT is reset at power up by mm_rst and under software control by mm_rst_jesd. - -- The mm_rst_jesd will cause a reset on the rx_rst by the reset sequencer in the u_jesd204b. - -- The mm_rst_jesd is intended for node AIT resynchronisation tests of the u_jesd204b. - -- The mm_rst_jesd should not be applied in an active SDP application, because this will cause - -- a disturbance in the block timing of the out_sosi_arr(i).sync,bsn,sop,eop. The other logic - -- in an SDP application assumes that the block timing of the out_sosi_arr(i) only contains - -- complete blocks, so from sop to eop. Therefore, first mms_dp_bsn_source_v2 should be - -- disabled to stop and flush the block processing, before applying mm_rst_jesd. - - -- Only accept JESD204B IP reset when the processing is disabled (indicated by bs_sosi.valid - -- = '0'), to avoid corrupt bs_sosi blocks entering the subsequent processing due to that a - -- JESD204B IP reset causes that the rx_clk stops. - mm_rst_jesd <= mm_rst or jesd204b_reset_request; - - jesd204b_disable_arr <= mm_jesd_ctrl_reg_wr(c_sdp_S_pn - 1 downto 0); - jesd204b_reset_request <= mm_jesd_ctrl_reg_wr(c_sdp_jesd_ctrl_reset_bi) and not bs_sosi.valid; - - p_mm_jesd_ctrl_reg_rd : process(mm_jesd_ctrl_reg_wr, jesd204b_reset_request) - begin - -- default readback what was written - mm_jesd_ctrl_reg_rd <= mm_jesd_ctrl_reg_wr; - -- report actual JESD204B reset status - mm_jesd_ctrl_reg_rd(c_sdp_jesd_ctrl_reset_bi) <= jesd204b_reset_request; - end process; + dp_sysref <= dp_pps; + + jesd204b_miso <= c_mem_miso_rst; + jesd_ctrl_miso <= c_mem_miso_rst; + end generate; -- gen_no_jesd gen_jesd : if g_no_jesd = false generate ----------------------------------------------------------------------------- - -- JESD204B IP (ADC Handler) + -- JESD Control register ----------------------------------------------------------------------------- + -- The node AIT is reset at power up by mm_rst and under software control by mm_rst_jesd. + -- The mm_rst_jesd will cause a reset on the rx_rst by the reset sequencer in the u_jesd204b. + -- The mm_rst_jesd is intended for node AIT resynchronisation tests of the u_jesd204b. + -- The mm_rst_jesd should not be applied in an active SDP application, because this will cause + -- a disturbance in the block timing of the out_sosi_arr(i).sync,bsn,sop,eop. The other logic + -- in an SDP application assumes that the block timing of the out_sosi_arr(i) only contains + -- complete blocks, so from sop to eop. Therefore, first mms_dp_bsn_source_v2 should be + -- disabled to stop and flush the block processing, before applying mm_rst_jesd. + + -- Only accept JESD204B IP reset when the processing is disabled (indicated by bs_sosi_valid + -- = '0'), to avoid corrupt bs_sosi blocks entering the subsequent processing due to that a + -- JESD204B IP reset causes that the rx_clk stops. + mm_rst_jesd <= mm_rst or jesd204b_reset_request; + + jesd204b_disable_arr <= mm_jesd_ctrl_reg_wr(c_sdp_S_pn - 1 downto 0); + jesd204b_reset_request <= mm_jesd_ctrl_reg_wr(c_sdp_jesd_ctrl_reset_bi) and not bs_sosi_valid; + + p_mm_jesd_ctrl_reg_rd : process(mm_jesd_ctrl_reg_wr, jesd204b_reset_request) + begin + -- default readback what was written + mm_jesd_ctrl_reg_rd <= mm_jesd_ctrl_reg_wr; + -- report actual JESD204B reset status + mm_jesd_ctrl_reg_rd(c_sdp_jesd_ctrl_reset_bi) <= jesd204b_reset_request; + end process; - u_jesd204b: entity tech_jesd204b_lib.tech_jesd204b - generic map( - g_sim => false, -- do not use g_sim, because JESD204B IP does support mm_clk in sim - g_nof_streams => c_sdp_S_pn, - g_nof_sync_n => c_sdp_N_sync_jesd, - g_jesd_freq => c_sdp_jesd204b_freq + u_mm_jesd_ctrl_reg : entity common_lib.common_reg_r_w + generic map ( + g_reg => c_sdp_mm_jesd_ctrl_reg, + g_init_reg => (others => '0') ) - port map( - jesd204b_refclk => JESD204B_REFCLK, - jesd204b_sysref => JESD204B_SYSREF, - jesd204b_sync_n_arr => jesd204b_sync_n, - - rx_sosi_arr => rx_sosi_arr, - rx_clk => rx_clk, - rx_rst => rx_rst, - rx_sysref => rx_sysref, - - jesd204b_disable_arr => jesd204b_disable_arr, - - -- MM - mm_clk => mm_clk, - mm_rst => mm_rst_jesd, - - jesd204b_mosi => jesd204b_mosi, - jesd204b_miso => jesd204b_miso, - - -- Serial - serial_tx_arr => open, - serial_rx_arr => JESD204B_SERIAL_DATA(c_sdp_S_pn - 1 downto 0) + port map ( + rst => mm_rst, + clk => mm_clk, + -- control side + wr_en => jesd_ctrl_mosi.wr, + wr_adr => jesd_ctrl_mosi.address(c_sdp_mm_jesd_ctrl_reg.adr_w - 1 downto 0), + wr_dat => jesd_ctrl_mosi.wrdata(c_sdp_mm_jesd_ctrl_reg.dat_w - 1 downto 0), + rd_en => jesd_ctrl_mosi.rd, + rd_adr => jesd_ctrl_mosi.address(c_sdp_mm_jesd_ctrl_reg.adr_w - 1 downto 0), + rd_dat => jesd_ctrl_miso.rddata(c_sdp_mm_jesd_ctrl_reg.dat_w - 1 downto 0), + rd_val => OPEN, + -- data side + out_reg => mm_jesd_ctrl_reg_wr, + in_reg => mm_jesd_ctrl_reg_rd ); ----------------------------------------------------------------------------- - -- Time delay: dp_shiftram - -- . copied from unb1_bn_capture_input (apertif) - -- Array range reversal is not done because everything is DOWNTO - -- . the input valid is always '1', even when there is no data + -- JESD204B IP (ADC Handler) ----------------------------------------------------------------------------- - - p_dp_shiftram_snk_in_arr : process(rx_sosi_arr) - begin - dp_shiftram_snk_in_arr <= rx_sosi_arr; - for I in 0 to c_sdp_S_pn - 1 loop - -- ADC data is stored in the upper 14 bits of the jesd rx_sosi. - dp_shiftram_snk_in_arr(I).data <= RESIZE_DP_SDATA(rx_sosi_arr(I).data(c_sdp_W_adc_jesd - 1 downto (c_sdp_W_adc_jesd - c_sdp_W_adc) )); - -- Force valid. - dp_shiftram_snk_in_arr(I).valid <= '1'; - end loop; - end process; - - u_dp_shiftram : entity dp_lib.dp_shiftram + gen_jesd204b_v1 : if g_use_tech_jesd204b_v2 = false generate + u_jesd204b_v1 : entity tech_jesd204b_lib.tech_jesd204b + generic map( + g_sim => false, -- do not use g_sim, because JESD204B IP does support mm_clk in sim + g_nof_streams => c_sdp_S_pn, + g_nof_sync_n => c_sdp_N_sync_jesd, + g_jesd_freq => c_sdp_jesd204b_freq + ) + port map( + jesd204b_refclk => JESD204B_REFCLK, + jesd204b_sysref => JESD204B_SYSREF, + jesd204b_sync_n_arr => jesd204b_sync_n, + + rx_sosi_arr => rx_sosi_arr, + rx_clk => rx_clk, + rx_rst => rx_rst, + rx_sysref => rx_sysref, + + jesd204b_disable_arr => jesd204b_disable_arr, + + -- MM + mm_clk => mm_clk, + mm_rst => mm_rst_jesd, + + jesd204b_mosi => jesd204b_mosi, + jesd204b_miso => jesd204b_miso, + + -- Serial + serial_tx_arr => open, + serial_rx_arr => JESD204B_SERIAL_DATA(c_sdp_S_pn - 1 downto 0) + ); + end generate; + + gen_jesd204b_v2 : if g_use_tech_jesd204b_v2 = true generate + u_jesd204b_v2: entity tech_jesd204b_lib.tech_jesd204b_v2 + generic map( + g_sim => false, -- do not use g_sim, because JESD204B IP does support mm_clk in sim + g_nof_streams => c_sdp_S_pn, + g_nof_sync_n => c_sdp_N_sync_jesd, + g_jesd_freq => c_sdp_jesd204b_freq + ) + port map( + jesd204b_refclk => JESD204B_REFCLK, + jesd204b_sysref => JESD204B_SYSREF, + jesd204b_sync_n_arr => jesd204b_sync_n, + + dp_clk => dp_clk, + dp_rst => dp_rst, + dp_sysref => dp_sysref, + dp_sosi_arr => rx_sosi_arr, + + jesd204b_disable_arr => jesd204b_disable_arr, + + -- MM + mm_clk => mm_clk, + mm_rst => mm_rst_jesd, + + jesd204b_mosi => jesd204b_mosi, + jesd204b_miso => jesd204b_miso, + + -- Serial + serial_tx_arr => open, + serial_rx_arr => JESD204B_SERIAL_DATA(c_sdp_S_pn - 1 downto 0) + ); + end generate; + end generate; -- gen_jesd + + -- Wire rx_clk from tech_jesd204b to AIT + gen_rx_ait : if g_no_jesd = false and g_use_tech_jesd204b_v2 = false generate + u_rx_ait : entity work.sdp_adc_input_and_timing generic map ( - g_nof_streams => c_sdp_S_pn, - g_nof_words => c_sdp_V_sample_delay, - g_data_w => c_sdp_W_adc, - g_use_sync_in => true + g_no_rx => g_no_jesd, -- when false use Rx and WG, else only use WG + g_no_st_histogram => g_no_st_histogram, + g_buf_nof_data => g_buf_nof_data, + g_bsn_nof_clk_per_sync => g_bsn_nof_clk_per_sync, -- Default 200M, overide for short simulation + g_sim => g_sim ) port map ( - dp_rst => rx_rst, - dp_clk => rx_clk, - - mm_rst => mm_rst, - mm_clk => mm_clk, - - sync_in => bs_sosi.sync, - - reg_mosi => reg_dp_shiftram_mosi, - reg_miso => reg_dp_shiftram_miso, - - snk_in_arr => dp_shiftram_snk_in_arr, - - src_out_arr => ant_sosi_arr + -- clocks and resets + mm_clk => mm_clk, + mm_rst => mm_rst, + rx_clk => rx_clk, + rx_rst => rx_rst, + rx_sysref => rx_sysref, + + -- input samples + rx_sosi_arr => rx_sosi_arr, + + -- processing status + bs_sosi_valid => bs_sosi_valid, + -- MM control buses + -- Shiftram (applies per-antenna delay) + reg_dp_shiftram_mosi => reg_dp_shiftram_mosi, + reg_dp_shiftram_miso => reg_dp_shiftram_miso, + + -- bsn source + reg_bsn_source_v2_mosi => reg_bsn_source_v2_mosi, + reg_bsn_source_v2_miso => reg_bsn_source_v2_miso, + + -- bsn scheduler + reg_bsn_scheduler_wg_mosi => reg_bsn_scheduler_wg_mosi, + reg_bsn_scheduler_wg_miso => reg_bsn_scheduler_wg_miso, + + -- WG + reg_wg_mosi => reg_wg_mosi, + reg_wg_miso => reg_wg_miso, + ram_wg_mosi => ram_wg_mosi, + ram_wg_miso => ram_wg_miso, + + -- BSN MONITOR + reg_bsn_monitor_input_mosi => reg_bsn_monitor_input_mosi, + reg_bsn_monitor_input_miso => reg_bsn_monitor_input_miso, + + -- Data buffer for framed samples (variable depth) + ram_diag_data_buf_bsn_mosi => ram_diag_data_buf_bsn_mosi, + ram_diag_data_buf_bsn_miso => ram_diag_data_buf_bsn_miso, + reg_diag_data_buf_bsn_mosi => reg_diag_data_buf_bsn_mosi, + reg_diag_data_buf_bsn_miso => reg_diag_data_buf_bsn_miso, + + -- ST Histogram + ram_st_histogram_mosi => ram_st_histogram_mosi, + ram_st_histogram_miso => ram_st_histogram_miso, + + -- Aduh (statistics) monitor + reg_aduh_monitor_mosi => reg_aduh_monitor_mosi, + reg_aduh_monitor_miso => reg_aduh_monitor_miso, + + -- Streaming data output + out_sosi_arr => st_sosi_arr, + rx_bsn_source_restart => rx_bsn_source_restart, + rx_bsn_source_new_interval => rx_bsn_source_new_interval, + rx_bsn_source_nof_clk_per_sync => rx_bsn_source_nof_clk_per_sync ); - end generate; - - ----------------------------------------------------------------------------- - -- Timestamp - ----------------------------------------------------------------------------- - u_bsn_source_v2 : entity dp_lib.mms_dp_bsn_source_v2 - generic map ( - g_cross_clock_domain => true, - g_block_size => c_bs_block_size, - g_nof_clk_per_sync => g_bsn_nof_clk_per_sync, - g_bsn_w => c_bs_bsn_w - ) - port map ( - -- Clocks and reset - mm_rst => mm_rst, - mm_clk => mm_clk, - dp_rst => rx_rst, - dp_clk => rx_clk, - dp_pps => rx_sysref, - - -- Memory-mapped clock domain - reg_mosi => reg_bsn_source_v2_mosi, - reg_miso => reg_bsn_source_v2_miso, - - -- Streaming clock domain - bs_sosi => bs_sosi, - - bs_restart => rx_bsn_source_restart, - bs_new_interval => rx_bsn_source_new_interval, - bs_nof_clk_per_sync => rx_bsn_source_nof_clk_per_sync - ); - - u_bsn_trigger_wg : entity dp_lib.mms_dp_bsn_scheduler - generic map ( - g_cross_clock_domain => true, - g_bsn_w => c_bs_bsn_w - ) - port map ( - -- Memory-mapped clock domain - mm_rst => mm_rst, - mm_clk => mm_clk, - - reg_mosi => reg_bsn_scheduler_wg_mosi, - reg_miso => reg_bsn_scheduler_wg_miso, - - -- Streaming clock domain - dp_rst => rx_rst, - dp_clk => rx_clk, - - snk_in => bs_sosi, -- only uses eop (= block sync), bsn[] - trigger_out => trigger_wg - ); - - ----------------------------------------------------------------------------- - -- WG (Test Signal Generator) - ----------------------------------------------------------------------------- - - u_wg_arr : entity diag_lib.mms_diag_wg_wideband_arr - generic map ( - g_nof_streams => c_sdp_S_pn, - g_cross_clock_domain => true, - g_buf_dir => c_wg_buf_directory, - - -- Wideband parameters - g_wideband_factor => 1, - - -- Basic WG parameters, see diag_wg.vhd for their meaning - g_buf_dat_w => c_wg_buf_dat_w, - g_buf_addr_w => c_wg_buf_addr_w, - g_calc_support => true, - g_calc_gain_w => 1, - g_calc_dat_w => c_sdp_W_adc - ) - port map ( - -- Memory-mapped clock domain - mm_rst => mm_rst, - mm_clk => mm_clk, - - reg_mosi => reg_wg_mosi, - reg_miso => reg_wg_miso, - - buf_mosi => ram_wg_mosi, - buf_miso => ram_wg_miso, - - -- Streaming clock domain - st_rst => rx_rst, - st_clk => rx_clk, - st_restart => trigger_wg, - - out_sosi_arr => wg_sosi_arr - ); - - ----------------------------------------------------------------------------- - -- ADC/WG Mux (Input Select) - ----------------------------------------------------------------------------- - - gen_mux : for I in 0 to c_sdp_S_pn - 1 generate - p_sosi : process(ant_sosi_arr(I), wg_sosi_arr(I)) - begin - -- Default use the ADC data - nxt_mux_sosi_arr(I).data <= ant_sosi_arr(I).data; - if wg_sosi_arr(I).valid = '1' then - -- Valid WG data overrules ADC data - nxt_mux_sosi_arr(I).data <= wg_sosi_arr(I).data; - end if; - end process; - end generate; - - mux_sosi_arr <= nxt_mux_sosi_arr when rising_edge(rx_clk); - - ----------------------------------------------------------------------------- - -- Concatenate muxed data streams with bsn framing - ----------------------------------------------------------------------------- - - gen_concat : for I in 0 to c_sdp_S_pn - 1 generate - p_sosi : process(mux_sosi_arr(I), bs_sosi) - begin - st_sosi_arr(I) <= bs_sosi; - st_sosi_arr(I).data <= mux_sosi_arr(I).data; - end process; - end generate; - - --------------------------------------------------------------------------------------- - -- Diagnostics on the bsn-framed data - -- . BSN Monitor (ToDo: can be removed as not part of the spec) - -- . Aduh monitor - -- . Data Buffer (variable depth from 1k-128k) - --------------------------------------------------------------------------------------- - - --------------------------------------------------------------------------------------- - -- BSN monitor (Block Checker) - --------------------------------------------------------------------------------------- - u_bsn_monitor : entity dp_lib.mms_dp_bsn_monitor - generic map ( - g_nof_streams => 1, -- They're all the same - g_sync_timeout => c_bs_sync_timeout, - g_bsn_w => c_bs_bsn_w, - g_log_first_bsn => false - ) - port map ( - -- Memory-mapped clock domain - mm_rst => mm_rst, - mm_clk => mm_clk, - reg_mosi => reg_bsn_monitor_input_mosi, - reg_miso => reg_bsn_monitor_input_miso, - - -- Streaming clock domain - dp_rst => rx_rst, - dp_clk => rx_clk, - in_sosi_arr => st_sosi_arr(0 downto 0) - ); - ----------------------------------------------------------------------------- - -- Monitor ADU/WG output - ----------------------------------------------------------------------------- - u_aduh_monitor : entity aduh_lib.mms_aduh_monitor_arr - generic map ( - g_cross_clock_domain => true, - g_nof_streams => c_sdp_S_pn, - g_symbol_w => c_sdp_W_adc, - g_nof_symbols_per_data => 1, -- Wideband factor is 1 - g_nof_accumulations => g_bsn_nof_clk_per_sync - ) - port map ( - -- Memory-mapped clock domain - mm_rst => mm_rst, - mm_clk => mm_clk, - - reg_mosi => reg_aduh_monitor_mosi, -- read only access to the signal path data mean sum and power sum registers - reg_miso => reg_aduh_monitor_miso, - buf_mosi => c_mem_mosi_rst, -- Unused - buf_miso => OPEN, - - -- Streaming clock domain - st_rst => rx_rst, - st_clk => rx_clk, - - in_sosi_arr => st_sosi_arr - ); - - ----------------------------------------------------------------------------- - -- Diagnostic Data Buffer - ----------------------------------------------------------------------------- - - u_diag_data_buffer_bsn : entity diag_lib.mms_diag_data_buffer - generic map ( - g_nof_streams => c_sdp_S_pn, - g_data_w => c_sdp_W_adc, - g_buf_nof_data => g_buf_nof_data, - g_buf_use_sync => true -- when TRUE start filling the buffer at the in_sync, else after the last word was read - ) - port map ( - mm_rst => mm_rst, - mm_clk => mm_clk, - dp_rst => rx_rst, - dp_clk => rx_clk, - - ram_data_buf_mosi => ram_diag_data_buf_bsn_mosi, - ram_data_buf_miso => ram_diag_data_buf_bsn_miso, - reg_data_buf_mosi => reg_diag_data_buf_bsn_mosi, - reg_data_buf_miso => reg_diag_data_buf_bsn_miso, - - in_sosi_arr => st_sosi_arr, - in_sync => st_sosi_arr(0).sync - ); - - ----------------------------------------------------------------------------- - -- ST Histogram - ----------------------------------------------------------------------------- - u_st_histogram : entity st_lib.mmp_st_histogram - generic map ( - g_nof_instances => c_sdp_S_pn, - g_data_w => c_sdp_W_adc, - g_nof_bins => c_sdp_V_si_histogram, - g_nof_data_per_sync => g_bsn_nof_clk_per_sync, - g_nof_data_per_sync_diff => c_sdp_N_fft / 2 - ) - port map ( - mm_rst => mm_rst, - mm_clk => mm_clk, - dp_rst => rx_rst, - dp_clk => rx_clk, - - ram_copi => ram_st_histogram_mosi, - ram_cipo => ram_st_histogram_miso, - - snk_in_arr => st_sosi_arr - ); - - ----------------------------------------------------------------------------- - -- Output Stage - -- . Thin dual clock fifo to cross from jesd frame clock (rx_clk) to dp_clk domain - ----------------------------------------------------------------------------- - - -- rx_aux is synchronous with st_sosi_arr - rx_aux(0) <= rx_bsn_source_restart; - rx_aux(1) <= rx_bsn_source_new_interval; - - -- dp_aux is synchronous with out_sosi_arr - dp_bsn_source_restart <= dp_aux(0); - dp_bsn_source_new_interval <= dp_aux(1); + ----------------------------------------------------------------------------- + -- Output rx_clk to dp_clk clock domain crossing + ----------------------------------------------------------------------------- + -- rx_aux is synchronous with st_sosi_arr + rx_aux(0) <= rx_bsn_source_restart; + rx_aux(1) <= rx_bsn_source_new_interval; + + -- dp_aux is synchronous with out_sosi_arr + dp_bsn_source_restart <= dp_aux(0); + dp_bsn_source_new_interval <= dp_aux(1); + + -- Thin dual clock fifo to cross from jesd frame clock (rx_clk) to dp_clk domain + u_dp_fifo_dc_arr : entity dp_lib.dp_fifo_dc_arr + generic map ( + g_nof_streams => c_sdp_S_pn, + g_data_w => c_sdp_W_adc, + g_data_signed => true, + g_bsn_w => c_bs_bsn_w, + g_aux_w => c_bs_aux_w, + g_use_empty => false, + g_use_ctrl => true, + g_use_sync => true, + g_use_bsn => true, + g_use_aux => true, + g_fifo_size => c_dp_fifo_dc_size + ) + port map ( + wr_rst => rx_rst, + wr_clk => rx_clk, + rd_rst => dp_rst, + rd_clk => dp_clk, + snk_in_arr => st_sosi_arr, + src_out_arr => out_sosi_arr, + in_aux => rx_aux, + out_aux => dp_aux + ); + + -- MM write of rx_bsn_source_nof_clk_per_sync occurs with sufficient margin before it + -- is used. Still use common_reg_cross_domain nonetheless to get from mm_clk to rx_clk + -- in mms_dp_bsn_monitor, and from rx_clk to dp_clk here. No need to go via + -- u_dp_fifo_dc_arr, use common_reg_cross_domain instead to save logic and/or RAM. + u_dp_nof_block_per_sync : entity common_lib.common_reg_cross_domain + port map ( + in_rst => rx_rst, + in_clk => rx_clk, + in_dat => rx_bsn_source_nof_clk_per_sync, + out_rst => dp_rst, + out_clk => dp_clk, + out_dat => dp_bsn_source_nof_clk_per_sync + ); + end generate; -- gen_rx_ait - u_dp_fifo_dc_arr : entity dp_lib.dp_fifo_dc_arr + -- Wire dp_clk to AIT when jesd is not used or when jesd IP tech_jesd204b_v2 is used + gen_dp_ait : if g_no_jesd = true or (g_no_jesd = false and g_use_tech_jesd204b_v2 = true) generate + u_dp_ait : entity work.sdp_adc_input_and_timing generic map ( - g_nof_streams => c_sdp_S_pn, - g_data_w => c_sdp_W_adc, - g_data_signed => true, - g_bsn_w => c_bs_bsn_w, - g_aux_w => c_bs_aux_w, - g_use_empty => false, - g_use_ctrl => true, - g_use_sync => true, - g_use_bsn => true, - g_use_aux => true, - g_fifo_size => c_dp_fifo_dc_size + g_no_rx => g_no_jesd, -- when false use Rx and WG, else only use WG + g_no_st_histogram => g_no_st_histogram, + g_buf_nof_data => g_buf_nof_data, + g_bsn_nof_clk_per_sync => g_bsn_nof_clk_per_sync, -- Default 200M, overide for short simulation + g_sim => g_sim ) port map ( - wr_rst => rx_rst, - wr_clk => rx_clk, - rd_rst => dp_rst, - rd_clk => dp_clk, - snk_in_arr => st_sosi_arr, - src_out_arr => out_sosi_arr, - in_aux => rx_aux, - out_aux => dp_aux + -- clocks and resets + mm_clk => mm_clk, + mm_rst => mm_rst, + rx_clk => dp_clk, + rx_rst => dp_rst, + rx_sysref => dp_sysref, + + -- input samples + rx_sosi_arr => rx_sosi_arr, + + -- processing status + bs_sosi_valid => bs_sosi_valid, + + -- MM control buses + -- Shiftram (applies per-antenna delay) + reg_dp_shiftram_mosi => reg_dp_shiftram_mosi, + reg_dp_shiftram_miso => reg_dp_shiftram_miso, + + -- bsn source + reg_bsn_source_v2_mosi => reg_bsn_source_v2_mosi, + reg_bsn_source_v2_miso => reg_bsn_source_v2_miso, + + -- bsn scheduler + reg_bsn_scheduler_wg_mosi => reg_bsn_scheduler_wg_mosi, + reg_bsn_scheduler_wg_miso => reg_bsn_scheduler_wg_miso, + + -- WG + reg_wg_mosi => reg_wg_mosi, + reg_wg_miso => reg_wg_miso, + ram_wg_mosi => ram_wg_mosi, + ram_wg_miso => ram_wg_miso, + + -- BSN MONITOR + reg_bsn_monitor_input_mosi => reg_bsn_monitor_input_mosi, + reg_bsn_monitor_input_miso => reg_bsn_monitor_input_miso, + + -- Data buffer for framed samples (variable depth) + ram_diag_data_buf_bsn_mosi => ram_diag_data_buf_bsn_mosi, + ram_diag_data_buf_bsn_miso => ram_diag_data_buf_bsn_miso, + reg_diag_data_buf_bsn_mosi => reg_diag_data_buf_bsn_mosi, + reg_diag_data_buf_bsn_miso => reg_diag_data_buf_bsn_miso, + + -- ST Histogram + ram_st_histogram_mosi => ram_st_histogram_mosi, + ram_st_histogram_miso => ram_st_histogram_miso, + + -- Aduh (statistics) monitor + reg_aduh_monitor_mosi => reg_aduh_monitor_mosi, + reg_aduh_monitor_miso => reg_aduh_monitor_miso, + + -- Streaming data output + out_sosi_arr => out_sosi_arr, + rx_bsn_source_restart => dp_bsn_source_restart, + rx_bsn_source_new_interval => dp_bsn_source_new_interval, + rx_bsn_source_nof_clk_per_sync => dp_bsn_source_nof_clk_per_sync ); - - -- MM write of rx_bsn_source_nof_clk_per_sync occurs with sufficient margin before it - -- is used. Still use common_reg_cross_domain nonetheless to get from mm_clk to rx_clk - -- in mms_dp_bsn_monitor, and from rx_clk to dp_clk here. No need to go via - -- u_dp_fifo_dc_arr, use common_reg_cross_domain instead to save logic and/or RAM. - u_dp_nof_block_per_sync : entity common_lib.common_reg_cross_domain - port map ( - in_rst => rx_rst, - in_clk => rx_clk, - in_dat => rx_bsn_source_nof_clk_per_sync, - out_rst => dp_rst, - out_clk => dp_clk, - out_dat => dp_bsn_source_nof_clk_per_sync - ); - - ----------------------------------------------------------------------------- - -- JESD Control register - ----------------------------------------------------------------------------- - u_mm_jesd_ctrl_reg : entity common_lib.common_reg_r_w - generic map ( - g_reg => c_sdp_mm_jesd_ctrl_reg, - g_init_reg => (others => '0') - ) - port map ( - rst => mm_rst, - clk => mm_clk, - -- control side - wr_en => jesd_ctrl_mosi.wr, - wr_adr => jesd_ctrl_mosi.address(c_sdp_mm_jesd_ctrl_reg.adr_w - 1 downto 0), - wr_dat => jesd_ctrl_mosi.wrdata(c_sdp_mm_jesd_ctrl_reg.dat_w - 1 downto 0), - rd_en => jesd_ctrl_mosi.rd, - rd_adr => jesd_ctrl_mosi.address(c_sdp_mm_jesd_ctrl_reg.adr_w - 1 downto 0), - rd_dat => jesd_ctrl_miso.rddata(c_sdp_mm_jesd_ctrl_reg.dat_w - 1 downto 0), - rd_val => OPEN, - -- data side - out_reg => mm_jesd_ctrl_reg_wr, - in_reg => mm_jesd_ctrl_reg_rd - ); + end generate; -- gen_rx_ait end str; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_adc_input_and_timing.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_adc_input_and_timing.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a821ed5603536208ae8e9b3bb253d0af90390e9b --- /dev/null +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_adc_input_and_timing.vhd @@ -0,0 +1,406 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2024 +-- 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. +-- +------------------------------------------------------------------------------- + +-- Authors : J Hargreaves, L Hiemstra, R van der Walle, E. Kooistra +-- Purpose: +-- AIT - ADC / WG input, timing and associated diagnostic blocks +-- Description: +-- Contains all the signal processing blocks to receive and time the ADC input data +-- See https://support.astron.nl/confluence/display/STAT/L5+SDPFW+DD%3A+ADC+data+input+and+timestamp + +library IEEE, common_lib, diag_lib, aduh_lib, dp_lib, tech_jesd204b_lib, st_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 diag_lib.diag_pkg.all; +use dp_lib.dp_stream_pkg.all; +use work.sdp_pkg.all; + +entity sdp_adc_input_and_timing is + generic ( + g_no_rx : boolean := false; -- when false use Rx and WG, else use only WG + g_no_st_histogram : boolean := true; -- when false use input histogram, else not to save block RAM + g_buf_nof_data : natural := c_sdp_V_si_db; + g_bsn_nof_clk_per_sync : natural := c_sdp_N_clk_per_sync; -- Default 200M, overide for short simulation + g_sim : boolean := false + ); + port ( + -- clocks and resets + mm_clk : in std_logic; + mm_rst : in std_logic; + rx_clk : in std_logic; + rx_rst : in std_logic; + rx_sysref : in std_logic; + + -- input samples + rx_sosi_arr : in t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); + + -- processing status + bs_sosi_valid : out std_logic; + + -- MM control buses + -- Shiftram (applies per-antenna delay) + reg_dp_shiftram_mosi : in t_mem_mosi := c_mem_mosi_rst; + reg_dp_shiftram_miso : out t_mem_miso := c_mem_miso_rst; + + -- bsn source + reg_bsn_source_v2_mosi : in t_mem_mosi := c_mem_mosi_rst; + reg_bsn_source_v2_miso : out t_mem_miso := c_mem_miso_rst; + + -- bsn scheduler + reg_bsn_scheduler_wg_mosi : in t_mem_mosi := c_mem_mosi_rst; + reg_bsn_scheduler_wg_miso : out t_mem_miso := c_mem_miso_rst; + + -- WG + reg_wg_mosi : in t_mem_mosi := c_mem_mosi_rst; + reg_wg_miso : out t_mem_miso := c_mem_miso_rst; + ram_wg_mosi : in t_mem_mosi := c_mem_mosi_rst; + ram_wg_miso : out t_mem_miso := c_mem_miso_rst; + + -- BSN MONITOR + reg_bsn_monitor_input_mosi : in t_mem_mosi; + reg_bsn_monitor_input_miso : out t_mem_miso; + + -- Data buffer for framed samples (variable depth) + ram_diag_data_buf_bsn_mosi : in t_mem_mosi; + ram_diag_data_buf_bsn_miso : out t_mem_miso; + reg_diag_data_buf_bsn_mosi : in t_mem_mosi; + reg_diag_data_buf_bsn_miso : out t_mem_miso; + + -- ST Histogram + ram_st_histogram_mosi : in t_mem_mosi; + ram_st_histogram_miso : out t_mem_miso; + + -- Aduh (statistics) monitor + reg_aduh_monitor_mosi : in t_mem_mosi; + reg_aduh_monitor_miso : out t_mem_miso; + + -- Streaming data output + out_sosi_arr : out t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0); + rx_bsn_source_restart : out std_logic; -- for dp_sync_recover in WPFB + rx_bsn_source_new_interval : out std_logic; -- for SST and BST statistics offload, XST uses new_interval based on xst_processing_enable + rx_bsn_source_nof_clk_per_sync : out std_logic_vector(c_word_w - 1 downto 0) -- for RSN source in transient buffer + ); +end sdp_adc_input_and_timing; + +architecture str of sdp_adc_input_and_timing is + -- Waveform Generator + constant c_wg_buf_directory : string := "data/"; + constant c_wg_buf_dat_w : natural := 18; -- default value of WG that fits 14 bits of ADC data + constant c_wg_buf_addr_w : natural := 10; -- default value of WG for 1024 samples; + signal trigger_wg : std_logic; + + -- Frame parameters + constant c_bs_sync_timeout : natural := g_bsn_nof_clk_per_sync + g_bsn_nof_clk_per_sync / 10; -- +10% margin + constant c_bs_bsn_w : natural := 64; -- > 51; + constant c_bs_aux_w : natural := 2; + constant c_bs_block_size : natural := c_sdp_N_fft; -- =1024; + constant c_dp_fifo_dc_size : natural := 64; + + -- Sosis and sosi arrays + signal dp_shiftram_snk_in_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); + signal ant_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); + signal bs_sosi : t_dp_sosi := c_dp_sosi_rst; + signal wg_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); + signal mux_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); + signal nxt_mux_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); + signal st_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst); +begin + out_sosi_arr <= st_sosi_arr; + + gen_rx : if g_no_rx = false generate + ----------------------------------------------------------------------------- + -- Time delay: dp_shiftram + -- . copied from unb1_bn_capture_input (apertif) + -- Array range reversal is not done because everything is DOWNTO + -- . the input valid is always '1', even when there is no data + ----------------------------------------------------------------------------- + p_dp_shiftram_snk_in_arr : process(rx_sosi_arr) + begin + dp_shiftram_snk_in_arr <= rx_sosi_arr; + for I in 0 to c_sdp_S_pn - 1 loop + -- ADC data is stored in the upper 14 bits of the jesd rx_sosi. + dp_shiftram_snk_in_arr(I).data <= RESIZE_DP_SDATA(rx_sosi_arr(I).data(c_sdp_W_adc_jesd - 1 downto (c_sdp_W_adc_jesd - c_sdp_W_adc) )); + -- Force valid. + dp_shiftram_snk_in_arr(I).valid <= '1'; + end loop; + end process; + + u_dp_shiftram : entity dp_lib.dp_shiftram + generic map ( + g_nof_streams => c_sdp_S_pn, + g_nof_words => c_sdp_V_sample_delay, + g_data_w => c_sdp_W_adc, + g_use_sync_in => true + ) + port map ( + dp_rst => rx_rst, + dp_clk => rx_clk, + + mm_rst => mm_rst, + mm_clk => mm_clk, + + sync_in => bs_sosi.sync, + + reg_mosi => reg_dp_shiftram_mosi, + reg_miso => reg_dp_shiftram_miso, + + snk_in_arr => dp_shiftram_snk_in_arr, + + src_out_arr => ant_sosi_arr + ); + end generate; + + ----------------------------------------------------------------------------- + -- Timestamp + ----------------------------------------------------------------------------- + u_bsn_source_v2 : entity dp_lib.mms_dp_bsn_source_v2 + generic map ( + g_cross_clock_domain => true, + g_block_size => c_bs_block_size, + g_nof_clk_per_sync => g_bsn_nof_clk_per_sync, + g_bsn_w => c_bs_bsn_w + ) + port map ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => rx_rst, + dp_clk => rx_clk, + dp_pps => rx_sysref, + + -- Memory-mapped clock domain + reg_mosi => reg_bsn_source_v2_mosi, + reg_miso => reg_bsn_source_v2_miso, + + -- Streaming clock domain + bs_sosi => bs_sosi, + + bs_restart => rx_bsn_source_restart, + bs_new_interval => rx_bsn_source_new_interval, + bs_nof_clk_per_sync => rx_bsn_source_nof_clk_per_sync + ); + + bs_sosi_valid <= bs_sosi.valid; + + u_bsn_trigger_wg : entity dp_lib.mms_dp_bsn_scheduler + generic map ( + g_cross_clock_domain => true, + g_bsn_w => c_bs_bsn_w + ) + port map ( + -- Memory-mapped clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + + reg_mosi => reg_bsn_scheduler_wg_mosi, + reg_miso => reg_bsn_scheduler_wg_miso, + + -- Streaming clock domain + dp_rst => rx_rst, + dp_clk => rx_clk, + + snk_in => bs_sosi, -- only uses eop (= block sync), bsn[] + trigger_out => trigger_wg + ); + + ----------------------------------------------------------------------------- + -- WG (Test Signal Generator) + ----------------------------------------------------------------------------- + + u_wg_arr : entity diag_lib.mms_diag_wg_wideband_arr + generic map ( + g_nof_streams => c_sdp_S_pn, + g_cross_clock_domain => true, + g_buf_dir => c_wg_buf_directory, + + -- Wideband parameters + g_wideband_factor => 1, + + -- Basic WG parameters, see diag_wg.vhd for their meaning + g_buf_dat_w => c_wg_buf_dat_w, + g_buf_addr_w => c_wg_buf_addr_w, + g_calc_support => true, + g_calc_gain_w => 1, + g_calc_dat_w => c_sdp_W_adc + ) + port map ( + -- Memory-mapped clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + + reg_mosi => reg_wg_mosi, + reg_miso => reg_wg_miso, + + buf_mosi => ram_wg_mosi, + buf_miso => ram_wg_miso, + + -- Streaming clock domain + st_rst => rx_rst, + st_clk => rx_clk, + st_restart => trigger_wg, + + out_sosi_arr => wg_sosi_arr + ); + + ----------------------------------------------------------------------------- + -- ADC/WG Mux (Input Select) + ----------------------------------------------------------------------------- + + gen_mux : for I in 0 to c_sdp_S_pn - 1 generate + p_sosi : process(ant_sosi_arr(I), wg_sosi_arr(I)) + begin + -- Default use the ADC data + nxt_mux_sosi_arr(I).data <= ant_sosi_arr(I).data; + if wg_sosi_arr(I).valid = '1' then + -- Valid WG data overrules ADC data + nxt_mux_sosi_arr(I).data <= wg_sosi_arr(I).data; + end if; + end process; + end generate; + + mux_sosi_arr <= nxt_mux_sosi_arr when rising_edge(rx_clk); + + ----------------------------------------------------------------------------- + -- Concatenate muxed data streams with bsn framing + ----------------------------------------------------------------------------- + + gen_concat : for I in 0 to c_sdp_S_pn - 1 generate + p_sosi : process(mux_sosi_arr(I), bs_sosi) + begin + st_sosi_arr(I) <= bs_sosi; + st_sosi_arr(I).data <= mux_sosi_arr(I).data; + end process; + end generate; + + --------------------------------------------------------------------------------------- + -- Diagnostics on the bsn-framed data + -- . BSN Monitor (ToDo: can be removed as not part of the spec) + -- . Aduh monitor + -- . Data Buffer (variable depth from 1k-128k) + --------------------------------------------------------------------------------------- + + --------------------------------------------------------------------------------------- + -- BSN monitor (Block Checker) + --------------------------------------------------------------------------------------- + u_bsn_monitor : entity dp_lib.mms_dp_bsn_monitor + generic map ( + g_nof_streams => 1, -- They're all the same + g_sync_timeout => c_bs_sync_timeout, + g_bsn_w => c_bs_bsn_w, + g_log_first_bsn => false + ) + port map ( + -- Memory-mapped clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + reg_mosi => reg_bsn_monitor_input_mosi, + reg_miso => reg_bsn_monitor_input_miso, + + -- Streaming clock domain + dp_rst => rx_rst, + dp_clk => rx_clk, + in_sosi_arr => st_sosi_arr(0 downto 0) + ); + + ----------------------------------------------------------------------------- + -- Monitor ADU/WG output + ----------------------------------------------------------------------------- + u_aduh_monitor : entity aduh_lib.mms_aduh_monitor_arr + generic map ( + g_cross_clock_domain => true, + g_nof_streams => c_sdp_S_pn, + g_symbol_w => c_sdp_W_adc, + g_nof_symbols_per_data => 1, -- Wideband factor is 1 + g_nof_accumulations => g_bsn_nof_clk_per_sync + ) + port map ( + -- Memory-mapped clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + + reg_mosi => reg_aduh_monitor_mosi, -- read only access to the signal path data mean sum and power sum registers + reg_miso => reg_aduh_monitor_miso, + buf_mosi => c_mem_mosi_rst, -- Unused + buf_miso => OPEN, + + -- Streaming clock domain + st_rst => rx_rst, + st_clk => rx_clk, + + in_sosi_arr => st_sosi_arr + ); + + ----------------------------------------------------------------------------- + -- Diagnostic Data Buffer + ----------------------------------------------------------------------------- + + u_diag_data_buffer_bsn : entity diag_lib.mms_diag_data_buffer + generic map ( + g_nof_streams => c_sdp_S_pn, + g_data_w => c_sdp_W_adc, + g_buf_nof_data => g_buf_nof_data, + g_buf_use_sync => true -- when TRUE start filling the buffer at the in_sync, else after the last word was read + ) + port map ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => rx_rst, + dp_clk => rx_clk, + + ram_data_buf_mosi => ram_diag_data_buf_bsn_mosi, + ram_data_buf_miso => ram_diag_data_buf_bsn_miso, + reg_data_buf_mosi => reg_diag_data_buf_bsn_mosi, + reg_data_buf_miso => reg_diag_data_buf_bsn_miso, + + in_sosi_arr => st_sosi_arr, + in_sync => st_sosi_arr(0).sync + ); + + ----------------------------------------------------------------------------- + -- ST Histogram + ----------------------------------------------------------------------------- + no_st_histogram : if g_no_st_histogram = true generate + ram_st_histogram_miso <= c_mem_miso_rst; + end generate; + + gen_st_histogram : if g_no_st_histogram = false generate + u_st_histogram : entity st_lib.mmp_st_histogram + generic map ( + g_nof_instances => c_sdp_S_pn, + g_data_w => c_sdp_W_adc, + g_nof_bins => c_sdp_V_si_histogram, + g_nof_data_per_sync => g_bsn_nof_clk_per_sync, + g_nof_data_per_sync_diff => c_sdp_N_fft / 2 + ) + port map ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => rx_rst, + dp_clk => rx_clk, + + ram_copi => ram_st_histogram_mosi, + ram_cipo => ram_st_histogram_miso, + + snk_in_arr => st_sosi_arr + ); + end generate; +end str; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd index e33f2166ab48f8e3c6b0c3ba91232a8b110323fb..d19cf03a6bc05de9ef2f36ef7f76b668869b5d9e 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_pkg.vhd @@ -59,11 +59,17 @@ package sdp_bdo_pkg is -- nof_destinations > 1 and how many block RAM resources are available for -- the reordering. Therefore c_sdp_bdo_reorder_nof_blocks_max = 16 is a -- suitable compromise value. - constant c_sdp_bdo_reorder_nof_blocks_max : natural := 16; + -- Conclusion (14 feb 2024): + -- . Choose c_sdp_bdo_reorder_nof_blocks_max = 4 to save block RAM resources, + -- and because it is acceptable to have smaller packets in case of more + -- than 4 destinations. Note that the reorder buffer is dual page. + -- . Choose nof_bdo_destinations_max = 8 in design revision, because it is + -- enough for CEP, and to save logic resources and to ease timing closure. + constant c_sdp_bdo_reorder_nof_blocks_max : natural := 4; constant c_sdp_bdo_reorder_nof_blocks_w : natural := ceil_log2(c_sdp_bdo_reorder_nof_blocks_max + 1); constant c_sdp_bdo_reorder_nof_ch_max : natural := c_sdp_bdo_reorder_nof_blocks_max * c_sdp_nof_beamlets_per_block * - c_sdp_nof_words_per_beamlet; -- = 7808 + c_sdp_nof_words_per_beamlet; -- = 4 * 488 * 1 = 1952 32b -- 32 * 3 + 4 = 100 fields constant c_sdp_bdo_destinations_info_nof_hdr_fields : natural := c_sdp_bdo_mm_nof_destinations_max * 3 + 4; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd index 5cb70ece517fb1fadfc6b05c3e0b9eebfc1ac4bc..727c59d7774ed8e9207a182450e5452e177994d0 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd @@ -62,7 +62,11 @@ entity sdp_station is g_bsn_nof_clk_per_sync : natural := c_sdp_N_clk_per_sync; -- Default 200M, overide for short simulation g_scope_selected_subband : natural := 0; -- Use no default, to force instance to set it - g_no_jesd : boolean; + g_no_jesd : boolean; -- when false use Rx JESD204B and WG, else use only WG + -- When g_use_tech_jesd204b_v2 = false use tech_jesd204b with tech_jesd204b and FIFO in ait, + -- else use tech_jesd204b_v2 with FIFO in tech_jesd204b_v2 + g_use_tech_jesd204b_v2 : boolean := true; --false; + g_no_st_histogram : boolean := true; -- when false use input histogram, else not to save block RAM g_use_fsub : boolean; g_use_oversample : boolean; g_use_xsub : boolean; @@ -671,6 +675,8 @@ begin generic map( g_sim => g_sim, g_no_jesd => g_no_jesd, + g_no_st_histogram => g_no_st_histogram, + g_use_tech_jesd204b_v2 => g_use_tech_jesd204b_v2, g_bsn_nof_clk_per_sync => g_bsn_nof_clk_per_sync ) port map( diff --git a/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd b/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd index 5bc9dffb7f286cb79db7b3d6c6994c6cd236657c..5a6d2b1441b06c503b019b891732c203a0c3c30e 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_dc_arr.vhd @@ -68,7 +68,7 @@ entity dp_fifo_dc_arr is -- ST sink snk_out_arr : out t_dp_siso_arr(g_nof_streams - 1 downto 0); snk_in_arr : in t_dp_sosi_arr(g_nof_streams - 1 downto 0); - in_aux : in std_logic_vector(g_aux_w - 1 downto 0); + in_aux : in std_logic_vector(g_aux_w - 1 downto 0) := (others => '0'); -- ST source src_in_arr : in t_dp_siso_arr(g_nof_streams - 1 downto 0) := (others => c_dp_siso_rdy); src_out_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); diff --git a/libraries/technology/ip_arria10_e1sg/jesd204b/hdllib.cfg b/libraries/technology/ip_arria10_e1sg/jesd204b/hdllib.cfg index 33d3183e33517dbf202c9ff51cfba91e832f48b5..ead2a546eb5e393245d1636834cc7350d7f310a9 100644 --- a/libraries/technology/ip_arria10_e1sg/jesd204b/hdllib.cfg +++ b/libraries/technology/ip_arria10_e1sg/jesd204b/hdllib.cfg @@ -3,11 +3,12 @@ hdl_lib_name = ip_arria10_e1sg_jesd204b hdl_library_clause_name = ip_arria10_e1sg_jesd204b_lib hdl_lib_uses_synth = technology tech_pll common dp hdl_lib_uses_sim = ip_arria10_e1sg_altera_jesd204_180 ip_arria10_e1sg_altera_xcvr_reset_control_180 ip_arria10_e1sg_altera_iopll_180 ip_arria10_e1sg_altera_reset_sequencer_180 -hdl_lib_technology = ip_arria10_e1sg +hdl_lib_technology = ip_arria10_e1sg synth_files = ip_arria10_e1sg_jesd204b_component_pkg.vhd ip_arria10_e1sg_jesd204b.vhd + ip_arria10_e1sg_jesd204b_v2.vhd test_bench_files = @@ -25,7 +26,7 @@ quartus_qip_files = $HDL_BUILD_DIR/<buildset_name>/qsys-generate/ip_arria10_e1sg_jesd204b_tx/ip_arria10_e1sg_jesd204b_tx.qip [generate_ip_libs] -qsys-generate_ip_files = +qsys-generate_ip_files = ip_arria10_e1sg_jesd204b_rx_200MHz.ip ip_arria10_e1sg_jesd204b_rx_core_pll_200MHz.ip ip_arria10_e1sg_jesd204b_rx_reset_seq.ip diff --git a/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b.vhd b/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b.vhd index 554b93b24765987e6d81470ada650b9804adf087..75fd5401f758dc7dc82f0470c68c1b84cd807205 100644 --- a/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b.vhd +++ b/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b.vhd @@ -46,9 +46,12 @@ entity ip_arria10_e1sg_jesd204b is ); port ( -- JESD204B external signals - jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock reference pin - jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase wrt jesd204b_device_clk - jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock + -- reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with + -- respect to jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization / + -- syncronization phase -- Data to fabric rx_src_out_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data out to fabric @@ -76,10 +79,11 @@ architecture str of ip_arria10_e1sg_jesd204b is -- but using mm_addr_w = 8 and span = 256 words is fine too. constant c_jesd204b_mm_addr_w : natural := 8; constant c_jesd204b_rx_data_w : natural := 32; - constant c_jesd204b_rx_framer_data_w : natural := c_jesd204b_rx_data_w / 2; -- IP outputs two samples in parallel - constant c_jesd204b_rx_somf_w : natural := c_jesd204b_rx_data_w / 8; -- One somf bit per octet - constant c_jesd204b_rx_framer_somf_w : natural := c_jesd204b_rx_somf_w / 2; -- IP outputs two samples in parallel - constant c_nof_sync_n_per_group : natural := sel_a_b(g_nof_streams / g_nof_sync_n = 0, 1, g_nof_streams / g_nof_sync_n); + constant c_jesd204b_rx_framer_data_w : natural := c_jesd204b_rx_data_w / 2; -- = 16, two samples in parallel + constant c_jesd204b_rx_somf_w : natural := c_jesd204b_rx_data_w / 8; -- = 4, one somf bit per octet + constant c_jesd204b_rx_framer_somf_w : natural := c_jesd204b_rx_somf_w / 2; -- = 2, two samples in parallel + constant c_nof_sync_n_per_group : natural := sel_a_b(g_nof_streams / g_nof_sync_n = 0, + 1, g_nof_streams / g_nof_sync_n); -- JESD204 control status registers signal jesd204b_mosi_arr : t_mem_mosi_arr(g_nof_streams - 1 downto 0); @@ -92,8 +96,8 @@ architecture str of ip_arria10_e1sg_jesd204b is signal rxlink_clk : std_logic; signal jesd204b_avs_clk : std_logic; - -- Reset and control signals - signal dev_lane_aligned : std_logic_vector(g_nof_streams - 1 downto 0); -- 1 bit, each interface channel has 1 lane + -- Reset and control signals, 1 bit per lane + signal dev_lane_aligned : std_logic_vector(g_nof_streams - 1 downto 0); signal rx_analogreset_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rx_cal_busy_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rx_digitalreset_arr : std_logic_vector(g_nof_streams - 1 downto 0); @@ -114,22 +118,34 @@ architecture str of ip_arria10_e1sg_jesd204b is signal rx_avs_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxframe_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); - signal f2_div1_cnt_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rxframe_toggle_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal core_pll_locked : std_logic; - signal mm_core_pll_locked_reg : std_logic; - signal jesd204b_sysref_1 : std_logic; - signal jesd204b_sysref_2 : std_logic; - signal jesd204b_sysref_frameclk_1 : std_logic; - signal jesd204b_sysref_frameclk_2 : std_logic; + signal mm_core_pll_locked : std_logic; + signal rxlink_sysref_1 : std_logic; + signal rxlink_sysref_2 : std_logic; + signal rxframe_sysref_1 : std_logic; + signal rxframe_sysref_2 : std_logic; + signal i_rx_src_out_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); + -- debug signal used to view input 0 in Wave Window + signal rx_src_out : t_dp_sosi; -- Data path signal jesd204b_rx_link_data_arr : std_logic_vector(c_jesd204b_rx_data_w * g_nof_streams - 1 downto 0); signal jesd204b_rx_link_valid_arr : std_logic_vector(g_nof_streams - 1 downto 0); - signal jesd204b_rx_somf_arr : std_logic_vector(c_jesd204b_rx_somf_w * g_nof_streams - 1 downto 0); - - signal jesd204b_sync_n_internal_arr : std_logic_vector(g_nof_streams - 1 downto 0); -- output to control ADC initialization/syncronization phase - signal jesd204b_sync_n_enabled_arr : std_logic_vector(g_nof_streams - 1 downto 0); -- output to control ADC initialization/syncronization phase - signal jesd204b_sync_n_combined_arr : std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + signal jesd204b_rx_link_somf_arr : std_logic_vector(c_jesd204b_rx_somf_w * g_nof_streams - 1 downto 0); + -- debug signal to view input 0 in Wave Window + signal jesd204b_rx_link_data : std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); + signal jesd204b_rx_link_data_hi : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal jesd204b_rx_link_data_lo : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal jesd204b_rx_link_valid : std_logic; + signal jesd204b_rx_link_somf : std_logic_vector(c_jesd204b_rx_somf_w - 1 downto 0); + signal jesd204b_rx_link_somf_hi : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); + signal jesd204b_rx_link_somf_lo : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); + + -- outputs to control ADC initialization/syncronization phase + signal jesd204b_sync_n_internal_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_sync_n_enabled_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_sync_n_combined_arr : std_logic_vector(g_nof_sync_n - 1 downto 0); -- Component declarations for the IP blocks @@ -150,15 +166,15 @@ architecture str of ip_arria10_e1sg_jesd204b is csr_s : out std_logic_vector(4 downto 0); -- export dev_lane_aligned : out std_logic; -- export dev_sync_n : out std_logic; -- export - jesd204_rx_avs_chipselect : in std_logic := 'X'; -- chipselect - jesd204_rx_avs_address : in std_logic_vector(c_jesd204b_mm_addr_w - 1 downto 0) := (others => 'X'); -- address - jesd204_rx_avs_read : in std_logic := 'X'; -- read - jesd204_rx_avs_readdata : out std_logic_vector(31 downto 0); -- readdata - jesd204_rx_avs_waitrequest : out std_logic; -- waitrequest - jesd204_rx_avs_write : in std_logic := 'X'; -- write - jesd204_rx_avs_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); -- writedata - jesd204_rx_avs_clk : in std_logic := 'X'; -- clk - jesd204_rx_avs_rst_n : in std_logic := 'X'; -- reset_n + jesd204_rx_avs_chipselect : in std_logic := 'X'; + jesd204_rx_avs_address : in std_logic_vector(c_jesd204b_mm_addr_w - 1 downto 0) := (others => 'X'); + jesd204_rx_avs_read : in std_logic := 'X'; + jesd204_rx_avs_readdata : out std_logic_vector(31 downto 0); + jesd204_rx_avs_waitrequest : out std_logic; + jesd204_rx_avs_write : in std_logic := 'X'; + jesd204_rx_avs_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); + jesd204_rx_avs_clk : in std_logic := 'X'; + jesd204_rx_avs_rst_n : in std_logic := 'X'; jesd204_rx_dlb_data : in std_logic_vector(31 downto 0) := (others => 'X'); -- export jesd204_rx_dlb_data_valid : in std_logic_vector(0 downto 0) := (others => 'X'); -- export jesd204_rx_dlb_disperr : in std_logic_vector(3 downto 0) := (others => 'X'); -- export @@ -231,8 +247,20 @@ architecture str of ip_arria10_e1sg_jesd204b is ); end component ip_arria10_e1sg_jesd204b_rx_xcvr_reset_control_12; begin + -- Debug signals to view input 0 in Wave Window + jesd204b_rx_link_data <= jesd204b_rx_link_data_arr(c_jesd204b_rx_data_w - 1 downto 0); + jesd204b_rx_link_data_hi <= jesd204b_rx_link_data(c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w); + jesd204b_rx_link_data_lo <= jesd204b_rx_link_data(c_jesd204b_rx_framer_data_w - 1 downto 0); + jesd204b_rx_link_valid <= jesd204b_rx_link_valid_arr(0); + jesd204b_rx_link_somf <= jesd204b_rx_link_somf_arr(c_jesd204b_rx_somf_w - 1 downto 0); + jesd204b_rx_link_somf_hi <= jesd204b_rx_link_somf(c_jesd204b_rx_somf_w - 1 downto c_jesd204b_rx_framer_somf_w); + jesd204b_rx_link_somf_lo <= jesd204b_rx_link_somf(c_jesd204b_rx_framer_somf_w - 1 downto 0); + rx_src_out_arr <= i_rx_src_out_arr; + rx_src_out <= i_rx_src_out_arr(0); + -- The mm_rst resets the MM interface, but is also used to reset the JESD IP reset sequencer. - -- Therefore a reset of mm_rst effectively resets the entire ip_arria10_e1sg_jesd204b and causes a reset on the rx_rst output. + -- Therefore a reset of mm_rst effectively resets the entire ip_arria10_e1sg_jesd204b and + -- causes a reset on the rx_rst output. rx_clk <= rxframe_clk; rx_rst <= not core_pll_locked; @@ -252,7 +280,6 @@ begin ----------------------------------------------------------------------------- -- The JESD204 IP (rx only) ----------------------------------------------------------------------------- - gen_jesd204b_rx_freqsel : if g_jesd_freq = "200MHz" generate u_ip_arria10_e1sg_jesd204b_rx_200MHz : ip_arria10_e1sg_jesd204b_rx_200MHz port map ( @@ -271,26 +298,28 @@ begin csr_s => OPEN, dev_lane_aligned => dev_lane_aligned_arr(i), dev_sync_n => jesd204b_sync_n_internal_arr(i), - jesd204_rx_avs_chipselect => '1', - jesd204_rx_avs_address => jesd204b_mosi_arr(i).address(c_jesd204b_mm_addr_w - 1 downto 0), - jesd204_rx_avs_read => jesd204b_mosi_arr(i).rd, - jesd204_rx_avs_readdata => jesd204b_miso_arr(i).rddata(31 downto 0), - jesd204_rx_avs_waitrequest => jesd204b_miso_arr(i).waitrequest, - jesd204_rx_avs_write => jesd204b_mosi_arr(i).wr, - jesd204_rx_avs_writedata => jesd204b_mosi_arr(i).wrdata(31 downto 0), - jesd204_rx_avs_clk => jesd204b_avs_clk, - jesd204_rx_avs_rst_n => rx_avs_rst_n_arr(i), - jesd204_rx_dlb_data => (others => '0'), -- debug/loopback testing + jesd204_rx_avs_chipselect => '1', + jesd204_rx_avs_address => jesd204b_mosi_arr(i).address(c_jesd204b_mm_addr_w - 1 downto 0), + jesd204_rx_avs_read => jesd204b_mosi_arr(i).rd, + jesd204_rx_avs_readdata => jesd204b_miso_arr(i).rddata(31 downto 0), + jesd204_rx_avs_waitrequest => jesd204b_miso_arr(i).waitrequest, + jesd204_rx_avs_write => jesd204b_mosi_arr(i).wr, + jesd204_rx_avs_writedata => jesd204b_mosi_arr(i).wrdata(31 downto 0), + jesd204_rx_avs_clk => jesd204b_avs_clk, + jesd204_rx_avs_rst_n => rx_avs_rst_n_arr(i), + jesd204_rx_dlb_data => (others => '0'), -- debug/loopback testing jesd204_rx_dlb_data_valid => (others => '0'), -- debug/loopback testing jesd204_rx_dlb_disperr => (others => '0'), -- debug/loopback testing jesd204_rx_dlb_errdetect => (others => '0'), -- debug/loopback testing jesd204_rx_dlb_kchar_data => (others => '0'), -- debug/loopback testing jesd204_rx_frame_error => '0', -- jesd204_rx_frame_error.export jesd204_rx_int => OPEN, -- Connected to status IO in example design - jesd204_rx_link_data => jesd204b_rx_link_data_arr(i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 downto i * c_jesd204b_rx_data_w), - jesd204_rx_link_valid => jesd204b_rx_link_valid_arr(i), - jesd204_rx_link_ready => '1', - pll_ref_clk => jesd204b_refclk, -- Aka device_clock, same as reference for the link/frame clock IOPLL (Intel JESD204B-UG p63) + jesd204_rx_link_data => jesd204b_rx_link_data_arr(i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 + downto i * c_jesd204b_rx_data_w), + jesd204_rx_link_valid => jesd204b_rx_link_valid_arr(i), + jesd204_rx_link_ready => '1', + pll_ref_clk => jesd204b_refclk, -- Aka device_clock, same as reference for the link/frame + -- clock IOPLL (Intel JESD204B-UG p63) rx_analogreset => rx_analogreset_arr(I downto I), rx_cal_busy => rx_cal_busy_arr(I downto I), rx_digitalreset => rx_digitalreset_arr(I downto I), @@ -300,8 +329,9 @@ begin rxlink_rst_n_reset_n => rxlink_rst_n_arr(i), -- Assoc with rxlink_clk (Intel JESD204B-UG p69) rxphy_clk => OPEN, -- Not used in Subclass 0 (Intel JESD204B-UG p63) sof => OPEN, - somf => jesd204b_rx_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 downto c_jesd204b_rx_somf_w * i), - sysref => jesd204b_sysref_2 + somf => jesd204b_rx_link_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 + downto c_jesd204b_rx_somf_w * i), + sysref => rxlink_sysref_2 ); -- One cycle rd-rdval latency, waitrequest = '0' fixed @@ -321,7 +351,7 @@ begin irq => open, clk => mm_clk, -- use clk = mm_clk for av_* port csr_reset => mm_rst, - reset1_dsrt_qual => mm_core_pll_locked_reg, -- core pll_locked synchronised to clk = mm_clk domain + reset1_dsrt_qual => mm_core_pll_locked, -- core pll_locked synchronised to clk = mm_clk domain reset2_dsrt_qual => '1', -- Tied to '1' in example design. Tx xcvr is not used. reset5_dsrt_qual => mm_rx_xcvr_ready_in_arr(i), reset_in0 => mm_rst, @@ -360,7 +390,9 @@ begin out_rst => rxframe_rst_arr(i) ); - rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0'; + rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or + xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0'; + -- synchronize rx_xcvr_ready_in_arr to mm_clk u_common_async_rx_xcvr_ready : entity common_lib.common_async generic map ( @@ -373,7 +405,7 @@ begin dout => mm_rx_xcvr_ready_in_arr(i) ); - -- Invert thr active-low resets + -- Invert the active-low resets rx_avs_rst_n_arr(i) <= not rx_avs_rst_arr(i); rxlink_rst_n_arr(i) <= not rxlink_rst_arr(i); rxframe_rst_n_arr(i) <= not rxframe_rst_arr(i); @@ -385,24 +417,34 @@ begin begin if rising_edge(rxframe_clk) then if rxframe_rst_n_arr(i) = '0' then - rx_src_out_arr(i).data(c_jesd204b_rx_framer_data_w - 1 downto 0) <= (others => '0'); - rx_src_out_arr(i).channel(c_jesd204b_rx_framer_somf_w - 1 downto 0) <= (others => '0'); - f2_div1_cnt_arr(i) <= '0'; - rx_src_out_arr(i).valid <= '0'; + i_rx_src_out_arr(i).data <= (others => '0'); + i_rx_src_out_arr(i).channel <= (others => '0'); + i_rx_src_out_arr(i).valid <= '0'; + rxframe_toggle_arr(i) <= '0'; else - rx_src_out_arr(i).valid <= jesd204b_rx_link_valid_arr(i); if jesd204b_rx_link_valid_arr(i) = '0' then - rx_src_out_arr(i).data(c_jesd204b_rx_framer_data_w - 1 downto 0) <= (others => '0'); - rx_src_out_arr(i).channel(c_jesd204b_rx_framer_somf_w - 1 downto 0) <= (others => '0'); + i_rx_src_out_arr(i).data <= (others => '0'); + i_rx_src_out_arr(i).channel <= (others => '0'); + i_rx_src_out_arr(i).valid <= '0'; + rxframe_toggle_arr(i) <= '0'; else - if f2_div1_cnt_arr(i) = '1' then - rx_src_out_arr(i).data(c_jesd204b_rx_framer_data_w - 1 downto 0) <= jesd204b_rx_link_data_arr(c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto c_jesd204b_rx_data_w * i); - rx_src_out_arr(i).channel(c_jesd204b_rx_framer_somf_w - 1 downto 0) <= jesd204b_rx_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_framer_somf_w - 1 downto c_jesd204b_rx_somf_w * i); + if rxframe_toggle_arr(i) = '1' then + i_rx_src_out_arr(i).data <= RESIZE_DP_SDATA(jesd204b_rx_link_data_arr( + c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto + c_jesd204b_rx_data_w * i)); + i_rx_src_out_arr(i).channel <= RESIZE_DP_CHANNEL(jesd204b_rx_link_somf_arr( + c_jesd204b_rx_somf_w * i + c_jesd204b_rx_framer_somf_w - 1 downto + c_jesd204b_rx_somf_w * i)); else - rx_src_out_arr(i).data(c_jesd204b_rx_framer_data_w - 1 downto 0) <= jesd204b_rx_link_data_arr(c_jesd204b_rx_data_w * i + c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w); - rx_src_out_arr(i).channel(c_jesd204b_rx_framer_somf_w - 1 downto 0) <= jesd204b_rx_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 downto c_jesd204b_rx_somf_w * i + c_jesd204b_rx_framer_somf_w); + i_rx_src_out_arr(i).data <= RESIZE_DP_SDATA(jesd204b_rx_link_data_arr( + c_jesd204b_rx_data_w * i + c_jesd204b_rx_data_w - 1 downto + c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w)); + i_rx_src_out_arr(i).channel <= RESIZE_DP_CHANNEL(jesd204b_rx_link_somf_arr( + c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 downto + c_jesd204b_rx_somf_w * i + c_jesd204b_rx_framer_somf_w)); end if; - f2_div1_cnt_arr(i) <= not f2_div1_cnt_arr(i); + i_rx_src_out_arr(i).valid <= '1'; + rxframe_toggle_arr(i) <= not rxframe_toggle_arr(i); end if; end if; end if; @@ -414,39 +456,35 @@ begin -- See: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_jesd204b.pdf -- Figure 25, page 151 ----------------------------------------------------------------------------- - p_reclocksysref : process (rxlink_clk, core_pll_locked) + p_reclocksysref : process (core_pll_locked, rxlink_clk) begin if core_pll_locked = '0' then - jesd204b_sysref_1 <= '0'; - jesd204b_sysref_2 <= '0'; + rxlink_sysref_1 <= '0'; + rxlink_sysref_2 <= '0'; jesd204b_sync_n_arr <= (others => '0'); - else - if rising_edge(rxlink_clk) then - jesd204b_sysref_1 <= jesd204b_sysref; - jesd204b_sysref_2 <= jesd204b_sysref_1; - jesd204b_sync_n_arr <= jesd204b_sync_n_combined_arr; - end if; + elsif rising_edge(rxlink_clk) then + rxlink_sysref_1 <= jesd204b_sysref; + rxlink_sysref_2 <= rxlink_sysref_1; + jesd204b_sync_n_arr <= jesd204b_sync_n_combined_arr; end if; end process; ----------------------------------------------------------------------------- -- Move sysref from rxlink_clk to rxframe_clk ----------------------------------------------------------------------------- - p_rx_sysref : process (rxframe_clk, core_pll_locked) + p_rx_sysref : process (core_pll_locked, rxframe_clk) begin if core_pll_locked = '0' then - jesd204b_sysref_frameclk_1 <= '0'; - jesd204b_sysref_frameclk_2 <= '0'; + rxframe_sysref_1 <= '0'; + rxframe_sysref_2 <= '0'; rx_sysref <= '0'; - else - if rising_edge(rxframe_clk) then - jesd204b_sysref_frameclk_1 <= jesd204b_sysref_2; -- sysref from rxlink_clk domain - jesd204b_sysref_frameclk_2 <= jesd204b_sysref_frameclk_1; - if jesd204b_sysref_frameclk_1 = '1' and jesd204b_sysref_frameclk_2 = '0' then - rx_sysref <= '1'; - else - rx_sysref <= '0'; - end if; + elsif rising_edge(rxframe_clk) then + rxframe_sysref_1 <= rxlink_sysref_2; -- sysref from rxlink_clk domain + rxframe_sysref_2 <= rxframe_sysref_1; + if rxframe_sysref_1 = '1' and rxframe_sysref_2 = '0' then + rx_sysref <= '1'; + else + rx_sysref <= '0'; end if; end if; end process; @@ -471,7 +509,7 @@ begin port map ( in_rst => core_pll_locked, clk => mm_clk, - out_rst => mm_core_pll_locked_reg + out_rst => mm_core_pll_locked ); -- Transceiver reset controller. Use g_nof_streams out of 12 channels. Receive only @@ -480,20 +518,26 @@ begin u_ip_arria10_e1sg_jesd204b_rx_xcvr_reset_control : ip_arria10_e1sg_jesd204b_rx_xcvr_reset_control_12 port map ( clock => rxlink_clk, - reset => xcvr_rst_arr(0), -- From Reset Sequencer output1 as per example design, the reset input is synchronised internally. - rx_analogreset => rx_analogreset_arr, -- output to reset RX PMA. Release before deasserting link and avs resets (Intel JESD204B-UG p70) + reset => xcvr_rst_arr(0), -- From Reset Sequencer output1 as per example design, + -- the reset input is synchronised internally. + rx_analogreset => rx_analogreset_arr, -- output to reset RX PMA. Release before deasserting + -- link and avs resets (Intel JESD204B-UG p70) rx_cal_busy => rx_cal_busy_arr, -- input from PHY - rx_digitalreset => rx_digitalreset_arr, -- output to reset RX PCS. Release before deasserting link and avs resets (Intel JESD204B-UG p70) + rx_digitalreset => rx_digitalreset_arr, -- output to reset RX PCS. Release before deasserting + -- link and avs resets (Intel JESD204B-UG p70) rx_is_lockedtodata => rx_islockedtodata_arr, -- input from PHY - rx_ready => xcvr_rst_ctrl_rx_ready_arr -- From example design: gate with rx_csr_lane_powerdown to reset transceiver + rx_ready => xcvr_rst_ctrl_rx_ready_arr -- From example design: gate with + -- rx_csr_lane_powerdown to reset transceiver ); end generate; -- gen_jesd204b_rx : IF g_direction = "RX_ONLY" GENERATE gen_enable_sync_n : for i in 0 to g_nof_streams - 1 generate - -- The sync_n_enabled output is active '0'. For disabled signal inputs the sync_n_enabled output is forced to '1', so that for the disabled (= inactive = not used) + -- The sync_n_enabled output is active '0'. For disabled signal inputs the sync_n_enabled output + -- is forced to '1', so that for the disabled (= inactive = not used) -- signal inputs the sync_n_internal from the JESD IP will not pull sync_n_enabled low. - -- The purpose of being able to disable inactive signal inputs is that this avoids that one inactive signal input will cause all signal inputs in a group that share - -- the sync_n_combined to become unavailable (see gen_group_sync_n). + -- The purpose of being able to disable inactive signal inputs is that this avoids that one + -- inactive signal input will cause all signal inputs in a group that share the sync_n_combined + -- to become unavailable (see gen_group_sync_n). -- For disabled channels (in jesd204b_disable_arr), the SYNC_N output will not be used jesd204b_sync_n_enabled_arr(i) <= jesd204b_sync_n_internal_arr(i) or jesd204b_disable_arr(i); @@ -503,7 +547,9 @@ begin -- Group the SYNC_N outputs ----------------------------------------------------------------------------- gen_group_sync_n : for i in 0 to g_nof_sync_n - 1 generate - jesd204b_sync_n_combined_arr(i) <= vector_and(jesd204b_sync_n_enabled_arr(c_nof_sync_n_per_group * i + c_nof_sync_n_per_group - 1 downto c_nof_sync_n_per_group * i)); + jesd204b_sync_n_combined_arr(i) <= vector_and(jesd204b_sync_n_enabled_arr( + c_nof_sync_n_per_group * i + c_nof_sync_n_per_group - 1 downto + c_nof_sync_n_per_group * i)); end generate; ----------------------------------------------------------------------------- diff --git a/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b_v2.vhd b/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b_v2.vhd new file mode 100644 index 0000000000000000000000000000000000000000..1c0d8ec310a410658266cf2f48a8c9ab18e41c86 --- /dev/null +++ b/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b_v2.vhd @@ -0,0 +1,681 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. +-- +-------------------------------------------------------------------------------- + +-- Authors : J Hargreaves, L Hiemstra, E. Kooistra +-- Purpose: Combine IP components needed to create a JESD204B interface +-- Initially supports RX_ONLY for receiving data from an ADC +-- Description +-- Currently only 12 streams because of the 12 channel reset block +-- The sync_n signals are gated together to form g_nof_sync_n outputs +-- . v2 uses FIFO in IP to get from rxlink_clk at 100 MHz to dp_clk at 200 MHz + +library IEEE, common_lib, dp_lib, technology_lib, ip_arria10_e1sg_jesd204b_lib; +use IEEE.std_logic_1164.all; +use technology_lib.technology_pkg.all; +use common_lib.common_pkg.all; +use common_lib.common_mem_pkg.all; +use dp_lib.dp_stream_pkg.all; +use ip_arria10_e1sg_jesd204b_lib.ip_arria10_e1sg_jesd204b_component_pkg.all; + +entity ip_arria10_e1sg_jesd204b_v2 is + generic ( + g_sim : boolean := false; + g_nof_streams : natural := 1; + g_nof_sync_n : natural := 1; + g_direction : string := "RX_ONLY"; -- "TX_RX", "TX_ONLY", "RX_ONLY" + g_jesd_freq : string := "200MHz" + ); + port ( + -- JESD204B external signals + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock + -- reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with + -- respect to jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization / + -- syncronization phase + + -- Data to fabric + dp_clk : in std_logic; + dp_rst : in std_logic; + dp_sysref : out std_logic; -- = dp_sosi_arr(0).sync, all dp_sosi_arr().sync carry the dp_sysref + dp_sosi_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data and sync to fabric + + -- MM Control + mm_clk : in std_logic; + mm_rst : in std_logic; + jesd204b_disable_arr : in std_logic_vector(g_nof_streams - 1 downto 0); + + jesd204b_mosi : in t_mem_mosi; -- mm control + jesd204b_miso : out t_mem_miso; + + -- Serial connections to transceiver pins + serial_tx_arr : out std_logic_vector(g_nof_streams - 1 downto 0); -- Not used for ADC + serial_rx_arr : in std_logic_vector(g_nof_streams - 1 downto 0) + ); +end ip_arria10_e1sg_jesd204b_v2; + +architecture str of ip_arria10_e1sg_jesd204b_v2 is + -- JESD IP constants + -- . JESD204B MM has 256 bytes = 64 words, so mm_addr_w = 6 would be enough, + -- but using mm_addr_w = 8 and span = 256 words is fine too. + constant c_jesd204b_mm_addr_w : natural := 8; + constant c_jesd204b_rx_data_w : natural := 32; + constant c_jesd204b_rx_framer_data_w : natural := c_jesd204b_rx_data_w / 2; -- = 16, two samples in parallel + constant c_jesd204b_rx_somf_w : natural := c_jesd204b_rx_data_w / 8; -- = 4, one somf bit per octet + constant c_jesd204b_rx_framer_somf_w : natural := c_jesd204b_rx_somf_w / 2; -- = 2, two samples in parallel + constant c_nof_sync_n_per_group : natural := sel_a_b(g_nof_streams / g_nof_sync_n = 0, + 1, g_nof_streams / g_nof_sync_n); + constant c_fifo_size : natural := 64; + constant c_fifo_fill_level : natural := 10; + constant c_fifo_fill_margin : natural := 4; + + -- FSM for rxlink_clk to dp_clk FIFO read access + type t_fifo_state_enum is (s_fifo_low, s_fifo_filled); + + -- JESD204 control status registers + signal jesd204b_mosi_arr : t_mem_mosi_arr(g_nof_streams - 1 downto 0); + signal jesd204b_miso_arr : t_mem_miso_arr(g_nof_streams - 1 downto 0) := (others => c_mem_miso_rst); + signal reset_seq_mosi_arr : t_mem_mosi_arr(g_nof_streams - 1 downto 0) := (others => c_mem_mosi_rst); + signal reset_seq_miso_arr : t_mem_miso_arr(g_nof_streams - 1 downto 0) := (others => c_mem_miso_rst); + + -- Clocks + -- . The 200MHz rxframe_clk is not used in v2, the constraints on the PLL output frame_clk in + -- lofar2_unb2c_sdp_station.sdc will be ingored by Quartus. + signal rxframe_clk : std_logic; + signal rxlink_clk : std_logic; + signal jesd204b_avs_clk : std_logic; + + -- Reset and control signals, 1 bit per lane + signal dev_lane_aligned : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_analogreset_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_cal_busy_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_digitalreset_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_islockedtodata_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal dev_lane_aligned_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_csr_lane_powerdown_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal xcvr_rst_ctrl_rx_ready_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_xcvr_ready_in_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal mm_rx_xcvr_ready_in_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal pll_reset_async_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal pll_reset_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal xcvr_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0) := (others => '1'); + signal rx_avs_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_avs_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rxlink_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rxlink_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal core_pll_locked : std_logic; + signal mm_core_pll_locked : std_logic; + signal wr_core_pll_locked : std_logic; + signal wr_rst : std_logic := '1'; + signal rxlink_sysref_1 : std_logic; + signal rxlink_sysref_2 : std_logic; + signal rxlink_sysref_3 : std_logic; + signal rxlink_sysref : std_logic; -- single rxlink_clk cycle pulse + + -- Data path + signal jesd204b_rx_link_data_arr : std_logic_vector(c_jesd204b_rx_data_w * g_nof_streams - 1 downto 0); + signal jesd204b_rx_link_valid_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_rx_link_somf_arr : std_logic_vector(c_jesd204b_rx_somf_w * g_nof_streams - 1 downto 0); + + -- debug signal to view input 0 in Wave Window + signal jesd204b_rx_link_data : std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); + signal jesd204b_rx_link_data_hi : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal jesd204b_rx_link_data_lo : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal jesd204b_rx_link_valid : std_logic; + signal jesd204b_rx_link_somf : std_logic_vector(c_jesd204b_rx_somf_w - 1 downto 0); + signal jesd204b_rx_link_somf_hi : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); + signal jesd204b_rx_link_somf_lo : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); + + signal rxlink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0) := (others => c_dp_sosi_rst); + signal dplink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); + signal dplink_siso_arr : t_dp_siso_arr(g_nof_streams - 1 downto 0) := (others => c_dp_siso_rdy); + signal fifo_state : t_fifo_state_enum; + signal fifo_rd_usedw : std_logic_vector(ceil_log2(c_fifo_size) - 1 downto 0); + signal fifo_filled : std_logic := '0'; + signal dp_index : std_logic := '0'; + signal dp_ready : std_logic := '0'; + + -- debug signal to view input 0 in Wave Window + signal rxlink_sosi : t_dp_sosi; + signal rxlink_data : std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); + signal rxlink_data_hi : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal rxlink_data_lo : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal dplink_sosi : t_dp_sosi; + signal dplink_data : std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); + signal dplink_data_hi : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal dplink_data_lo : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + + signal i_dp_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); + signal dp_sosi : t_dp_sosi; -- input 0 + + -- outputs to control ADC initialization/syncronization phase + signal jesd204b_sync_n_internal_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_sync_n_enabled_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_sync_n_combined_arr : std_logic_vector(g_nof_sync_n - 1 downto 0); + + -- Component declarations for the IP blocks + + component ip_arria10_e1sg_jesd204b_rx_200MHz is + port ( + alldev_lane_aligned : in std_logic := 'X'; -- export + csr_cf : out std_logic_vector(4 downto 0); -- export + csr_cs : out std_logic_vector(1 downto 0); -- export + csr_f : out std_logic_vector(7 downto 0); -- export + csr_hd : out std_logic; -- export + csr_k : out std_logic_vector(4 downto 0); -- export + csr_l : out std_logic_vector(4 downto 0); -- export + csr_lane_powerdown : out std_logic_vector(0 downto 0); -- export + csr_m : out std_logic_vector(7 downto 0); -- export + csr_n : out std_logic_vector(4 downto 0); -- export + csr_np : out std_logic_vector(4 downto 0); -- export + csr_rx_testmode : out std_logic_vector(3 downto 0); -- export + csr_s : out std_logic_vector(4 downto 0); -- export + dev_lane_aligned : out std_logic; -- export + dev_sync_n : out std_logic; -- export + jesd204_rx_avs_chipselect : in std_logic := 'X'; + jesd204_rx_avs_address : in std_logic_vector(c_jesd204b_mm_addr_w - 1 downto 0) := (others => 'X'); + jesd204_rx_avs_read : in std_logic := 'X'; + jesd204_rx_avs_readdata : out std_logic_vector(31 downto 0); + jesd204_rx_avs_waitrequest : out std_logic; + jesd204_rx_avs_write : in std_logic := 'X'; + jesd204_rx_avs_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); + jesd204_rx_avs_clk : in std_logic := 'X'; + jesd204_rx_avs_rst_n : in std_logic := 'X'; + jesd204_rx_dlb_data : in std_logic_vector(31 downto 0) := (others => 'X'); -- export + jesd204_rx_dlb_data_valid : in std_logic_vector(0 downto 0) := (others => 'X'); -- export + jesd204_rx_dlb_disperr : in std_logic_vector(3 downto 0) := (others => 'X'); -- export + jesd204_rx_dlb_errdetect : in std_logic_vector(3 downto 0) := (others => 'X'); -- export + jesd204_rx_dlb_kchar_data : in std_logic_vector(3 downto 0) := (others => 'X'); -- export + jesd204_rx_frame_error : in std_logic := 'X'; -- export + jesd204_rx_int : out std_logic; -- irq + jesd204_rx_link_data : out std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); -- data + jesd204_rx_link_valid : out std_logic; -- valid + jesd204_rx_link_ready : in std_logic := 'X'; -- ready + pll_ref_clk : in std_logic := 'X'; -- clk + rx_analogreset : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_analogreset + rx_cal_busy : out std_logic_vector(0 downto 0); -- rx_cal_busy + rx_digitalreset : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_digitalreset + rx_islockedtodata : out std_logic_vector(0 downto 0); -- rx_is_lockedtodata + rx_serial_data : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_serial_data + rxlink_clk : in std_logic := 'X'; -- clk + rxlink_rst_n_reset_n : in std_logic := 'X'; -- reset_n + rxphy_clk : out std_logic_vector(0 downto 0); -- export + sof : out std_logic_vector(3 downto 0); -- export + somf : out std_logic_vector(c_jesd204b_rx_somf_w - 1 downto 0); -- export + sysref : in std_logic := 'X' -- export + ); + end component ip_arria10_e1sg_jesd204b_rx_200MHz; + + component ip_arria10_e1sg_jesd204b_rx_core_pll_200MHz is + port ( + locked : out std_logic; -- export + outclk_0 : out std_logic; -- clk + outclk_1 : out std_logic; -- clk + refclk : in std_logic := 'X'; -- clk + rst : in std_logic := 'X' -- reset + ); + end component ip_arria10_e1sg_jesd204b_rx_core_pll_200MHz; + + component ip_arria10_e1sg_jesd204b_rx_reset_seq is + port ( + av_address : in std_logic_vector(7 downto 0) := (others => 'X'); -- address + av_readdata : out std_logic_vector(31 downto 0); -- readdata + av_read : in std_logic := 'X'; -- read + av_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); -- writedata + av_write : in std_logic := 'X'; -- write + irq : out std_logic; -- irq + clk : in std_logic := 'X'; -- clk + csr_reset : in std_logic := 'X'; -- reset + reset1_dsrt_qual : in std_logic := 'X'; -- reset1_dsrt_qual + reset2_dsrt_qual : in std_logic := 'X'; -- reset2_dsrt_qual + reset5_dsrt_qual : in std_logic := 'X'; -- reset5_dsrt_qual + reset_in0 : in std_logic := 'X'; -- reset + reset_out0 : out std_logic; -- reset + reset_out1 : out std_logic; -- reset + reset_out2 : out std_logic; -- reset + reset_out3 : out std_logic; -- reset + reset_out4 : out std_logic; -- reset + reset_out5 : out std_logic; -- reset + reset_out6 : out std_logic; -- reset + reset_out7 : out std_logic -- reset + ); + end component ip_arria10_e1sg_jesd204b_rx_reset_seq; + + component ip_arria10_e1sg_jesd204b_rx_xcvr_reset_control_12 is + port ( + clock : in std_logic := 'X'; -- clk + reset : in std_logic := 'X'; -- reset + rx_analogreset : out std_logic_vector(11 downto 0); -- rx_analogreset + rx_cal_busy : in std_logic_vector(11 downto 0) := (others => 'X'); -- rx_cal_busy + rx_digitalreset : out std_logic_vector(11 downto 0); -- rx_digitalreset + rx_is_lockedtodata : in std_logic_vector(11 downto 0) := (others => 'X'); -- rx_is_lockedtodata + rx_ready : out std_logic_vector(11 downto 0) -- rx_ready + ); + end component ip_arria10_e1sg_jesd204b_rx_xcvr_reset_control_12; +begin + dp_sosi_arr <= i_dp_sosi_arr; + dp_sosi <= i_dp_sosi_arr(0); + + -- wire dp_sysref from dp_sosi_arr().sync, all sync carry the dp_sysref + dp_sysref <= dp_sosi.sync; + + -- Debug signals to view input 0 in Wave Window + jesd204b_rx_link_data <= jesd204b_rx_link_data_arr(c_jesd204b_rx_data_w - 1 downto 0); + jesd204b_rx_link_data_hi <= jesd204b_rx_link_data(c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w); + jesd204b_rx_link_data_lo <= jesd204b_rx_link_data(c_jesd204b_rx_framer_data_w - 1 downto 0); + jesd204b_rx_link_valid <= jesd204b_rx_link_valid_arr(0); + jesd204b_rx_link_somf <= jesd204b_rx_link_somf_arr(c_jesd204b_rx_somf_w - 1 downto 0); + jesd204b_rx_link_somf_hi <= jesd204b_rx_link_somf(c_jesd204b_rx_somf_w - 1 downto c_jesd204b_rx_framer_somf_w); + jesd204b_rx_link_somf_lo <= jesd204b_rx_link_somf(c_jesd204b_rx_framer_somf_w - 1 downto 0); + + rxlink_sosi <= rxlink_sosi_arr(0); + rxlink_data <= rxlink_sosi.data(c_jesd204b_rx_data_w - 1 downto 0); + rxlink_data_hi <= rxlink_data(c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w); + rxlink_data_lo <= rxlink_data(c_jesd204b_rx_framer_data_w - 1 downto 0); + + dplink_sosi <= dplink_sosi_arr(0); + dplink_data <= dplink_sosi.data(c_jesd204b_rx_data_w - 1 downto 0); + dplink_data_hi <= dplink_data(c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w); + dplink_data_lo <= dplink_data(c_jesd204b_rx_framer_data_w - 1 downto 0); + + -- The mm_rst resets the MM interface, but is also used to reset the JESD IP reset sequencer. + -- Therefore a reset of mm_rst effectively resets the entire JESD IP. + + -- The avs clock is driven by the rxlink_clk for simulation. This is a workaround for a bug + -- in the Q18.0 IP where the jesd receiver fails to recognize the SYSREF pulse + gen_simclock : if g_sim = true generate + jesd204b_avs_clk <= rxlink_clk; + end generate; + + -- For synthesis the avs clock is driven by the mm_clk as usual + gen_synthclock : if g_sim = false generate + jesd204b_avs_clk <= mm_clk; + end generate; + + gen_jesd204b_rx : if g_direction = "RX_ONLY" generate + gen_jesd204b_rx_channels : for I in 0 to g_nof_streams - 1 generate + ----------------------------------------------------------------------------- + -- The JESD204 IP (rx only) + ----------------------------------------------------------------------------- + gen_jesd204b_rx_freqsel : if g_jesd_freq = "200MHz" generate + u_ip_arria10_e1sg_jesd204b_rx_200MHz : ip_arria10_e1sg_jesd204b_rx_200MHz + port map ( + alldev_lane_aligned => dev_lane_aligned_arr(i), + csr_cf => OPEN, + csr_cs => OPEN, + csr_f => OPEN, + csr_hd => OPEN, + csr_k => OPEN, + csr_l => OPEN, + csr_lane_powerdown => rx_csr_lane_powerdown_arr(i downto i), + csr_m => OPEN, + csr_n => OPEN, + csr_np => OPEN, + csr_rx_testmode => OPEN, + csr_s => OPEN, + dev_lane_aligned => dev_lane_aligned_arr(i), + dev_sync_n => jesd204b_sync_n_internal_arr(i), + jesd204_rx_avs_chipselect => '1', + jesd204_rx_avs_address => jesd204b_mosi_arr(i).address(c_jesd204b_mm_addr_w - 1 downto 0), + jesd204_rx_avs_read => jesd204b_mosi_arr(i).rd, + jesd204_rx_avs_readdata => jesd204b_miso_arr(i).rddata(31 downto 0), + jesd204_rx_avs_waitrequest => jesd204b_miso_arr(i).waitrequest, + jesd204_rx_avs_write => jesd204b_mosi_arr(i).wr, + jesd204_rx_avs_writedata => jesd204b_mosi_arr(i).wrdata(31 downto 0), + jesd204_rx_avs_clk => jesd204b_avs_clk, + jesd204_rx_avs_rst_n => rx_avs_rst_n_arr(i), + jesd204_rx_dlb_data => (others => '0'), -- debug/loopback testing + jesd204_rx_dlb_data_valid => (others => '0'), -- debug/loopback testing + jesd204_rx_dlb_disperr => (others => '0'), -- debug/loopback testing + jesd204_rx_dlb_errdetect => (others => '0'), -- debug/loopback testing + jesd204_rx_dlb_kchar_data => (others => '0'), -- debug/loopback testing + jesd204_rx_frame_error => '0', -- jesd204_rx_frame_error.export + jesd204_rx_int => OPEN, -- Connected to status IO in example design + jesd204_rx_link_data => jesd204b_rx_link_data_arr(i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 + downto i * c_jesd204b_rx_data_w), + jesd204_rx_link_valid => jesd204b_rx_link_valid_arr(i), + jesd204_rx_link_ready => '1', + pll_ref_clk => jesd204b_refclk, -- Aka device_clock, same as reference for the link/frame + -- clock IOPLL (Intel JESD204B-UG p63) + rx_analogreset => rx_analogreset_arr(I downto I), + rx_cal_busy => rx_cal_busy_arr(I downto I), + rx_digitalreset => rx_digitalreset_arr(I downto I), + rx_islockedtodata => rx_islockedtodata_arr(I downto I), + rx_serial_data => serial_rx_arr(i downto i), + rxlink_clk => rxlink_clk, + rxlink_rst_n_reset_n => rxlink_rst_n_arr(i), -- Assoc with rxlink_clk (Intel JESD204B-UG p69) + rxphy_clk => OPEN, -- Not used in Subclass 0 (Intel JESD204B-UG p63) + sof => OPEN, + somf => jesd204b_rx_link_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 + downto c_jesd204b_rx_somf_w * i), + sysref => rxlink_sysref + ); + + -- Group jesd204b_rx_link data and sync (= sysref) into rxlink_sosi_arr. When an JESD204B interface + -- input is in lock, then its jesd204b_rx_link data and sync are synchronous, and the MSpart of the + -- data then contains the even (0) sample and the LSpart contains the odd (1) sample (= big endian). + -- In the rxframe_clk domain the sync is active in the even (0) sample, so in the dp_clk domain the + -- sync is passed on when the data MSpart is read and forced to '0' for the data LSpart, + -- All synchronization info is contained in the alignment of rxlink_clk, data and sync, the valid + -- does not provide additional synchronization info. The valid does indicate whether the link is in + -- lock or not, but for the subsequent data processing the sync is sufficient to start. The valid + -- could be used as monitor point, but it is sufficient to use the JESD204B IP monitor points. For + -- same reason it is also not necessary to pass on the jesd204b_rx_link_somf_arr status. + -- Therefore always write the FIFO when rxlink_clk is active and rxlink_rst is released, independent + -- of whether the input is in lock or not. + rxlink_sosi_arr(i).data <= RESIZE_DP_DATA(jesd204b_rx_link_data_arr + (i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 downto + i * c_jesd204b_rx_data_w)); + rxlink_sosi_arr(i).sync <= rxlink_sysref; + rxlink_sosi_arr(i).valid <= '1'; + + -- One cycle rd-rdval latency, waitrequest = '0' fixed + jesd204b_miso_arr(i).rdval <= jesd204b_mosi_arr(i).rd when rising_edge(jesd204b_avs_clk); + end generate; + + ----------------------------------------------------------------------------- + -- Reset sequencer for each channel + ----------------------------------------------------------------------------- + u_ip_arria10_e1sg_jesd204b_rx_reset_seq : ip_arria10_e1sg_jesd204b_rx_reset_seq + port map ( + av_address => reset_seq_mosi_arr(i).address(7 downto 0), + av_readdata => reset_seq_miso_arr(i).rddata(31 downto 0), + av_read => reset_seq_mosi_arr(i).rd, + av_writedata => reset_seq_mosi_arr(i).wrdata(31 downto 0), + av_write => reset_seq_mosi_arr(i).wr, + irq => open, + clk => mm_clk, -- use clk = mm_clk for av_* port + csr_reset => mm_rst, + reset1_dsrt_qual => mm_core_pll_locked, -- core pll_locked synchronised to clk = mm_clk domain + reset2_dsrt_qual => '1', -- Tied to '1' in example design. Tx xcvr is not used. + reset5_dsrt_qual => mm_rx_xcvr_ready_in_arr(i), + reset_in0 => mm_rst, + -- reset_out* signals are in mm_clk domain + reset_out0 => pll_reset_async_arr(i), -- Use channel 0 to reset the core pll + reset_out1 => xcvr_rst_arr(i), -- Use channel 1 to reset the transceiver reset controller + reset_out2 => open, + reset_out3 => open, + reset_out4 => open, + reset_out5 => rx_avs_rst_arr(i), + reset_out6 => rxlink_rst_async_arr(i), + reset_out7 => open + ); + + -- synchronize pll_reset + u_common_areset_pll : entity common_lib.common_areset + port map ( + in_rst => pll_reset_async_arr(i), + clk => jesd204b_refclk, + out_rst => pll_reset_arr(i) + ); + + -- synchronize rxlink reset + u_common_areset_rxlink : entity common_lib.common_areset + port map ( + in_rst => rxlink_rst_async_arr(i), + clk => rxlink_clk, + out_rst => rxlink_rst_arr(i) + ); + + rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or + xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0'; + + -- synchronize rx_xcvr_ready_in_arr to mm_clk + u_common_async_rx_xcvr_ready : entity common_lib.common_async + generic map ( + g_rst_level => '0' -- When in_rst is asserted, dout = '0' + ) + port map ( + rst => mm_rst, + clk => mm_clk, + din => rx_xcvr_ready_in_arr(i), + dout => mm_rx_xcvr_ready_in_arr(i) + ); + + -- Invert the active-low resets + rx_avs_rst_n_arr(i) <= not rx_avs_rst_arr(i); + rxlink_rst_n_arr(i) <= not rxlink_rst_arr(i); + + ----------------------------------------------------------------------------- + -- Deframers in dp_clk domain + ----------------------------------------------------------------------------- + p_deframer : process (dp_clk) + begin + if rising_edge(dp_clk) then + if fifo_filled = '0' then + i_dp_sosi_arr(i) <= c_dp_sosi_rst; -- Force all to 0 when Rx JESD204B has stopped + else + i_dp_sosi_arr(i).valid <= '1'; + if dp_index = '0' then + -- MS data with sync at even dp_index = 0 + i_dp_sosi_arr(i).sync <= dplink_sosi_arr(i).sync; + i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( + c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w)); + else + -- LS data at odd dp_index = 1 + i_dp_sosi_arr(i).sync <= '0'; + i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( + c_jesd204b_rx_framer_data_w - 1 downto 0)); + end if; + end if; + end if; + end process; + + -- Apply toggling ready control for cross 100 MHz rxlink_clk domain to 200MHz dp_clk domain + -- u_dp_fifo_dc_arr FIFO. + dplink_siso_arr(i).xon <= '1'; + dplink_siso_arr(i).ready <= dp_ready; + end generate; -- gen_jesd204b_rx_channels : for I in 0 to g_nof_streams-1 generate + + ----------------------------------------------------------------------------- + -- Cross from 100 MHz rxlink_clk domain to 200MHz dp_clk domain using a FIFO + ----------------------------------------------------------------------------- + -- The dp_fifo_core_arr.vhd FIFO in dp_fifo_dc_arr.vhd.vhd passes on for ctrl and info + -- fields from snk_in_arr(0) and data fields from all snk_in_arr(). Similar for flow + -- control the FIFO uses src_in_arr(0).ready as read strobe. Using only input (0) is + -- possible, because all snk_in_arr() inputs will have same ctrl and info when Rx + -- JESD204B IP is synchronized. + wr_rst <= not wr_core_pll_locked; + + u_dp_fifo_dc_arr : entity dp_lib.dp_fifo_dc_arr + generic map ( + g_nof_streams => g_nof_streams, + g_data_w => c_jesd204b_rx_data_w, -- 32b + g_data_signed => false, + g_use_sync => true, + g_use_ctrl => false, + g_use_channel => false, -- no need to pass on jesd204b_rx_link_somf_arr + g_fifo_size => c_fifo_size + ) + port map ( + wr_rst => wr_rst, + wr_clk => rxlink_clk, + rd_rst => dp_rst, + rd_clk => dp_clk, + rd_usedw => fifo_rd_usedw, + snk_in_arr => rxlink_sosi_arr, + src_in_arr => dplink_siso_arr, + src_out_arr => dplink_sosi_arr + ); + + -- The dp_clk at 200 MHz and rxlink_clk at 100 MHz are locked to same reference. + -- Toggle dp_index every dp_clk cycle to have the same read rate in dp_clk domain, + -- as the write rate in rxlink_clk domain. + -- + -- Use a finite state machine (FSM) to fill the FIFO with fill margin above a + -- nominal FIFO fill level, so that the dp_index keeps on toggling once it has + -- started, as long as the FIFO remains filled. The fill margin avoids that + -- there can occur once a one dp_clk cycle disturbance in the toggling, in case + -- rxlink_clk and dp_clk almost coincide. + -- + -- Simulation with tb_tech_jesd204b_v2.vhd reveals that the double data word is + -- always read high part first and low part next, independent of the phase of + -- dp_index. This is because reading ab, cd, ef, ... is equivalent to reading + -- bc, de, fg, ... However the phase of dp_ready with respect to dp_index is + -- important for reading the sync, because if dp_ready has the wrong phase, + -- then the sync is missed at the FIFO output. + -- . If dp_index = '0' or '1' initialy, then in both cases use dp_ready <= not + -- dp_index, and then in both cases the latency dp_sosi.sync and data = 1000 is + -- then 340 ns + -- . Do not use dp_ready <= dp_index, because then the dp_sosi.sync gets missed. + -- Therefore choose to use dp_index = '0' initially, because then dp_ready = + -- dp_index always. + p_fsm_dp_index : process(dp_rst, dp_clk) + begin + if dp_rst = '1' then + dp_index <= '0'; + dp_ready <= '0'; + fifo_filled <= '0'; + fifo_state <= s_fifo_low; + elsif rising_edge(dp_clk) then + case fifo_state is + when s_fifo_low => + dp_index <= '0'; + dp_ready <= '0'; -- fill the FIFO, so no double data word request + fifo_filled <= '0'; + if to_uint(fifo_rd_usedw) >= c_fifo_fill_level + c_fifo_fill_margin then + fifo_state <= s_fifo_filled; + end if; + when others => -- = s_fifo_filled + dp_index <= not dp_index; + dp_ready <= not dp_index; -- alternately request next double data word + fifo_filled <= '1'; + if to_uint(fifo_rd_usedw) < c_fifo_fill_level then + fifo_state <= s_fifo_low; + end if; + end case; + end if; + end process; + + ----------------------------------------------------------------------------- + -- Reclock sysref and the sync_n output + -- See: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_jesd204b.pdf + -- Figure 25, page 151 + ----------------------------------------------------------------------------- + p_reclocksysref : process (core_pll_locked, rxlink_clk) + begin + if core_pll_locked = '0' then + rxlink_sysref_1 <= '0'; + rxlink_sysref_2 <= '0'; + rxlink_sysref_3 <= '0'; + jesd204b_sync_n_arr <= (others => '0'); + elsif rising_edge(rxlink_clk) then + rxlink_sysref_1 <= jesd204b_sysref; + rxlink_sysref_2 <= rxlink_sysref_1; + rxlink_sysref_3 <= rxlink_sysref_2; + jesd204b_sync_n_arr <= jesd204b_sync_n_combined_arr; + end if; + end process; + + -- Make single rxlink_clk cycle pulse of rxlink_sysref_2 + rxlink_sysref <= rxlink_sysref_2 and not rxlink_sysref_3; + + -- IOPLL in source synchronous or normal mode. (Intel JESD204B-UG p66) + gen_jesd204b_rx_corepll_freqsel : if g_jesd_freq = "200MHz" generate + u_ip_arria10_e1sg_jesd204b_rx_corepll_200MHz : ip_arria10_e1sg_jesd204b_rx_core_pll_200MHz + port map ( + locked => core_pll_locked, + outclk_0 => rxlink_clk, -- out 100 MHz + outclk_1 => rxframe_clk, -- out 200 MHz + refclk => jesd204b_refclk, -- in 200 MHz + rst => pll_reset_arr(0) + ); + end generate; + + u_common_areset_wr_core_pll_locked : entity common_lib.common_areset + generic map ( + g_in_rst_level => '0', -- synchronises the rising edge of input in_rst. + g_rst_level => '0' + ) + port map ( + in_rst => core_pll_locked, + clk => rxlink_clk, + out_rst => wr_core_pll_locked + ); + + u_common_areset_mm_core_pll_locked : entity common_lib.common_areset + generic map ( + g_in_rst_level => '0', -- synchronises the rising edge of input in_rst. + g_rst_level => '0' + ) + port map ( + in_rst => core_pll_locked, + clk => mm_clk, + out_rst => mm_core_pll_locked + ); + + -- Transceiver reset controller. Use g_nof_streams out of 12 channels. Receive only + -- Clock set to 100MHz (use rxlink_clk) + + u_ip_arria10_e1sg_jesd204b_rx_xcvr_reset_control : ip_arria10_e1sg_jesd204b_rx_xcvr_reset_control_12 + port map ( + clock => rxlink_clk, + reset => xcvr_rst_arr(0), -- From Reset Sequencer output1 as per example design, + -- the reset input is synchronised internally. + rx_analogreset => rx_analogreset_arr, -- output to reset RX PMA. Release before deasserting + -- link and avs resets (Intel JESD204B-UG p70) + rx_cal_busy => rx_cal_busy_arr, -- input from PHY + rx_digitalreset => rx_digitalreset_arr, -- output to reset RX PCS. Release before deasserting + -- link and avs resets (Intel JESD204B-UG p70) + rx_is_lockedtodata => rx_islockedtodata_arr, -- input from PHY + rx_ready => xcvr_rst_ctrl_rx_ready_arr -- From example design: gate with + -- rx_csr_lane_powerdown to reset transceiver + ); + end generate; -- gen_jesd204b_rx : IF g_direction = "RX_ONLY" GENERATE + + gen_enable_sync_n : for i in 0 to g_nof_streams - 1 generate + -- The sync_n_enabled output is active '0'. For disabled signal inputs the sync_n_enabled output + -- is forced to '1', so that for the disabled (= inactive = not used) + -- signal inputs the sync_n_internal from the JESD IP will not pull sync_n_enabled low. + -- The purpose of being able to disable inactive signal inputs is that this avoids that one + -- inactive signal input will cause all signal inputs in a group that share the sync_n_combined + -- to become unavailable (see gen_group_sync_n). + + -- For disabled channels (in jesd204b_disable_arr), the SYNC_N output will not be used + jesd204b_sync_n_enabled_arr(i) <= jesd204b_sync_n_internal_arr(i) or jesd204b_disable_arr(i); + end generate; + + ----------------------------------------------------------------------------- + -- Group the SYNC_N outputs + ----------------------------------------------------------------------------- + gen_group_sync_n : for i in 0 to g_nof_sync_n - 1 generate + jesd204b_sync_n_combined_arr(i) <= vector_and(jesd204b_sync_n_enabled_arr( + c_nof_sync_n_per_group * i + c_nof_sync_n_per_group - 1 downto + c_nof_sync_n_per_group * i)); + end generate; + + ----------------------------------------------------------------------------- + -- MM bus mux + ----------------------------------------------------------------------------- + u_common_mem_mux_mac : entity common_lib.common_mem_mux + generic map ( + g_nof_mosi => g_nof_streams, + g_mult_addr_w => c_jesd204b_mm_addr_w + ) + port map ( + mosi => jesd204b_mosi, + miso => jesd204b_miso, + mosi_arr => jesd204b_mosi_arr, + miso_arr => jesd204b_miso_arr + ); +end str; diff --git a/libraries/technology/ip_arria10_e2sg/jesd204b/hdllib.cfg b/libraries/technology/ip_arria10_e2sg/jesd204b/hdllib.cfg index 0872ac39324cc51a15a130e7018926655cc0124d..81cfbf3b394de9e2f519f6ce25df54e385b07f43 100644 --- a/libraries/technology/ip_arria10_e2sg/jesd204b/hdllib.cfg +++ b/libraries/technology/ip_arria10_e2sg/jesd204b/hdllib.cfg @@ -2,11 +2,12 @@ hdl_lib_name = ip_arria10_e2sg_jesd204b hdl_library_clause_name = ip_arria10_e2sg_jesd204b_lib hdl_lib_uses_synth = technology tech_pll common dp hdl_lib_uses_sim = ip_arria10_e2sg_altera_iopll_1930 ip_arria10_e2sg_altera_jesd204_1920 ip_arria10_e2sg_altera_reset_sequencer_191 ip_arria10_e2sg_altera_xcvr_reset_control_191 -hdl_lib_technology = ip_arria10_e2sg +hdl_lib_technology = ip_arria10_e2sg synth_files = ip_arria10_e2sg_jesd204b_component_pkg.vhd ip_arria10_e2sg_jesd204b.vhd + ip_arria10_e2sg_jesd204b_v2.vhd test_bench_files = @@ -24,7 +25,7 @@ quartus_qip_files = $HDL_BUILD_DIR/<buildset_name>/qsys-generate/ip_arria10_e2sg_jesd204b_tx/ip_arria10_e2sg_jesd204b_tx.qip [generate_ip_libs] -qsys-generate_ip_files = +qsys-generate_ip_files = ip_arria10_e2sg_jesd204b_rx_200MHz.ip ip_arria10_e2sg_jesd204b_rx_core_pll_200MHz.ip ip_arria10_e2sg_jesd204b_rx_reset_seq.ip diff --git a/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b.vhd b/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b.vhd index 87a34d3c9c97e45cb0e42637a452552975a2ac17..091ca476a5417596f2ed77ad63e31f2f19788306 100644 --- a/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b.vhd +++ b/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b.vhd @@ -46,9 +46,12 @@ entity ip_arria10_e2sg_jesd204b is ); port ( -- JESD204B external signals - jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock reference pin - jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase wrt jesd204b_device_clk - jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock + -- reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with + -- respect to jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization / + -- syncronization phase -- Data to fabric rx_src_out_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data out to fabric @@ -76,10 +79,11 @@ architecture str of ip_arria10_e2sg_jesd204b is -- but using mm_addr_w = 8 and span = 256 words is fine too. constant c_jesd204b_mm_addr_w : natural := 8; constant c_jesd204b_rx_data_w : natural := 32; - constant c_jesd204b_rx_framer_data_w : natural := c_jesd204b_rx_data_w / 2; -- IP outputs two samples in parallel - constant c_jesd204b_rx_somf_w : natural := c_jesd204b_rx_data_w / 8; -- One somf bit per octet - constant c_jesd204b_rx_framer_somf_w : natural := c_jesd204b_rx_somf_w / 2; -- IP outputs two samples in parallel - constant c_nof_sync_n_per_group : natural := sel_a_b(g_nof_streams / g_nof_sync_n = 0, 1, g_nof_streams / g_nof_sync_n); + constant c_jesd204b_rx_framer_data_w : natural := c_jesd204b_rx_data_w / 2; -- = 16, two samples in parallel + constant c_jesd204b_rx_somf_w : natural := c_jesd204b_rx_data_w / 8; -- = 4, one somf bit per octet + constant c_jesd204b_rx_framer_somf_w : natural := c_jesd204b_rx_somf_w / 2; -- = 2, two samples in parallel + constant c_nof_sync_n_per_group : natural := sel_a_b(g_nof_streams / g_nof_sync_n = 0, + 1, g_nof_streams / g_nof_sync_n); -- JESD204 control status registers signal jesd204b_mosi_arr : t_mem_mosi_arr(g_nof_streams - 1 downto 0); @@ -92,8 +96,8 @@ architecture str of ip_arria10_e2sg_jesd204b is signal rxlink_clk : std_logic; signal jesd204b_avs_clk : std_logic; - -- Reset and control signals - signal dev_lane_aligned : std_logic_vector(g_nof_streams - 1 downto 0); -- 1 bit, each interface channel has 1 lane + -- Reset and control signals, 1 bit per lane + signal dev_lane_aligned : std_logic_vector(g_nof_streams - 1 downto 0); signal rx_analogreset_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rx_cal_busy_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rx_digitalreset_arr : std_logic_vector(g_nof_streams - 1 downto 0); @@ -114,22 +118,34 @@ architecture str of ip_arria10_e2sg_jesd204b is signal rx_avs_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal rxframe_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); - signal f2_div1_cnt_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rxframe_toggle_arr : std_logic_vector(g_nof_streams - 1 downto 0); signal core_pll_locked : std_logic; - signal mm_core_pll_locked_reg : std_logic; - signal jesd204b_sysref_1 : std_logic; - signal jesd204b_sysref_2 : std_logic; - signal jesd204b_sysref_frameclk_1 : std_logic; - signal jesd204b_sysref_frameclk_2 : std_logic; + signal mm_core_pll_locked : std_logic; + signal rxlink_sysref_1 : std_logic; + signal rxlink_sysref_2 : std_logic; + signal rxframe_sysref_1 : std_logic; + signal rxframe_sysref_2 : std_logic; + signal i_rx_src_out_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); + -- debug signal used to view input 0 in Wave Window + signal rx_src_out : t_dp_sosi; -- Data path signal jesd204b_rx_link_data_arr : std_logic_vector(c_jesd204b_rx_data_w * g_nof_streams - 1 downto 0); signal jesd204b_rx_link_valid_arr : std_logic_vector(g_nof_streams - 1 downto 0); - signal jesd204b_rx_somf_arr : std_logic_vector(c_jesd204b_rx_somf_w * g_nof_streams - 1 downto 0); - - signal jesd204b_sync_n_internal_arr : std_logic_vector(g_nof_streams - 1 downto 0); -- output to control ADC initialization/syncronization phase - signal jesd204b_sync_n_enabled_arr : std_logic_vector(g_nof_streams - 1 downto 0); -- output to control ADC initialization/syncronization phase - signal jesd204b_sync_n_combined_arr : std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + signal jesd204b_rx_link_somf_arr : std_logic_vector(c_jesd204b_rx_somf_w * g_nof_streams - 1 downto 0); + -- debug signal to view input 0 in Wave Window + signal jesd204b_rx_link_data : std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); + signal jesd204b_rx_link_data_hi : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal jesd204b_rx_link_data_lo : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal jesd204b_rx_link_valid : std_logic; + signal jesd204b_rx_link_somf : std_logic_vector(c_jesd204b_rx_somf_w - 1 downto 0); + signal jesd204b_rx_link_somf_hi : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); + signal jesd204b_rx_link_somf_lo : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); + + -- outputs to control ADC initialization/syncronization phase + signal jesd204b_sync_n_internal_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_sync_n_enabled_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_sync_n_combined_arr : std_logic_vector(g_nof_sync_n - 1 downto 0); -- Component declarations for the IP blocks @@ -150,15 +166,15 @@ architecture str of ip_arria10_e2sg_jesd204b is csr_s : out std_logic_vector(4 downto 0); -- export dev_lane_aligned : out std_logic; -- export dev_sync_n : out std_logic; -- export - jesd204_rx_avs_chipselect : in std_logic := 'X'; -- chipselect - jesd204_rx_avs_address : in std_logic_vector(c_jesd204b_mm_addr_w - 1 downto 0) := (others => 'X'); -- address - jesd204_rx_avs_read : in std_logic := 'X'; -- read - jesd204_rx_avs_readdata : out std_logic_vector(31 downto 0); -- readdata - jesd204_rx_avs_waitrequest : out std_logic; -- waitrequest - jesd204_rx_avs_write : in std_logic := 'X'; -- write - jesd204_rx_avs_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); -- writedata - jesd204_rx_avs_clk : in std_logic := 'X'; -- clk - jesd204_rx_avs_rst_n : in std_logic := 'X'; -- reset_n + jesd204_rx_avs_chipselect : in std_logic := 'X'; + jesd204_rx_avs_address : in std_logic_vector(c_jesd204b_mm_addr_w - 1 downto 0) := (others => 'X'); + jesd204_rx_avs_read : in std_logic := 'X'; + jesd204_rx_avs_readdata : out std_logic_vector(31 downto 0); + jesd204_rx_avs_waitrequest : out std_logic; + jesd204_rx_avs_write : in std_logic := 'X'; + jesd204_rx_avs_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); + jesd204_rx_avs_clk : in std_logic := 'X'; + jesd204_rx_avs_rst_n : in std_logic := 'X'; jesd204_rx_dlb_data : in std_logic_vector(31 downto 0) := (others => 'X'); -- export jesd204_rx_dlb_data_valid : in std_logic_vector(0 downto 0) := (others => 'X'); -- export jesd204_rx_dlb_disperr : in std_logic_vector(3 downto 0) := (others => 'X'); -- export @@ -231,8 +247,20 @@ architecture str of ip_arria10_e2sg_jesd204b is ); end component ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control_12; begin + -- Debug signals to view input 0 in Wave Window + jesd204b_rx_link_data <= jesd204b_rx_link_data_arr(c_jesd204b_rx_data_w - 1 downto 0); + jesd204b_rx_link_data_hi <= jesd204b_rx_link_data(c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w); + jesd204b_rx_link_data_lo <= jesd204b_rx_link_data(c_jesd204b_rx_framer_data_w - 1 downto 0); + jesd204b_rx_link_valid <= jesd204b_rx_link_valid_arr(0); + jesd204b_rx_link_somf <= jesd204b_rx_link_somf_arr(c_jesd204b_rx_somf_w - 1 downto 0); + jesd204b_rx_link_somf_hi <= jesd204b_rx_link_somf(c_jesd204b_rx_somf_w - 1 downto c_jesd204b_rx_framer_somf_w); + jesd204b_rx_link_somf_lo <= jesd204b_rx_link_somf(c_jesd204b_rx_framer_somf_w - 1 downto 0); + rx_src_out_arr <= i_rx_src_out_arr; + rx_src_out <= i_rx_src_out_arr(0); + -- The mm_rst resets the MM interface, but is also used to reset the JESD IP reset sequencer. - -- Therefore a reset of mm_rst effectively resets the entire ip_arria10_e2sg_jesd204b and causes a reset on the rx_rst output. + -- Therefore a reset of mm_rst effectively resets the entire ip_arria10_e2sg_jesd204b and + -- causes a reset on the rx_rst output. rx_clk <= rxframe_clk; rx_rst <= not core_pll_locked; @@ -252,7 +280,6 @@ begin ----------------------------------------------------------------------------- -- The JESD204 IP (rx only) ----------------------------------------------------------------------------- - gen_jesd204b_rx_freqsel : if g_jesd_freq = "200MHz" generate u_ip_arria10_e2sg_jesd204b_rx_200MHz : ip_arria10_e2sg_jesd204b_rx_200MHz port map ( @@ -271,26 +298,28 @@ begin csr_s => OPEN, dev_lane_aligned => dev_lane_aligned_arr(i), dev_sync_n => jesd204b_sync_n_internal_arr(i), - jesd204_rx_avs_chipselect => '1', - jesd204_rx_avs_address => jesd204b_mosi_arr(i).address(c_jesd204b_mm_addr_w - 1 downto 0), - jesd204_rx_avs_read => jesd204b_mosi_arr(i).rd, - jesd204_rx_avs_readdata => jesd204b_miso_arr(i).rddata(31 downto 0), - jesd204_rx_avs_waitrequest => jesd204b_miso_arr(i).waitrequest, - jesd204_rx_avs_write => jesd204b_mosi_arr(i).wr, - jesd204_rx_avs_writedata => jesd204b_mosi_arr(i).wrdata(31 downto 0), - jesd204_rx_avs_clk => jesd204b_avs_clk, - jesd204_rx_avs_rst_n => rx_avs_rst_n_arr(i), - jesd204_rx_dlb_data => (others => '0'), -- debug/loopback testing + jesd204_rx_avs_chipselect => '1', + jesd204_rx_avs_address => jesd204b_mosi_arr(i).address(c_jesd204b_mm_addr_w - 1 downto 0), + jesd204_rx_avs_read => jesd204b_mosi_arr(i).rd, + jesd204_rx_avs_readdata => jesd204b_miso_arr(i).rddata(31 downto 0), + jesd204_rx_avs_waitrequest => jesd204b_miso_arr(i).waitrequest, + jesd204_rx_avs_write => jesd204b_mosi_arr(i).wr, + jesd204_rx_avs_writedata => jesd204b_mosi_arr(i).wrdata(31 downto 0), + jesd204_rx_avs_clk => jesd204b_avs_clk, + jesd204_rx_avs_rst_n => rx_avs_rst_n_arr(i), + jesd204_rx_dlb_data => (others => '0'), -- debug/loopback testing jesd204_rx_dlb_data_valid => (others => '0'), -- debug/loopback testing jesd204_rx_dlb_disperr => (others => '0'), -- debug/loopback testing jesd204_rx_dlb_errdetect => (others => '0'), -- debug/loopback testing jesd204_rx_dlb_kchar_data => (others => '0'), -- debug/loopback testing jesd204_rx_frame_error => '0', -- jesd204_rx_frame_error.export jesd204_rx_int => OPEN, -- Connected to status IO in example design - jesd204_rx_link_data => jesd204b_rx_link_data_arr(i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 downto i * c_jesd204b_rx_data_w), - jesd204_rx_link_valid => jesd204b_rx_link_valid_arr(i), - jesd204_rx_link_ready => '1', - pll_ref_clk => jesd204b_refclk, -- Aka device_clock, same as reference for the link/frame clock IOPLL (Intel JESD204B-UG p63) + jesd204_rx_link_data => jesd204b_rx_link_data_arr(i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 + downto i * c_jesd204b_rx_data_w), + jesd204_rx_link_valid => jesd204b_rx_link_valid_arr(i), + jesd204_rx_link_ready => '1', + pll_ref_clk => jesd204b_refclk, -- Aka device_clock, same as reference for the link/frame + -- clock IOPLL (Intel JESD204B-UG p63) rx_analogreset => rx_analogreset_arr(I downto I), rx_cal_busy => rx_cal_busy_arr(I downto I), rx_digitalreset => rx_digitalreset_arr(I downto I), @@ -300,8 +329,9 @@ begin rxlink_rst_n_reset_n => rxlink_rst_n_arr(i), -- Assoc with rxlink_clk (Intel JESD204B-UG p69) rxphy_clk => OPEN, -- Not used in Subclass 0 (Intel JESD204B-UG p63) sof => OPEN, - somf => jesd204b_rx_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 downto c_jesd204b_rx_somf_w * i), - sysref => jesd204b_sysref_2 + somf => jesd204b_rx_link_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 + downto c_jesd204b_rx_somf_w * i), + sysref => rxlink_sysref_2 ); -- One cycle rd-rdval latency, waitrequest = '0' fixed @@ -321,7 +351,7 @@ begin irq => open, clk => mm_clk, -- use clk = mm_clk for av_* port csr_reset => mm_rst, - reset1_dsrt_qual => mm_core_pll_locked_reg, -- core pll_locked synchronised to clk = mm_clk domain + reset1_dsrt_qual => mm_core_pll_locked, -- core pll_locked synchronised to clk = mm_clk domain reset2_dsrt_qual => '1', -- Tied to '1' in example design. Tx xcvr is not used. reset5_dsrt_qual => mm_rx_xcvr_ready_in_arr(i), reset_in0 => mm_rst, @@ -360,7 +390,9 @@ begin out_rst => rxframe_rst_arr(i) ); - rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0'; + rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or + xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0'; + -- synchronize rx_xcvr_ready_in_arr to mm_clk u_common_async_rx_xcvr_ready : entity common_lib.common_async generic map ( @@ -373,7 +405,7 @@ begin dout => mm_rx_xcvr_ready_in_arr(i) ); - -- Invert thr active-low resets + -- Invert the active-low resets rx_avs_rst_n_arr(i) <= not rx_avs_rst_arr(i); rxlink_rst_n_arr(i) <= not rxlink_rst_arr(i); rxframe_rst_n_arr(i) <= not rxframe_rst_arr(i); @@ -385,24 +417,34 @@ begin begin if rising_edge(rxframe_clk) then if rxframe_rst_n_arr(i) = '0' then - rx_src_out_arr(i).data(c_jesd204b_rx_framer_data_w - 1 downto 0) <= (others => '0'); - rx_src_out_arr(i).channel(c_jesd204b_rx_framer_somf_w - 1 downto 0) <= (others => '0'); - f2_div1_cnt_arr(i) <= '0'; - rx_src_out_arr(i).valid <= '0'; + i_rx_src_out_arr(i).data <= (others => '0'); + i_rx_src_out_arr(i).channel <= (others => '0'); + i_rx_src_out_arr(i).valid <= '0'; + rxframe_toggle_arr(i) <= '0'; else - rx_src_out_arr(i).valid <= jesd204b_rx_link_valid_arr(i); if jesd204b_rx_link_valid_arr(i) = '0' then - rx_src_out_arr(i).data(c_jesd204b_rx_framer_data_w - 1 downto 0) <= (others => '0'); - rx_src_out_arr(i).channel(c_jesd204b_rx_framer_somf_w - 1 downto 0) <= (others => '0'); + i_rx_src_out_arr(i).data <= (others => '0'); + i_rx_src_out_arr(i).channel <= (others => '0'); + i_rx_src_out_arr(i).valid <= '0'; + rxframe_toggle_arr(i) <= '0'; else - if f2_div1_cnt_arr(i) = '1' then - rx_src_out_arr(i).data(c_jesd204b_rx_framer_data_w - 1 downto 0) <= jesd204b_rx_link_data_arr(c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto c_jesd204b_rx_data_w * i); - rx_src_out_arr(i).channel(c_jesd204b_rx_framer_somf_w - 1 downto 0) <= jesd204b_rx_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_framer_somf_w - 1 downto c_jesd204b_rx_somf_w * i); + if rxframe_toggle_arr(i) = '1' then + i_rx_src_out_arr(i).data <= RESIZE_DP_SDATA(jesd204b_rx_link_data_arr( + c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto + c_jesd204b_rx_data_w * i)); + i_rx_src_out_arr(i).channel <= RESIZE_DP_CHANNEL(jesd204b_rx_link_somf_arr( + c_jesd204b_rx_somf_w * i + c_jesd204b_rx_framer_somf_w - 1 downto + c_jesd204b_rx_somf_w * i)); else - rx_src_out_arr(i).data(c_jesd204b_rx_framer_data_w - 1 downto 0) <= jesd204b_rx_link_data_arr(c_jesd204b_rx_data_w * i + c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w); - rx_src_out_arr(i).channel(c_jesd204b_rx_framer_somf_w - 1 downto 0) <= jesd204b_rx_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 downto c_jesd204b_rx_somf_w * i + c_jesd204b_rx_framer_somf_w); + i_rx_src_out_arr(i).data <= RESIZE_DP_SDATA(jesd204b_rx_link_data_arr( + c_jesd204b_rx_data_w * i + c_jesd204b_rx_data_w - 1 downto + c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w)); + i_rx_src_out_arr(i).channel <= RESIZE_DP_CHANNEL(jesd204b_rx_link_somf_arr( + c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 downto + c_jesd204b_rx_somf_w * i + c_jesd204b_rx_framer_somf_w)); end if; - f2_div1_cnt_arr(i) <= not f2_div1_cnt_arr(i); + i_rx_src_out_arr(i).valid <= '1'; + rxframe_toggle_arr(i) <= not rxframe_toggle_arr(i); end if; end if; end if; @@ -414,39 +456,35 @@ begin -- See: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_jesd204b.pdf -- Figure 25, page 151 ----------------------------------------------------------------------------- - p_reclocksysref : process (rxlink_clk, core_pll_locked) + p_reclocksysref : process (core_pll_locked, rxlink_clk) begin if core_pll_locked = '0' then - jesd204b_sysref_1 <= '0'; - jesd204b_sysref_2 <= '0'; + rxlink_sysref_1 <= '0'; + rxlink_sysref_2 <= '0'; jesd204b_sync_n_arr <= (others => '0'); - else - if rising_edge(rxlink_clk) then - jesd204b_sysref_1 <= jesd204b_sysref; - jesd204b_sysref_2 <= jesd204b_sysref_1; - jesd204b_sync_n_arr <= jesd204b_sync_n_combined_arr; - end if; + elsif rising_edge(rxlink_clk) then + rxlink_sysref_1 <= jesd204b_sysref; + rxlink_sysref_2 <= rxlink_sysref_1; + jesd204b_sync_n_arr <= jesd204b_sync_n_combined_arr; end if; end process; ----------------------------------------------------------------------------- -- Move sysref from rxlink_clk to rxframe_clk ----------------------------------------------------------------------------- - p_rx_sysref : process (rxframe_clk, core_pll_locked) + p_rx_sysref : process (core_pll_locked, rxframe_clk) begin if core_pll_locked = '0' then - jesd204b_sysref_frameclk_1 <= '0'; - jesd204b_sysref_frameclk_2 <= '0'; + rxframe_sysref_1 <= '0'; + rxframe_sysref_2 <= '0'; rx_sysref <= '0'; - else - if rising_edge(rxframe_clk) then - jesd204b_sysref_frameclk_1 <= jesd204b_sysref_2; -- sysref from rxlink_clk domain - jesd204b_sysref_frameclk_2 <= jesd204b_sysref_frameclk_1; - if jesd204b_sysref_frameclk_1 = '1' and jesd204b_sysref_frameclk_2 = '0' then - rx_sysref <= '1'; - else - rx_sysref <= '0'; - end if; + elsif rising_edge(rxframe_clk) then + rxframe_sysref_1 <= rxlink_sysref_2; -- sysref from rxlink_clk domain + rxframe_sysref_2 <= rxframe_sysref_1; + if rxframe_sysref_1 = '1' and rxframe_sysref_2 = '0' then + rx_sysref <= '1'; + else + rx_sysref <= '0'; end if; end if; end process; @@ -471,7 +509,7 @@ begin port map ( in_rst => core_pll_locked, clk => mm_clk, - out_rst => mm_core_pll_locked_reg + out_rst => mm_core_pll_locked ); -- Transceiver reset controller. Use g_nof_streams out of 12 channels. Receive only @@ -480,20 +518,26 @@ begin u_ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control : ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control_12 port map ( clock => rxlink_clk, - reset => xcvr_rst_arr(0), -- From Reset Sequencer output1 as per example design, the reset input is synchronised internally. - rx_analogreset => rx_analogreset_arr, -- output to reset RX PMA. Release before deasserting link and avs resets (Intel JESD204B-UG p70) + reset => xcvr_rst_arr(0), -- From Reset Sequencer output1 as per example design, + -- the reset input is synchronised internally. + rx_analogreset => rx_analogreset_arr, -- output to reset RX PMA. Release before deasserting + -- link and avs resets (Intel JESD204B-UG p70) rx_cal_busy => rx_cal_busy_arr, -- input from PHY - rx_digitalreset => rx_digitalreset_arr, -- output to reset RX PCS. Release before deasserting link and avs resets (Intel JESD204B-UG p70) + rx_digitalreset => rx_digitalreset_arr, -- output to reset RX PCS. Release before deasserting + -- link and avs resets (Intel JESD204B-UG p70) rx_is_lockedtodata => rx_islockedtodata_arr, -- input from PHY - rx_ready => xcvr_rst_ctrl_rx_ready_arr -- From example design: gate with rx_csr_lane_powerdown to reset transceiver + rx_ready => xcvr_rst_ctrl_rx_ready_arr -- From example design: gate with + -- rx_csr_lane_powerdown to reset transceiver ); end generate; -- gen_jesd204b_rx : IF g_direction = "RX_ONLY" GENERATE gen_enable_sync_n : for i in 0 to g_nof_streams - 1 generate - -- The sync_n_enabled output is active '0'. For disabled signal inputs the sync_n_enabled output is forced to '1', so that for the disabled (= inactive = not used) + -- The sync_n_enabled output is active '0'. For disabled signal inputs the sync_n_enabled output + -- is forced to '1', so that for the disabled (= inactive = not used) -- signal inputs the sync_n_internal from the JESD IP will not pull sync_n_enabled low. - -- The purpose of being able to disable inactive signal inputs is that this avoids that one inactive signal input will cause all signal inputs in a group that share - -- the sync_n_combined to become unavailable (see gen_group_sync_n). + -- The purpose of being able to disable inactive signal inputs is that this avoids that one + -- inactive signal input will cause all signal inputs in a group that share the sync_n_combined + -- to become unavailable (see gen_group_sync_n). -- For disabled channels (in jesd204b_disable_arr), the SYNC_N output will not be used jesd204b_sync_n_enabled_arr(i) <= jesd204b_sync_n_internal_arr(i) or jesd204b_disable_arr(i); @@ -503,7 +547,9 @@ begin -- Group the SYNC_N outputs ----------------------------------------------------------------------------- gen_group_sync_n : for i in 0 to g_nof_sync_n - 1 generate - jesd204b_sync_n_combined_arr(i) <= vector_and(jesd204b_sync_n_enabled_arr(c_nof_sync_n_per_group * i + c_nof_sync_n_per_group - 1 downto c_nof_sync_n_per_group * i)); + jesd204b_sync_n_combined_arr(i) <= vector_and(jesd204b_sync_n_enabled_arr( + c_nof_sync_n_per_group * i + c_nof_sync_n_per_group - 1 downto + c_nof_sync_n_per_group * i)); end generate; ----------------------------------------------------------------------------- diff --git a/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd b/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd new file mode 100644 index 0000000000000000000000000000000000000000..79501ebef68c71773c63068d39457489e14adaf6 --- /dev/null +++ b/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd @@ -0,0 +1,681 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. +-- +-------------------------------------------------------------------------------- + +-- Authors : J Hargreaves, L Hiemstra, E. Kooistra +-- Purpose: Combine IP components needed to create a JESD204B interface +-- Initially supports RX_ONLY for receiving data from an ADC +-- Description +-- Currently only 12 streams because of the 12 channel reset block +-- The sync_n signals are gated together to form g_nof_sync_n outputs +-- . v2 uses FIFO in IP to get from rxlink_clk at 100 MHz to dp_clk at 200 MHz + +library IEEE, common_lib, dp_lib, technology_lib, ip_arria10_e2sg_jesd204b_lib; +use IEEE.std_logic_1164.all; +use technology_lib.technology_pkg.all; +use common_lib.common_pkg.all; +use common_lib.common_mem_pkg.all; +use dp_lib.dp_stream_pkg.all; +use ip_arria10_e2sg_jesd204b_lib.ip_arria10_e2sg_jesd204b_component_pkg.all; + +entity ip_arria10_e2sg_jesd204b_v2 is + generic ( + g_sim : boolean := false; + g_nof_streams : natural := 1; + g_nof_sync_n : natural := 1; + g_direction : string := "RX_ONLY"; -- "TX_RX", "TX_ONLY", "RX_ONLY" + g_jesd_freq : string := "200MHz" + ); + port ( + -- JESD204B external signals + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock + -- reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with + -- respect to jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization / + -- syncronization phase + + -- Data to fabric + dp_clk : in std_logic; + dp_rst : in std_logic; + dp_sysref : out std_logic; -- = dp_sosi_arr(0).sync, all dp_sosi_arr().sync carry the dp_sysref + dp_sosi_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data and sync to fabric + + -- MM Control + mm_clk : in std_logic; + mm_rst : in std_logic; + jesd204b_disable_arr : in std_logic_vector(g_nof_streams - 1 downto 0); + + jesd204b_mosi : in t_mem_mosi; -- mm control + jesd204b_miso : out t_mem_miso; + + -- Serial connections to transceiver pins + serial_tx_arr : out std_logic_vector(g_nof_streams - 1 downto 0); -- Not used for ADC + serial_rx_arr : in std_logic_vector(g_nof_streams - 1 downto 0) + ); +end ip_arria10_e2sg_jesd204b_v2; + +architecture str of ip_arria10_e2sg_jesd204b_v2 is + -- JESD IP constants + -- . JESD204B MM has 256 bytes = 64 words, so mm_addr_w = 6 would be enough, + -- but using mm_addr_w = 8 and span = 256 words is fine too. + constant c_jesd204b_mm_addr_w : natural := 8; + constant c_jesd204b_rx_data_w : natural := 32; + constant c_jesd204b_rx_framer_data_w : natural := c_jesd204b_rx_data_w / 2; -- = 16, two samples in parallel + constant c_jesd204b_rx_somf_w : natural := c_jesd204b_rx_data_w / 8; -- = 4, one somf bit per octet + constant c_jesd204b_rx_framer_somf_w : natural := c_jesd204b_rx_somf_w / 2; -- = 2, two samples in parallel + constant c_nof_sync_n_per_group : natural := sel_a_b(g_nof_streams / g_nof_sync_n = 0, + 1, g_nof_streams / g_nof_sync_n); + constant c_fifo_size : natural := 64; + constant c_fifo_fill_level : natural := 10; + constant c_fifo_fill_margin : natural := 4; + + -- FSM for rxlink_clk to dp_clk FIFO read access + type t_fifo_state_enum is (s_fifo_low, s_fifo_filled); + + -- JESD204 control status registers + signal jesd204b_mosi_arr : t_mem_mosi_arr(g_nof_streams - 1 downto 0); + signal jesd204b_miso_arr : t_mem_miso_arr(g_nof_streams - 1 downto 0) := (others => c_mem_miso_rst); + signal reset_seq_mosi_arr : t_mem_mosi_arr(g_nof_streams - 1 downto 0) := (others => c_mem_mosi_rst); + signal reset_seq_miso_arr : t_mem_miso_arr(g_nof_streams - 1 downto 0) := (others => c_mem_miso_rst); + + -- Clocks + -- . The 200MHz rxframe_clk is not used in v2, the constraints on the PLL output frame_clk in + -- lofar2_unb2c_sdp_station.sdc will be ingored by Quartus. + signal rxframe_clk : std_logic; + signal rxlink_clk : std_logic; + signal jesd204b_avs_clk : std_logic; + + -- Reset and control signals, 1 bit per lane + signal dev_lane_aligned : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_analogreset_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_cal_busy_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_digitalreset_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_islockedtodata_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal dev_lane_aligned_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_csr_lane_powerdown_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal xcvr_rst_ctrl_rx_ready_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_xcvr_ready_in_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal mm_rx_xcvr_ready_in_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal pll_reset_async_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal pll_reset_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal xcvr_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0) := (others => '1'); + signal rx_avs_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rx_avs_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rxlink_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rxlink_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal rxlink_rst_n_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal core_pll_locked : std_logic; + signal mm_core_pll_locked : std_logic; + signal wr_core_pll_locked : std_logic; + signal wr_rst : std_logic := '1'; + signal rxlink_sysref_1 : std_logic; + signal rxlink_sysref_2 : std_logic; + signal rxlink_sysref_3 : std_logic; + signal rxlink_sysref : std_logic; -- single rxlink_clk cycle pulse + + -- Data path + signal jesd204b_rx_link_data_arr : std_logic_vector(c_jesd204b_rx_data_w * g_nof_streams - 1 downto 0); + signal jesd204b_rx_link_valid_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_rx_link_somf_arr : std_logic_vector(c_jesd204b_rx_somf_w * g_nof_streams - 1 downto 0); + + -- debug signal to view input 0 in Wave Window + signal jesd204b_rx_link_data : std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); + signal jesd204b_rx_link_data_hi : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal jesd204b_rx_link_data_lo : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal jesd204b_rx_link_valid : std_logic; + signal jesd204b_rx_link_somf : std_logic_vector(c_jesd204b_rx_somf_w - 1 downto 0); + signal jesd204b_rx_link_somf_hi : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); + signal jesd204b_rx_link_somf_lo : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); + + signal rxlink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0) := (others => c_dp_sosi_rst); + signal dplink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); + signal dplink_siso_arr : t_dp_siso_arr(g_nof_streams - 1 downto 0) := (others => c_dp_siso_rdy); + signal fifo_state : t_fifo_state_enum; + signal fifo_rd_usedw : std_logic_vector(ceil_log2(c_fifo_size) - 1 downto 0); + signal fifo_filled : std_logic := '0'; + signal dp_index : std_logic := '0'; + signal dp_ready : std_logic := '0'; + + -- debug signal to view input 0 in Wave Window + signal rxlink_sosi : t_dp_sosi; + signal rxlink_data : std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); + signal rxlink_data_hi : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal rxlink_data_lo : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal dplink_sosi : t_dp_sosi; + signal dplink_data : std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); + signal dplink_data_hi : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + signal dplink_data_lo : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); + + signal i_dp_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); + signal dp_sosi : t_dp_sosi; -- input 0 + + -- outputs to control ADC initialization/syncronization phase + signal jesd204b_sync_n_internal_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_sync_n_enabled_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal jesd204b_sync_n_combined_arr : std_logic_vector(g_nof_sync_n - 1 downto 0); + + -- Component declarations for the IP blocks + + component ip_arria10_e2sg_jesd204b_rx_200MHz is + port ( + alldev_lane_aligned : in std_logic := 'X'; -- export + csr_cf : out std_logic_vector(4 downto 0); -- export + csr_cs : out std_logic_vector(1 downto 0); -- export + csr_f : out std_logic_vector(7 downto 0); -- export + csr_hd : out std_logic; -- export + csr_k : out std_logic_vector(4 downto 0); -- export + csr_l : out std_logic_vector(4 downto 0); -- export + csr_lane_powerdown : out std_logic_vector(0 downto 0); -- export + csr_m : out std_logic_vector(7 downto 0); -- export + csr_n : out std_logic_vector(4 downto 0); -- export + csr_np : out std_logic_vector(4 downto 0); -- export + csr_rx_testmode : out std_logic_vector(3 downto 0); -- export + csr_s : out std_logic_vector(4 downto 0); -- export + dev_lane_aligned : out std_logic; -- export + dev_sync_n : out std_logic; -- export + jesd204_rx_avs_chipselect : in std_logic := 'X'; + jesd204_rx_avs_address : in std_logic_vector(c_jesd204b_mm_addr_w - 1 downto 0) := (others => 'X'); + jesd204_rx_avs_read : in std_logic := 'X'; + jesd204_rx_avs_readdata : out std_logic_vector(31 downto 0); + jesd204_rx_avs_waitrequest : out std_logic; + jesd204_rx_avs_write : in std_logic := 'X'; + jesd204_rx_avs_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); + jesd204_rx_avs_clk : in std_logic := 'X'; + jesd204_rx_avs_rst_n : in std_logic := 'X'; + jesd204_rx_dlb_data : in std_logic_vector(31 downto 0) := (others => 'X'); -- export + jesd204_rx_dlb_data_valid : in std_logic_vector(0 downto 0) := (others => 'X'); -- export + jesd204_rx_dlb_disperr : in std_logic_vector(3 downto 0) := (others => 'X'); -- export + jesd204_rx_dlb_errdetect : in std_logic_vector(3 downto 0) := (others => 'X'); -- export + jesd204_rx_dlb_kchar_data : in std_logic_vector(3 downto 0) := (others => 'X'); -- export + jesd204_rx_frame_error : in std_logic := 'X'; -- export + jesd204_rx_int : out std_logic; -- irq + jesd204_rx_link_data : out std_logic_vector(c_jesd204b_rx_data_w - 1 downto 0); -- data + jesd204_rx_link_valid : out std_logic; -- valid + jesd204_rx_link_ready : in std_logic := 'X'; -- ready + pll_ref_clk : in std_logic := 'X'; -- clk + rx_analogreset : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_analogreset + rx_cal_busy : out std_logic_vector(0 downto 0); -- rx_cal_busy + rx_digitalreset : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_digitalreset + rx_islockedtodata : out std_logic_vector(0 downto 0); -- rx_is_lockedtodata + rx_serial_data : in std_logic_vector(0 downto 0) := (others => 'X'); -- rx_serial_data + rxlink_clk : in std_logic := 'X'; -- clk + rxlink_rst_n_reset_n : in std_logic := 'X'; -- reset_n + rxphy_clk : out std_logic_vector(0 downto 0); -- export + sof : out std_logic_vector(3 downto 0); -- export + somf : out std_logic_vector(c_jesd204b_rx_somf_w - 1 downto 0); -- export + sysref : in std_logic := 'X' -- export + ); + end component ip_arria10_e2sg_jesd204b_rx_200MHz; + + component ip_arria10_e2sg_jesd204b_rx_core_pll_200MHz is + port ( + locked : out std_logic; -- export + outclk_0 : out std_logic; -- clk + outclk_1 : out std_logic; -- clk + refclk : in std_logic := 'X'; -- clk + rst : in std_logic := 'X' -- reset + ); + end component ip_arria10_e2sg_jesd204b_rx_core_pll_200MHz; + + component ip_arria10_e2sg_jesd204b_rx_reset_seq is + port ( + av_address : in std_logic_vector(7 downto 0) := (others => 'X'); -- address + av_readdata : out std_logic_vector(31 downto 0); -- readdata + av_read : in std_logic := 'X'; -- read + av_writedata : in std_logic_vector(31 downto 0) := (others => 'X'); -- writedata + av_write : in std_logic := 'X'; -- write + irq : out std_logic; -- irq + clk : in std_logic := 'X'; -- clk + csr_reset : in std_logic := 'X'; -- reset + reset1_dsrt_qual : in std_logic := 'X'; -- reset1_dsrt_qual + reset2_dsrt_qual : in std_logic := 'X'; -- reset2_dsrt_qual + reset5_dsrt_qual : in std_logic := 'X'; -- reset5_dsrt_qual + reset_in0 : in std_logic := 'X'; -- reset + reset_out0 : out std_logic; -- reset + reset_out1 : out std_logic; -- reset + reset_out2 : out std_logic; -- reset + reset_out3 : out std_logic; -- reset + reset_out4 : out std_logic; -- reset + reset_out5 : out std_logic; -- reset + reset_out6 : out std_logic; -- reset + reset_out7 : out std_logic -- reset + ); + end component ip_arria10_e2sg_jesd204b_rx_reset_seq; + + component ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control_12 is + port ( + clock : in std_logic := 'X'; -- clk + reset : in std_logic := 'X'; -- reset + rx_analogreset : out std_logic_vector(11 downto 0); -- rx_analogreset + rx_cal_busy : in std_logic_vector(11 downto 0) := (others => 'X'); -- rx_cal_busy + rx_digitalreset : out std_logic_vector(11 downto 0); -- rx_digitalreset + rx_is_lockedtodata : in std_logic_vector(11 downto 0) := (others => 'X'); -- rx_is_lockedtodata + rx_ready : out std_logic_vector(11 downto 0) -- rx_ready + ); + end component ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control_12; +begin + dp_sosi_arr <= i_dp_sosi_arr; + dp_sosi <= i_dp_sosi_arr(0); + + -- wire dp_sysref from dp_sosi_arr().sync, all sync carry the dp_sysref + dp_sysref <= dp_sosi.sync; + + -- Debug signals to view input 0 in Wave Window + jesd204b_rx_link_data <= jesd204b_rx_link_data_arr(c_jesd204b_rx_data_w - 1 downto 0); + jesd204b_rx_link_data_hi <= jesd204b_rx_link_data(c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w); + jesd204b_rx_link_data_lo <= jesd204b_rx_link_data(c_jesd204b_rx_framer_data_w - 1 downto 0); + jesd204b_rx_link_valid <= jesd204b_rx_link_valid_arr(0); + jesd204b_rx_link_somf <= jesd204b_rx_link_somf_arr(c_jesd204b_rx_somf_w - 1 downto 0); + jesd204b_rx_link_somf_hi <= jesd204b_rx_link_somf(c_jesd204b_rx_somf_w - 1 downto c_jesd204b_rx_framer_somf_w); + jesd204b_rx_link_somf_lo <= jesd204b_rx_link_somf(c_jesd204b_rx_framer_somf_w - 1 downto 0); + + rxlink_sosi <= rxlink_sosi_arr(0); + rxlink_data <= rxlink_sosi.data(c_jesd204b_rx_data_w - 1 downto 0); + rxlink_data_hi <= rxlink_data(c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w); + rxlink_data_lo <= rxlink_data(c_jesd204b_rx_framer_data_w - 1 downto 0); + + dplink_sosi <= dplink_sosi_arr(0); + dplink_data <= dplink_sosi.data(c_jesd204b_rx_data_w - 1 downto 0); + dplink_data_hi <= dplink_data(c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w); + dplink_data_lo <= dplink_data(c_jesd204b_rx_framer_data_w - 1 downto 0); + + -- The mm_rst resets the MM interface, but is also used to reset the JESD IP reset sequencer. + -- Therefore a reset of mm_rst effectively resets the entire JESD IP. + + -- The avs clock is driven by the rxlink_clk for simulation. This is a workaround for a bug + -- in the Q18.0 IP where the jesd receiver fails to recognize the SYSREF pulse + gen_simclock : if g_sim = true generate + jesd204b_avs_clk <= rxlink_clk; + end generate; + + -- For synthesis the avs clock is driven by the mm_clk as usual + gen_synthclock : if g_sim = false generate + jesd204b_avs_clk <= mm_clk; + end generate; + + gen_jesd204b_rx : if g_direction = "RX_ONLY" generate + gen_jesd204b_rx_channels : for I in 0 to g_nof_streams - 1 generate + ----------------------------------------------------------------------------- + -- The JESD204 IP (rx only) + ----------------------------------------------------------------------------- + gen_jesd204b_rx_freqsel : if g_jesd_freq = "200MHz" generate + u_ip_arria10_e2sg_jesd204b_rx_200MHz : ip_arria10_e2sg_jesd204b_rx_200MHz + port map ( + alldev_lane_aligned => dev_lane_aligned_arr(i), + csr_cf => OPEN, + csr_cs => OPEN, + csr_f => OPEN, + csr_hd => OPEN, + csr_k => OPEN, + csr_l => OPEN, + csr_lane_powerdown => rx_csr_lane_powerdown_arr(i downto i), + csr_m => OPEN, + csr_n => OPEN, + csr_np => OPEN, + csr_rx_testmode => OPEN, + csr_s => OPEN, + dev_lane_aligned => dev_lane_aligned_arr(i), + dev_sync_n => jesd204b_sync_n_internal_arr(i), + jesd204_rx_avs_chipselect => '1', + jesd204_rx_avs_address => jesd204b_mosi_arr(i).address(c_jesd204b_mm_addr_w - 1 downto 0), + jesd204_rx_avs_read => jesd204b_mosi_arr(i).rd, + jesd204_rx_avs_readdata => jesd204b_miso_arr(i).rddata(31 downto 0), + jesd204_rx_avs_waitrequest => jesd204b_miso_arr(i).waitrequest, + jesd204_rx_avs_write => jesd204b_mosi_arr(i).wr, + jesd204_rx_avs_writedata => jesd204b_mosi_arr(i).wrdata(31 downto 0), + jesd204_rx_avs_clk => jesd204b_avs_clk, + jesd204_rx_avs_rst_n => rx_avs_rst_n_arr(i), + jesd204_rx_dlb_data => (others => '0'), -- debug/loopback testing + jesd204_rx_dlb_data_valid => (others => '0'), -- debug/loopback testing + jesd204_rx_dlb_disperr => (others => '0'), -- debug/loopback testing + jesd204_rx_dlb_errdetect => (others => '0'), -- debug/loopback testing + jesd204_rx_dlb_kchar_data => (others => '0'), -- debug/loopback testing + jesd204_rx_frame_error => '0', -- jesd204_rx_frame_error.export + jesd204_rx_int => OPEN, -- Connected to status IO in example design + jesd204_rx_link_data => jesd204b_rx_link_data_arr(i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 + downto i * c_jesd204b_rx_data_w), + jesd204_rx_link_valid => jesd204b_rx_link_valid_arr(i), + jesd204_rx_link_ready => '1', + pll_ref_clk => jesd204b_refclk, -- Aka device_clock, same as reference for the link/frame + -- clock IOPLL (Intel JESD204B-UG p63) + rx_analogreset => rx_analogreset_arr(I downto I), + rx_cal_busy => rx_cal_busy_arr(I downto I), + rx_digitalreset => rx_digitalreset_arr(I downto I), + rx_islockedtodata => rx_islockedtodata_arr(I downto I), + rx_serial_data => serial_rx_arr(i downto i), + rxlink_clk => rxlink_clk, + rxlink_rst_n_reset_n => rxlink_rst_n_arr(i), -- Assoc with rxlink_clk (Intel JESD204B-UG p69) + rxphy_clk => OPEN, -- Not used in Subclass 0 (Intel JESD204B-UG p63) + sof => OPEN, + somf => jesd204b_rx_link_somf_arr(c_jesd204b_rx_somf_w * i + c_jesd204b_rx_somf_w - 1 + downto c_jesd204b_rx_somf_w * i), + sysref => rxlink_sysref + ); + + -- Group jesd204b_rx_link data and sync (= sysref) into rxlink_sosi_arr. When an JESD204B interface + -- input is in lock, then its jesd204b_rx_link data and sync are synchronous, and the MSpart of the + -- data then contains the even (0) sample and the LSpart contains the odd (1) sample (= big endian). + -- In the rxframe_clk domain the sync is active in the even (0) sample, so in the dp_clk domain the + -- sync is passed on when the data MSpart is read and forced to '0' for the data LSpart, + -- All synchronization info is contained in the alignment of rxlink_clk, data and sync, the valid + -- does not provide additional synchronization info. The valid does indicate whether the link is in + -- lock or not, but for the subsequent data processing the sync is sufficient to start. The valid + -- could be used as monitor point, but it is sufficient to use the JESD204B IP monitor points. For + -- same reason it is also not necessary to pass on the jesd204b_rx_link_somf_arr status. + -- Therefore always write the FIFO when rxlink_clk is active and rxlink_rst is released, independent + -- of whether the input is in lock or not. + rxlink_sosi_arr(i).data <= RESIZE_DP_DATA(jesd204b_rx_link_data_arr + (i * c_jesd204b_rx_data_w + c_jesd204b_rx_data_w - 1 downto + i * c_jesd204b_rx_data_w)); + rxlink_sosi_arr(i).sync <= rxlink_sysref; + rxlink_sosi_arr(i).valid <= '1'; + + -- One cycle rd-rdval latency, waitrequest = '0' fixed + jesd204b_miso_arr(i).rdval <= jesd204b_mosi_arr(i).rd when rising_edge(jesd204b_avs_clk); + end generate; + + ----------------------------------------------------------------------------- + -- Reset sequencer for each channel + ----------------------------------------------------------------------------- + u_ip_arria10_e2sg_jesd204b_rx_reset_seq : ip_arria10_e2sg_jesd204b_rx_reset_seq + port map ( + av_address => reset_seq_mosi_arr(i).address(7 downto 0), + av_readdata => reset_seq_miso_arr(i).rddata(31 downto 0), + av_read => reset_seq_mosi_arr(i).rd, + av_writedata => reset_seq_mosi_arr(i).wrdata(31 downto 0), + av_write => reset_seq_mosi_arr(i).wr, + irq => open, + clk => mm_clk, -- use clk = mm_clk for av_* port + csr_reset => mm_rst, + reset1_dsrt_qual => mm_core_pll_locked, -- core pll_locked synchronised to clk = mm_clk domain + reset2_dsrt_qual => '1', -- Tied to '1' in example design. Tx xcvr is not used. + reset5_dsrt_qual => mm_rx_xcvr_ready_in_arr(i), + reset_in0 => mm_rst, + -- reset_out* signals are in mm_clk domain + reset_out0 => pll_reset_async_arr(i), -- Use channel 0 to reset the core pll + reset_out1 => xcvr_rst_arr(i), -- Use channel 1 to reset the transceiver reset controller + reset_out2 => open, + reset_out3 => open, + reset_out4 => open, + reset_out5 => rx_avs_rst_arr(i), + reset_out6 => rxlink_rst_async_arr(i), + reset_out7 => open + ); + + -- synchronize pll_reset + u_common_areset_pll : entity common_lib.common_areset + port map ( + in_rst => pll_reset_async_arr(i), + clk => jesd204b_refclk, + out_rst => pll_reset_arr(i) + ); + + -- synchronize rxlink reset + u_common_areset_rxlink : entity common_lib.common_areset + port map ( + in_rst => rxlink_rst_async_arr(i), + clk => rxlink_clk, + out_rst => rxlink_rst_arr(i) + ); + + rx_xcvr_ready_in_arr(i) <= '1' when rx_csr_lane_powerdown_arr(i) = '1' or + xcvr_rst_ctrl_rx_ready_arr(i) = '1' else '0'; + + -- synchronize rx_xcvr_ready_in_arr to mm_clk + u_common_async_rx_xcvr_ready : entity common_lib.common_async + generic map ( + g_rst_level => '0' -- When in_rst is asserted, dout = '0' + ) + port map ( + rst => mm_rst, + clk => mm_clk, + din => rx_xcvr_ready_in_arr(i), + dout => mm_rx_xcvr_ready_in_arr(i) + ); + + -- Invert the active-low resets + rx_avs_rst_n_arr(i) <= not rx_avs_rst_arr(i); + rxlink_rst_n_arr(i) <= not rxlink_rst_arr(i); + + ----------------------------------------------------------------------------- + -- Deframers in dp_clk domain + ----------------------------------------------------------------------------- + p_deframer : process (dp_clk) + begin + if rising_edge(dp_clk) then + if fifo_filled = '0' then + i_dp_sosi_arr(i) <= c_dp_sosi_rst; -- Force all to 0 when Rx JESD204B has stopped + else + i_dp_sosi_arr(i).valid <= '1'; + if dp_index = '0' then + -- MS data with sync at even dp_index = 0 + i_dp_sosi_arr(i).sync <= dplink_sosi_arr(i).sync; + i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( + c_jesd204b_rx_data_w - 1 downto c_jesd204b_rx_framer_data_w)); + else + -- LS data at odd dp_index = 1 + i_dp_sosi_arr(i).sync <= '0'; + i_dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( + c_jesd204b_rx_framer_data_w - 1 downto 0)); + end if; + end if; + end if; + end process; + + -- Apply toggling ready control for cross 100 MHz rxlink_clk domain to 200MHz dp_clk domain + -- u_dp_fifo_dc_arr FIFO. + dplink_siso_arr(i).xon <= '1'; + dplink_siso_arr(i).ready <= dp_ready; + end generate; -- gen_jesd204b_rx_channels : for I in 0 to g_nof_streams-1 generate + + ----------------------------------------------------------------------------- + -- Cross from 100 MHz rxlink_clk domain to 200MHz dp_clk domain using a FIFO + ----------------------------------------------------------------------------- + -- The dp_fifo_core_arr.vhd FIFO in dp_fifo_dc_arr.vhd.vhd passes on for ctrl and info + -- fields from snk_in_arr(0) and data fields from all snk_in_arr(). Similar for flow + -- control the FIFO uses src_in_arr(0).ready as read strobe. Using only input (0) is + -- possible, because all snk_in_arr() inputs will have same ctrl and info when Rx + -- JESD204B IP is synchronized. + wr_rst <= not wr_core_pll_locked; + + u_dp_fifo_dc_arr : entity dp_lib.dp_fifo_dc_arr + generic map ( + g_nof_streams => g_nof_streams, + g_data_w => c_jesd204b_rx_data_w, -- 32b + g_data_signed => false, + g_use_sync => true, + g_use_ctrl => false, + g_use_channel => false, -- no need to pass on jesd204b_rx_link_somf_arr + g_fifo_size => c_fifo_size + ) + port map ( + wr_rst => wr_rst, + wr_clk => rxlink_clk, + rd_rst => dp_rst, + rd_clk => dp_clk, + rd_usedw => fifo_rd_usedw, + snk_in_arr => rxlink_sosi_arr, + src_in_arr => dplink_siso_arr, + src_out_arr => dplink_sosi_arr + ); + + -- The dp_clk at 200 MHz and rxlink_clk at 100 MHz are locked to same reference. + -- Toggle dp_index every dp_clk cycle to have the same read rate in dp_clk domain, + -- as the write rate in rxlink_clk domain. + -- + -- Use a finite state machine (FSM) to fill the FIFO with fill margin above a + -- nominal FIFO fill level, so that the dp_index keeps on toggling once it has + -- started, as long as the FIFO remains filled. The fill margin avoids that + -- there can occur once a one dp_clk cycle disturbance in the toggling, in case + -- rxlink_clk and dp_clk almost coincide. + -- + -- Simulation with tb_tech_jesd204b_v2.vhd reveals that the double data word is + -- always read high part first and low part next, independent of the phase of + -- dp_index. This is because reading ab, cd, ef, ... is equivalent to reading + -- bc, de, fg, ... However the phase of dp_ready with respect to dp_index is + -- important for reading the sync, because if dp_ready has the wrong phase, + -- then the sync is missed at the FIFO output. + -- . If dp_index = '0' or '1' initialy, then in both cases use dp_ready <= not + -- dp_index, and then in both cases the latency dp_sosi.sync and data = 1000 is + -- then 340 ns + -- . Do not use dp_ready <= dp_index, because then the dp_sosi.sync gets missed. + -- Therefore choose to use dp_index = '0' initially, because then dp_ready = + -- dp_index always. + p_fsm_dp_index : process(dp_rst, dp_clk) + begin + if dp_rst = '1' then + dp_index <= '0'; + dp_ready <= '0'; + fifo_filled <= '0'; + fifo_state <= s_fifo_low; + elsif rising_edge(dp_clk) then + case fifo_state is + when s_fifo_low => + dp_index <= '0'; + dp_ready <= '0'; -- fill the FIFO, so no double data word request + fifo_filled <= '0'; + if to_uint(fifo_rd_usedw) >= c_fifo_fill_level + c_fifo_fill_margin then + fifo_state <= s_fifo_filled; + end if; + when others => -- = s_fifo_filled + dp_index <= not dp_index; + dp_ready <= not dp_index; -- alternately request next double data word + fifo_filled <= '1'; + if to_uint(fifo_rd_usedw) < c_fifo_fill_level then + fifo_state <= s_fifo_low; + end if; + end case; + end if; + end process; + + ----------------------------------------------------------------------------- + -- Reclock sysref and the sync_n output + -- See: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_jesd204b.pdf + -- Figure 25, page 151 + ----------------------------------------------------------------------------- + p_reclocksysref : process (core_pll_locked, rxlink_clk) + begin + if core_pll_locked = '0' then + rxlink_sysref_1 <= '0'; + rxlink_sysref_2 <= '0'; + rxlink_sysref_3 <= '0'; + jesd204b_sync_n_arr <= (others => '0'); + elsif rising_edge(rxlink_clk) then + rxlink_sysref_1 <= jesd204b_sysref; + rxlink_sysref_2 <= rxlink_sysref_1; + rxlink_sysref_3 <= rxlink_sysref_2; + jesd204b_sync_n_arr <= jesd204b_sync_n_combined_arr; + end if; + end process; + + -- Make single rxlink_clk cycle pulse of rxlink_sysref_2 + rxlink_sysref <= rxlink_sysref_2 and not rxlink_sysref_3; + + -- IOPLL in source synchronous or normal mode. (Intel JESD204B-UG p66) + gen_jesd204b_rx_corepll_freqsel : if g_jesd_freq = "200MHz" generate + u_ip_arria10_e2sg_jesd204b_rx_corepll_200MHz : ip_arria10_e2sg_jesd204b_rx_core_pll_200MHz + port map ( + locked => core_pll_locked, + outclk_0 => rxlink_clk, -- out 100 MHz + outclk_1 => rxframe_clk, -- out 200 MHz + refclk => jesd204b_refclk, -- in 200 MHz + rst => pll_reset_arr(0) + ); + end generate; + + u_common_areset_wr_core_pll_locked : entity common_lib.common_areset + generic map ( + g_in_rst_level => '0', -- synchronises the rising edge of input in_rst. + g_rst_level => '0' + ) + port map ( + in_rst => core_pll_locked, + clk => rxlink_clk, + out_rst => wr_core_pll_locked + ); + + u_common_areset_mm_core_pll_locked : entity common_lib.common_areset + generic map ( + g_in_rst_level => '0', -- synchronises the rising edge of input in_rst. + g_rst_level => '0' + ) + port map ( + in_rst => core_pll_locked, + clk => mm_clk, + out_rst => mm_core_pll_locked + ); + + -- Transceiver reset controller. Use g_nof_streams out of 12 channels. Receive only + -- Clock set to 100MHz (use rxlink_clk) + + u_ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control : ip_arria10_e2sg_jesd204b_rx_xcvr_reset_control_12 + port map ( + clock => rxlink_clk, + reset => xcvr_rst_arr(0), -- From Reset Sequencer output1 as per example design, + -- the reset input is synchronised internally. + rx_analogreset => rx_analogreset_arr, -- output to reset RX PMA. Release before deasserting + -- link and avs resets (Intel JESD204B-UG p70) + rx_cal_busy => rx_cal_busy_arr, -- input from PHY + rx_digitalreset => rx_digitalreset_arr, -- output to reset RX PCS. Release before deasserting + -- link and avs resets (Intel JESD204B-UG p70) + rx_is_lockedtodata => rx_islockedtodata_arr, -- input from PHY + rx_ready => xcvr_rst_ctrl_rx_ready_arr -- From example design: gate with + -- rx_csr_lane_powerdown to reset transceiver + ); + end generate; -- gen_jesd204b_rx : IF g_direction = "RX_ONLY" GENERATE + + gen_enable_sync_n : for i in 0 to g_nof_streams - 1 generate + -- The sync_n_enabled output is active '0'. For disabled signal inputs the sync_n_enabled output + -- is forced to '1', so that for the disabled (= inactive = not used) + -- signal inputs the sync_n_internal from the JESD IP will not pull sync_n_enabled low. + -- The purpose of being able to disable inactive signal inputs is that this avoids that one + -- inactive signal input will cause all signal inputs in a group that share the sync_n_combined + -- to become unavailable (see gen_group_sync_n). + + -- For disabled channels (in jesd204b_disable_arr), the SYNC_N output will not be used + jesd204b_sync_n_enabled_arr(i) <= jesd204b_sync_n_internal_arr(i) or jesd204b_disable_arr(i); + end generate; + + ----------------------------------------------------------------------------- + -- Group the SYNC_N outputs + ----------------------------------------------------------------------------- + gen_group_sync_n : for i in 0 to g_nof_sync_n - 1 generate + jesd204b_sync_n_combined_arr(i) <= vector_and(jesd204b_sync_n_enabled_arr( + c_nof_sync_n_per_group * i + c_nof_sync_n_per_group - 1 downto + c_nof_sync_n_per_group * i)); + end generate; + + ----------------------------------------------------------------------------- + -- MM bus mux + ----------------------------------------------------------------------------- + u_common_mem_mux_mac : entity common_lib.common_mem_mux + generic map ( + g_nof_mosi => g_nof_streams, + g_mult_addr_w => c_jesd204b_mm_addr_w + ) + port map ( + mosi => jesd204b_mosi, + miso => jesd204b_miso, + mosi_arr => jesd204b_mosi_arr, + miso_arr => jesd204b_miso_arr + ); +end str; diff --git a/libraries/technology/jesd204b/hdllib.cfg b/libraries/technology/jesd204b/hdllib.cfg index 79a8465a5d6c85ac5bb1772d66cc98f605848739..79a10e579ad7c38d607d80a08de2a0bd765bc6a0 100644 --- a/libraries/technology/jesd204b/hdllib.cfg +++ b/libraries/technology/jesd204b/hdllib.cfg @@ -2,7 +2,7 @@ hdl_lib_name = tech_jesd204b hdl_library_clause_name = tech_jesd204b_lib hdl_lib_uses_synth = technology common dp ip_arria10_e1sg_jesd204b ip_arria10_e2sg_jesd204b hdl_lib_uses_ip = ip_arria10_e1sg_jesd204b ip_arria10_e2sg_jesd204b -hdl_lib_uses_sim = +hdl_lib_uses_sim = hdl_lib_technology = hdl_lib_disclose_library_clause_names = ip_arria10_e1sg_jesd204b ip_arria10_e1sg_jesd204b_180 @@ -14,16 +14,21 @@ synth_files = tech_jesd204b_arria10_e2sg.vhd tech_jesd204b_pkg.vhd tech_jesd204b.vhd + tech_jesd204b_arria10_e1sg_v2.vhd + tech_jesd204b_arria10_e2sg_v2.vhd + tech_jesd204b_v2.vhd test_bench_files = tech_jesd204b_tx.vhd tb_tech_jesd204b.vhd + tb_tech_jesd204b_v2.vhd -regression_test_vhdl = +regression_test_vhdl = tb_tech_jesd204b.vhd - + tb_tech_jesd204b_v2.vhd + [modelsim_project_file] modelsim_copy_files = wave_tb_tech_jesd204b.do . - + [quartus_project_file] diff --git a/libraries/technology/jesd204b/tb_tech_jesd204b.vhd b/libraries/technology/jesd204b/tb_tech_jesd204b.vhd index 47421d3e5d0aa7645b04034943f9126d892dc5bf..c3ee7ab19d2b84d001fc312e1786c798060c06c6 100644 --- a/libraries/technology/jesd204b/tb_tech_jesd204b.vhd +++ b/libraries/technology/jesd204b/tb_tech_jesd204b.vhd @@ -400,7 +400,7 @@ begin v_count := 0; else if rising_edge(jesd204b_sampclk) then - if (v_count = c_sysref_period - 1) then + if (v_count = c_sysref_period - 1) then v_count := 0; else v_count := v_count + 1; diff --git a/libraries/technology/jesd204b/tb_tech_jesd204b_v2.vhd b/libraries/technology/jesd204b/tb_tech_jesd204b_v2.vhd new file mode 100644 index 0000000000000000000000000000000000000000..4da60d79b3503244bdcbcc2bba437d62e4f7c352 --- /dev/null +++ b/libraries/technology/jesd204b/tb_tech_jesd204b_v2.vhd @@ -0,0 +1,532 @@ +------------------------------------------------------------------------------- +-- +-- 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: J Hargreaves, E. Kooistra +-- Purpose: Tb for tech_jesd204b IP +-- Description: +-- Includes 3 JESD transmit sources to test multichannel syncronization +-- Relative delays between TX and RX channels can be varied by editing c_delay_* +-- Used default technology e1sg +-- Remark: +-- . v2 uses FIFO in IP to get from rxlink_clk at 100 MHz to dp_clk at 200 MHz +-- . The self checking is minimal. It only checks that Tx data from the DAC in +-- the tb does come out the JESD Rx. Some more data and strobe testing would +-- be nice, but is not needed because it works on HW. +-- Usage: +-- Load sim # check that design can load in vsim +-- > as 3 # check that the hierarchy for g_design_name is complete (or use do wave_tb_tech_jesd204b.do) +-- > run -a # enough time to reset and syncronize the JESD IP + +library IEEE, common_lib, dp_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 common_lib.tb_common_pkg.all; +use common_lib.tb_common_mem_pkg.all; +use dp_lib.dp_stream_pkg.all; +use work.tech_jesd204b_component_pkg.all; +use work.tech_jesd204b_pkg.all; + +entity tb_tech_jesd204b_v2 is +end tb_tech_jesd204b_v2; + +architecture tb of tb_tech_jesd204b_v2 is + -- FALSE is use mm_clk in JESD IP, TRUE is use rxlink_clk as mm_clk in JESD IP + constant c_sim : boolean := false; -- use FALSE as on HW, to verify jesd204b_rddata + + constant c_jesd204b_sampclk_period : time := 5 ns; + constant c_bondingclk_period : time := 10 ns; + constant c_sysref_period : natural := 10000; -- number of sample clocks between sysref pulses + constant c_sysref_pulselength : natural := 7; -- number of sample clocks that sysref is high (>= 1) + + constant c_nof_jesd204b_tx : natural := 3; -- number of jesd204b input sources to instantiate + constant c_nof_streams_jesd204b : natural := 12; -- number of jesd204b receiver channels + + constant c_jesd204b_rx_data_w : natural := 32; + constant c_jesd204b_rx_somf_w : natural := c_jesd204b_rx_data_w / 8; -- One somf bit per octet + constant c_jesd204b_rx_framer_data_w : natural := c_jesd204b_rx_data_w / 2; -- IP outputs two samples in parallel + constant c_jesd204b_rx_framer_somf_w : natural := c_jesd204b_rx_somf_w / 2; -- IP outputs two samples in parallel + + -- Transport delays + type t_time_arr is array (0 to c_nof_streams_jesd204b - 1) of time; + constant c_delay_data_arr : t_time_arr := (4000 ps, + 5000 ps, + 6000 ps, + 5000 ps, + 5000 ps, + 5000 ps, + 5000 ps, + 5000 ps, + 5000 ps, + 5000 ps, + 5000 ps, + 5000 ps); -- transport delays tx to rx data + constant c_delay_sysreftoadc_arr : t_time_arr := (4000 ps, + 5000 ps, + 6000 ps, + 1000 ps, + 1000 ps, + 1000 ps, + 1000 ps, + 1000 ps, + 1000 ps, + 1000 ps, + 1000 ps, + 1000 ps); -- transport delays clock source to adc(tx) + constant c_delay_sysreftofpga : time := 10200 ps; + + -- clocks and resets for the jesd204b tx + signal txlink_clk : std_logic_vector(c_nof_jesd204b_tx - 1 downto 0); + signal dev_sync_n : std_logic_vector(c_nof_jesd204b_tx - 1 downto 0); + signal txphy_clk : std_logic_vector(c_nof_jesd204b_tx - 1 downto 0); + signal mm_rst : std_logic; + signal avs_rst_n : std_logic; + signal txlink_rst_n : std_logic; + signal tx_analogreset : std_logic_vector(0 downto 0); + signal tx_digitalreset : std_logic_vector(0 downto 0); + signal tx_bonding_clocks : std_logic_vector(5 downto 0) := (others => '0'); + signal bonding_clock_0 : std_logic := '0'; + signal bonding_clock_1 : std_logic := '0'; + signal bonding_clock_2 : std_logic := '0'; + signal bonding_clock_3 : std_logic := '0'; + signal bonding_clock_4 : std_logic := '0'; + signal bonding_clock_5 : std_logic := '0'; + signal pll_locked : std_logic_vector(0 downto 0); + + constant c_mm_clk_period : time := 20 ns; + signal mm_clk : std_logic := '0'; + + -- Tb + signal tb_end : std_logic := '0'; + signal tb_timeout : std_logic := '0'; + signal sim_done : std_logic := '0'; + + -- mm control buses + -- JESD + signal jesd204b_mosi : t_mem_mosi := c_mem_mosi_rst; + signal jesd204b_miso : t_mem_miso := c_mem_miso_rst; + signal jesd204b_rddata : std_logic_vector(c_word_w - 1 downto 0); + + -- serial transceivers + signal serial_tx : std_logic_vector(c_nof_jesd204b_tx - 1 downto 0); + signal bck_rx : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0) := (others => '0'); + + -- jesd204b syncronization signals and delayed copies + signal jesd204b_sysref : std_logic; + signal jesd204b_sampclk : std_logic := '0'; + signal dp_clk : std_logic := '0'; + signal dp_rst : std_logic := '0'; + signal dp_sysref : std_logic; + signal dp_sosi_arr : t_dp_sosi_arr(c_nof_streams_jesd204b - 1 downto 0); + + -- Debug signals for dp_sosi_arr + signal dp_sosi : t_dp_sosi; + signal dp_sosi_data : std_logic_vector(c_jesd204b_rx_framer_data_w - 1 downto 0); -- 16 bit samples + signal dp_sosi_channel : std_logic_vector(c_jesd204b_rx_framer_somf_w - 1 downto 0); -- two samples + signal dp_sosi_valid : std_logic; + signal dp_sosi_sync : std_logic; + signal dp_sosi_sop : std_logic; + signal dp_sosi_eop : std_logic; + signal dp_sosi_valid_arr : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + + signal jesd204b_sampclk_fpga : std_logic := '1'; + signal jesd204b_sampclk_adc : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal jesd204b_sysref_fpga : std_logic; + signal jesd204b_sysref_adc : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal jesd204b_sysref_adc_1 : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal jesd204b_sysref_adc_2 : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal jesd204b_sync_n_adc : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal jesd204b_sync_n_fpga : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + + -- Test bench data + signal jesd204b_tx_link_data_arr : t_slv_32_arr(c_nof_streams_jesd204b - 1 downto 0); + signal jesd204b_tx_link_valid : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal jesd204b_tx_link_ready : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal jesd204b_tx_frame_ready : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + + -- Diagnostic signals + signal avs_chipselect : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal avs_read : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); + signal avs_readdata : t_slv_32_arr(c_nof_streams_jesd204b - 1 downto 0); + signal avs_address : t_slv_8_arr(c_nof_streams_jesd204b - 1 downto 0); + + signal jesd204b_disable_arr : std_logic_vector(c_nof_streams_jesd204b - 1 downto 0); +begin + ---------------------------------------------------------------------------- + -- System setup + ---------------------------------------------------------------------------- + jesd204b_sampclk <= not jesd204b_sampclk after c_jesd204b_sampclk_period / 2; -- JESD sample clock (200MHz) + dp_clk <= jesd204b_sampclk; + dp_rst <= mm_rst; + mm_clk <= not mm_clk after c_mm_clk_period / 2; + mm_rst <= '1', '0' after 800 ns; + + jesd204b_disable_arr <= (others => '0'); + + ------------------------------------------------------------------------------ + -- DUT + ------------------------------------------------------------------------------ + u_jesd204b_v2 : entity work.tech_jesd204b_v2 + generic map( + g_sim => c_sim, + g_nof_streams => c_nof_streams_jesd204b, + g_nof_sync_n => c_nof_streams_jesd204b + ) + port map( + jesd204b_refclk => jesd204b_sampclk_fpga, + jesd204b_sysref => jesd204b_sysref_fpga, + jesd204b_sync_n_arr => jesd204b_sync_n_fpga, + + jesd204b_disable_arr => jesd204b_disable_arr, + + dp_clk => dp_clk, + dp_rst => dp_rst, + dp_sysref => dp_sysref, + dp_sosi_arr => dp_sosi_arr, + + -- MM + mm_clk => mm_clk, + mm_rst => mm_rst, + + jesd204b_mosi => jesd204b_mosi, + jesd204b_miso => jesd204b_miso, + + -- Serial + serial_tx_arr => open, + serial_rx_arr => bck_rx(c_nof_streams_jesd204b - 1 downto 0) + ); + + p_monitor_jesd204b : process + begin + -- Wait until after MM interface reset_out5 = rx_avs_rst_arr in ip_arria10_e2sg_jesd204b has been released + wait until sim_done = '1'; + proc_common_wait_some_cycles(mm_clk, 1); -- align with mm_clk domain + + proc_mem_mm_bus_rd(tech_jesd204b_field_rx_err_enable_adr, mm_clk, jesd204b_miso, jesd204b_mosi); + proc_common_wait_some_cycles(mm_clk, 1); + assert unsigned(jesd204b_rddata) = tech_jesd204b_field_rx_err_enable_reset + report "Wrong rx_err_enable_reset: " & integer'image(TO_SINT(jesd204b_rddata)) & " /= " & integer'image(tech_jesd204b_field_rx_err_enable_reset) severity ERROR; + + proc_mem_mm_bus_rd(tech_jesd204b_field_rx_err_link_reinit_adr, mm_clk, jesd204b_miso, jesd204b_mosi); + proc_common_wait_some_cycles(mm_clk, 1); + assert unsigned(jesd204b_rddata) = tech_jesd204b_field_rx_err_link_reinit_reset + report "Wrong rx_err_link_reinit_reset: " & integer'image(TO_SINT(jesd204b_rddata)) & " /= " & integer'image(tech_jesd204b_field_rx_err_link_reinit_reset) severity ERROR; + + proc_mem_mm_bus_rd(tech_jesd204b_field_rx_syncn_sysref_ctrl_adr, mm_clk, jesd204b_miso, jesd204b_mosi); + + proc_mem_mm_bus_rd(tech_jesd204b_field_rx_err0_adr, mm_clk, jesd204b_miso, jesd204b_mosi); + proc_mem_mm_bus_rd(tech_jesd204b_field_rx_err1_adr, mm_clk, jesd204b_miso, jesd204b_mosi); + proc_mem_mm_bus_rd(tech_jesd204b_field_csr_rbd_count_adr, mm_clk, jesd204b_miso, jesd204b_mosi); + proc_mem_mm_bus_rd(tech_jesd204b_field_csr_dev_syncn_adr, mm_clk, jesd204b_miso, jesd204b_mosi); + wait; + end process; + + jesd204b_rddata <= jesd204b_miso.rddata(c_word_w - 1 downto 0); + + ----------------------------------------------------------------------------- + -- Transport + ----------------------------------------------------------------------------- + + gen_transport : for i in 0 to c_nof_jesd204b_tx - 1 generate + jesd204b_sampclk_adc(i) <= transport jesd204b_sampclk after c_delay_sysreftoadc_arr(i); + jesd204b_sysref_adc(i) <= transport jesd204b_sysref after c_delay_sysreftoadc_arr(i); +-- txlink_clk(i) <= jesd204b_sampclk_div2 after c_delay_sysreftoadc_arr(i); + bck_rx(i) <= transport serial_tx(i) after c_delay_data_arr(i); + jesd204b_sync_n_adc(i) <= transport jesd204b_sync_n_fpga(i) after c_delay_data_arr(i); + end generate; + + jesd204b_sampclk_fpga <= transport jesd204b_sampclk after c_delay_sysreftofpga; + jesd204b_sysref_fpga <= transport jesd204b_sysref after c_delay_sysreftofpga; + + ----------------------------------------------------------------------------- + -- Use a jesd204b instance in TX-ONLY modeTransmit Only. + ----------------------------------------------------------------------------- + + gen_jesd204b_tx : for i in 0 to c_nof_jesd204b_tx - 1 generate + -- Tb DAC + u_tech_jesd204b_tx : entity work.tech_jesd204b_tx + port map ( + csr_cf => OPEN, + csr_cs => OPEN, + csr_f => OPEN, + csr_hd => OPEN, + csr_k => OPEN, + csr_l => OPEN, + csr_lane_powerdown => open, -- out + csr_m => OPEN, + csr_n => OPEN, + csr_np => OPEN, + csr_tx_testmode => OPEN, + csr_tx_testpattern_a => OPEN, + csr_tx_testpattern_b => OPEN, + csr_tx_testpattern_c => OPEN, + csr_tx_testpattern_d => OPEN, + csr_s => OPEN, + dev_sync_n => dev_sync_n(i), -- out + jesd204_tx_avs_chipselect => avs_chipselect(i), -- jesd204b_mosi_arr(i).chipselect, + jesd204_tx_avs_address => avs_address(i), + jesd204_tx_avs_read => avs_read(i), + jesd204_tx_avs_readdata => avs_readdata(i), + jesd204_tx_avs_waitrequest => open, + jesd204_tx_avs_write => '0', + jesd204_tx_avs_writedata => (others => '0'), + jesd204_tx_avs_clk => mm_clk, + jesd204_tx_avs_rst_n => avs_rst_n, + jesd204_tx_dlb_data => open, -- debug/loopback testing + jesd204_tx_dlb_kchar_data => open, -- debug/loopback testing + jesd204_tx_frame_ready => jesd204b_tx_frame_ready(i), + jesd204_tx_frame_error => '0', + jesd204_tx_int => OPEN, -- Connected to status IO in example design + jesd204_tx_link_data => jesd204b_tx_link_data_arr(i), -- in + jesd204_tx_link_valid => jesd204b_tx_link_valid(i), -- in + jesd204_tx_link_ready => jesd204b_tx_link_ready(i), -- out + mdev_sync_n => dev_sync_n(i), -- in + pll_locked => pll_locked, -- in + sync_n => jesd204b_sync_n_adc(i), -- in + tx_analogreset => tx_analogreset, + tx_bonding_clocks => tx_bonding_clocks, -- : in std_logic_vector(5 downto 0) := (others => 'X'); -- clk + tx_cal_busy => open, + tx_digitalreset => tx_digitalreset, + tx_serial_data => serial_tx(i downto i), + txlink_clk => txlink_clk(i), + txlink_rst_n_reset_n => txlink_rst_n, + txphy_clk => txphy_clk(i downto i), + somf => OPEN, + sysref => jesd204b_sysref_adc(i) + ); + + -- Generate test pattern at each ADC + proc_data : process (jesd204b_sampclk_adc(i), mm_rst) + variable v_data : integer := 0; + variable v_even_sample : boolean := true; + begin + if mm_rst = '1' then + jesd204b_tx_link_data_arr(i) <= (others => '0'); + jesd204b_tx_link_valid(i) <= '0'; + txlink_clk(i) <= '0'; + v_data := 0; + v_even_sample := true; + elsif rising_edge(jesd204b_sampclk_adc(i)) then + txlink_clk(i) <= not txlink_clk(i); + jesd204b_sysref_adc_1(i) <= jesd204b_sysref_adc(i); + jesd204b_sysref_adc_2(i) <= jesd204b_sysref_adc_1(i); + + --generate a positive and negative going pulse after the rising edge of SYSREF + if (jesd204b_sysref_adc(i) = '1' and jesd204b_sysref_adc_1(i) = '0') then + v_data := 1000; + elsif (jesd204b_sysref_adc_1(i) = '1' and jesd204b_sysref_adc_2(i) = '0') then + v_data := -1000; + else + v_data := 0; + end if; + + -- Frame the data to 32 bits at half the rate + if(jesd204b_tx_link_ready(i) = '0') then + v_even_sample := true; + else + v_even_sample := not v_even_sample; + end if; + if (v_even_sample = true) then + jesd204b_tx_link_data_arr(i)(15 downto 0) <= TO_SVEC(v_data, 16); + jesd204b_tx_link_valid(i) <= '0'; + else + jesd204b_tx_link_data_arr(i)(31 downto 16) <= TO_SVEC(v_data, 16); + jesd204b_tx_link_valid(i) <= '1'; + end if; + end if; + end process; + + end generate; + + ----------------------------------------------------------------------------- + -- Stimulii + ----------------------------------------------------------------------------- + + -- Clocks and resets + avs_rst_n <= '0', '1' after 23500 ns; + tx_analogreset(0) <= '1', '0' after 18500 ns; + tx_digitalreset(0) <= '1', '0' after 23000 ns; + txlink_rst_n <= '0', '1' after 25500 ns; + pll_locked(0) <= '0', '1' after 1000 ns; + + -- Create bonding clocks + -- The clock periods and offsets are copied from the JESD TX sample design + -- They are created directly to simplifiy the test bench + -- bonding_clock_1 has an uneven duty cycle + + bonding_clock_5 <= not bonding_clock_5 after 250 ps; + bonding_clock_4 <= not bonding_clock_4 after 250 ps; + bonding_clock_3 <= not bonding_clock_3 after 500 ps; + bonding_clock_2 <= not bonding_clock_2 after 500 ps; + bonding_clock_0 <= not bonding_clock_0 after 2500 ps; + + bonding_clock_1_process : process + begin + bonding_clock_1 <= '0'; + wait for 4000 ps; + bonding_clock_1 <= '1'; + wait for 1000 ps; + end process; + + tx_bonding_clocks(5) <= transport bonding_clock_5 after 4890 ps; + tx_bonding_clocks(4) <= transport bonding_clock_4 after 4640 ps; + tx_bonding_clocks(3) <= transport bonding_clock_3 after 4920 ps; + tx_bonding_clocks(2) <= transport bonding_clock_2 after 4930 ps; + tx_bonding_clocks(1) <= transport bonding_clock_1 after 7490 ps; + tx_bonding_clocks(0) <= transport bonding_clock_0 after 4000 ps; + + -- clock source process + -- generate the sysref pulses + proc_sysref : process (jesd204b_sampclk, mm_rst) + variable v_count : natural := 0; + begin + if mm_rst = '1' then + jesd204b_sysref <= '0'; + v_count := 0; + else + if rising_edge(jesd204b_sampclk) then + if (v_count = c_sysref_period - 1) then + v_count := 0; + else + v_count := v_count + 1; + end if; + + if v_count > c_sysref_period - 1 - c_sysref_pulselength then + jesd204b_sysref <= '1'; + else + jesd204b_sysref <= '0'; + end if; + end if; + end if; + end process; + + ------------------------------------------------------------------------------ + -- Diagnostics + -- Read registers in the tx jesd core to check it comes out of reset Ok + -- The meaning of specific register bits is defined in section 4.7.2 of the User Guide + -- https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_jesd204b.pdf + ------------------------------------------------------------------------------ + proc_read_avs_regs : process + begin + wait for 100 ns; + avs_address(0) <= (others => '0'); + avs_chipselect(0) <= '0'; + avs_read(0) <= '0'; + wait until avs_rst_n = '1'; + while true loop + wait until rising_edge(mm_clk); + avs_address(0) <= X"14"; -- dll control + avs_chipselect(0) <= '1'; + avs_read(0) <= '1'; + wait for c_mm_clk_period * 1; + wait until rising_edge(mm_clk); + avs_address(0) <= (others => '0'); + avs_chipselect(0) <= '0'; + avs_read(0) <= '0'; + wait for c_mm_clk_period * 32; + wait until rising_edge(mm_clk); + avs_address(0) <= X"15"; -- syncn_sysref control + avs_chipselect(0) <= '1'; + avs_read(0) <= '1'; + wait for c_mm_clk_period * 1; + wait until rising_edge(mm_clk); + avs_address(0) <= (others => '0'); + avs_chipselect(0) <= '0'; + avs_read(0) <= '0'; + wait for c_mm_clk_period * 32; + wait until rising_edge(mm_clk); + + avs_address(0) <= X"18"; -- syncn_sysref control + avs_chipselect(0) <= '1'; + avs_read(0) <= '1'; + wait for c_mm_clk_period * 1; + wait until rising_edge(mm_clk); + avs_address(0) <= (others => '0'); + avs_chipselect(0) <= '0'; + avs_read(0) <= '0'; + wait for c_mm_clk_period * 32; + wait until rising_edge(mm_clk); + avs_address(0) <= X"19"; -- syncn_sysref control + avs_chipselect(0) <= '1'; + avs_read(0) <= '1'; + wait for c_mm_clk_period * 1; + wait until rising_edge(mm_clk); + avs_address(0) <= (others => '0'); + avs_chipselect(0) <= '0'; + avs_read(0) <= '0'; + wait for c_mm_clk_period * 32; + wait until rising_edge(mm_clk); + + avs_address(0) <= X"20"; -- tx control0 + avs_chipselect(0) <= '1'; + avs_read(0) <= '1'; + wait for c_mm_clk_period * 1; + wait until rising_edge(mm_clk); + avs_address(0) <= (others => '0'); + avs_chipselect(0) <= '0'; + avs_read(0) <= '0'; + wait for c_mm_clk_period * 32; + wait until rising_edge(mm_clk); + avs_address(0) <= X"26"; -- tx control0 + avs_chipselect(0) <= '1'; + avs_read(0) <= '1'; + wait for c_mm_clk_period * 1; + wait until rising_edge(mm_clk); + avs_address(0) <= (others => '0'); + avs_chipselect(0) <= '0'; + avs_read(0) <= '0'; + wait for c_mm_clk_period * 32; + end loop; + end process; + + ------------------------------------------------------------------------------ + -- Debug signals + ------------------------------------------------------------------------------ + + -- Wire dp_sosi_arr(0), because for some reason dp_sosi_arr does not show with as in wave window + dp_sosi <= dp_sosi_arr(0); + dp_sosi_data <= dp_sosi.data(dp_sosi_data'range); + dp_sosi_channel <= dp_sosi.channel(dp_sosi_channel'range); + dp_sosi_valid <= dp_sosi.valid; + dp_sosi_sync <= dp_sosi.sync; + dp_sosi_sop <= dp_sosi.sop; + dp_sosi_eop <= dp_sosi.eop; + + dp_sosi_valid_arr <= func_dp_stream_arr_get(dp_sosi_arr, "VALID"); + + ------------------------------------------------------------------------------ + -- Simulation end + ------------------------------------------------------------------------------ + + sim_done <= '1' when dp_sosi_arr(0).valid = '1' and dp_sosi_arr(1).valid = '1' and dp_sosi_arr(2).valid = '1' else '0'; + + p_tb_end : process + begin + wait for 2 * c_sysref_period * c_jesd204b_sampclk_period; + + assert sim_done = '1' report "No rx samples were received." severity ERROR; + wait for 10 us; + tb_end <= '1'; + end process; + + proc_common_timeout_failure(200 us, tb_timeout); -- ERROR: end simulation if it fails to end in time + proc_common_stop_simulation(tb_end); -- OK: end simulation +end tb; diff --git a/libraries/technology/jesd204b/tech_jesd204b_arria10_e1sg_v2.vhd b/libraries/technology/jesd204b/tech_jesd204b_arria10_e1sg_v2.vhd new file mode 100644 index 0000000000000000000000000000000000000000..dfd1705abf98226374c5ae946be92d48fb5d4ad0 --- /dev/null +++ b/libraries/technology/jesd204b/tech_jesd204b_arria10_e1sg_v2.vhd @@ -0,0 +1,107 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. +-- +-------------------------------------------------------------------------------- + +-- Author: J Hargreaves, E. Kooistra +-- Purpose: Wrapper for the Intel Arria 10 e1sg (unb2b, unb2c) tecnology version of the +-- JESD204b interface for ADCs and DACs +-- Description +-- Current configuration supports 12 channels receive only +-- +-- . v2 uses FIFO in IP to get from rxlink_clk at 100 MHz to dp_clk at 200 MHz + +library IEEE, common_lib, dp_lib, technology_lib, ip_arria10_e1sg_jesd204b_lib; +use IEEE.std_logic_1164.all; +use technology_lib.technology_pkg.all; +use common_lib.common_pkg.all; +use common_lib.common_mem_pkg.all; +use dp_lib.dp_stream_pkg.all; +use work.tech_jesd204b_component_pkg.all; + +entity tech_jesd204b_arria10_e1sg_v2 is + generic ( + g_sim : boolean := false; + g_nof_streams : natural := 12; + g_nof_sync_n : natural := 12; + g_direction : string := "RX_ONLY"; -- "TX_RX", "TX_ONLY", "RX_ONLY" + g_jesd_freq : string := "200MHz" + ); + port ( + -- JESD204B external signals + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase wrt jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + + jesd204b_disable_arr : in std_logic_vector(g_nof_streams - 1 downto 0); + + -- Data to fabric + dp_clk : in std_logic; + dp_rst : in std_logic; + dp_sysref : out std_logic; -- = dp_sosi_arr(0).sync, all dp_sosi_arr().sync carry the dp_sysref + dp_sosi_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data and sync to fabric + + -- MM Control + mm_clk : in std_logic; + mm_rst : in std_logic; + + jesd204b_mosi : in t_mem_mosi; -- mm control + jesd204b_miso : out t_mem_miso; + + -- Serial connections to transceiver pins + serial_tx_arr : out std_logic_vector(g_nof_streams - 1 downto 0); -- Not used for ADC + serial_rx_arr : in std_logic_vector(g_nof_streams - 1 downto 0) + ); +end tech_jesd204b_arria10_e1sg_v2; + +architecture str of tech_jesd204b_arria10_e1sg_v2 is +begin + u_ip_arria10_e1sg_jesd204b_v2 : ip_arria10_e1sg_jesd204b_v2 + generic map( + g_sim => g_sim, + g_nof_streams => g_nof_streams, + g_nof_sync_n => g_nof_sync_n, + g_direction => g_direction, + g_jesd_freq => g_jesd_freq + ) + port map( + jesd204b_refclk => jesd204b_refclk, + jesd204b_sysref => jesd204b_sysref, + jesd204b_sync_n_arr => jesd204b_sync_n_arr, + + jesd204b_disable_arr => jesd204b_disable_arr, + + dp_clk => dp_clk, + dp_rst => dp_rst, + dp_sysref => dp_sysref, + dp_sosi_arr => dp_sosi_arr, + + -- MM + mm_clk => mm_clk, + mm_rst => mm_rst, + + jesd204b_mosi => jesd204b_mosi, + jesd204b_miso => jesd204b_miso, + + -- Serial + serial_tx_arr => serial_tx_arr, + serial_rx_arr => serial_rx_arr + ); +end str; diff --git a/libraries/technology/jesd204b/tech_jesd204b_arria10_e2sg_v2.vhd b/libraries/technology/jesd204b/tech_jesd204b_arria10_e2sg_v2.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a07c80d975782c8babeaf218fbf9b2b15c3cf0e7 --- /dev/null +++ b/libraries/technology/jesd204b/tech_jesd204b_arria10_e2sg_v2.vhd @@ -0,0 +1,107 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. +-- +-------------------------------------------------------------------------------- + +-- Author: J Hargreaves, E. Kooistra +-- Purpose: Wrapper for the Intel Arria 10 e2sg (unb2b, unb2c) tecnology version of the +-- JESD204b interface for ADCs and DACs +-- Description +-- Current configuration supports 12 channels receive only +-- +-- . v2 uses FIFO in IP to get from rxlink_clk at 100 MHz to dp_clk at 200 MHz + +library IEEE, common_lib, dp_lib, technology_lib, ip_arria10_e2sg_jesd204b_lib; +use IEEE.std_logic_1164.all; +use technology_lib.technology_pkg.all; +use common_lib.common_pkg.all; +use common_lib.common_mem_pkg.all; +use dp_lib.dp_stream_pkg.all; +use work.tech_jesd204b_component_pkg.all; + +entity tech_jesd204b_arria10_e2sg_v2 is + generic ( + g_sim : boolean := false; + g_nof_streams : natural := 12; + g_nof_sync_n : natural := 12; + g_direction : string := "RX_ONLY"; -- "TX_RX", "TX_ONLY", "RX_ONLY" + g_jesd_freq : string := "200MHz" + ); + port ( + -- JESD204B external signals + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase wrt jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + + jesd204b_disable_arr : in std_logic_vector(g_nof_streams - 1 downto 0); + + -- Data to fabric + dp_clk : in std_logic; + dp_rst : in std_logic; + dp_sysref : out std_logic; -- = dp_sosi_arr(0).sync, all dp_sosi_arr().sync carry the dp_sysref + dp_sosi_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data and sync to fabric + + -- MM Control + mm_clk : in std_logic; + mm_rst : in std_logic; + + jesd204b_mosi : in t_mem_mosi; -- mm control + jesd204b_miso : out t_mem_miso; + + -- Serial connections to transceiver pins + serial_tx_arr : out std_logic_vector(g_nof_streams - 1 downto 0); -- Not used for ADC + serial_rx_arr : in std_logic_vector(g_nof_streams - 1 downto 0) + ); +end tech_jesd204b_arria10_e2sg_v2; + +architecture str of tech_jesd204b_arria10_e2sg_v2 is +begin + u_ip_arria10_e2sg_jesd204b_v2 : ip_arria10_e2sg_jesd204b_v2 + generic map( + g_sim => g_sim, + g_nof_streams => g_nof_streams, + g_nof_sync_n => g_nof_sync_n, + g_direction => g_direction, + g_jesd_freq => g_jesd_freq + ) + port map( + jesd204b_refclk => jesd204b_refclk, + jesd204b_sysref => jesd204b_sysref, + jesd204b_sync_n_arr => jesd204b_sync_n_arr, + + jesd204b_disable_arr => jesd204b_disable_arr, + + dp_clk => dp_clk, + dp_rst => dp_rst, + dp_sysref => dp_sysref, + dp_sosi_arr => dp_sosi_arr, + + -- MM + mm_clk => mm_clk, + mm_rst => mm_rst, + + jesd204b_mosi => jesd204b_mosi, + jesd204b_miso => jesd204b_miso, + + -- Serial + serial_tx_arr => serial_tx_arr, + serial_rx_arr => serial_rx_arr + ); +end str; diff --git a/libraries/technology/jesd204b/tech_jesd204b_component_pkg.vhd b/libraries/technology/jesd204b/tech_jesd204b_component_pkg.vhd index 3661f25e565078f9cf693c7d68946687b9285f4a..9cbe9ea812051084e3cd645424d707cb9accdeb9 100644 --- a/libraries/technology/jesd204b/tech_jesd204b_component_pkg.vhd +++ b/libraries/technology/jesd204b/tech_jesd204b_component_pkg.vhd @@ -47,9 +47,12 @@ package tech_jesd204b_component_pkg is ); port ( -- JESD204B external signals - jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock reference pin - jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase wrt jesd204b_device_clk - jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock + -- reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with + -- respect to jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization / + -- syncronization phase -- Data to fabric rx_src_out_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data out to fabric @@ -72,6 +75,43 @@ package tech_jesd204b_component_pkg is ); end component; + component ip_arria10_e1sg_jesd204b_v2 is + generic ( + g_sim : boolean := false; + g_nof_streams : natural := 1; + g_nof_sync_n : natural := 1; + g_direction : string := "RX_ONLY"; -- "TX_RX", "TX_ONLY", "RX_ONLY" + g_jesd_freq : string := "200MHz" + ); + port ( + -- JESD204B external signals + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock + -- reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with + -- respect to jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization / + -- syncronization phase + + -- Data to fabric + dp_clk : in std_logic; + dp_rst : in std_logic; + dp_sysref : out std_logic; -- = dp_sosi_arr(0).sync, all dp_sosi_arr().sync carry the dp_sysref + dp_sosi_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data and sync to fabric + + -- MM Control + mm_clk : in std_logic; + mm_rst : in std_logic; + jesd204b_disable_arr : in std_logic_vector(g_nof_streams - 1 downto 0); + + jesd204b_mosi : in t_mem_mosi; -- mm control + jesd204b_miso : out t_mem_miso; + + -- Serial connections to transceiver pins + serial_tx_arr : out std_logic_vector(g_nof_streams - 1 downto 0); -- Not used for ADC + serial_rx_arr : in std_logic_vector(g_nof_streams - 1 downto 0) + ); + end component; + ------------------------------------------------------------------------------ -- TX ONLY, 1 channel ------------------------------------------------------------------------------ @@ -142,9 +182,12 @@ package tech_jesd204b_component_pkg is ); port ( -- JESD204B external signals - jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock reference pin - jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase wrt jesd204b_device_clk - jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock + -- reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with + -- respet to jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization / + -- syncronization phase -- Data to fabric rx_src_out_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data out to fabric @@ -167,6 +210,43 @@ package tech_jesd204b_component_pkg is ); end component; + component ip_arria10_e2sg_jesd204b_v2 is + generic ( + g_sim : boolean := false; + g_nof_streams : natural := 1; + g_nof_sync_n : natural := 1; + g_direction : string := "RX_ONLY"; -- "TX_RX", "TX_ONLY", "RX_ONLY" + g_jesd_freq : string := "200MHz" + ); + port ( + -- JESD204B external signals + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock + -- reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase with + -- respect to jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization / + -- syncronization phase + + -- Data to fabric + dp_clk : in std_logic; + dp_rst : in std_logic; + dp_sysref : out std_logic; -- = dp_sosi_arr(0).sync, all dp_sosi_arr().sync carry the dp_sysref + dp_sosi_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data and sync to fabric + + -- MM Control + mm_clk : in std_logic; + mm_rst : in std_logic; + jesd204b_disable_arr : in std_logic_vector(g_nof_streams - 1 downto 0); + + jesd204b_mosi : in t_mem_mosi; -- mm control + jesd204b_miso : out t_mem_miso; + + -- Serial connections to transceiver pins + serial_tx_arr : out std_logic_vector(g_nof_streams - 1 downto 0); -- Not used for ADC + serial_rx_arr : in std_logic_vector(g_nof_streams - 1 downto 0) + ); + end component; + -- TX ONLY, 1 channel component ip_arria10_e2sg_jesd204b_tx is port ( diff --git a/libraries/technology/jesd204b/tech_jesd204b_v2.vhd b/libraries/technology/jesd204b/tech_jesd204b_v2.vhd new file mode 100644 index 0000000000000000000000000000000000000000..f11c2502b5177fcce911f64b9df3c339aa48a27c --- /dev/null +++ b/libraries/technology/jesd204b/tech_jesd204b_v2.vhd @@ -0,0 +1,162 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. +-- +-------------------------------------------------------------------------------- + +-- Author : J Hargreaves, E. Kooistra +-- Purpose: Technology selection wrapper to instantiate +-- JESD204b interface for ADCs and DACs +-- Description: +-- +-- Select g_direction = RX_ONLY for ADC +-- IP settings are for the AD9683 ADC +-- Technology currently supported: Intel Arria 10 (e1sg, e2sg), unb2b, unb2c +-- +-- . For c_tech_arria10_e1sg: +-- +-- device_clk (ADC sample clock) --> +-- sysref (ADC 1PPS) --> +-- ___________________ +-- | | +-- tx_snk --->|tech_jesd204b |---> sync_n +-- rx_src <---|_arria10_e2sg_v2 |<--- serial_rx +-- |_________________| +-- | +-- | +-- mac_mm +-- +-- . v2 uses FIFO in IP to get from rxlink_clk at 100 MHz to dp_clk at 200 MHz + +library IEEE, common_lib, dp_lib, technology_lib; +use IEEE.std_logic_1164.all; +use technology_lib.technology_pkg.all; +use technology_lib.technology_select_pkg.all; +use common_lib.common_pkg.all; +use common_lib.common_mem_pkg.all; +use dp_lib.dp_stream_pkg.all; +use work.tech_jesd204b_component_pkg.all; + +entity tech_jesd204b_v2 is + generic ( + g_sim : boolean := false; + g_technology : natural := c_tech_select_default; + g_nof_streams : natural := 12; + g_nof_sync_n : natural := 12; + g_direction : string := "RX_ONLY"; -- "TX_RX", "TX_ONLY", "RX_ONLY" + g_jesd_freq : string := "200MHz" + ); + port ( + -- JESD204B external signals + jesd204b_refclk : in std_logic := '0'; -- Reference clock. For AD9683 use 200MHz direct from clock reference pin + jesd204b_sysref : in std_logic := '0'; -- SYSREF should drive ADC and FPGA with correct phase wrt jesd204b_device_clk + jesd204b_sync_n_arr : out std_logic_vector(g_nof_sync_n - 1 downto 0); -- output to control ADC initialization/syncronization phase + + jesd204b_disable_arr : in std_logic_vector(g_nof_streams - 1 downto 0); + + -- Data to fabric + dp_clk : in std_logic; + dp_rst : in std_logic; + dp_sysref : out std_logic; -- = dp_sosi_arr(0).sync, all dp_sosi_arr().sync carry the dp_sysref + dp_sosi_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0); -- Parallel data and sync to fabric + + -- MM Control + mm_clk : in std_logic; + mm_rst : in std_logic; + + jesd204b_mosi : in t_mem_mosi; -- mm control + jesd204b_miso : out t_mem_miso; + + -- Serial connections to transceiver pins + serial_tx_arr : out std_logic_vector(g_nof_streams - 1 downto 0); -- Not used for ADC + serial_rx_arr : in std_logic_vector(g_nof_streams - 1 downto 0) + ); +end tech_jesd204b_v2; + +architecture str of tech_jesd204b_v2 is +begin + gen_ip_arria10_e1sg_v2 : if g_technology = c_tech_arria10_e1sg generate + u0 : entity work.tech_jesd204b_arria10_e1sg_v2 + generic map( + g_sim => g_sim, + g_nof_streams => g_nof_streams, + g_nof_sync_n => g_nof_sync_n, + g_direction => g_direction, + g_jesd_freq => g_jesd_freq + ) + port map( + jesd204b_refclk => jesd204b_refclk, + jesd204b_sysref => jesd204b_sysref, + jesd204b_sync_n_arr => jesd204b_sync_n_arr, + + jesd204b_disable_arr => jesd204b_disable_arr, + + dp_clk => dp_clk, + dp_rst => dp_rst, + dp_sysref => dp_sysref, + dp_sosi_arr => dp_sosi_arr, + + -- MM + mm_clk => mm_clk, + mm_rst => mm_rst, + + jesd204b_mosi => jesd204b_mosi, + jesd204b_miso => jesd204b_miso, + + -- Serial + serial_tx_arr => serial_tx_arr, + serial_rx_arr => serial_rx_arr + ); + end generate; + + gen_ip_arria10_e2sg_v2 : if g_technology = c_tech_arria10_e2sg generate + u0 : entity work.tech_jesd204b_arria10_e2sg_v2 + generic map( + g_sim => g_sim, + g_nof_streams => g_nof_streams, + g_nof_sync_n => g_nof_sync_n, + g_direction => g_direction, + g_jesd_freq => g_jesd_freq + ) + port map( + jesd204b_refclk => jesd204b_refclk, + jesd204b_sysref => jesd204b_sysref, + jesd204b_sync_n_arr => jesd204b_sync_n_arr, + + jesd204b_disable_arr => jesd204b_disable_arr, + + dp_clk => dp_clk, + dp_rst => dp_rst, + dp_sysref => dp_sysref, + dp_sosi_arr => dp_sosi_arr, + + -- MM + mm_clk => mm_clk, + mm_rst => mm_rst, + + jesd204b_mosi => jesd204b_mosi, + jesd204b_miso => jesd204b_miso, + + -- Serial + serial_tx_arr => serial_tx_arr, + serial_rx_arr => serial_rx_arr + ); + end generate; + +end str;