]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
starting to work on serdes data readout from mupix. so far only status signal and...
authorTobias Weber <toweber86@gmail.com>
Thu, 1 Feb 2018 16:08:57 +0000 (17:08 +0100)
committerTobias Weber <toweber86@gmail.com>
Thu, 1 Feb 2018 16:08:57 +0000 (17:08 +0100)
mupix/Mupix8/sources/MupixDataLink.vhd [new file with mode: 0644]

diff --git a/mupix/Mupix8/sources/MupixDataLink.vhd b/mupix/Mupix8/sources/MupixDataLink.vhd
new file mode 100644 (file)
index 0000000..9db2fcb
--- /dev/null
@@ -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