------------------------------------------------------------------------------ -- Paul Scherrer Institute (PSI) ------------------------------------------------------------------------------ -- Unit : v6vlx_gtxe1_wrapper.vhd -- Author : Goran Marinkovic, Section Diagnostic -- : Waldemar Koprek, Section Diagnostic -- : Patric Bucher, Section DSV -- Version : $Revision: 1.1 $ ------------------------------------------------------------------------------ -- Copyright© PSI, Section Diagnostic ------------------------------------------------------------------------------ -- Comment : Wrapper vor Virtex-6 GTX ready to use in HIPA and SwissFEL (SFEL) ------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library unisim; use unisim.vcomponents.all; use work.v6vlx_gtxe1_pkg.all; entity v6vlx_gtxe1_wrapper is generic( g_MGT_LOCATION : string; -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19" g_FACILITY : string -- "HIPA" | "SFEL" ); port( -- MGT serial interface i_mgt_refclk : in std_logic; o_mgt_refclk : out std_logic; i_mgt_rx_p : in std_logic; i_mgt_rx_n : in std_logic; o_mgt_tx_p : out std_logic; o_mgt_tx_n : out std_logic; -- MGT parallel interface o_mgt_status : out std_logic_vector(31 downto 0); -- see lines 134-139 for details i_mgt_control : in std_logic_vector(31 downto 0); -- see lines 127-131 for details o_mgt_recclk : out std_logic; o_mgt_rx_data : out std_logic_vector(15 downto 0); o_mgt_rx_charisk : out std_logic_vector( 1 downto 0) ); end v6vlx_gtxe1_wrapper; architecture RTL of v6vlx_gtxe1_wrapper is type typ_align_fsm is ( align_idle, align_slide , align_wait_for_sync ); signal s_align_fsm : typ_align_fsm := align_idle; -- GTXE signal i_mgt : gtxe_in_type; signal o_mgt : gtxe_out_type; signal sl_txoutclk : std_logic; --fifo signal sl_cpu_rx_empty : std_logic; signal sl_gtxe_fifo_rst : std_logic; signal sl_gtxe_rx_sync_done : std_logic; signal slv_rxresetdone : std_logic_vector(7 downto 0); signal sl_rx_sync_rst : std_logic; signal sl_rxrecclk : std_logic; signal sl_rx0_slide : std_logic; signal slv_cnt : unsigned(5 downto 0); -- MMCM signal mmcm_CLKFB : std_logic; signal mmcm_CLKFBOUT : std_logic; signal mmcm_LOCKED : std_logic; signal mmcm_RESET : std_logic; signal mmcm_CLOCK : std_logic; begin -- inst_mgt_refclk_bufg: BUFG -- port map -- ( -- I => o_mgt.ctrl.REFCLKOUT, -- O => o_mgt_refclk -- ); -- GTXE INSTANCE ------------------------------------------------------------------ gen_gtxe1_sfel: if g_FACILITY = "SFEL" generate ins_v6vlx_gtxe1_sfel: entity work.v6vlx_gtxe1_142MHz8_2Gbps856 generic map ( g_MGT_LOCATION => g_MGT_LOCATION ) port map ( i_mgt => i_mgt, o_mgt => o_mgt ); end generate; gen_gtxe1_hipa: if g_FACILITY = "HIPA" generate ins_v6vlx_gtxe1_hipa: entity work.v6vlx_gtxe1_101MHz27_1Gbps0127 generic map ( g_MGT_LOCATION => g_MGT_LOCATION ) port map ( i_mgt => i_mgt, o_mgt => o_mgt ); end generate; assert not(g_FACILITY /= "HIPA" and g_FACILITY /= "SFEL") report "Invalid value for g_FACILITY, valid values are 'HIPA'|'SFEL'" severity failure; -- GTXE CONTROL IF ---------------------------------------------------------------- i_mgt.ctrl.GTXRESET <= i_mgt_control(0); i_mgt.ctrl.PLLRXRESET <= '0'; i_mgt.ctrl.PLLTXRESET <= '0'; i_mgt.ctrl.LOOPBACK <= "100"; -- Far-End PMA Loopback --> UG366 page 125 i_mgt.ctrl.CLKIN <= i_mgt_refclk; -- GTXE STATUS IF (adapted to PSI generic part) ----------------------------------- o_mgt_status( 0) <= o_mgt.ctrl.TXPLLLKDET; o_mgt_status( 1) <= o_mgt.ctrl.RXPLLLKDET; o_mgt_status( 2) <= mmcm_LOCKED; o_mgt_status( 3) <= o_mgt.ctrl.TXRESETDONE; o_mgt_status( 4) <= o_mgt.ctrl.RXRESETDONE; o_mgt_status( 5) <= '0'; -- TX_polarity inverted o_mgt_status( 6) <= '0'; -- RX_polarity inverted o_mgt_status( 7) <= '0'; -- reserved o_mgt_status(12 downto 8) <= "00000"; -- DFEEYEDACMON[4:0] o_mgt_status(13) <= '0'; -- RXPRBSERR o_mgt_status(14) <= o_mgt.rx.RXBYTEISALIGNED; o_mgt_status(15) <= o_mgt.rx.RXLOSSOFSYNC(1); ---------- additional status ------------- o_mgt_status(16) <= sl_rx0_slide; o_mgt_status(17) <= sl_gtxe_rx_sync_done; o_mgt_status(19 downto 18) <= o_mgt.rx.RXNOTINTABLE(1 downto 0); -- Byte 1 + Byte 0 o_mgt_status(21 downto 20) <= o_mgt.rx.RXDISPERR(1 downto 0); -- Byte 1 + Byte 0 o_mgt_status(31 downto 22) <= B"00_0000_0000"; -- undefined -- GTXE RX IF --------------------------------------------------------------------- -- MMCM use model based on AR#39430 gen_MMCM: if g_FACILITY = "SFEL" generate begin -- Use Core Generator to define parameters -> actual frequency 142.8 MHz mmcm_rxclk : MMCM_BASE generic map ( CLKFBOUT_MULT_F => 33.000 , -- Counter multiply value, Now supports non-integer values CLKIN1_PERIOD => 7.002 , -- The reference clock frequency is required for properly configuring the -- LOCK detect circuit and checking to make sure the VCO is operating within -- the allowed range. If no value is specified, a warning should be issued -- stating it was not provided so no error checking will be done. CLKOUT0_DIVIDE_F => 8.250 , -- Counter divide value, Now supports non-integer values but you lose CLKOUT5 DIVCLK_DIVIDE => 4 -- Counter divide value, always configured for 50% duty cycle ) port map ( CLKFBOUT => mmcm_CLKFBOUT, -- 1-bit MMCM Feedback clock output CLKFBOUTB => open, -- 1-bit Inverted MMCM feedback clock output CLKOUT0 => mmcm_CLOCK, -- 1-bit MMCM clock output 0 CLKOUT0B => open, -- 1-bit Inverted MMCM clock output 0 CLKOUT1 => open, -- 1-bit MMCM clock output 1 CLKOUT1B => open, -- 1-bit Inverted MMCM clock output 1 CLKOUT2 => open, -- 1-bit MMCM clock output 2 CLKOUT2B => open, -- 1-bit Inverted MMCM clock output 2 CLKOUT3 => open, -- 1-bit MMCM clock output 3 CLKOUT3B => open, -- 1-bit Inverted MMCM clock output 3 CLKOUT4 => open, -- 1-bit MMCM clock output 4 CLKOUT5 => open, -- 1-bit MMCM clock output 5, not used if CLKOUT0 is not an integer CLKOUT6 => open, -- 1-bit MMCM clock output 6, not used if CLKFBOUT_MULT is not an integer LOCKED => mmcm_LOCKED, -- 1-bit MMC locked signal CLKFBIN => mmcm_CLKFB, -- 1-bit Feedback clock pin to the MMCM CLKIN1 => o_mgt.rx.RXRECCLK, -- 1-bit Reference clock pin 1 to the MMCM PWRDWN => '0', -- 1-bit Power down RST => mmcm_RESET -- 1-bit MMCM global reset pin ); mmcm_RESET <= not o_mgt.ctrl.RXPLLLKDET; rxoutCLKFB_bufg0_i : BUFG port map ( O => mmcm_CLKFB, I => mmcm_CLKFBOUT ); rxoutclk_bufg1_i : BUFG port map ( O => sl_rxrecclk, I => mmcm_CLOCK ); end generate; gen_BUFG: if g_FACILITY = "HIPA" generate begin rxoutclk_bufg0_i : BUFG port map ( O => sl_rxrecclk, I => o_mgt.rx.RXRECCLK ); -- forward lock state mmcm_LOCKED <= o_mgt.ctrl.RXPLLLKDET; -- unused without mmcm mmcm_CLKFB <= '0'; mmcm_CLKFBOUT <= '0'; mmcm_RESET <= '0'; mmcm_CLOCK <= '0'; end generate; o_mgt_recclk <= sl_rxrecclk; ins_v6vlx_gtxe1_sync : entity work.v6vlx_gtxe1_sync port map ( RXENPMAPHASEALIGN => i_mgt.rx.RXENPMAPHASEALIGN , RXPMASETPHASE => i_mgt.rx.RXPMASETPHASE , RXDLYALIGNDISABLE => i_mgt.rx.RXDLYALIGNDISABLE , RXDLYALIGNOVERRIDE => i_mgt.rx.RXDLYALIGNOVERRIDE, RXDLYALIGNRESET => i_mgt.rx.RXDLYALIGNRESET , SYNC_DONE => sl_gtxe_rx_sync_done, USER_CLK => sl_rxrecclk, RESET => sl_rx_sync_rst ); prc_rx_reset_done_delay : process ( sl_rxrecclk ) begin if rising_edge( sl_rxrecclk ) then slv_rxresetdone <= slv_rxresetdone(6 downto 0) & o_mgt.ctrl.RXRESETDONE; end if; end process ; sl_rx_sync_rst <= not slv_rxresetdone(7); i_mgt.rx.RXUSRCLK <= sl_rxrecclk; i_mgt.rx.RXUSRCLK2 <= sl_rxrecclk; i_mgt.rx.RXP <= i_mgt_rx_p; i_mgt.rx.RXN <= i_mgt_rx_n; i_mgt.rx.RXENMCOMMAALIGN <= '0'; i_mgt.rx.RXENPCOMMAALIGN <= '0'; i_mgt.rx.RXRESET <= not mmcm_LOCKED; i_mgt.rx.RXCDRRESET <= i_mgt_control(5); i_mgt.rx.RXDLYALIGNMONENB <= '0'; o_mgt_rx_data <= o_mgt.rx.RXDATA(15 downto 0); o_mgt_rx_charisk <= o_mgt.rx.RXCHARISK( 1 downto 0); ------------------------------------------------------------------------------ --RX comma alignment ------------------------------------------------------------------------------ prc_comma_align : process ( sl_rxrecclk ) begin if rising_edge( sl_rxrecclk ) then if o_mgt.ctrl.RXRESETDONE = '0' then s_align_fsm <= align_idle; else case s_align_fsm is when align_idle => if o_mgt.rx.RXLOSSOFSYNC( 1) = '1' or o_mgt.rx.RXBYTEISALIGNED = '0' then s_align_fsm <= align_slide; end if; when align_slide => slv_cnt <= (others => '0'); s_align_fsm <= align_wait_for_sync; when align_wait_for_sync => if slv_cnt(slv_cnt'left) = '1' then if o_mgt.rx.RXLOSSOFSYNC( 1) = '0' and o_mgt.rx.RXBYTEISALIGNED = '1' then s_align_fsm <= align_idle; else s_align_fsm <= align_slide; end if; else slv_cnt <= slv_cnt + X"1"; end if; end case; end if; end if; end process ; sl_rx0_slide <= '1' when s_align_fsm = align_slide or i_mgt_control(2) = '1' else '0'; i_mgt.rx.RXSLIDE <= sl_rx0_slide; -- GTXE TX IF --------------------------------------------------------------------- o_mgt_tx_p <= o_mgt.tx.TXP; o_mgt_tx_n <= o_mgt.tx.TXN; -- txoutclk_bufg0_i : BUFG -- port map ( -- I => o_mgt.tx.TXOUTCLK, -- O => sl_txoutclk -- ); i_mgt.tx.TXRESET <= not mmcm_LOCKED; i_mgt.tx.TXBYPASS8B10B <= X"0"; i_mgt.tx.TXCHARDISPMODE <= X"0"; i_mgt.tx.TXCHARDISPVAL <= X"0"; i_mgt.tx.TXUSRCLK <= sl_rxrecclk; i_mgt.tx.TXUSRCLK2 <= sl_rxrecclk; i_mgt.tx.TXDIFFCTRL <= "0110"; i_mgt.tx.TXPOSTEMPHASIS <= "00000"; i_mgt.tx.TXPREEMPHASIS <= "0000"; end RTL;