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