From e98b6f48f36bd79aa71d3825410da1a28e6af958 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Tue, 6 Feb 2024 10:38:29 +0100 Subject: [PATCH] Add ip_arria10_e2sg_jesd204b_v2.vhd with clock domain crossing FIFO in IP --- .../ip_arria10_e2sg/jesd204b/hdllib.cfg | 5 +- .../jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd | 599 ++++++++++++++++++ 2 files changed, 602 insertions(+), 2 deletions(-) create mode 100644 libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd diff --git a/libraries/technology/ip_arria10_e2sg/jesd204b/hdllib.cfg b/libraries/technology/ip_arria10_e2sg/jesd204b/hdllib.cfg index 0872ac3932..81cfbf3b39 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_v2.vhd b/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd new file mode 100644 index 0000000000..381fd623ea --- /dev/null +++ b/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd @@ -0,0 +1,599 @@ +-------------------------------------------------------------------------------- +-- +-- 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 +-- 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 +-- + +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_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 + 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 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 : std_logic; + signal rxframe_rst_async_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal dpframe_rst_arr : std_logic_vector(g_nof_streams - 1 downto 0); + signal dpframe_rst : std_logic; + 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 core_pll_locked : 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; + + -- 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 rxlink_valid : std_logic; + signal jesd204b_rx_somf_arr : std_logic_vector(c_jesd204b_rx_somf_w * g_nof_streams - 1 downto 0); + signal rxlink_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0); + 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); + signal fifo_state : t_fifo_state_enum; + signal fifo_rd_usedw : std_logic_vector(ceil_log2(c_fifo_size) - 1 downto 0); + signal dp_toggle : std_logic := '0'; + signal dp_valid : std_logic := '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 + -- 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. + + -- 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_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 + ); + + -- Group jesd204b_rx_link data, valid and sync (= sysref) into rxlink_sosi_arr, + -- no need to transfer jesd204b rx_somf + 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_2; + rxlink_sosi_arr(i).valid <= rxlink_valid; + + -- 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; + + -- Combine into single valid if one or more inputs are valid, because all inputs are passed on + -- to dp_clk domain in parallel via a single FIFO + rxlink_valid <= vector_or(jesd204b_rx_link_valid_arr) when rising_edge(rxlink_clk); + + ----------------------------------------------------------------------------- + -- 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 => rxframe_rst_async_arr(i) + ); + + -- 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) + ); + + -- synchronize rxframe reset + u_common_areset_rxframe : entity common_lib.common_areset + port map ( + in_rst => rxframe_rst_async_arr(i), + clk => dp_clk, + out_rst => dpframe_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 dp_valid = '0' then + dp_sosi_arr(i) <= c_dp_sosi_rst; -- Force all to 0 when Rx JESD204B has stopped + else + dp_sosi_arr(i).valid <= '1'; + if dp_toggle = '1' then + dp_sosi_arr(i).sync <= dplink_sosi_arr(i).sync; + dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( + c_jesd204b_rx_data_w * i + c_jesd204b_rx_framer_data_w - 1 downto + c_jesd204b_rx_data_w * i)); + else + dp_sosi_arr(i).sync <= '0'; + dp_sosi_arr(i).data <= RESIZE_DP_SDATA(dplink_sosi_arr(i).data( + 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)); + end if; + end if; + end if; + end process; + end generate; -- gen_jesd204b_rx_channels : for I in 0 to g_nof_streams-1 generate + + -- Combine into single resets + rxlink_rst <= vector_or(rxlink_rst_arr) when rising_edge(rxlink_clk); + dpframe_rst <= vector_or(dpframe_rst_arr) when rising_edge(dp_clk); + + ----------------------------------------------------------------------------- + -- 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. + 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_framer_data_w, -- 16b + g_data_signed => true, + g_use_sync => true, + g_use_channel => false, -- no need to pass on jesd204b_rx_somf_arr + g_fifo_size => c_fifo_size + ) + port map ( + wr_rst => rxlink_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_toggle every dp_clk cycle to have the same read rate in dp_clk domain, + -- as the write rate in rxlink_clk domain. + -- Use finite state machine to fill the FIFO with fill margin above a nominal FIFO + -- fill level, so that the dp_toggle keep on toggling once it has started, as long + -- as the input rxlink_sosi_arr(0).valid is active. 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. + dplink_siso_arr <= func_dp_stream_arr_set(dplink_siso_arr, dp_toggle, "READY"); + + p_fsm_dp_toggle : process(dp_rst, dp_clk) + begin + if dp_rst = '1' then + dp_toggle <= '0'; + dp_valid <= '0'; + fifo_state <= s_fifo_low; + elsif rising_edge(dp_clk) then + case fifo_state is + when s_fifo_low => + dp_toggle <= '0'; + dp_valid <= '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_toggle <= not dp_toggle; + dp_valid <= '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'; + jesd204b_sync_n_arr <= (others => '0'); + 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; + + -- 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_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; -- GitLab