From: Tobias Weber Date: Thu, 1 Feb 2018 16:08:57 +0000 (+0100) Subject: starting to work on serdes data readout from mupix. so far only status signal and... X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=da64d2f589462118dd9b00d551d2881214e6e6f4;p=trb3.git starting to work on serdes data readout from mupix. so far only status signal and assuming generic 8b10b mode of serdes pcs. maybe more level approach is needed. --- diff --git a/mupix/Mupix8/sources/MupixDataLink.vhd b/mupix/Mupix8/sources/MupixDataLink.vhd new file mode 100644 index 0000000..9db2fcb --- /dev/null +++ b/mupix/Mupix8/sources/MupixDataLink.vhd @@ -0,0 +1,238 @@ +------------------------------------------------------------------ +-- Mupix data 10b8b readout with internal FIFO +--T. Weber, Ruhr Universität Bochum +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity MupixDataLink is + port( + sysclk : in std_logic; --trb system clock (typically 100 MHz) + dataclk : in std_logic; --mupix link clock from FPGA PLL(50 - 150 MHz) + rst : in std_logic; --synchronous reset + clear : in std_logic; --asynchronous reset + rst_fifo : in std_logic; --synchronous fifo reset + --lattice serdes + mupix_data : in std_logic_vector(7 downto 0); --lvds pairs of 4 incoming data channels + refclk2core : out std_logic; --reference clk from serdes (not really needed since clock sync is done internally with FIFOs?) + clk_rx_half_out : out std_logic; --serdes receive clock half + clk_rx_full_out : out std_logic; --serdes receive clock + --fifo signals + fifo_rden : in std_logic_vector(3 downto 0); -- read enable to FIFOs + fifo_empty : out std_logic_vector(3 downto 0); -- input FIFO empty flags + fifo_full : out std_logic_vector(3 downto 0); -- input FIFO full flags + fifo_data : out std_logic_vector(127 downto 0); -- input data from FIFOs + --misc + channel_status_led : out std_logic_vector(3 downto 0); + --TRB slow control channel + SLV_READ_IN : in std_logic; + SLV_WRITE_IN : in std_logic; + SLV_DATA_OUT : out std_logic_vector(31 downto 0); + SLV_DATA_IN : in std_logic_vector(31 downto 0); + SLV_ADDR_IN : in std_logic_vector(15 downto 0); + SLV_ACK_OUT : out std_logic; + SLV_NO_MORE_DATA_OUT : out std_logic; + SLV_UNKNOWN_ADDR_OUT : out std_logic); +end entity MupixDataLink; + +architecture rtl of MupixDataLink is + + ----------------------------------- + -- Mupix data channel to serdes map + -- Serdes0 = Data4 + -- Serdes1 = Data1 + -- Serdes2 = Data3 + -- Serdes3 = Data2 + ------------------------------------ + constant c_used_serdes_channels : integer := 4; + constant c_serdes_data_width : integer := 8; + constant c_serdes_fifo_rdcnt_width : integer := 10; + constant c_serdes_fifo_large_rdcnt_width : integer := 11; + + signal data_from_serdes_i : std_logic_vector(c_used_serdes_channels*c_serdes_data_width - 1 downto 0); + signal data_from_fifos_i : std_logic_vector(127 downto 0); + signal serdes_fifo_rdcnt_i : std_logic_vector((c_used_serdes_channels - 1)*c_serdes_fifo_rdcnt_width - 1 downto 0); + signal serdes_fifo_large_rdcnt_i : std_logic_vector(c_serdes_fifo_large_rdcnt_width - 1 downto 0); + + signal rx_los_low_s, rx_los_low_s_sync : std_logic_vector(c_used_serdes_channels - 1 downto 0); + signal lsm_status_s, lsm_status_s_sync : std_logic_vector(c_used_serdes_channels - 1 downto 0); + signal rx_cdr_lol_s, rx_cdr_lol_s_sync : std_logic_vector(c_used_serdes_channels - 1 downto 0); + + component InputSynchronizer + generic(depth : integer := 2; + width : integer := 1); + port( + clk : in std_logic; + rst : in std_logic; + input : in std_logic_vector(width - 1 downto 0); + sync_output : out std_logic_vector(width - 1 downto 0)); + end component InputSynchronizer; + + component serdes_fifo is + port( + Data : in std_logic_vector(c_serdes_data_width - 1 downto 0); + WrClock : in std_logic; + RdClock : in std_logic; + WrEn : in std_logic; + RdEn : in std_logic; + Reset : in std_logic; + RPReset : in std_logic; + Q : out std_logic_vector(31 downto 0); + RCNT : out std_logic_vector(c_serdes_fifo_rdcnt_width - 1 downto 0); + Empty : out std_logic; + Full : out std_logic); + end component serdes_fifo; + + component serdes_fifo_large is + port( + Data : in std_logic_vector(c_serdes_data_width - 1 downto 0); + WrClock : in std_logic; + RdClock : in std_logic; + WrEn : in std_logic; + RdEn : in std_logic; + Reset : in std_logic; + RPReset : in std_logic; + Q : out std_logic_vector(31 downto 0); + RCNT : out std_logic_vector(c_serdes_fifo_large_rdcnt_width - 1 downto 0); + Empty : out std_logic; + Full : out std_logic); + end component serdes_fifo_large; + + component mupix_serdes is + GENERIC(USER_CONFIG_FILE : String := "mupix_serdes.txt"); + port( + ------------------ + -- CH0 -- + hdinp_ch0, hdinn_ch0 : in std_logic; + rxiclk_ch0 : in std_logic; + rx_full_clk_ch0 : out std_logic; + rx_half_clk_ch0 : out std_logic; + fpga_rxrefclk_ch0 : in std_logic; + rxdata_ch0 : out std_logic_vector(c_serdes_data_width - 1 downto 0); + rx_k_ch0 : out std_logic; + rx_disp_err_ch0 : out std_logic; + rx_cv_err_ch0 : out std_logic; + rx_pwrup_ch0_c : in std_logic; + rx_los_low_ch0_s : out std_logic; + lsm_status_ch0_s : out std_logic; + rx_cdr_lol_ch0_s : out std_logic; + rx_div2_mode_ch0_c : in std_logic; + -- CH1 -- + hdinp_ch1, hdinn_ch1 : in std_logic; + rxiclk_ch1 : in std_logic; + rx_full_clk_ch1 : out std_logic; + rx_half_clk_ch1 : out std_logic; + fpga_rxrefclk_ch1 : in std_logic; + rxdata_ch1 : out std_logic_vector(c_serdes_data_width - 1 downto 0); + rx_k_ch1 : out std_logic; + rx_disp_err_ch1 : out std_logic; + rx_cv_err_ch1 : out std_logic; + rx_pwrup_ch1_c : in std_logic; + rx_los_low_ch1_s : out std_logic; + lsm_status_ch1_s : out std_logic; + rx_cdr_lol_ch1_s : out std_logic; + rx_div2_mode_ch1_c : in std_logic; + -- CH2 -- + hdinp_ch2, hdinn_ch2 : in std_logic; + rxiclk_ch2 : in std_logic; + rx_full_clk_ch2 : out std_logic; + rx_half_clk_ch2 : out std_logic; + fpga_rxrefclk_ch2 : in std_logic; + rxdata_ch2 : out std_logic_vector(c_serdes_data_width - 1 downto 0); + rx_k_ch2 : out std_logic; + rx_disp_err_ch2 : out std_logic; + rx_cv_err_ch2 : out std_logic; + rx_pwrup_ch2_c : in std_logic; + rx_los_low_ch2_s : out std_logic; + lsm_status_ch2_s : out std_logic; + rx_cdr_lol_ch2_s : out std_logic; + rx_div2_mode_ch2_c : in std_logic; + -- CH3 -- + hdinp_ch3, hdinn_ch3 : in std_logic; + rxiclk_ch3 : in std_logic; + rx_full_clk_ch3 : out std_logic; + rx_half_clk_ch3 : out std_logic; + fpga_rxrefclk_ch3 : in std_logic; + rxdata_ch3 : out std_logic_vector(c_serdes_data_width - 1 downto 0); + rx_k_ch3 : out std_logic; + rx_disp_err_ch3 : out std_logic; + rx_cv_err_ch3 : out std_logic; + rx_pwrup_ch3_c : in std_logic; + rx_los_low_ch3_s : out std_logic; + lsm_status_ch3_s : out std_logic; + rx_cdr_lol_ch3_s : out std_logic; + rx_div2_mode_ch3_c : in std_logic; + ---- Miscillaneous ports + fpga_txrefclk : in std_logic; + tx_sync_qd_c : in std_logic; + refclk2fpga : out std_logic; + rst_n : in std_logic; + serdes_rst_qd_c : in std_logic); + end component mupix_serdes; + +begin + + SLV_BUS : process(sysclk) is + begin + if rising_edge(sysclk) then + if rst = '1' then + SLV_DATA_OUT <= (others => '0'); + SLV_UNKNOWN_ADDR_OUT <= '0'; + SLV_NO_MORE_DATA_OUT <= '0'; + SLV_ACK_OUT <= '0'; + else + if SLV_READ_IN = '1' then + case SLV_ADDR_IN is + when x"0001" => --read counters are already synchronous to trb system clock + SLV_DATA_OUT(c_serdes_fifo_rdcnt_width - 1 downto 0) <= serdes_fifo_rdcnt_i(c_serdes_fifo_rdcnt_width - 1 downto 0); + SLV_ACK_OUT <= '1'; + when x"0002" => + SLV_DATA_OUT(c_serdes_fifo_rdcnt_width - 1 downto 0) <= serdes_fifo_rdcnt_i(2*c_serdes_fifo_rdcnt_width - 1 downto c_serdes_fifo_rdcnt_width); + SLV_ACK_OUT <= '1'; + when x"0003" => + SLV_DATA_OUT(c_serdes_fifo_rdcnt_width - 1 downto 0) <= serdes_fifo_rdcnt_i(3*c_serdes_fifo_rdcnt_width - 1 downto 2*c_serdes_fifo_rdcnt_width); + SLV_ACK_OUT <= '1'; + when x"0004" => + SLV_DATA_OUT(c_serdes_fifo_rdcnt_width - 1 downto 0) <= serdes_fifo_large_rdcnt_i(c_serdes_fifo_large_rdcnt_width - 1 downto 0); + SLV_ACK_OUT <= '1'; + when x"0005" => + SLV_DATA_OUT(c_used_serdes_channels - 1 downto 0) <= lsm_status_s_sync; + SLV_ACK_OUT <= '1'; + when x"0006" => + SLV_DATA_OUT(c_used_serdes_channels - 1 downto 0) <= rx_los_low_s_sync; + SLV_ACK_OUT <= '1'; + when x"0007" => + SLV_DATA_OUT(c_used_serdes_channels - 1 downto 0) <= rx_cdr_lol_s_sync; + SLV_ACK_OUT <= '1'; + when others => + SLV_UNKNOWN_ADDR_OUT <= '1'; + end case; + end if; + end if; + end if; + end process SLV_BUS; + + --serdes status to led + led_status : process (rx_los_low_s, lsm_status_s, rx_cdr_lol_s) is + begin + for i in 0 to c_used_serdes_channels - 1 loop + channel_status_led(i) <= lsm_status_s(i) and not rx_cdr_lol_s(i) and not rx_los_low_s(i); + end loop; + end process led_status; + + --synchronize status signals to trb clock domain + sync_lsm_status : component InputSynchronizer + generic map(depth => 2, width => c_used_serdes_channels) + port map(clk => sysclk, rst => rst, input => lsm_status_s, sync_output => lsm_status_s_sync); + + sync_los_low : component InputSynchronizer + generic map(depth => 2, width => c_used_serdes_channels) + port map(clk => sysclk, rst => rst, input => rx_los_low_s, sync_output => rx_los_low_s_sync); + + sync_cdr_lol : component InputSynchronizer + generic map(depth => 2, width => c_used_serdes_channels) + port map(clk => sysclk, rst => rst, input => rx_cdr_lol_s, sync_output => rx_cdr_lol_s_sync); + + +end architecture; \ No newline at end of file