From 22a727a7815ba97b1b84ee2cf99836bcb4a3cb6d Mon Sep 17 00:00:00 2001
From: Frans Schreuder <f.schreuder@nikhef.nl>
Date: Tue, 21 Dec 2021 15:58:52 +0100
Subject: [PATCH] Removed reset of the FIFO (FULL Mode) when link is not
 aligned. This should fix FLX-1758

---
 .../UVVMExample/tb/FULLModeToHost_tb.vhd      |   3 +-
 .../FullModeDataEmulator.vhd                  |   5 +-
 sources/centralRouter/thFMdm.vhd              | 959 +++++++++---------
 sources/decoding/FullToAxis.vhd               |  42 +-
 4 files changed, 496 insertions(+), 513 deletions(-)

diff --git a/simulation/UVVMExample/tb/FULLModeToHost_tb.vhd b/simulation/UVVMExample/tb/FULLModeToHost_tb.vhd
index 3218d5238..bc9386374 100644
--- a/simulation/UVVMExample/tb/FULLModeToHost_tb.vhd
+++ b/simulation/UVVMExample/tb/FULLModeToHost_tb.vhd
@@ -269,7 +269,8 @@ port map(
      generic map(
         do_implement => true,
         use_blockram => false,
-        Phase2CRToHost_FM => true
+        Phase2CRToHost_FM => true,
+        START_WITH_SOME_JUNK => '0'
      )
      port map(
          appreg_clk                         => appreg_clk,--: in  std_logic;
diff --git a/sources/FullModeDataEmulator/FullModeDataEmulator.vhd b/sources/FullModeDataEmulator/FullModeDataEmulator.vhd
index 36821a280..724fcf7d2 100644
--- a/sources/FullModeDataEmulator/FullModeDataEmulator.vhd
+++ b/sources/FullModeDataEmulator/FullModeDataEmulator.vhd
@@ -42,7 +42,8 @@ entity FullModeDataEmulator is
 generic (
     do_implement : boolean := true;
     use_blockram: boolean := true;
-    Phase2CRToHost_FM : boolean := false
+    Phase2CRToHost_FM : boolean := false;
+    START_WITH_SOME_JUNK: std_logic := '0'
     );
 port (
     appreg_clk                         : in  std_logic;
@@ -312,7 +313,7 @@ begin
             else
                 if cnt < 300000 then
                     cnt := cnt + 1;
-                    generate_junk <= '1';
+                    generate_junk <= START_WITH_SOME_JUNK;
                 else
                     generate_junk <= '0';
                 end if;
diff --git a/sources/centralRouter/thFMdm.vhd b/sources/centralRouter/thFMdm.vhd
index 71634472c..da434a6a8 100644
--- a/sources/centralRouter/thFMdm.vhd
+++ b/sources/centralRouter/thFMdm.vhd
@@ -19,485 +19,480 @@
 --!   See the License for the specific language governing permissions and
 --!   limitations under the License.
 
-----------------------------------------------------------------------------------
---! Company:  EDAQ WIS.  
---! Engineer: juna
---! 
---! Create Date:    12/09/2016  
---! Module Name:    thFMdm
---! Project Name:   FELIX
-----------------------------------------------------------------------------------
---! Use standard library
-library IEEE, work;
-use IEEE.std_logic_1164.all;
-use IEEE.numeric_std.all;
-use IEEE.std_logic_unsigned.all;
-use work.pcie_package.all;
-use work.centralRouter_package.all;
-use work.all;
-library xpm;
-use xpm.vcomponents.all;
-use work.axi_stream_package.all;
-
---! to-Host centralRouter logic
-
-entity thFMdm is
-generic (
-    FMCHid                  : integer := 0;
-    FIRMWARE_MODE           : integer := 1;
-    STATIC_CENTRALROUTER    : boolean := false;  -- removes update process from central router register map, only initial constant values are used
-    toHostTimeoutBitn       : integer := 8;
-    SUPER_CHUNK_FACTOR      : integer := 1;
-    BLOCKSIZE               : integer := 1024;
-    CHUNK_TRAILER_32B       : boolean := false;
-    Phase2CRToHost_FM       : boolean := false
-    );
-port  ( 
-    clk40       : in  std_logic;   
-    clk250      : in  std_logic;       
-    clk_wrth    : in  std_logic;    -- clock for write to host (fifo)
-    rst40       : in  std_logic;   
-    rst250      : in  std_logic;
-    clk240      : in  std_logic;   
-    register_map_control               : in  register_map_control_type; --! configuration settings, 64 bit per EGROUP (7 EGROUPS total)
-    register_map_control_appreg_clk    : in  register_map_control_type; --! configuration settings, 64 bit per EGROUP (7 EGROUPS total)
-    appreg_clk                         : in  std_logic;
-    -- RX side
-    FMCHdin         : in std_logic_vector(31 downto 0); -- 32 bit
-    FMCHdtype       : in std_logic; -- isK-array, indicates if the lowest byte is a K-character
-    FMCHlink_valid  : in std_logic;    
-    FM_Emu_dout     : in  std_logic_vector(32 downto 0); --FULL mode data emulator output, fanout selector in FMdm for phase 2 axi stream implementation.   
-    -- wupper side: 
-    -- 1. read from specified channel
-    fmchFifo_flush      : in  std_logic;
-    fmchFifo_re         : in  std_logic;
-    fmchFifo_dout       : out std_logic_vector (255 downto 0);
-    fmchFifo_dvalid     : out std_logic;
-    fmchFifo_hasBlock   : out std_logic; -- out, 'block_ready' flag
-    fmchXoffout         : out std_logic; -- out test purposes only, flag to a data source to stop transmitting
-    fmchHighThreshCrossed      : out std_logic;
-    fmchHighThreshCrossedLatch : out std_logic;
-    fmchLowThreshCrossed       : out std_logic;
-    --fmchXoffin          : in  std_logic; -- in, crOUTfifo is pfull 4060/3830 (out of 4096), stop writing flag 
-    fmch_monitor        : out std_logic_vector (7 downto 0); -- out
-    fmch_busy           : out std_logic; -- one busy bit per fm channel
-    rxusrclk            : in std_logic  
-    );
-end thFMdm;
-
-architecture Behavioral of thFMdm is
-
---
-component FMwmfifo16KB_32to256 -- IP
-port (
-    wr_clk      : in std_logic;
-    rd_clk      : in std_logic;
-    rst        : in std_logic;
-    din         : in std_logic_vector(31 downto 0);
-    wr_en       : in std_logic;
-    rd_en       : in std_logic;
-    dout        : out std_logic_vector(255 downto 0);
-    valid       : out std_logic;
-    full        : out std_logic;
-    empty       : out std_logic;
-    prog_full   : out std_logic; -- '1' when a space for only one block is left (threshold 3580/3581)
-    prog_empty  : out std_logic;  -- '1' when less then one block is written (threshold 31/32)
-    wr_data_count : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
-    prog_empty_thresh : in std_logic_vector(8 downto 0);
-    prog_full_thresh  : in std_logic_vector(11 downto 0)
-    );
-end component;
---
---
-signal fmch_ena_reg  : std_logic;
-signal fmch_ena         : std_logic;
---
---signal timeCnt          : std_logic_vector ((toHostTimeoutBitn-1) downto 0);
-signal timeCnt_max    : std_logic_vector ((toHostTimeoutBitn-1) downto 0);
-signal timeCnt_ena    : std_logic;
---
---signal chINfifo_dout36  : std_logic_vector(35 downto 0);
---signal chINfifo_re,chINfifo_empty,chINfifo_valid : std_logic;
-signal chFIFO_full, chFIFO_pfull, chFIFO_pfull_r1 : std_logic;
-signal chFIFO_empty, chFIFO_pempty  : std_logic;
-signal chFIFO_din32_rdy, ch_xoff  : std_logic;
-signal chFIFO_din32     : std_logic_vector(31 downto 0);
-signal chFIFO_dout_s    : std_logic_vector(255 downto 0);
-signal chfifo_driver_din  : std_logic_vector(32 downto 0);
---
-signal wr_data_count      : std_logic_vector(3 downto 0);
-
-signal xoff_threshold_low  : std_logic_vector(3 downto 0);
-signal xoff_threshold_high : std_logic_vector(3 downto 0);
-signal xoff_clear_latch    : std_logic;
-signal xoff_threshold_low_clk_wrth : std_logic_vector(3 downto 0);
-signal xoff_threshold_high_clk_wrth : std_logic_vector(3 downto 0);
-signal xoff_clear_latch_clk_wrth : std_logic;
-
-begin
-
-fmchFifo_dout <= 
-  chFIFO_dout_s(31  downto 0)   &
-  chFIFO_dout_s(63  downto 32)  &
-  chFIFO_dout_s(95  downto 64)  &
-  chFIFO_dout_s(127 downto 96)  &
-  chFIFO_dout_s(159 downto 128) &
-  chFIFO_dout_s(191 downto 160) &
-  chFIFO_dout_s(223 downto 192) &
-  chFIFO_dout_s(255 downto 224);  -- swap 32bit word order
-
-fmchFifo_hasBlock <= '1' when (chFIFO_pempty = '0' and fmchFifo_flush = '0') else '0';
-  -- chFIFO_pempty is '0' when there is at least one whole block in the fifo
-
-fmch_monitor <= "0000000" & ch_xoff;
-
-------------------------------------------------------------
--- configuration registers map
-------------------------------------------------------------
-cfg0: entity work.crTHFMconfigMap
-generic map (
-    FMCHid                  => FMCHid,
-    toHostTimeoutBitn       => toHostTimeoutBitn
-    )
-port  map ( 
-    register_map_control_appreg_clk    => register_map_control_appreg_clk, 
-    appreg_clk                         => appreg_clk,
-    clk250 => clk250,
-    -----
-    path_ena      => fmch_ena_reg,
-    timeCnt_ena             => timeCnt_ena,
-    timeCnt_max             => timeCnt_max
-    );
-
-
-
-------------------------------------------------------------
--- to-Host GBT channel of 'FMCHid' timeout counter
-------------------------------------------------------------
---TOUTcnt: entity work.counterNbit 
---generic map(N=>toHostTimeoutBitn)
---port map (
---    clk        => clk40,		     
---	rst        => rst,
---	ce         => timeCnt_ena, -- 
---	count_max  => timeCnt_max, -- 
---	count_out  => timeCnt
---);
---
-
-------------------------------------------------------------
--- downstream full mode channel input fifo
-------------------------------------------------------------
---chINfifo: thFMch_input_fifo -- IP 
---port map (
---    wr_rst  => fmchFifo_flush,
---    wr_clk  => clk240,
---    wr_en   => fmch_ena,
---    din     => "000" & FMCHdtype & FMCHdin,
---    full    => open, -- can't be full
---    --
---    rd_rst  => fmchFifo_flush,    
---    rd_clk  => clk250,
---    rd_en   => chINfifo_re,
---    dout    => chINfifo_dout36,
---    empty   => chINfifo_empty,
---    valid   => chINfifo_valid    
---    );
---    
---chINfifo_re <= not chINfifo_empty;
-
-------------------------------------------------------------
---  full mode channel FIFO driver
-------------------------------------------------------------
-chfifo_driver_din <= FMCHdtype & FMCHdin;
-
-g_ph1: if Phase2CRToHost_FM = false generate
-
-fmch_ena <= '1' when (fmch_ena_reg = '1' and FMCHlink_valid = '1') else '0';
-
-chFIFOdriver: entity work.thFMch_fifo_driver 
-generic map(
-    FMCHid              => FMCHid,
-    FIRMWARE_MODE       => FIRMWARE_MODE,
-    toHostTimeoutBitn   => toHostTimeoutBitn,
-    SUPER_CHUNK_FACTOR  => SUPER_CHUNK_FACTOR,
-    BLOCKSIZE           => BLOCKSIZE,
-    CHUNK_TRAILER_32B   => CHUNK_TRAILER_32B
-    )
-port map (
-    clk250          => clk_wrth,        -- write to host clock
-    rst250             => rst250,
-    din_rdy         => fmch_ena,
-    din             => chfifo_driver_din,
-    timeOutEna_i    => timeCnt_ena,
-    timeCnt_max     => timeCnt_max,
-    busy_o          => fmch_busy,
-    xoff            => ch_xoff, -- in, downstream wm fifo is full or main , can't happen in normal operation
-    word32out       => chFIFO_din32,    -- to chFIFO
-    word32out_rdy   => chFIFO_din32_rdy -- to chFIFO
-    );
-end generate g_ph1;
-
-g_ph2: if Phase2CRToHost_FM generate
-component FullToAxis is
-    generic(
-      BLOCKSIZE : integer
-    );
-port (
-  clk240 : in std_logic;
-  FMdin : in std_logic_vector(32 downto 0);
-  LinkAligned : in std_logic;
-  aclk : in std_logic;
-  aresetn : in std_logic;
-  m_axis : out axis_32_type;
-  m_axis_tready : in std_logic;
-  m_axis_prog_empty : out std_logic;
-  path_ena : in std_logic;
-  super_chunk_factor_link : in unsigned(7 downto 0);
-  Use32bSOP : in std_logic
-  );
-end component FullToAxis;
-component ToHostAxiStreamController is
-generic (
-    FMCHid                  : integer := 0;
-    toHostTimeoutBitn       : integer := 8;
-    BLOCKSIZE           : integer := 1024;
-    CHUNK_TRAILER_32B   : boolean := false;
-    STREAMS_TOHOST      : integer := 1
-    );
-port ( 
-    aclk        : in  std_logic;
-    aresetn     : in  std_logic;
-    
-    s_axis_in            : in axis_32_array_type(0 to STREAMS_TOHOST-1);
-    s_axis_tready_out    : out axis_tready_array_type(0 to STREAMS_TOHOST-1);
-    s_axis_prog_empty_in : in axis_tready_array_type(0 to STREAMS_TOHOST-1);
-    
-    timeOutEna_i    : in  std_logic;
-    timeCnt_max     : in  std_logic_vector ((toHostTimeoutBitn-1) downto 0);
-    prog_full_in    : in  std_logic;-- in, downstream wm fifo is full or main , can't happen in normal operation     
-    ----------
-    word32out       : out std_logic_vector (31 downto 0); -- to chFIFO
-    word32out_valid   : out std_logic
-    );
-end component ToHostAxiStreamController;
-  signal aresetn: std_logic;
-  signal decoding_axis : axis_32_type;
-  signal decoding_axis_tready : std_logic;
-  signal decoding_axis_prog_empty : std_logic;
-  signal emu_axis : axis_32_type;
-  signal emu_axis_tready : std_logic;
-  signal emu_axis_prog_empty : std_logic;
-  signal fanout_sel_axis : axis_32_type;
-  signal fanout_sel_axis_tready : std_logic;
-  signal fanout_sel_axis_prog_empty : std_logic;
-  signal fosel_r, fosel_aclk: std_logic;
-begin  
- fmch_ena <= '1' when (fmch_ena_reg = '1' and (FMCHlink_valid = '1' or fosel_r = '1')) else '0';
-
- aresetn <= not rst250;
-toaxis0: FullToAxis 
-    generic map(
-      BLOCKSIZE => BLOCKSIZE
-    )
-port map(
-  clk240 => rxusrclk,
-  FMdin => chfifo_driver_din,
-  LinkAligned => FMCHlink_valid,
-  aclk => clk_wrth,
-  aresetn => aresetn,
-  m_axis => decoding_axis,
-  m_axis_tready => decoding_axis_tready,
-  m_axis_prog_empty => decoding_axis_prog_empty,
-  path_ena => fmch_ena,
-  super_chunk_factor_link => x"01",
-  Use32bSOP => register_map_control_appreg_clk.FULLMODE_32B_SOP(0)
-  );
-  
- emu_toaxis0: FullToAxis 
-    generic map(
-      BLOCKSIZE => BLOCKSIZE
-    )
-port map(
-  clk240 => clk240,
-  FMdin => FM_Emu_dout,
-  LinkAligned => fosel_aclk,
-  aclk => clk_wrth,
-  aresetn => aresetn,
-  m_axis => emu_axis,
-  m_axis_tready => emu_axis_tready,
-  m_axis_prog_empty => emu_axis_prog_empty,
-  path_ena => fmch_ena,
-  super_chunk_factor_link => x"01",
-  Use32bSOP => register_map_control_appreg_clk.FULLMODE_32B_SOP(0)
-  );
-  
-   xpm_cdc_single_fosel0 : xpm_cdc_single
-   generic map (
-      DEST_SYNC_FF => 2,
-      INIT_SYNC_FF => 0,
-      SIM_ASSERT_CHK => 0,
-      SRC_INPUT_REG => 1
-   )
-   port map (
-      dest_out => fosel_aclk,
-      dest_clk => clk_wrth,
-      src_clk => appreg_clk,
-      src_in => fosel_r
-   );
-   
-   fosel_r <= register_map_control_appreg_clk.GBT_TOHOST_FANOUT.SEL(FMCHid);
-        
-
-  
-  decoding_axis_tready <= fanout_sel_axis_tready;
-  emu_axis_tready <= fanout_sel_axis_tready;
-    
-  fanout: process(fanout_sel_axis_tready, fosel_aclk, emu_axis, decoding_axis, emu_axis_prog_empty, decoding_axis_prog_empty)
-  begin
-      if fosel_aclk = '1' then --use emulator data
-        fanout_sel_axis <= emu_axis;
-      else          --use frontend link data
-        fanout_sel_axis <= decoding_axis;
-      end if;
-      if fosel_aclk = '1' then --use emulator data
-        fanout_sel_axis_prog_empty <= emu_axis_prog_empty;
-      else          --use frontend link data
-        fanout_sel_axis_prog_empty <= decoding_axis_prog_empty;
-      end if;
-  end process;
-  
-  streamctrl0: ToHostAxiStreamController 
-generic map(
-    FMCHid => FMCHid,
-    toHostTimeoutBitn => toHostTimeoutBitn,
-    BLOCKSIZE         => BLOCKSIZE,
-    CHUNK_TRAILER_32B => CHUNK_TRAILER_32B,
-    STREAMS_TOHOST    => 1
-    )
-port map( 
-    aclk        => clk_wrth,
-    aresetn     => aresetn,
-    
-    s_axis_in(0) => fanout_sel_axis,
-    s_axis_tready_out(0)  => fanout_sel_axis_tready,
-    s_axis_prog_empty_in(0) => fanout_sel_axis_prog_empty,
-    
-    timeOutEna_i    => timeCnt_ena,
-    timeCnt_max     => timeCnt_max,
-    prog_full_in    => ch_xoff, 
-    word32out       => chFIFO_din32,
-    word32out_valid => chFIFO_din32_rdy
-    );    
-  
-end generate g_ph2;
---
-------------------------------------------------------------
--- global Downstream data truncation in case of  
--- wm-fifo full or external xoff (DMA stopped reading?)
-------------------------------------------------------------
-pr1: process(clk_wrth)                  -- write to host clock
-begin
-    if rising_edge(clk_wrth) then
-        chFIFO_pfull_r1 <= chFIFO_pfull;
-    end if;
-end process;
-
-ch_xoff <= '1' when (chFIFO_pfull='1' or chFIFO_pfull_r1='1') else '0'; -- or fmchXoffin;
-
---
-------------------------------------------------------------
---  full mode channel FIFO
-------------------------------------------------------------
-chFIFO: FMwmfifo16KB_32to256 -- IP
-port map (
-    wr_clk      => clk_wrth,            -- write to host clock
-    rd_clk      => clk250,
-    rst         => fmchFifo_flush,
-    din         => chFIFO_din32,
-    wr_en       => chFIFO_din32_rdy,
-    rd_en       => fmchFifo_re,
-    dout        => chFIFO_dout_s, -- 256 bit
-    full        => chFIFO_full,
-    empty       => chFIFO_empty,
-    valid       => fmchFifo_dvalid,
-    prog_full   => chFIFO_pfull, -- '1' when a space for only one block is left (threshold 3580/3581)
-    prog_empty  => chFIFO_pempty, -- '1' when less then one block is written (threshold 31/32)
-    wr_data_count => wr_data_count,
-    prog_full_thresh  => std_logic_vector(to_unsigned(4093-(BLOCKSIZE/2), 12)),
-    prog_empty_thresh => std_logic_vector(to_unsigned((BLOCKSIZE/32)-1, 9))
-    );
-
-xoff_threshold_low  <= register_map_control_appreg_clk.XOFF_FM_CH_FIFO_THRESH_LOW;
-xoff_threshold_high <= register_map_control_appreg_clk.XOFF_FM_CH_FIFO_THRESH_HIGH;
-xoff_clear_latch    <= to_sl(register_map_control_appreg_clk.XOFF_FM_HIGH_THRESH.CLEAR_LATCH);
-
-xpm_cdc_array_single_inst_threshold_low : xpm_cdc_array_single
-   generic map (
-      DEST_SYNC_FF => 2,
-      INIT_SYNC_FF => 0,
-      SIM_ASSERT_CHK => 0,
-      SRC_INPUT_REG => 1,
-      WIDTH => 4
-   )
-   port map (
-      dest_out => xoff_threshold_low_clk_wrth,
-      dest_clk => clk_wrth,
-      src_clk => appreg_clk,
-      src_in => xoff_threshold_low
-   );
-   
-xpm_cdc_array_single_inst_threshold_high : xpm_cdc_array_single
-   generic map (
-      DEST_SYNC_FF => 2,
-      INIT_SYNC_FF => 0,
-      SIM_ASSERT_CHK => 0,
-      SRC_INPUT_REG => 1,
-      WIDTH => 4
-   )
-   port map (
-      dest_out => xoff_threshold_high_clk_wrth,
-      dest_clk => clk_wrth,
-      src_clk => appreg_clk,
-      src_in => xoff_threshold_high
-   );
-   
-xpm_cdc_single_inst : xpm_cdc_single
-   generic map (
-      DEST_SYNC_FF => 2,
-      INIT_SYNC_FF => 0,
-      SIM_ASSERT_CHK => 0,
-      SRC_INPUT_REG => 1
-   )
-   port map (
-      dest_out => xoff_clear_latch_clk_wrth,
-      dest_clk => clk_wrth,
-      src_clk => appreg_clk,
-      src_in => xoff_clear_latch
-   );
-
-pr2: process(clk_wrth)                  -- fifo write clock
-begin
-    if rising_edge(clk_wrth) then
-        if(wr_data_count > xoff_threshold_high_clk_wrth) then
-            fmchXoffout <= '1';
-            fmchHighThreshCrossed <= '1';
-            fmchHighThreshCrossedLatch <= '1';
-        else
-            fmchHighThreshCrossed <= '0';
-        end if;
-        if(xoff_clear_latch_clk_wrth='1') then
-            fmchHighThreshCrossedLatch <= '0';
-        end if;
-        if(wr_data_count < xoff_threshold_low_clk_wrth) then
-            fmchXoffout <= '0';
-            fmchLowThreshCrossed <= '0';
-        else
-            fmchLowThreshCrossed <= '1';
-        end if;
-        --fmchXoffout <= chFIFO_pfull;
-    end if;
-end process;
-
-end Behavioral;
-
+----------------------------------------------------------------------------------
+--! Company:  EDAQ WIS.  
+--! Engineer: juna
+--! 
+--! Create Date:    12/09/2016  
+--! Module Name:    thFMdm
+--! Project Name:   FELIX
+----------------------------------------------------------------------------------
+--! Use standard library
+library IEEE, work;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+use IEEE.std_logic_unsigned.all;
+use work.pcie_package.all;
+use work.centralRouter_package.all;
+use work.all;
+library xpm;
+use xpm.vcomponents.all;
+use work.axi_stream_package.all;
+
+--! to-Host centralRouter logic
+
+entity thFMdm is
+generic (
+    FMCHid                  : integer := 0;
+    FIRMWARE_MODE           : integer := 1;
+    STATIC_CENTRALROUTER    : boolean := false;  -- removes update process from central router register map, only initial constant values are used
+    toHostTimeoutBitn       : integer := 8;
+    SUPER_CHUNK_FACTOR      : integer := 1;
+    BLOCKSIZE               : integer := 1024;
+    CHUNK_TRAILER_32B       : boolean := false;
+    Phase2CRToHost_FM       : boolean := false
+    );
+port  ( 
+    clk40       : in  std_logic;   
+    clk250      : in  std_logic;       
+    clk_wrth    : in  std_logic;    -- clock for write to host (fifo)
+    rst40       : in  std_logic;   
+    rst250      : in  std_logic;
+    clk240      : in  std_logic;   
+    register_map_control               : in  register_map_control_type; --! configuration settings, 64 bit per EGROUP (7 EGROUPS total)
+    register_map_control_appreg_clk    : in  register_map_control_type; --! configuration settings, 64 bit per EGROUP (7 EGROUPS total)
+    appreg_clk                         : in  std_logic;
+    -- RX side
+    FMCHdin         : in std_logic_vector(31 downto 0); -- 32 bit
+    FMCHdtype       : in std_logic; -- isK-array, indicates if the lowest byte is a K-character
+    FMCHlink_valid  : in std_logic;    
+    FM_Emu_dout     : in  std_logic_vector(32 downto 0); --FULL mode data emulator output, fanout selector in FMdm for phase 2 axi stream implementation.   
+    -- wupper side: 
+    -- 1. read from specified channel
+    fmchFifo_flush      : in  std_logic;
+    fmchFifo_re         : in  std_logic;
+    fmchFifo_dout       : out std_logic_vector (255 downto 0);
+    fmchFifo_dvalid     : out std_logic;
+    fmchFifo_hasBlock   : out std_logic; -- out, 'block_ready' flag
+    fmchXoffout         : out std_logic; -- out test purposes only, flag to a data source to stop transmitting
+    fmchHighThreshCrossed      : out std_logic;
+    fmchHighThreshCrossedLatch : out std_logic;
+    fmchLowThreshCrossed       : out std_logic;
+    --fmchXoffin          : in  std_logic; -- in, crOUTfifo is pfull 4060/3830 (out of 4096), stop writing flag 
+    fmch_monitor        : out std_logic_vector (7 downto 0); -- out
+    fmch_busy           : out std_logic; -- one busy bit per fm channel
+    rxusrclk            : in std_logic  
+    );
+end thFMdm;
+
+architecture Behavioral of thFMdm is
+
+--
+component FMwmfifo16KB_32to256 -- IP
+port (
+    wr_clk      : in std_logic;
+    rd_clk      : in std_logic;
+    rst        : in std_logic;
+    din         : in std_logic_vector(31 downto 0);
+    wr_en       : in std_logic;
+    rd_en       : in std_logic;
+    dout        : out std_logic_vector(255 downto 0);
+    valid       : out std_logic;
+    full        : out std_logic;
+    empty       : out std_logic;
+    prog_full   : out std_logic; -- '1' when a space for only one block is left (threshold 3580/3581)
+    prog_empty  : out std_logic;  -- '1' when less then one block is written (threshold 31/32)
+    wr_data_count : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
+    prog_empty_thresh : in std_logic_vector(8 downto 0);
+    prog_full_thresh  : in std_logic_vector(11 downto 0)
+    );
+end component;
+--
+--
+signal fmch_ena_reg  : std_logic;
+signal fmch_ena         : std_logic;
+--
+--signal timeCnt          : std_logic_vector ((toHostTimeoutBitn-1) downto 0);
+signal timeCnt_max    : std_logic_vector ((toHostTimeoutBitn-1) downto 0);
+signal timeCnt_ena    : std_logic;
+--
+--signal chINfifo_dout36  : std_logic_vector(35 downto 0);
+--signal chINfifo_re,chINfifo_empty,chINfifo_valid : std_logic;
+signal chFIFO_full, chFIFO_pfull, chFIFO_pfull_r1 : std_logic;
+signal chFIFO_empty, chFIFO_pempty  : std_logic;
+signal chFIFO_din32_rdy, ch_xoff  : std_logic;
+signal chFIFO_din32     : std_logic_vector(31 downto 0);
+signal chFIFO_dout_s    : std_logic_vector(255 downto 0);
+signal chfifo_driver_din  : std_logic_vector(32 downto 0);
+--
+signal wr_data_count      : std_logic_vector(3 downto 0);
+
+signal xoff_threshold_low  : std_logic_vector(3 downto 0);
+signal xoff_threshold_high : std_logic_vector(3 downto 0);
+signal xoff_clear_latch    : std_logic;
+signal xoff_threshold_low_clk_wrth : std_logic_vector(3 downto 0);
+signal xoff_threshold_high_clk_wrth : std_logic_vector(3 downto 0);
+signal xoff_clear_latch_clk_wrth : std_logic;
+
+begin
+
+fmchFifo_dout <= 
+  chFIFO_dout_s(31  downto 0)   &
+  chFIFO_dout_s(63  downto 32)  &
+  chFIFO_dout_s(95  downto 64)  &
+  chFIFO_dout_s(127 downto 96)  &
+  chFIFO_dout_s(159 downto 128) &
+  chFIFO_dout_s(191 downto 160) &
+  chFIFO_dout_s(223 downto 192) &
+  chFIFO_dout_s(255 downto 224);  -- swap 32bit word order
+
+fmchFifo_hasBlock <= '1' when (chFIFO_pempty = '0' and fmchFifo_flush = '0') else '0';
+  -- chFIFO_pempty is '0' when there is at least one whole block in the fifo
+
+fmch_monitor <= "0000000" & ch_xoff;
+
+------------------------------------------------------------
+-- configuration registers map
+------------------------------------------------------------
+cfg0: entity work.crTHFMconfigMap
+generic map (
+    FMCHid                  => FMCHid,
+    toHostTimeoutBitn       => toHostTimeoutBitn
+    )
+port  map ( 
+    register_map_control_appreg_clk    => register_map_control_appreg_clk, 
+    appreg_clk                         => appreg_clk,
+    clk250 => clk250,
+    -----
+    path_ena      => fmch_ena_reg,
+    timeCnt_ena             => timeCnt_ena,
+    timeCnt_max             => timeCnt_max
+    );
+
+
+
+------------------------------------------------------------
+-- to-Host GBT channel of 'FMCHid' timeout counter
+------------------------------------------------------------
+--TOUTcnt: entity work.counterNbit 
+--generic map(N=>toHostTimeoutBitn)
+--port map (
+--    clk        => clk40,		     
+--	rst        => rst,
+--	ce         => timeCnt_ena, -- 
+--	count_max  => timeCnt_max, -- 
+--	count_out  => timeCnt
+--);
+--
+
+------------------------------------------------------------
+-- downstream full mode channel input fifo
+------------------------------------------------------------
+--chINfifo: thFMch_input_fifo -- IP 
+--port map (
+--    wr_rst  => fmchFifo_flush,
+--    wr_clk  => clk240,
+--    wr_en   => fmch_ena,
+--    din     => "000" & FMCHdtype & FMCHdin,
+--    full    => open, -- can't be full
+--    --
+--    rd_rst  => fmchFifo_flush,    
+--    rd_clk  => clk250,
+--    rd_en   => chINfifo_re,
+--    dout    => chINfifo_dout36,
+--    empty   => chINfifo_empty,
+--    valid   => chINfifo_valid    
+--    );
+--    
+--chINfifo_re <= not chINfifo_empty;
+
+------------------------------------------------------------
+--  full mode channel FIFO driver
+------------------------------------------------------------
+chfifo_driver_din <= FMCHdtype & FMCHdin;
+
+g_ph1: if Phase2CRToHost_FM = false generate
+
+fmch_ena <= '1' when (fmch_ena_reg = '1' and FMCHlink_valid = '1') else '0';
+
+chFIFOdriver: entity work.thFMch_fifo_driver 
+generic map(
+    FMCHid              => FMCHid,
+    FIRMWARE_MODE       => FIRMWARE_MODE,
+    toHostTimeoutBitn   => toHostTimeoutBitn,
+    SUPER_CHUNK_FACTOR  => SUPER_CHUNK_FACTOR,
+    BLOCKSIZE           => BLOCKSIZE,
+    CHUNK_TRAILER_32B   => CHUNK_TRAILER_32B
+    )
+port map (
+    clk250          => clk_wrth,        -- write to host clock
+    rst250             => rst250,
+    din_rdy         => fmch_ena,
+    din             => chfifo_driver_din,
+    timeOutEna_i    => timeCnt_ena,
+    timeCnt_max     => timeCnt_max,
+    busy_o          => fmch_busy,
+    xoff            => ch_xoff, -- in, downstream wm fifo is full or main , can't happen in normal operation
+    word32out       => chFIFO_din32,    -- to chFIFO
+    word32out_rdy   => chFIFO_din32_rdy -- to chFIFO
+    );
+end generate g_ph1;
+
+g_ph2: if Phase2CRToHost_FM generate
+component FullToAxis is
+    generic(
+      BLOCKSIZE : integer
+    );
+port (
+  clk240 : in std_logic;
+  FMdin : in std_logic_vector(32 downto 0);
+  aclk : in std_logic;
+  aresetn : in std_logic;
+  m_axis : out axis_32_type;
+  m_axis_tready : in std_logic;
+  m_axis_prog_empty : out std_logic;
+  path_ena : in std_logic;
+  super_chunk_factor_link : in unsigned(7 downto 0);
+  Use32bSOP : in std_logic
+  );
+end component FullToAxis;
+component ToHostAxiStreamController is
+generic (
+    FMCHid                  : integer := 0;
+    toHostTimeoutBitn       : integer := 8;
+    BLOCKSIZE           : integer := 1024;
+    CHUNK_TRAILER_32B   : boolean := false;
+    STREAMS_TOHOST      : integer := 1
+    );
+port ( 
+    aclk        : in  std_logic;
+    aresetn     : in  std_logic;
+    
+    s_axis_in            : in axis_32_array_type(0 to STREAMS_TOHOST-1);
+    s_axis_tready_out    : out axis_tready_array_type(0 to STREAMS_TOHOST-1);
+    s_axis_prog_empty_in : in axis_tready_array_type(0 to STREAMS_TOHOST-1);
+    
+    timeOutEna_i    : in  std_logic;
+    timeCnt_max     : in  std_logic_vector ((toHostTimeoutBitn-1) downto 0);
+    prog_full_in    : in  std_logic;-- in, downstream wm fifo is full or main , can't happen in normal operation     
+    ----------
+    word32out       : out std_logic_vector (31 downto 0); -- to chFIFO
+    word32out_valid   : out std_logic
+    );
+end component ToHostAxiStreamController;
+  signal aresetn: std_logic;
+  signal decoding_axis : axis_32_type;
+  signal decoding_axis_tready : std_logic;
+  signal decoding_axis_prog_empty : std_logic;
+  signal emu_axis : axis_32_type;
+  signal emu_axis_tready : std_logic;
+  signal emu_axis_prog_empty : std_logic;
+  signal fanout_sel_axis : axis_32_type;
+  signal fanout_sel_axis_tready : std_logic;
+  signal fanout_sel_axis_prog_empty : std_logic;
+  signal fosel_r, fosel_aclk: std_logic;
+begin  
+ fmch_ena <= '1' when (fmch_ena_reg = '1' and (FMCHlink_valid = '1' or fosel_r = '1')) else '0';
+
+ aresetn <= not rst250;
+toaxis0: FullToAxis 
+    generic map(
+      BLOCKSIZE => BLOCKSIZE
+    )
+port map(
+  clk240 => rxusrclk,
+  FMdin => chfifo_driver_din,
+  aclk => clk_wrth,
+  aresetn => aresetn,
+  m_axis => decoding_axis,
+  m_axis_tready => decoding_axis_tready,
+  m_axis_prog_empty => decoding_axis_prog_empty,
+  path_ena => fmch_ena,
+  super_chunk_factor_link => x"01",
+  Use32bSOP => register_map_control_appreg_clk.FULLMODE_32B_SOP(0)
+  );
+  
+ emu_toaxis0: FullToAxis 
+    generic map(
+      BLOCKSIZE => BLOCKSIZE
+    )
+port map(
+  clk240 => clk240,
+  FMdin => FM_Emu_dout,
+  aclk => clk_wrth,
+  aresetn => aresetn,
+  m_axis => emu_axis,
+  m_axis_tready => emu_axis_tready,
+  m_axis_prog_empty => emu_axis_prog_empty,
+  path_ena => fmch_ena,
+  super_chunk_factor_link => x"01",
+  Use32bSOP => register_map_control_appreg_clk.FULLMODE_32B_SOP(0)
+  );
+  
+   xpm_cdc_single_fosel0 : xpm_cdc_single
+   generic map (
+      DEST_SYNC_FF => 2,
+      INIT_SYNC_FF => 0,
+      SIM_ASSERT_CHK => 0,
+      SRC_INPUT_REG => 1
+   )
+   port map (
+      dest_out => fosel_aclk,
+      dest_clk => clk_wrth,
+      src_clk => appreg_clk,
+      src_in => fosel_r
+   );
+   
+   fosel_r <= register_map_control_appreg_clk.GBT_TOHOST_FANOUT.SEL(FMCHid);
+  
+  decoding_axis_tready <= fanout_sel_axis_tready;
+  emu_axis_tready <= fanout_sel_axis_tready;
+    
+  fanout: process(fanout_sel_axis_tready, fosel_aclk, emu_axis, decoding_axis, emu_axis_prog_empty, decoding_axis_prog_empty)
+  begin
+      if fosel_aclk = '1' then --use emulator data
+        fanout_sel_axis <= emu_axis;
+      else          --use frontend link data
+        fanout_sel_axis <= decoding_axis;
+      end if;
+      if fosel_aclk = '1' then --use emulator data
+        fanout_sel_axis_prog_empty <= emu_axis_prog_empty;
+      else          --use frontend link data
+        fanout_sel_axis_prog_empty <= decoding_axis_prog_empty;
+      end if;
+  end process;
+  
+  streamctrl0: ToHostAxiStreamController 
+generic map(
+    FMCHid => FMCHid,
+    toHostTimeoutBitn => toHostTimeoutBitn,
+    BLOCKSIZE         => BLOCKSIZE,
+    CHUNK_TRAILER_32B => CHUNK_TRAILER_32B,
+    STREAMS_TOHOST    => 1
+    )
+port map( 
+    aclk        => clk_wrth,
+    aresetn     => aresetn,
+    
+    s_axis_in(0) => fanout_sel_axis,
+    s_axis_tready_out(0)  => fanout_sel_axis_tready,
+    s_axis_prog_empty_in(0) => fanout_sel_axis_prog_empty,
+    
+    timeOutEna_i    => timeCnt_ena,
+    timeCnt_max     => timeCnt_max,
+    prog_full_in    => ch_xoff, 
+    word32out       => chFIFO_din32,
+    word32out_valid => chFIFO_din32_rdy
+    );    
+  
+end generate g_ph2;
+--
+------------------------------------------------------------
+-- global Downstream data truncation in case of  
+-- wm-fifo full or external xoff (DMA stopped reading?)
+------------------------------------------------------------
+pr1: process(clk_wrth)                  -- write to host clock
+begin
+    if rising_edge(clk_wrth) then
+        chFIFO_pfull_r1 <= chFIFO_pfull;
+    end if;
+end process;
+
+ch_xoff <= '1' when (chFIFO_pfull='1' or chFIFO_pfull_r1='1') else '0'; -- or fmchXoffin;
+
+--
+------------------------------------------------------------
+--  full mode channel FIFO
+------------------------------------------------------------
+chFIFO: FMwmfifo16KB_32to256 -- IP
+port map (
+    wr_clk      => clk_wrth,            -- write to host clock
+    rd_clk      => clk250,
+    rst         => fmchFifo_flush,
+    din         => chFIFO_din32,
+    wr_en       => chFIFO_din32_rdy,
+    rd_en       => fmchFifo_re,
+    dout        => chFIFO_dout_s, -- 256 bit
+    full        => chFIFO_full,
+    empty       => chFIFO_empty,
+    valid       => fmchFifo_dvalid,
+    prog_full   => chFIFO_pfull, -- '1' when a space for only one block is left (threshold 3580/3581)
+    prog_empty  => chFIFO_pempty, -- '1' when less then one block is written (threshold 31/32)
+    wr_data_count => wr_data_count,
+    prog_full_thresh  => std_logic_vector(to_unsigned(4093-(BLOCKSIZE/2), 12)),
+    prog_empty_thresh => std_logic_vector(to_unsigned((BLOCKSIZE/32)-1, 9))
+    );
+
+xoff_threshold_low  <= register_map_control_appreg_clk.XOFF_FM_CH_FIFO_THRESH_LOW;
+xoff_threshold_high <= register_map_control_appreg_clk.XOFF_FM_CH_FIFO_THRESH_HIGH;
+xoff_clear_latch    <= to_sl(register_map_control_appreg_clk.XOFF_FM_HIGH_THRESH.CLEAR_LATCH);
+
+xpm_cdc_array_single_inst_threshold_low : xpm_cdc_array_single
+   generic map (
+      DEST_SYNC_FF => 2,
+      INIT_SYNC_FF => 0,
+      SIM_ASSERT_CHK => 0,
+      SRC_INPUT_REG => 1,
+      WIDTH => 4
+   )
+   port map (
+      dest_out => xoff_threshold_low_clk_wrth,
+      dest_clk => clk_wrth,
+      src_clk => appreg_clk,
+      src_in => xoff_threshold_low
+   );
+   
+xpm_cdc_array_single_inst_threshold_high : xpm_cdc_array_single
+   generic map (
+      DEST_SYNC_FF => 2,
+      INIT_SYNC_FF => 0,
+      SIM_ASSERT_CHK => 0,
+      SRC_INPUT_REG => 1,
+      WIDTH => 4
+   )
+   port map (
+      dest_out => xoff_threshold_high_clk_wrth,
+      dest_clk => clk_wrth,
+      src_clk => appreg_clk,
+      src_in => xoff_threshold_high
+   );
+   
+xpm_cdc_single_inst : xpm_cdc_single
+   generic map (
+      DEST_SYNC_FF => 2,
+      INIT_SYNC_FF => 0,
+      SIM_ASSERT_CHK => 0,
+      SRC_INPUT_REG => 1
+   )
+   port map (
+      dest_out => xoff_clear_latch_clk_wrth,
+      dest_clk => clk_wrth,
+      src_clk => appreg_clk,
+      src_in => xoff_clear_latch
+   );
+
+pr2: process(clk_wrth)                  -- fifo write clock
+begin
+    if rising_edge(clk_wrth) then
+        if(wr_data_count > xoff_threshold_high_clk_wrth) then
+            fmchXoffout <= '1';
+            fmchHighThreshCrossed <= '1';
+            fmchHighThreshCrossedLatch <= '1';
+        else
+            fmchHighThreshCrossed <= '0';
+        end if;
+        if(xoff_clear_latch_clk_wrth='1') then
+            fmchHighThreshCrossedLatch <= '0';
+        end if;
+        if(wr_data_count < xoff_threshold_low_clk_wrth) then
+            fmchXoffout <= '0';
+            fmchLowThreshCrossed <= '0';
+        else
+            fmchLowThreshCrossed <= '1';
+        end if;
+        --fmchXoffout <= chFIFO_pfull;
+    end if;
+end process;
+
+end Behavioral;
+
diff --git a/sources/decoding/FullToAxis.vhd b/sources/decoding/FullToAxis.vhd
index 04eb61f94..bbf2472f6 100644
--- a/sources/decoding/FullToAxis.vhd
+++ b/sources/decoding/FullToAxis.vhd
@@ -32,7 +32,6 @@ entity FullToAxis is
 port (
   clk240 : in std_logic;
   FMdin : in std_logic_vector(32 downto 0);
-  LinkAligned : in std_logic;
   aclk : in std_logic;
   aresetn : in std_logic;
   m_axis : out axis_32_type;
@@ -61,10 +60,10 @@ signal tlast: std_logic;
 signal fifo_resetn: std_logic;
 signal trunc: std_logic;
 
-signal LinkAligned_240, PathEnable_240: std_logic; --CDC to clk240 domain using xpm_cdc_single
+signal PathEnable_240: std_logic; --CDC to clk240 domain using xpm_cdc_single
 signal EnableTlast : std_logic;
 signal notTruncated : std_logic;
-signal aresetn_240 : std_logic;
+signal aresetn_240, aresetn_240_i: std_logic;
 signal invalidate_data : std_logic; --Add an extra tlast/tvalid/chunk_error to the fifo.
 signal chunk_busy: std_logic; --1 when we are in between SOP/EOP. Ignore any other data.
 signal Use32bSOP_clk240: std_logic; --Register setting: 1 to check for 0x0000003C for Start of Chunk, when '0' only check 0x3C.
@@ -80,27 +79,14 @@ begin
           SIM_ASSERT_CHK => 0
        )
        port map (
-          dest_rst => aresetn_240, -- 1-bit output: src_rst synchronized to the destination clock domain. This output
+          dest_rst => aresetn_240_i, -- 1-bit output: src_rst synchronized to the destination clock domain. This output
                                 -- is registered.
     
           dest_clk => clk240, -- 1-bit input: Destination clock.
           src_rst => aresetn    -- 1-bit input: Source reset signal.
        );
+    aresetn_240 <= aresetn_240_i and (not wr_rst_busy);
 
-
-    xpm_cdc_LinkAligned : xpm_cdc_single
-      generic map (
-        DEST_SYNC_FF => 2, 
-        INIT_SYNC_FF => 0, 
-        SIM_ASSERT_CHK => 0,
-        SRC_INPUT_REG => 0
-      )
-      port map (
-        src_clk => '0',
-        src_in => LinkAligned,
-        dest_clk => clk240,
-        dest_out => LinkAligned_240
-      );
     
     xpm_cdc_PathEnable : xpm_cdc_single
       generic map (
@@ -143,7 +129,7 @@ begin
         else
             EnableTlast <= '0';
         end if;
-        if LinkAligned_240 = '1' and FMdin(32) = '1' and FMdin(7 downto 0) = Kchar_eop and chunk_busy = '1' then
+        if PathEnable_240 = '1' and FMdin(32) = '1' and FMdin(7 downto 0) = Kchar_eop and chunk_busy = '1' then
             if superchunk_cnt < super_chunk_factor_link-1 then
                 superchunk_cnt := superchunk_cnt + 1;
             else
@@ -154,11 +140,11 @@ begin
     end if;
 end process;
 
-toAxis_proc: process(LinkAligned_240, FMdin, EnableTlast)
+toAxis_proc: process(PathEnable_240, FMdin, EnableTlast)
 begin
   tlast <= '0';
   s_axis.tlast <= '0'; --added later in pipelining.
-  if LinkAligned_240 = '1' then
+  if PathEnable_240 = '1' then
     if FMdin(32) = '1' then
       s_axis.tvalid <= '0'; --other comma characters are ignored.
       if FMdin(7 downto 0) = Kchar_eop then
@@ -181,7 +167,7 @@ begin
     if aresetn_240 = '0' then
       busy_240 <= '0';
     else
-      if LinkAligned_240 = '1' and PathEnable_240 = '1' then
+      if PathEnable_240 = '1' then
         if FMdin(32) = '1' then
           if FMdin(7 downto 0) = Kchar_sob then
             busy_240 <= '1';
@@ -219,13 +205,13 @@ begin
             chunk_contains_data <= '0';
         end if;
     end if;
-    if LinkAligned_240 = '0' or PathEnable_240 = '0' then
+    if PathEnable_240 = '0' or PathEnable_240 = '0' then
         invalidate_data <= chunk_contains_data;
     end if;
-    if LinkAligned_240 = '0' and chunk_busy = '1' then
+    if PathEnable_240 = '0' and chunk_busy = '1' then
       chunk_busy <= '0';
     end if;
-    if LinkAligned_240 = '0' then
+    if PathEnable_240 = '0' then
       sop_error := '0';
       eop_error := '0';
       chunk_busy <= '0';
@@ -370,7 +356,7 @@ begin
     end if;
 end process;
 
-fifo_resetn <= aresetn_240 and LinkAligned_240;
+fifo_resetn <= aresetn_240_i; -- and PathEnable_240;
 
 s_axis_fifo.tvalid <= (s_axis_p4.tvalid and PathEnable_240 and notTruncated) or invalidate_data;
 s_axis_fifo.tdata <= s_axis_p4.tdata;
@@ -403,13 +389,13 @@ fifo0: entity work.Axis32Fifo
 
 
 rst_busy_proc: process(clk240)
-  variable cnt: integer range 0 to 7;
+  variable cnt: integer range 0 to 15;
 begin
   if rising_edge(clk240) then
     if fifo_resetn = '0' then
       wr_rst_busy <= '1';
       rd_rst_busy <= '1';
-      cnt := 7;
+      cnt := 15;
     else
       if cnt /= 0 then
         cnt := cnt - 1;
-- 
GitLab