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