From: hadeshyp Date: Thu, 2 Apr 2009 14:04:29 +0000 (+0000) Subject: added serdes for ecp2m X-Git-Tag: oldGBE~465 X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=344692cc775380623f92c36a75fab317deaf2c3b;p=trbnet.git added serdes for ecp2m --- diff --git a/media_interfaces/trb_net16_lsm_sfp.vhd b/media_interfaces/trb_net16_lsm_sfp.vhd new file mode 100644 index 0000000..d3debd7 --- /dev/null +++ b/media_interfaces/trb_net16_lsm_sfp.vhd @@ -0,0 +1,435 @@ +-- LinkStateMachine for SFPs (2GBit) + +-- Still missing: link reset features, fifo full error handling, signals on stat_op +-- Take care: all input signals must be synchronous to SYSCLK, +-- all output signals are synchronous to SYSCLK. +-- Clock Domain Crossing is in your responsibility! + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.std_logic_ARITH.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; + +entity trb_net16_lsm_sfp is +port( SYSCLK : in std_logic; -- fabric clock (100MHz) + RESET : in std_logic; -- synchronous reset + CLEAR : in std_logic; -- asynchronous reset, connect to '0' if not needed / available + -- status signals + SFP_MISSING_IN : in std_logic; -- SFP Missing ('1' = no SFP mounted, '0' = SFP in place) + SFP_LOS_IN : in std_logic; -- SFP Loss Of Signal ('0' = OK, '1' = no signal) + SD_LINK_OK_IN : in std_logic; -- SerDes Link OK ('0' = not linked, '1' link established) + SD_LOS_IN : in std_logic; -- SerDes Loss Of Signal ('0' = OK, '1' = signal lost) + SD_TXCLK_BAD_IN : in std_logic; -- SerDes Tx Clock locked ('0' = locked, '1' = not locked) + SD_RXCLK_BAD_IN : in std_logic; -- SerDes Rx Clock locked ('0' = locked, '1' = not locked) + SD_RETRY_IN : in std_logic; -- '0' = handle byte swapping in logic, '1' = simply restart link and hope + SD_ALIGNMENT_IN : in std_logic_vector(1 downto 0); -- SerDes Byte alignment ("10" = swapped, "01" = correct) + SD_CV_IN : in std_logic_vector(1 downto 0); -- SerDes Code Violation ("00" = OK, everything else = BAD) + -- control signals + FULL_RESET_OUT : out std_logic; -- full reset AKA quad_reset + LANE_RESET_OUT : out std_logic; -- partial reset AKA lane_reset + TX_ALLOW_OUT : out std_logic; -- allow normal transmit operation + RX_ALLOW_OUT : out std_logic; -- allow normal receive operation + SWAP_BYTES_OUT : out std_logic; -- bytes need swapping ('0' = correct order, '1' = swapped order) + -- debug signals + STAT_OP : out std_logic_vector(15 downto 0); + CTRL_OP : in std_logic_vector(15 downto 0); + STAT_DEBUG : out std_logic_vector(31 downto 0) + ); +end entity; + +architecture lsm_sfp of trb_net16_lsm_sfp is + +-- state machine signals +type STATES is ( QRST, SLEEP, WPAR, WLOS, ALIGN, WRXA, WTXA, LINK, CVFND, CVBAD ); +signal CURRENT_STATE, NEXT_STATE: STATES; + +signal state_bits : std_logic_vector(3 downto 0); + +signal next_med_error : std_logic_vector(2 downto 0); +signal med_error : std_logic_vector(2 downto 0); +signal next_ce_tctr : std_logic; +signal ce_tctr : std_logic; +signal next_rst_tctr : std_logic; +signal rst_tctr : std_logic; +signal next_quad_rst : std_logic; +signal quad_rst : std_logic; +signal next_lane_rst : std_logic; +signal lane_rst : std_logic; +signal next_rx_allow : std_logic; +signal rx_allow : std_logic; +signal next_tx_allow : std_logic; +signal tx_allow : std_logic; +signal next_align_me : std_logic; +signal align_me : std_logic; +signal next_resync : std_logic; +signal resync : std_logic; +signal next_reset_me : std_logic; +signal reset_me : std_logic; +signal next_ce_cctr : std_logic; +signal ce_cctr : std_logic; +signal next_rst_cctr : std_logic; +signal rst_cctr : std_logic; + +signal buf_swap_bytes : std_logic; + +signal timing_ctr : std_logic_vector(28 downto 0); +signal cv_ctr : std_logic_vector(15 downto 0); + +signal link_status_led : std_logic; + +begin + +-------------------------------------------------------------------------- +-- Main control state machine, startup control for SFP +-------------------------------------------------------------------------- + +-- "Swap Bytes" indicator +THE_SWAP_BYTES_PROC: process( sysclk, clear ) +begin + if( clear = '1' ) then + buf_swap_bytes <= '0'; + elsif( rising_edge(sysclk) ) then + if ( (align_me = '1') and (sd_alignment_in = "10") ) then + buf_swap_bytes <= '1'; + elsif( (align_me = '1') and (sd_alignment_in = "01") ) then + buf_swap_bytes <= '0'; + end if; + end if; +end process THE_SWAP_BYTES_PROC; + +-- Timing counter for reset sequencing +THE_TIMING_COUNTER_PROC: process( sysclk, clear ) +begin + if( clear = '1' ) then + timing_ctr <= (others => '0'); + elsif( rising_edge(sysclk) ) then + if ( rst_tctr = '1' ) then + timing_ctr <= (others => '0'); + elsif( ce_tctr = '1' ) then + timing_ctr <= timing_ctr + 1; + end if; + end if; +end process THE_TIMING_COUNTER_PROC; + +-- CodeViolation counter for Michael Traxler +THE_CV_COUNTER_PROC: process( sysclk, clear ) +begin + if( clear = '1' ) then + cv_ctr <= (others => '0'); + elsif( rising_edge(sysclk) ) then + if ( rst_cctr = '1' ) then + cv_ctr <= (others => '0'); + elsif( ce_cctr = '1' ) then + cv_ctr <= cv_ctr + 1; + end if; + end if; +end process THE_CV_COUNTER_PROC; + +-- State machine +-- state registers +STATE_MEM: process( sysclk, clear ) +begin + if( clear = '1' ) then + CURRENT_STATE <= QRST; + ce_tctr <= '0'; + rst_tctr <= '0'; + ce_cctr <= '0'; + rst_cctr <= '0'; + quad_rst <= '1'; + lane_rst <= '1'; + rx_allow <= '0'; + tx_allow <= '0'; + align_me <= '0'; + reset_me <= '1'; + resync <= '1'; + med_error <= ERROR_NC; + elsif( rising_edge(sysclk) ) then + CURRENT_STATE <= NEXT_STATE; + ce_tctr <= next_ce_tctr; + rst_tctr <= next_rst_tctr; + ce_cctr <= next_ce_cctr; + rst_cctr <= next_rst_cctr; + quad_rst <= next_quad_rst; + lane_rst <= next_lane_rst; + rx_allow <= next_rx_allow; + tx_allow <= next_tx_allow; + align_me <= next_align_me; + reset_me <= next_reset_me; + resync <= next_resync; + med_error <= next_med_error; + end if; +end process STATE_MEM; + +-- state transitions +PROC_STATE_TRANSFORM: process( CURRENT_STATE, sfp_missing_in, sfp_los_in, timing_ctr, sd_alignment_in, cv_ctr, + sd_los_in, sd_link_ok_in, sd_txclk_bad_in, sd_rxclk_bad_in, sd_retry_in, rst_tctr ) +begin + NEXT_STATE <= QRST; -- avoid latches + next_ce_tctr <= '0'; + next_rst_tctr <= '0'; + next_ce_cctr <= '0'; + next_rst_cctr <= '0'; + next_quad_rst <= '0'; + next_lane_rst <= '0'; + next_rx_allow <= '0'; + next_tx_allow <= '0'; + next_align_me <= '0'; + next_reset_me <= '1'; + next_resync <= '1'; + next_med_error <= ERROR_NC; + case CURRENT_STATE is + when QRST => + if( (timing_ctr(4) = '1') and (rst_tctr = '0') ) then + NEXT_STATE <= SLEEP; -- release QUAD_RST, wait for lock of RxClock and TxClock + next_lane_rst <= '1'; + else + NEXT_STATE <= QRST; -- count delay + next_ce_tctr <= '1'; + next_quad_rst <= '1'; + next_lane_rst <= '1'; + end if; + when SLEEP => + if( (sfp_missing_in = '0') and (sfp_los_in = '0') ) then + NEXT_STATE <= WPAR; -- do a correctly timed QUAD reset (about 150ns) + next_rst_tctr <= '1'; + next_lane_rst <= '1'; + next_rst_cctr <= '1'; -- if we start the link, we clear the CV counter + else + NEXT_STATE <= SLEEP; -- wait for SFP present signal + next_ce_tctr <= '1'; + next_lane_rst <= '1'; + end if; + when WPAR => + if ( (sfp_missing_in = '1') or ( sfp_los_in = '1') ) then + NEXT_STATE <= SLEEP; -- SFP has been removed + next_lane_rst <= '1'; + next_ce_tctr <= '1'; + elsif( (sd_rxclk_bad_in = '0') and (sd_txclk_bad_in = '0') ) then + NEXT_STATE <= WLOS; -- PLLs locked, signal present + next_rst_tctr <= '1'; + else + NEXT_STATE <= WPAR; -- wait for RLOL and PLOL and incoming signal from SFP + next_lane_rst <= '1'; + next_ce_tctr <= '1'; + end if; + when WLOS => + if ( (timing_ctr(27) = '0') and (timing_ctr(26) = '0') and (rst_tctr = '0') ) then + NEXT_STATE <= WLOS; + next_resync <= '0'; + next_ce_tctr <= '1'; + elsif( (timing_ctr(27) = '1') and (rst_tctr = '0') ) then + NEXT_STATE <= ALIGN; -- debounce before aligning + next_align_me <= '1'; + next_reset_me <= '0'; + next_ce_tctr <= '1'; + else + NEXT_STATE <= WLOS; -- no alignment found yet + next_ce_tctr <= '1'; + end if; + when ALIGN => + if ( sd_cv_in /= "00" ) then + NEXT_STATE <= ALIGN; + next_ce_cctr <= '1'; -- increment CV counter + next_ce_tctr <= '1'; + next_align_me <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_WAIT; + elsif( (sd_retry_in = '0') and ((sd_alignment_in = "10") or (sd_alignment_in = "01")) ) then + NEXT_STATE <= WRXA; -- one komma character has been received + next_reset_me <= '0'; + next_med_error <= ERROR_WAIT; + elsif( (sd_retry_in = '1') and (sd_alignment_in = "10")) then + NEXT_STATE <= SLEEP; -- MAREK STYLE - CORRECT? + next_rst_tctr <= '1'; + next_lane_rst <= '1'; + else + NEXT_STATE <= ALIGN; -- wait for komma character + next_ce_tctr <= '1'; + next_align_me <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_WAIT; + end if; + when WRXA => + if ( sd_cv_in /= "00" ) then + NEXT_STATE <= WRXA; + next_ce_cctr <= '1'; -- increment CV counter + next_ce_tctr <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_WAIT; + elsif( (timing_ctr(28) = '1') and (rst_tctr = '0') ) then + NEXT_STATE <= WTXA; -- wait cycle done, allow reception of data + next_rst_tctr <= '1'; + next_rx_allow <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_WAIT; + else + NEXT_STATE <= WRXA; -- wait one complete cycle (2^27 x 10ns = 1.3s) + next_ce_tctr <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_WAIT; + end if; + when WTXA => + if ( sd_cv_in /= "00" ) then + NEXT_STATE <= WTXA; + next_ce_cctr <= '1'; -- increment CV counter + next_ce_tctr <= '1'; + next_rx_allow <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_WAIT; + elsif( (timing_ctr(28) = '1') and (rst_tctr = '0') ) then -- we could use [29:0] as counter and use [29] here + NEXT_STATE <= LINK; -- wait cycle done, allow transmission of data + next_rst_tctr <= '1'; + next_rx_allow <= '1'; + next_tx_allow <= '1'; + next_ce_tctr <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_OK; + else + NEXT_STATE <= WTXA; -- wait one complete cycle (2^27 x 10ns = 1.3s) + next_ce_tctr <= '1'; + next_rx_allow <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_WAIT; + end if; + when LINK => + if ( (sfp_missing_in = '1') or (sfp_los_in = '1') ) then + NEXT_STATE <= SLEEP; + next_lane_rst <= '1'; + next_rst_tctr <= '1'; + elsif( sd_cv_in /= "00" ) then + NEXT_STATE <= CVFND; + next_ce_cctr <= '1'; -- increment CV counter + next_rx_allow <= '1'; + next_tx_allow <= '1'; + next_ce_tctr <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_OK; + else + NEXT_STATE <= LINK; + next_rx_allow <= '1'; + next_tx_allow <= '1'; + next_ce_tctr <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_OK; + end if; + when CVFND => + if( cv_ctr(15) = '0' ) then + NEXT_STATE <= LINK; -- try again (?) + next_rx_allow <= '1'; + next_tx_allow <= '1'; + next_ce_tctr <= '1'; + next_reset_me <= '0'; + next_med_error <= ERROR_OK; + else + NEXT_STATE <= CVBAD; + next_ce_tctr <= '1'; + next_med_error <= ERROR_FATAL; + end if; + when CVBAD => + if ( (sfp_missing_in = '1') or (sfp_los_in = '1') ) then + NEXT_STATE <= SLEEP; + next_lane_rst <= '1'; + next_rst_tctr <= '1'; + else + NEXT_STATE <= CVBAD; + next_ce_tctr <= '1'; + next_med_error <= ERROR_FATAL; + end if; + when others => NEXT_STATE <= QRST; + end case; +end process; + +THE_DECODE_PROC: process( CURRENT_STATE, timing_ctr ) +begin + case CURRENT_STATE is + when QRST => state_bits <= "0000"; + link_status_led <= '0'; + when SLEEP => state_bits <= "0001"; + link_status_led <= '0'; + when WPAR => state_bits <= "0010"; + link_status_led <= timing_ctr(23) and timing_ctr(24); -- nice frequency for human eye + when WLOS => state_bits <= "0011"; + link_status_led <= timing_ctr(22); + when ALIGN => state_bits <= "0100"; + link_status_led <= timing_ctr(23); + when WRXA => state_bits <= "0101"; + link_status_led <= timing_ctr(24); + when WTXA => state_bits <= "0110"; + link_status_led <= timing_ctr(25); + when CVFND => state_bits <= "0111"; + link_status_led <= '1'; + when LINK => state_bits <= "1000"; + link_status_led <= '1'; + when CVBAD => state_bits <= "1001"; + link_status_led <= timing_ctr(25) and timing_ctr(24) and timing_ctr(23); + when others => state_bits <= "1111"; + link_status_led <= '0'; + end case; +end process THE_DECODE_PROC; + +-------------------------------------------------------------------------- +-- Output signals +-------------------------------------------------------------------------- +swap_bytes_out <= buf_swap_bytes; +full_reset_out <= quad_rst; +lane_reset_out <= lane_rst; +tx_allow_out <= tx_allow; +rx_allow_out <= rx_allow; + +-------------------------------------------------------------------------- +-- Status output signaled (normed) +-------------------------------------------------------------------------- +stat_op(2 downto 0) <= med_error; +stat_op(8 downto 3) <= (others => '0'); -- unused +stat_op(9) <= link_status_led; +stat_op(10) <= '0'; -- Rx LED, made outside LSM +stat_op(11) <= '0'; -- Tx LED, made outside LSM +stat_op(12) <= '0'; -- unused +stat_op(13) <= '0'; +stat_op(14) <= reset_me; -- reset out +stat_op(15) <= '0'; -- protocol error + +-------------------------------------------------------------------------- +-- Debug output +-------------------------------------------------------------------------- +stat_debug(3 downto 0) <= state_bits; +stat_debug(4) <= align_me; +stat_debug(5) <= buf_swap_bytes; +stat_debug(6) <= resync; +stat_debug(7) <= sfp_missing_in; +stat_debug(8) <= sfp_los_in; +stat_debug(31 downto 9) <= (others => '0'); + + +-------------------------------------------------------------------------- +-------------------------------------------------------------------------- +-- Code prions below +-------------------------------------------------------------------------- +-------------------------------------------------------------------------- + +--Generate LED signals +---------------------- +--process(clock) +-- begin +-- if rising_edge(clock) then +-- led_counter <= led_counter + 1; +-- +-- if buf_med_dataready_out = '1' then +-- rx_led <= '1'; +-- elsif led_counter = 0 then +-- rx_led <= '0'; +-- end if; +-- +-- if tx_k(0) = '0' then +-- tx_led <= '1'; +-- elsif led_counter = 0 then +-- tx_led <= '0'; +-- end if; +-- +-- end if; +-- end process; + +end architecture; \ No newline at end of file diff --git a/media_interfaces/trb_net16_med_ecp_fot_4.vhd b/media_interfaces/trb_net16_med_ecp_fot_4.vhd new file mode 100644 index 0000000..0393b5a --- /dev/null +++ b/media_interfaces/trb_net16_med_ecp_fot_4.vhd @@ -0,0 +1,720 @@ +LIBRARY ieee; +use ieee.std_logic_1164.all; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; + +entity trb_net16_med_ecp_fot_4 is + port( + CLK : in std_logic; + CLK_25 : in std_logic; + CLK_EN : in std_logic; + RESET : in std_logic; + + --Internal Connection + MED_DATA_IN : in std_logic_vector(c_DATA_WIDTH*4-1 downto 0); + MED_PACKET_NUM_IN : in std_logic_vector(c_NUM_WIDTH*4-1 downto 0); + MED_DATAREADY_IN : in std_logic_vector(3 downto 0); + MED_READ_OUT : out std_logic_vector(3 downto 0); + MED_DATA_OUT : out std_logic_vector(c_DATA_WIDTH*4-1 downto 0); + MED_PACKET_NUM_OUT : out std_logic_vector(c_NUM_WIDTH*4-1 downto 0); + MED_DATAREADY_OUT : out std_logic_vector(3 downto 0); + MED_READ_IN : in std_logic_vector(3 downto 0); + + --SFP Connection + TXP : out std_logic_vector(3 downto 0); + TXN : out std_logic_vector(3 downto 0); + RXP : in std_logic_vector(3 downto 0); + RXN : in std_logic_vector(3 downto 0); + SD : in std_logic_vector(3 downto 0); + + -- Status and control port + STAT_OP : out std_logic_vector (63 downto 0); + CTRL_OP : in std_logic_vector (63 downto 0); + STAT_DEBUG : out std_logic_vector (255 downto 0); + CTRL_DEBUG : in std_logic_vector (63 downto 0) + ); +end entity; + +architecture trb_net16_med_ecp_fot_4_arch of trb_net16_med_ecp_fot_4 is + +-- Placer Directives +attribute HGROUP : string; +-- for whole architecture +attribute HGROUP of trb_net16_med_ecp_fot_4_arch : architecture is "GROUP_PCS"; + +component serdes_full_quad is + generic( + USER_CONFIG_FILE : String := "serdes_full_quad.txt" ); + port( + core_txrefclk : in std_logic; + core_rxrefclk : in std_logic; + + hdinp0 : in std_logic; + hdinn0 : in std_logic; + hdoutp0 : out std_logic; + hdoutn0 : out std_logic; + ff_rxiclk_ch0 : in std_logic; + ff_txiclk_ch0 : in std_logic; + ff_ebrd_clk_0 : in std_logic; + ff_txdata_ch0 : in std_logic_vector (7 downto 0); + ff_rxdata_ch0 : out std_logic_vector (7 downto 0); + ff_tx_k_cntrl_ch0 : in std_logic; + ff_rx_k_cntrl_ch0 : out std_logic; + ff_rxfullclk_ch0 : out std_logic; + ff_force_disp_ch0 : in std_logic; + ff_disp_sel_ch0 : in std_logic; + ff_correct_disp_ch0 : in std_logic; + ff_disp_err_ch0 : out std_logic; + ff_cv_ch0 : out std_logic; + ffc_rrst_ch0 : in std_logic; + ffc_lane_tx_rst_ch0 : in std_logic; + ffc_lane_rx_rst_ch0 : in std_logic; + ffc_txpwdnb_ch0 : in std_logic; + ffc_rxpwdnb_ch0 : in std_logic; + ffs_rlos_lo_ch0 : out std_logic; + ffs_ls_sync_status_ch0 : out std_logic; + ffs_cc_underrun_ch0 : out std_logic; + ffs_cc_overrun_ch0 : out std_logic; + ffs_txfbfifo_error_ch0 : out std_logic; + ffs_rxfbfifo_error_ch0 : out std_logic; + ffs_rlol_ch0 : out std_logic; + oob_out_ch0 : out std_logic; + + hdinp1 : in std_logic; + hdinn1 : in std_logic; + hdoutp1 : out std_logic; + hdoutn1 : out std_logic; + ff_rxiclk_ch1 : in std_logic; + ff_txiclk_ch1 : in std_logic; + ff_ebrd_clk_1 : in std_logic; + ff_txdata_ch1 : in std_logic_vector (7 downto 0); + ff_rxdata_ch1 : out std_logic_vector (7 downto 0); + ff_tx_k_cntrl_ch1 : in std_logic; + ff_rx_k_cntrl_ch1 : out std_logic; + ff_rxfullclk_ch1 : out std_logic; + ff_force_disp_ch1 : in std_logic; + ff_disp_sel_ch1 : in std_logic; + ff_correct_disp_ch1 : in std_logic; + ff_disp_err_ch1 : out std_logic; + ff_cv_ch1 : out std_logic; + ffc_rrst_ch1 : in std_logic; + ffc_lane_tx_rst_ch1 : in std_logic; + ffc_lane_rx_rst_ch1 : in std_logic; + ffc_txpwdnb_ch1 : in std_logic; + ffc_rxpwdnb_ch1 : in std_logic; + ffs_rlos_lo_ch1 : out std_logic; + ffs_ls_sync_status_ch1 : out std_logic; + ffs_cc_underrun_ch1 : out std_logic; + ffs_cc_overrun_ch1 : out std_logic; + ffs_txfbfifo_error_ch1 : out std_logic; + ffs_rxfbfifo_error_ch1 : out std_logic; + ffs_rlol_ch1 : out std_logic; + oob_out_ch1 : out std_logic; + + hdinp2 : in std_logic; + hdinn2 : in std_logic; + hdoutp2 : out std_logic; + hdoutn2 : out std_logic; + ff_rxiclk_ch2 : in std_logic; + ff_txiclk_ch2 : in std_logic; + ff_ebrd_clk_2 : in std_logic; + ff_txdata_ch2 : in std_logic_vector (7 downto 0); + ff_rxdata_ch2 : out std_logic_vector (7 downto 0); + ff_tx_k_cntrl_ch2 : in std_logic; + ff_rx_k_cntrl_ch2 : out std_logic; + ff_rxfullclk_ch2 : out std_logic; + ff_force_disp_ch2 : in std_logic; + ff_disp_sel_ch2 : in std_logic; + ff_correct_disp_ch2 : in std_logic; + ff_disp_err_ch2 : out std_logic; + ff_cv_ch2 : out std_logic; + ffc_rrst_ch2 : in std_logic; + ffc_lane_tx_rst_ch2 : in std_logic; + ffc_lane_rx_rst_ch2 : in std_logic; + ffc_txpwdnb_ch2 : in std_logic; + ffc_rxpwdnb_ch2 : in std_logic; + ffs_rlos_lo_ch2 : out std_logic; + ffs_ls_sync_status_ch2 : out std_logic; + ffs_cc_underrun_ch2 : out std_logic; + ffs_cc_overrun_ch2 : out std_logic; + ffs_txfbfifo_error_ch2 : out std_logic; + ffs_rxfbfifo_error_ch2 : out std_logic; + ffs_rlol_ch2 : out std_logic; + oob_out_ch2 : out std_logic; + + hdinp3 : in std_logic; + hdinn3 : in std_logic; + hdoutp3 : out std_logic; + hdoutn3 : out std_logic; + ff_rxiclk_ch3 : in std_logic; + ff_txiclk_ch3 : in std_logic; + ff_ebrd_clk_3 : in std_logic; + ff_txdata_ch3 : in std_logic_vector (7 downto 0); + ff_rxdata_ch3 : out std_logic_vector (7 downto 0); + ff_tx_k_cntrl_ch3 : in std_logic; + ff_rx_k_cntrl_ch3 : out std_logic; + ff_rxfullclk_ch3 : out std_logic; + ff_force_disp_ch3 : in std_logic; + ff_disp_sel_ch3 : in std_logic; + ff_correct_disp_ch3 : in std_logic; + ff_disp_err_ch3 : out std_logic; + ff_cv_ch3 : out std_logic; + ffc_rrst_ch3 : in std_logic; + ffc_lane_tx_rst_ch3 : in std_logic; + ffc_lane_rx_rst_ch3 : in std_logic; + ffc_txpwdnb_ch3 : in std_logic; + ffc_rxpwdnb_ch3 : in std_logic; + ffs_rlos_lo_ch3 : out std_logic; + ffs_ls_sync_status_ch3 : out std_logic; + ffs_cc_underrun_ch3 : out std_logic; + ffs_cc_overrun_ch3 : out std_logic; + ffs_txfbfifo_error_ch3 : out std_logic; + ffs_rxfbfifo_error_ch3 : out std_logic; + ffs_rlol_ch3 : out std_logic; + oob_out_ch3 : out std_logic; + + ffc_macro_rst : in std_logic; + ffc_quad_rst : in std_logic; + ffc_trst : in std_logic; + ff_txfullclk : out std_logic; + ff_txhalfclk : out std_logic; + ffs_plol : out std_logic + ); + end component; + + component trb_net16_lsm_sfp is + port( + SYSCLK : in std_logic; -- fabric clock + RESET : in std_logic; -- synchronous reset + CLEAR : in std_logic; -- asynchronous reset, connect to '0' if not needed / available + -- status signals + SFP_MISSING_IN : in std_logic; -- SFP Present ('0' = no SFP mounted, '1' = SFP in place) + SFP_LOS_IN : in std_logic; -- SFP Loss Of Signal ('0' = OK, '1' = no signal) + SD_LINK_OK_IN : in std_logic; -- SerDes Link OK ('0' = not linked, '1' link established) + SD_LOS_IN : in std_logic; -- SerDes Loss Of Signal ('0' = OK, '1' = signal lost) + SD_TXCLK_BAD_IN : in std_logic; -- SerDes Tx Clock locked ('0' = locked, '1' = not locked) + SD_RXCLK_BAD_IN : in std_logic; -- SerDes Rx Clock locked ('0' = locked, '1' = not locked) + SD_RETRY_IN : in std_logic; -- '0' = handle byte swapping in logic, '1' = simply restart link and hope + SD_ALIGNMENT_IN : in std_logic_vector(1 downto 0); -- SerDes Byte alignment ("10" = swapped, "01" = correct) + SD_CV_IN : in std_logic_vector(1 downto 0); -- SerDes Code Violation ("00" = OK, everything else = BAD) + -- control signals + FULL_RESET_OUT : out std_logic; -- full reset AKA quad_reset + LANE_RESET_OUT : out std_logic; -- partial reset AKA lane_reset + TX_ALLOW_OUT : out std_logic; -- allow normal transmit operation + RX_ALLOW_OUT : out std_logic; -- allow normal receive operation + SWAP_BYTES_OUT : out std_logic; -- bytes need swapping ('0' = correct order, '1' = swapped order) + -- debug signals + STAT_OP : out std_logic_vector(15 downto 0); + CTRL_OP : in std_logic_vector(15 downto 0); + STAT_DEBUG : out std_logic_vector(31 downto 0) + ); + end component; + + component signal_sync is + generic( + WIDTH : integer := 1; -- + DEPTH : integer := 3 + ); + port( + RESET : in std_logic; --Reset is neceessary to avoid optimization to shift register + CLK0 : in std_logic; --clock for first FF + CLK1 : in std_logic; --Clock for other FF + D_IN : in std_logic_vector(WIDTH-1 downto 0); --Data input + D_OUT : out std_logic_vector(WIDTH-1 downto 0) --Data output + ); + end component; + + component lattice_ecp2m_fifo_8x8_dualport + port ( + Data: in std_logic_vector(7 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(7 downto 0); + Empty: out std_logic; + Full: out std_logic + ); + end component; + + component lattice_ecp2m_fifo_16x8_dualport + port ( + Data: in std_logic_vector(15 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(15 downto 0); + Empty: out std_logic; + Full: out std_logic + ); + end component; + + + + type link_error_t is array(0 to 3) of std_logic_vector(7 downto 0); + signal link_error : link_error_t; + signal link_error_q: link_error_t; + signal reg_link_error : link_error_t; + signal ffs_plol : std_logic; + signal link_ok : std_logic_vector(3 downto 0); + signal tx_data : std_logic_vector(8*4-1 downto 0); + signal rx_data : std_logic_vector(8*4-1 downto 0); + signal ff_rxfullclk : std_logic_vector(3 downto 0); + signal ff_txfullclk : std_logic; + signal rx_k : std_logic_vector(3 downto 0); + signal tx_k : std_logic_vector(3 downto 0); + signal lane_rst : std_logic_vector(3 downto 0); + signal quad_rst : std_logic_vector(3 downto 0); + + signal byte_waiting : std_logic_vector(3 downto 0); + signal byte_buffer : std_logic_vector(4*8-1 downto 0); + signal fifo_reset : std_logic_vector(3 downto 0); + signal tx_fifo_dout : std_logic_vector(4*16-1 downto 0); + signal tx_fifo_data_in : std_logic_vector(4*16-1 downto 0); + signal tx_fifo_read_en : std_logic_vector(3 downto 0); + signal tx_fifo_write_en : std_logic_vector(3 downto 0); + signal tx_fifo_empty : std_logic_vector(3 downto 0); + signal tx_fifo_full : std_logic_vector(3 downto 0); + signal last_tx_fifo_read_en : std_logic_vector(3 downto 0); + signal last_tx_fifo_empty : std_logic_vector(3 downto 0); + signal tx_fifo_valid_read : std_logic_vector(3 downto 0); + signal tx_allow : std_logic_vector(3 downto 0); + + signal rx_data_reg : std_logic_vector(4*8-1 downto 0); + signal buf_rx_data : std_logic_vector(4*8-1 downto 0); + signal buf_rx_k : std_logic_vector(3 downto 0); + signal rx_fifo_write_en : std_logic_vector(3 downto 0); + signal rx_fifo_read_en : std_logic_vector(3 downto 0); + signal rx_fifo_empty : std_logic_vector(3 downto 0); + signal rx_fifo_full : std_logic_vector(3 downto 0); + signal rx_fifo_dout : std_logic_vector(4*8-1 downto 0); + signal is_idle_word : std_logic_vector(3 downto 0); + signal rx_starting : std_logic_vector(3 downto 0); + signal rx_allow : std_logic_vector(3 downto 0); + signal sd_q : std_logic_vector(3 downto 0); + signal last_rx_fifo_read_en : std_logic_vector(3 downto 0); + signal last_rx_fifo_empty : std_logic_vector(3 downto 0); + + signal buf_med_dataready_out : std_logic_vector(3 downto 0); + signal buf_med_read_out : std_logic_vector(3 downto 0); + signal buf_med_data_out : std_logic_vector(16*4-1 downto 0); + signal byte_select : std_logic_vector(3 downto 0); + signal rx_counter : std_logic_vector(4*c_NUM_WIDTH-1 downto 0); + signal sfp_los : std_logic_vector(3 downto 0); + + type led_counter_t is array(0 to 3) of std_logic_vector(15 downto 0); + signal led_counter : led_counter_t; + signal rx_led : std_logic_vector(3 downto 0); + signal tx_led : std_logic_vector(3 downto 0); + + signal FSM_STAT_OP : std_logic_vector(4*16-1 downto 0); + signal FSM_STAT_DEBUG : std_logic_vector(4*64-1 downto 0); + signal FSM_CTRL_OP : std_logic_vector(4*16-1 downto 0); + +begin + + THE_SERDES: serdes_full_quad + port map( + core_txrefclk => CLK_25, + core_rxrefclk => CLK_25, + hdinp0 => RXP(0), + hdinn0 => RXN(0), + hdoutp0 => TXP(0), + hdoutn0 => TXN(0), + ff_rxiclk_ch0 => ff_rxfullclk(0), + ff_txiclk_ch0 => ff_txfullclk, + ff_ebrd_clk_0 => ff_rxfullclk(0), + ff_txdata_ch0 => tx_data(7 downto 0), + ff_rxdata_ch0 => rx_data(7 downto 0), + ff_tx_k_cntrl_ch0 => tx_k(0), + ff_rx_k_cntrl_ch0 => rx_k(0), + ff_rxfullclk_ch0 => ff_rxfullclk(0), + ff_force_disp_ch0 => '0', + ff_disp_sel_ch0 => '0', + ff_correct_disp_ch0 => '0', + ff_disp_err_ch0 => link_error(0)(0), + ff_cv_ch0 => link_error(0)(1), + ffc_rrst_ch0 => '0', + ffc_lane_tx_rst_ch0 => lane_rst(0), --lane_rst(0), + ffc_lane_rx_rst_ch0 => lane_rst(0), + ffc_txpwdnb_ch0 => '1', + ffc_rxpwdnb_ch0 => '1', + ffs_rlos_lo_ch0 => link_error(0)(2), + ffs_ls_sync_status_ch0 => link_ok(0), + ffs_cc_underrun_ch0 => link_error(0)(3), + ffs_cc_overrun_ch0 => link_error(0)(4), + ffs_txfbfifo_error_ch0 => link_error(0)(5), + ffs_rxfbfifo_error_ch0 => link_error(0)(6), + ffs_rlol_ch0 => link_error(0)(7), + oob_out_ch0 => open, + + hdinp1 => rxp(1), + hdinn1 => rxn(1), + hdoutp1 => txp(1), + hdoutn1 => txn(1), + ff_rxiclk_ch1 => ff_rxfullclk(1), + ff_txiclk_ch1 => ff_txfullclk, + ff_ebrd_clk_1 => ff_rxfullclk(1), + ff_txdata_ch1 => tx_data(15 downto 8), + ff_rxdata_ch1 => rx_data(15 downto 8), + ff_tx_k_cntrl_ch1 => tx_k(1), + ff_rx_k_cntrl_ch1 => rx_k(1), + ff_rxfullclk_ch1 => ff_rxfullclk(1), + ff_force_disp_ch1 => '0', + ff_disp_sel_ch1 => '0', + ff_correct_disp_ch1 => '0', + ff_disp_err_ch1 => link_error(1)(0), + ff_cv_ch1 => link_error(1)(1), + ffc_rrst_ch1 => '0', + ffc_lane_tx_rst_ch1 => lane_rst(1), --lane_rst(1), + ffc_lane_rx_rst_ch1 => lane_rst(1), + ffc_txpwdnb_ch1 => '1', + ffc_rxpwdnb_ch1 => '1', + ffs_rlos_lo_ch1 => link_error(1)(2), + ffs_ls_sync_status_ch1 => link_ok(1), + ffs_cc_underrun_ch1 => link_error(1)(3), + ffs_cc_overrun_ch1 => link_error(1)(4), + ffs_txfbfifo_error_ch1 => link_error(1)(5), + ffs_rxfbfifo_error_ch1 => link_error(1)(6), + ffs_rlol_ch1 => link_error(1)(7), + oob_out_ch1 => open, + + hdinp2 => rxp(2), + hdinn2 => rxn(2), + hdoutp2 => txp(2), + hdoutn2 => txn(2), + ff_rxiclk_ch2 => ff_rxfullclk(2), + ff_txiclk_ch2 => ff_txfullclk, + ff_ebrd_clk_2 => ff_rxfullclk(2), + ff_txdata_ch2 => tx_data(23 downto 16), + ff_rxdata_ch2 => rx_data(23 downto 16), + ff_tx_k_cntrl_ch2 => tx_k(2), + ff_rx_k_cntrl_ch2 => rx_k(2), + ff_rxfullclk_ch2 => ff_rxfullclk(2), + ff_force_disp_ch2 => '0', + ff_disp_sel_ch2 => '0', + ff_correct_disp_ch2 => '0', + ff_disp_err_ch2 => link_error(2)(0), + ff_cv_ch2 => link_error(2)(1), + ffc_rrst_ch2 => '0', + ffc_lane_tx_rst_ch2 => lane_rst(2), --lane_rst(2), + ffc_lane_rx_rst_ch2 => lane_rst(2), + ffc_txpwdnb_ch2 => '1', + ffc_rxpwdnb_ch2 => '1', + ffs_rlos_lo_ch2 => link_error(2)(2), + ffs_ls_sync_status_ch2 => link_ok(2), + ffs_cc_underrun_ch2 => link_error(2)(3), + ffs_cc_overrun_ch2 => link_error(2)(4), + ffs_txfbfifo_error_ch2 => link_error(2)(5), + ffs_rxfbfifo_error_ch2 => link_error(2)(6), + ffs_rlol_ch2 => link_error(2)(7), + oob_out_ch2 => open, + + hdinp3 => rxp(3), + hdinn3 => rxn(3), + hdoutp3 => txp(3), + hdoutn3 => txn(3), + ff_rxiclk_ch3 => ff_rxfullclk(3), + ff_txiclk_ch3 => ff_txfullclk, + ff_ebrd_clk_3 => ff_rxfullclk(3), + ff_txdata_ch3 => tx_data(31 downto 24), + ff_rxdata_ch3 => rx_data(31 downto 24), + ff_tx_k_cntrl_ch3 => tx_k(3), + ff_rx_k_cntrl_ch3 => rx_k(3), + ff_rxfullclk_ch3 => ff_rxfullclk(3), + ff_force_disp_ch3 => '0', + ff_disp_sel_ch3 => '0', + ff_correct_disp_ch3 => '0', + ff_disp_err_ch3 => link_error(3)(0), + ff_cv_ch3 => link_error(3)(1), + ffc_rrst_ch3 => '0', + ffc_lane_tx_rst_ch3 => lane_rst(3), --lane_rst(3), + ffc_lane_rx_rst_ch3 => lane_rst(3), + ffc_txpwdnb_ch3 => '1', + ffc_rxpwdnb_ch3 => '1', + ffs_rlos_lo_ch3 => link_error(3)(2), + ffs_ls_sync_status_ch3 => link_ok(3), + ffs_cc_underrun_ch3 => link_error(3)(3), + ffs_cc_overrun_ch3 => link_error(3)(4), + ffs_txfbfifo_error_ch3 => link_error(3)(5), + ffs_rxfbfifo_error_ch3 => link_error(3)(6), + ffs_rlol_ch3 => link_error(3)(7), + oob_out_ch3 => open, + + ffc_macro_rst => '0', + ffc_quad_rst => quad_rst(0), + ffc_trst => '0', + ff_txfullclk => ff_txfullclk, + ffs_plol => ffs_plol + ); + +--TX Control 25 +--------------- + + gen_tx_fifos : for i in 0 to 3 generate + + THE_TX_FIFO: lattice_ecp2m_fifo_16x8_dualport + port map( + Data => tx_fifo_data_in((i+1)*16-1 downto i*16), + WrClock => CLK, + RdClock => ff_txfullclk, + WrEn => tx_fifo_write_en(i), + RdEn => tx_fifo_read_en(i), + Reset => fifo_reset(i), + RPReset => fifo_reset(i), + Q => tx_fifo_dout((i+1)*16-1 downto i*16), + Empty => tx_fifo_empty(i), + Full => tx_fifo_full(i) + ); + + THE_READ_TX_FIFO_PROC: process( ff_txfullclk ) + begin + if( rising_edge(ff_txfullclk) ) then + if( reset = '1' ) then + byte_waiting(i) <= '0'; + tx_fifo_read_en(i) <= '0'; + tx_k(i) <= '1'; + tx_data((i+1)*8-1 downto i*8) <= x"EE"; + tx_fifo_valid_read(i) <= '0'; + else + tx_fifo_read_en(i) <= tx_allow(i); + last_tx_fifo_read_en(i) <= tx_fifo_read_en(i); + last_tx_fifo_empty(i) <= tx_fifo_empty(i); + tx_fifo_valid_read(i) <= tx_fifo_read_en(i) and not tx_fifo_empty(i); + if( byte_waiting(i) = '0' ) then + if( (tx_fifo_valid_read(i) = '1')) then + byte_buffer((i+1)*8-1 downto i*8) <= tx_fifo_dout((i)*16+15 downto i*16+8); + byte_waiting(i) <= '1'; + tx_k(i) <= '0'; + tx_data((i+1)*8-1 downto i*8) <= tx_fifo_dout(7 downto 0); + tx_fifo_read_en(i) <= tx_allow(i); + else + byte_buffer((i+1)*8-1 downto i*8) <= x"50"; + byte_waiting(i) <= '1'; + tx_k(i) <= '1'; + tx_data((i+1)*8-1 downto i*8) <= x"BC"; + tx_fifo_read_en(i) <= tx_allow(i); + end if; + else --if byte_waiting = '1' then + tx_data((i+1)*8-1 downto i*8) <= byte_buffer((i+1)*8-1 downto i*8); + tx_k(i) <= '0'; --second byte is always data + byte_waiting(i) <= '0'; + tx_fifo_read_en(i) <= '0'; + end if; + end if; + end if; + end process; + + fifo_reset(i) <= reset or quad_rst(0); + + --RX Control (25) + --------------------- + + THE_RX_FIFO: lattice_ecp2m_fifo_8x8_dualport + port map( + Data => rx_data_reg((i+1)*8-1 downto i*8), + WrClock => ff_rxfullclk(i), + RdClock => clk, + WrEn => rx_fifo_write_en(i), + RdEn => rx_fifo_read_en(i), + Reset => fifo_reset(i), + RPReset => fifo_reset(i), + Q => rx_fifo_dout((i+1)*8-1 downto i*8), + Empty => rx_fifo_empty(i), + Full => rx_fifo_full(i) + ); + + THE_WRITE_RX_FIFO_PROC: process( ff_rxfullclk ) + begin + if( rising_edge(ff_rxfullclk(i)) ) then + buf_rx_data((i+1)*8-1 downto i*8) <= rx_data((i+1)*8-1 downto i*8); + buf_rx_k(i) <= rx_k(i); + if( (reset = '1') or (rx_allow(i) = '0') ) then + rx_fifo_write_en(i) <= '0'; + is_idle_word(i) <= '1'; + rx_starting(i) <= '1'; + else + rx_data_reg((i+1)*8-1 downto i*8) <= buf_rx_data((i+1)*8-1 downto i*8); + if( rx_allow(i) = '1' ) then + if( (rx_k(i) = '0') and (is_idle_word(i) = '0') and (rx_starting(i) = '0') ) then + rx_fifo_write_en(i) <= '1'; + else + rx_fifo_write_en(i) <= '0'; + end if; + if ( buf_rx_k(i) = '1' ) then + is_idle_word(i) <= '1'; + rx_starting(i) <= '0'; + elsif( (buf_rx_k(i) = '0') and (is_idle_word(i) = '1') ) then + is_idle_word(i) <= '0'; + end if; + end if; + end if; + end if; + end process THE_WRITE_RX_FIFO_PROC; + +--TX Control (100) +--------------------- + buf_med_read_out(i) <= not tx_fifo_full(i) and tx_allow(i); + tx_fifo_write_en(i) <= buf_med_read_out(i) and med_dataready_in(i); + tx_fifo_data_in(i*16+15 downto i*16) <= med_data_in(i*16+15 downto i*16); + med_read_out(i) <= buf_med_read_out(i); + +--RX Control (100) +--------------------- + process( clk ) + begin + if( rising_edge(clk) ) then + if( reset = '1' ) then + buf_med_dataready_out(i) <= '0'; + byte_select(i) <= '0'; + last_rx_fifo_read_en(i) <= '0'; + else + last_rx_fifo_read_en(i) <= rx_fifo_read_en(i); + buf_med_dataready_out(i) <= '0'; + if( (last_rx_fifo_empty(i) = '0') and (last_rx_fifo_read_en(i) = '1') ) then + if( byte_select(i) = '1' ) then + buf_MED_DATA_OUT((i+1)*16-1 downto i*16) <= rx_fifo_dout((i+1)*8-1 downto i*8) + & buf_MED_DATA_OUT(i*16+7 downto i*16); + buf_MED_DATAREADY_OUT(i) <= '1'; + else + buf_MED_DATA_OUT((i+1)*16-1 downto i*16) <= x"00" & rx_fifo_dout((i+1)*8-1 downto i*8); + end if; + byte_select(i) <= not byte_select(i); + end if; + end if; + end if; + end process; + + rx_fifo_read_en(i) <= tx_allow(i); + MED_DATA_OUT((i+1)*16-1 downto i*16) <= buf_MED_DATA_OUT((i+1)*16-1 downto i*16); + MED_DATAREADY_OUT(i) <= buf_MED_DATAREADY_OUT(i); + MED_PACKET_NUM_OUT((i+1)*c_NUM_WIDTH-1 downto i*c_NUM_WIDTH) <= rx_counter((i+1)*c_NUM_WIDTH-1 downto i*c_NUM_WIDTH); + +--rx packet counter +--------------------- + THE_RX_PACKETS_PROC: process( clk ) + begin + if( rising_edge(clk) ) then + last_rx_fifo_empty(i) <= rx_fifo_empty(i); + if( (reset = '1') or (rx_allow(i) = '0') ) then + rx_counter(i*3+2 downto i*3) <= c_H0; + else + if( buf_med_dataready_out(i) = '1' ) then + if( rx_counter(i*3+2 downto i*3) = c_max_word_number ) then + rx_counter(i*3+2 downto i*3) <= (others => '0'); + else + rx_counter(i*3+2 downto i*3) <= rx_counter(i*3+2 downto i*3) + 1; + end if; + end if; + end if; + end if; + end process; + + + +--Link State machine +--------------------- + + + LINK_ERROR_SYNC: signal_sync + generic map( + DEPTH => 2, + WIDTH => 8 + ) + port map( + RESET => reset, + D_IN(7 downto 0) => link_error(i), + CLK0 => ff_rxfullclk(i), + CLK1 => CLK, + D_OUT(7 downto 0) => link_error_q(i) + ); + + SD_SYNC_2: signal_sync + generic map( + DEPTH => 2, + WIDTH => 1 + ) + port map( + RESET => reset, + D_IN(0) => sd(i), + CLK0 => ff_rxfullclk(i), + CLK1 => CLK, + D_OUT(0) => sd_q(i) + ); + +--LED Signals +--------------------- + THE_TX_RX_LED_PROC: process( clk ) + begin + if( rising_edge(CLK) ) then + led_counter(i) <= led_counter(i) + 1; + if ( buf_med_dataready_out(i) = '1' ) then + rx_led(i) <= '1'; + elsif( led_counter(i) = 0 ) then + rx_led(i) <= '0'; + end if; + if( tx_fifo_valid_read(i) = '1') then + tx_led(i) <= '1'; + elsif led_counter(i) = 0 then + tx_led(i) <= '0'; + end if; + end if; + end process; + + + STAT_OP(i*16+9 downto i*16+0) <= FSM_STAT_OP(i*16+9 downto i*16+0); + STAT_OP(i*16+10) <= rx_led(i); + STAT_OP(i*16+11) <= tx_led(i); + STAT_OP(i*16+15 downto i*16+12) <= FSM_STAT_OP(i*16+15 downto i*16+12); + + STAT_DEBUG(i*64+31 downto i*64+0) <= FSM_STAT_DEBUG(i*32+31 downto i*32); + STAT_DEBUG(i*64+39 downto i*64+32) <= rx_data_reg(i*8+7 downto i*8); + STAT_DEBUG(i*64+63 downto i*64+40) <= (others => '0'); + + end generate; + + + gen_lsm : for i in 0 to 3 generate + THE_SFP_LSM: trb_net16_lsm_sfp + port map( + SYSCLK => CLK, + RESET => reset, + CLEAR => reset, + SFP_MISSING_IN => '0', + SFP_LOS_IN => sfp_los(i), + SD_LINK_OK_IN => link_ok(i), + SD_LOS_IN => link_error(i)(2), + SD_TXCLK_BAD_IN => ffs_plol, + SD_RXCLK_BAD_IN => link_error(i)(7), + SD_RETRY_IN => '0', -- '0' = handle byte swapping in logic, '1' = simply restart link and hope + SD_ALIGNMENT_IN => "10", + SD_CV_IN(0) => link_error(i)(1), + SD_CV_IN(1) => '0', + FULL_RESET_OUT => quad_rst(i), + LANE_RESET_OUT => lane_rst(i), + TX_ALLOW_OUT => tx_allow(i), + RX_ALLOW_OUT => rx_allow(i), + SWAP_BYTES_OUT => open, + STAT_OP => FSM_STAT_OP(i*16+15 downto i*16), + CTRL_OP => FSM_CTRL_OP(i*16+15 downto i*16), + STAT_DEBUG => FSM_STAT_DEBUG(i*32+31 downto i*32) + ); + + end generate; + + sfp_los <= not sd_q; + FSM_CTRL_OP <= CTRL_OP; + + + + + +end architecture; \ No newline at end of file diff --git a/media_interfaces/trb_net16_med_ecp_sfp.vhd b/media_interfaces/trb_net16_med_ecp_sfp.vhd new file mode 100644 index 0000000..00e4ea6 --- /dev/null +++ b/media_interfaces/trb_net16_med_ecp_sfp.vhd @@ -0,0 +1,805 @@ +--Media interface for Lattice ECP2M using PCS at 2GHz + +--Still missing: link reset features, fifo full error handling, signals on stat_op + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.std_logic_ARITH.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; + +entity trb_net16_med_ecp_sfp is + generic( + SERDES_NUM : integer range 0 to 3 := 2 + ); + port( + CLK : in std_logic; -- SerDes clock + SYSCLK : in std_logic; -- fabric clock + RESET : in std_logic; -- synchronous reset + CLEAR : in std_logic; -- asynchronous reset + CLK_EN : in std_logic; + --Internal Connection + MED_DATA_IN : in std_logic_vector(c_DATA_WIDTH-1 downto 0); + MED_PACKET_NUM_IN : in std_logic_vector(c_NUM_WIDTH-1 downto 0); + MED_DATAREADY_IN : in std_logic; + MED_READ_OUT : out std_logic; + MED_DATA_OUT : out std_logic_vector(c_DATA_WIDTH-1 downto 0); + MED_PACKET_NUM_OUT : out std_logic_vector(c_NUM_WIDTH-1 downto 0); + MED_DATAREADY_OUT : out std_logic; + MED_READ_IN : in std_logic; + REFCLK2CORE_OUT : out std_logic; + --SFP Connection + SD_RXD_P_IN : in std_logic; + SD_RXD_N_IN : in std_logic; + SD_TXD_P_OUT : out std_logic; + SD_TXD_N_OUT : out std_logic; + SD_REFCLK_P_IN : in std_logic; + SD_REFCLK_N_IN : in std_logic; + SD_PRSNT_N_IN : in std_logic; -- SFP Present ('0' = SFP in place, '1' = no SFP mounted) + SD_LOS_IN : in std_logic; -- SFP Loss Of Signal ('0' = OK, '1' = no signal) + -- Status and control port + STAT_OP : out std_logic_vector (15 downto 0); + CTRL_OP : in std_logic_vector (15 downto 0); + STAT_DEBUG : out std_logic_vector (63 downto 0); + CTRL_DEBUG : in std_logic_vector (63 downto 0) + ); +end entity; + +architecture med_ecp_sfp of trb_net16_med_ecp_sfp is + + component serdes_0 + port( + core_txrefclk : in std_logic; + core_rxrefclk : in std_logic; + hdinp0 : in std_logic; + hdinn0 : in std_logic; + ff_rxiclk_ch0 : in std_logic; + ff_txiclk_ch0 : in std_logic; + ff_ebrd_clk_0 : in std_logic; + ff_txdata_ch0 : in std_logic_vector(15 downto 0); + ff_tx_k_cntrl_ch0 : in std_logic_vector(1 downto 0); + ff_force_disp_ch0 : in std_logic_vector(1 downto 0); + ff_disp_sel_ch0 : in std_logic_vector(1 downto 0); + ff_correct_disp_ch0 : in std_logic_vector(1 downto 0); + ffc_rrst_ch0 : in std_logic; + ffc_lane_tx_rst_ch0 : in std_logic; + ffc_lane_rx_rst_ch0 : in std_logic; + ffc_txpwdnb_ch0 : in std_logic; + ffc_rxpwdnb_ch0 : in std_logic; + ffc_macro_rst : in std_logic; + ffc_quad_rst : in std_logic; + ffc_trst : in std_logic; + hdoutp0 : out std_logic; + hdoutn0 : out std_logic; + ff_rxdata_ch0 : out std_logic_vector(15 downto 0); + ff_rx_k_cntrl_ch0 : out std_logic_vector(1 downto 0); + ff_rxfullclk_ch0 : out std_logic; + ff_rxhalfclk_ch0 : out std_logic; + ff_disp_err_ch0 : out std_logic_vector(1 downto 0); + ff_cv_ch0 : out std_logic_vector(1 downto 0); + ffs_rlos_lo_ch0 : out std_logic; + ffs_ls_sync_status_ch0 : out std_logic; + ffs_cc_underrun_ch0 : out std_logic; + ffs_cc_overrun_ch0 : out std_logic; + ffs_txfbfifo_error_ch0 : out std_logic; + ffs_rxfbfifo_error_ch0 : out std_logic; + ffs_rlol_ch0 : out std_logic; + oob_out_ch0 : out std_logic; + ff_txfullclk : out std_logic; + ff_txhalfclk : out std_logic; + refck2core : out std_logic; + ffs_plol : out std_logic + ); + end component; + + component serdes_1 + port( + core_txrefclk : in std_logic; + core_rxrefclk : in std_logic; + refclkp : IN std_logic; + refclkn : IN std_logic; + hdinp1 : in std_logic; + hdinn1 : in std_logic; + ff_rxiclk_ch1 : in std_logic; + ff_txiclk_ch1 : in std_logic; + ff_ebrd_clk_1 : in std_logic; + ff_txdata_ch1 : in std_logic_vector(15 downto 0); + ff_tx_k_cntrl_ch1 : in std_logic_vector(1 downto 0); + ff_force_disp_ch1 : in std_logic_vector(1 downto 0); + ff_disp_sel_ch1 : in std_logic_vector(1 downto 0); + ff_correct_disp_ch1 : in std_logic_vector(1 downto 0); + ffc_rrst_ch1 : in std_logic; + ffc_lane_tx_rst_ch1 : in std_logic; + ffc_lane_rx_rst_ch1 : in std_logic; + ffc_txpwdnb_ch1 : in std_logic; + ffc_rxpwdnb_ch1 : in std_logic; + ffc_macro_rst : in std_logic; + ffc_quad_rst : in std_logic; + ffc_trst : in std_logic; + hdoutp1 : out std_logic; + hdoutn1 : out std_logic; + ff_rxdata_ch1 : out std_logic_vector(15 downto 0); + ff_rx_k_cntrl_ch1 : out std_logic_vector(1 downto 0); + ff_rxfullclk_ch1 : out std_logic; + ff_rxhalfclk_ch1 : out std_logic; + ff_disp_err_ch1 : out std_logic_vector(1 downto 0); + ff_cv_ch1 : out std_logic_vector(1 downto 0); + ffs_rlos_lo_ch1 : out std_logic; + ffs_ls_sync_status_ch1 : out std_logic; + ffs_cc_underrun_ch1 : out std_logic; + ffs_cc_overrun_ch1 : out std_logic; + ffs_txfbfifo_error_ch1 : out std_logic; + ffs_rxfbfifo_error_ch1 : out std_logic; + ffs_rlol_ch1 : out std_logic; + oob_out_ch1 : out std_logic; + ff_txfullclk : out std_logic; + ff_txhalfclk : out std_logic; + refck2core : out std_logic; + ffs_plol : out std_logic + ); + end component; + + + component serdes_2 + port( + core_txrefclk : in std_logic; + core_rxrefclk : in std_logic; + hdinp2 : in std_logic; + hdinn2 : in std_logic; + ff_rxiclk_ch2 : in std_logic; + ff_txiclk_ch2 : in std_logic; + ff_ebrd_clk_2 : in std_logic; + ff_txdata_ch2 : in std_logic_vector(15 downto 0); + ff_tx_k_cntrl_ch2 : in std_logic_vector(1 downto 0); + ff_force_disp_ch2 : in std_logic_vector(1 downto 0); + ff_disp_sel_ch2 : in std_logic_vector(1 downto 0); + ff_correct_disp_ch2 : in std_logic_vector(1 downto 0); + ffc_rrst_ch2 : in std_logic; + ffc_lane_tx_rst_ch2 : in std_logic; + ffc_lane_rx_rst_ch2 : in std_logic; + ffc_txpwdnb_ch2 : in std_logic; + ffc_rxpwdnb_ch2 : in std_logic; + ffc_macro_rst : in std_logic; + ffc_quad_rst : in std_logic; + ffc_trst : in std_logic; + hdoutp2 : out std_logic; + hdoutn2 : out std_logic; + ff_rxdata_ch2 : out std_logic_vector(15 downto 0); + ff_rx_k_cntrl_ch2 : out std_logic_vector(1 downto 0); + ff_rxfullclk_ch2 : out std_logic; + ff_rxhalfclk_ch2 : out std_logic; + ff_disp_err_ch2 : out std_logic_vector(1 downto 0); + ff_cv_ch2 : out std_logic_vector(1 downto 0); + ffs_rlos_lo_ch2 : out std_logic; + ffs_ls_sync_status_ch2 : out std_logic; + ffs_cc_underrun_ch2 : out std_logic; + ffs_cc_overrun_ch2 : out std_logic; + ffs_txfbfifo_error_ch2 : out std_logic; + ffs_rxfbfifo_error_ch2 : out std_logic; + ffs_rlol_ch2 : out std_logic; + oob_out_ch2 : out std_logic; + ff_txfullclk : out std_logic; + ff_txhalfclk : out std_logic; + refck2core : out std_logic; + ffs_plol : out std_logic + ); + end component; + + component serdes_3 + port( + core_txrefclk : in std_logic; + core_rxrefclk : in std_logic; + hdinp3 : in std_logic; + hdinn3 : in std_logic; + ff_rxiclk_ch3 : in std_logic; + ff_txiclk_ch3 : in std_logic; + ff_ebrd_clk_3 : in std_logic; + ff_txdata_ch3 : in std_logic_vector(15 downto 0); + ff_tx_k_cntrl_ch3 : in std_logic_vector(1 downto 0); + ff_force_disp_ch3 : in std_logic_vector(1 downto 0); + ff_disp_sel_ch3 : in std_logic_vector(1 downto 0); + ff_correct_disp_ch3 : in std_logic_vector(1 downto 0); + ffc_rrst_ch3 : in std_logic; + ffc_lane_tx_rst_ch3 : in std_logic; + ffc_lane_rx_rst_ch3 : in std_logic; + ffc_txpwdnb_ch3 : in std_logic; + ffc_rxpwdnb_ch3 : in std_logic; + ffc_macro_rst : in std_logic; + ffc_quad_rst : in std_logic; + ffc_trst : in std_logic; + hdoutp3 : out std_logic; + hdoutn3 : out std_logic; + ff_rxdata_ch3 : out std_logic_vector(15 downto 0); + ff_rx_k_cntrl_ch3 : out std_logic_vector(1 downto 0); + ff_rxfullclk_ch3 : out std_logic; + ff_rxhalfclk_ch3 : out std_logic; + ff_disp_err_ch3 : out std_logic_vector(1 downto 0); + ff_cv_ch3 : out std_logic_vector(1 downto 0); + ffs_rlos_lo_ch3 : out std_logic; + ffs_ls_sync_status_ch3 : out std_logic; + ffs_cc_underrun_ch3 : out std_logic; + ffs_cc_overrun_ch3 : out std_logic; + ffs_txfbfifo_error_ch3 : out std_logic; + ffs_rxfbfifo_error_ch3 : out std_logic; + ffs_rlol_ch3 : out std_logic; + oob_out_ch3 : out std_logic; + ff_txfullclk : out std_logic; + ff_txhalfclk : out std_logic; + refck2core : out std_logic; + ffs_plol : out std_logic + ); + end component; + + component trb_net16_lsm_sfp is + port( + SYSCLK : in std_logic; -- fabric clock + RESET : in std_logic; -- synchronous reset + CLEAR : in std_logic; -- asynchronous reset, connect to '0' if not needed / available + -- status signals + SFP_MISSING_IN : in std_logic; -- SFP Present ('0' = no SFP mounted, '1' = SFP in place) + SFP_LOS_IN : in std_logic; -- SFP Loss Of Signal ('0' = OK, '1' = no signal) + SD_LINK_OK_IN : in std_logic; -- SerDes Link OK ('0' = not linked, '1' link established) + SD_LOS_IN : in std_logic; -- SerDes Loss Of Signal ('0' = OK, '1' = signal lost) + SD_TXCLK_BAD_IN : in std_logic; -- SerDes Tx Clock locked ('0' = locked, '1' = not locked) + SD_RXCLK_BAD_IN : in std_logic; -- SerDes Rx Clock locked ('0' = locked, '1' = not locked) + SD_RETRY_IN : in std_logic; -- '0' = handle byte swapping in logic, '1' = simply restart link and hope + SD_ALIGNMENT_IN : in std_logic_vector(1 downto 0); -- SerDes Byte alignment ("10" = swapped, "01" = correct) + SD_CV_IN : in std_logic_vector(1 downto 0); -- SerDes Code Violation ("00" = OK, everything else = BAD) + -- control signals + FULL_RESET_OUT : out std_logic; -- full reset AKA quad_reset + LANE_RESET_OUT : out std_logic; -- partial reset AKA lane_reset + TX_ALLOW_OUT : out std_logic; -- allow normal transmit operation + RX_ALLOW_OUT : out std_logic; -- allow normal receive operation + SWAP_BYTES_OUT : out std_logic; -- bytes need swapping ('0' = correct order, '1' = swapped order) + -- debug signals + STAT_OP : out std_logic_vector(15 downto 0); + CTRL_OP : in std_logic_vector(15 downto 0); + STAT_DEBUG : out std_logic_vector(31 downto 0) + ); + end component; + + component trb_net_fifo_16bit_bram_dualport is + generic( + USE_STATUS_FLAGS : integer := c_YES + ); + port( read_clock_in : in std_logic; + write_clock_in : in std_logic; + read_enable_in : in std_logic; + write_enable_in : in std_logic; + fifo_gsr_in : in std_logic; + write_data_in : in std_logic_vector(17 downto 0); + read_data_out : out std_logic_vector(17 downto 0); + full_out : out std_logic; + empty_out : out std_logic; + fifostatus_out : out std_logic_vector(3 downto 0); + valid_read_out : out std_logic; + almost_empty_out : out std_logic; + almost_full_out : out std_logic + ); + end component; + + component signal_sync is + generic( + WIDTH : integer := 1; -- + DEPTH : integer := 3 + ); + port( + RESET : in std_logic; --Reset is neceessary to avoid optimization to shift register + CLK0 : in std_logic; --clock for first FF + CLK1 : in std_logic; --Clock for other FF + D_IN : in std_logic_vector(WIDTH-1 downto 0); --Data input + D_OUT : out std_logic_vector(WIDTH-1 downto 0) --Data output + ); + end component; + + signal refck2core : std_logic; + signal clock : std_logic; + --reset signals + signal ffc_quad_rst : std_logic; + signal ffc_lane_tx_rst : std_logic; + signal ffc_lane_rx_rst : std_logic; + --serdes connections + signal tx_data : std_logic_vector(15 downto 0); + signal tx_k : std_logic_vector(1 downto 0); + signal rx_data : std_logic_vector(15 downto 0); + signal rx_k : std_logic_vector(1 downto 0); + signal link_ok : std_logic_vector(0 downto 0); + signal link_error : std_logic_vector(8 downto 0); + signal ff_rxhalfclk : std_logic; + signal ff_txhalfclk : std_logic; + --rx fifo signals + signal fifo_rx_rd_en : std_logic; + signal fifo_rx_wr_en : std_logic; + signal fifo_rx_reset : std_logic; + signal fifo_rx_din : std_logic_vector(17 downto 0); + signal fifo_rx_dout : std_logic_vector(17 downto 0); + signal fifo_rx_full : std_logic; + signal fifo_rx_empty : std_logic; + --tx fifo signals + signal fifo_tx_rd_en : std_logic; + signal fifo_tx_wr_en : std_logic; + signal fifo_tx_reset : std_logic; + signal fifo_tx_din : std_logic_vector(17 downto 0); + signal fifo_tx_dout : std_logic_vector(17 downto 0); + signal fifo_tx_full : std_logic; + signal fifo_tx_empty : std_logic; + --rx path + signal rx_counter : std_logic_vector(c_NUM_WIDTH-1 downto 0); + signal buf_med_dataready_out : std_logic; + signal buf_med_data_out : std_logic_vector(c_DATA_WIDTH-1 downto 0); + signal buf_med_packet_num_out : std_logic_vector(c_NUM_WIDTH-1 downto 0); + signal last_rx : std_logic_vector(8 downto 0); + signal last_fifo_rx_empty : std_logic; + --tx path + signal last_fifo_tx_empty : std_logic; + --link status + signal link_led : std_logic; + signal rx_k_q : std_logic_vector(1 downto 0); + + signal info_led : std_logic; + + signal quad_rst : std_logic; + signal lane_rst : std_logic; + signal tx_allow : std_logic; + signal rx_allow : std_logic; + + signal rx_allow_q : std_logic; -- clock domain changed signal + signal tx_allow_q : std_logic; + signal swap_bytes : std_logic; + signal buf_stat_debug : std_logic_vector(31 downto 0); + + -- status inputs from SFP + signal sfp_prsnt_n : std_logic; -- synchronized input signals + signal sfp_los : std_logic; -- synchronized input signals + + signal buf_STAT_OP : std_logic_vector(15 downto 0); + + signal led_counter : std_logic_vector(17 downto 0); + signal rx_led, tx_led : std_logic; + + +begin + +-------------------------------------------------------------------------- +-- Main control state machine, startup control for SFP +-------------------------------------------------------------------------- +clock <= SYSCLK; + +-- Input synchronizer + +THE_SFP_STATUS_SYNC: signal_sync + generic map( + DEPTH => 3, + WIDTH => 2 + ) + port map( + RESET => RESET, + D_IN(0) => SD_PRSNT_N_IN, + D_IN(1) => SD_LOS_IN, + CLK0 => clock, + CLK1 => clock, + D_OUT(0) => sfp_prsnt_n, + D_OUT(1) => sfp_los + ); + +-- Transfering the komma delimiter in the *training* phase +THE_RX_K_SYNC: signal_sync + generic map( + DEPTH => 3, + WIDTH => 2 + ) + port map( + RESET => RESET, + D_IN => rx_k, + CLK0 => ff_rxhalfclk, + CLK1 => clock, + D_OUT => rx_k_q + ); + +---------------------------------------------------------------------------------------------------------- +-- NEW STATEMACHINE START +---------------------------------------------------------------------------------------------------------- +THE_SFP_LSM: trb_net16_lsm_sfp + port map( + SYSCLK => clock, + RESET => reset, + CLEAR => clear, + SFP_MISSING_IN => sfp_prsnt_n, + SFP_LOS_IN => sfp_los, + SD_LINK_OK_IN => link_ok(0), + SD_LOS_IN => link_error(8), + SD_TXCLK_BAD_IN => link_error(5), + SD_RXCLK_BAD_IN => link_error(4), + SD_RETRY_IN => '0', -- '0' = handle byte swapping in logic, '1' = simply restart link and hope + SD_ALIGNMENT_IN => rx_k_q, + SD_CV_IN => link_error(7 downto 6), + FULL_RESET_OUT => quad_rst, + LANE_RESET_OUT => lane_rst, + TX_ALLOW_OUT => tx_allow, + RX_ALLOW_OUT => rx_allow, + SWAP_BYTES_OUT => swap_bytes, + STAT_OP => buf_stat_op, + CTRL_OP => ctrl_op, + STAT_DEBUG => buf_stat_debug + ); +---------------------------------------------------------------------------------------------------------- +-- NEW STATEMACHINE STOP +---------------------------------------------------------------------------------------------------------- + +THE_RX_ALLOW_SYNC: signal_sync -- really needed?!? + generic map( + DEPTH => 2, + WIDTH => 2 + ) + port map( + RESET => RESET, + D_IN(0) => rx_allow, + D_IN(1) => tx_allow, + CLK0 => clock, --ff_rxhalfclk, + CLK1 => clock, --ff_rxhalfclk, + D_OUT(0) => rx_allow_q, + D_OUT(1) => tx_allow_q + ); + +-------------------------------------------------------------------------- +-------------------------------------------------------------------------- + +ffc_quad_rst <= quad_rst; +ffc_lane_tx_rst <= lane_rst; +ffc_lane_rx_rst <= lane_rst; + +-- SerDes clock output to FPGA fabric +REFCLK2CORE_OUT <= refck2core; + +-- Instantiation of serdes module + gen_serdes_0 : if SERDES_NUM = 0 generate + THE_SERDES: serdes_0 + port map( + core_txrefclk => clk, + core_rxrefclk => clk, + hdinp0 => sd_rxd_p_in, + hdinn0 => sd_rxd_n_in, + ff_rxiclk_ch0 => ff_rxhalfclk, + ff_txiclk_ch0 => ff_txhalfclk, + ff_ebrd_clk_0 => ff_rxhalfclk, -- not used, just for completeness + ff_txdata_ch0 => tx_data, + ff_tx_k_cntrl_ch0 => tx_k, + ff_force_disp_ch0 => "00", + ff_disp_sel_ch0 => "00", + ff_correct_disp_ch0 => "00", + ffc_rrst_ch0 => '0', + ffc_lane_tx_rst_ch0 => ffc_lane_tx_rst, + ffc_lane_rx_rst_ch0 => ffc_lane_rx_rst, + ffc_txpwdnb_ch0 => '1', + ffc_rxpwdnb_ch0 => '1', + ffc_macro_rst => '0', + ffc_quad_rst => ffc_quad_rst, + ffc_trst => '0', + hdoutp0 => sd_txd_p_out, + hdoutn0 => sd_txd_n_out, + ff_rxdata_ch0 => rx_data, --comb_rx_data, + ff_rx_k_cntrl_ch0 => rx_k, --comb_rx_k, + ff_rxfullclk_ch0 => open, + ff_rxhalfclk_ch0 => ff_rxhalfclk, + ff_disp_err_ch0 => open, + ff_cv_ch0 => link_error(7 downto 6), + ffs_rlos_lo_ch0 => link_error(8), + ffs_ls_sync_status_ch0 => link_ok(0), + ffs_cc_underrun_ch0 => link_error(0), + ffs_cc_overrun_ch0 => link_error(1), + ffs_txfbfifo_error_ch0 => link_error(2), + ffs_rxfbfifo_error_ch0 => link_error(3), + ffs_rlol_ch0 => link_error(4), + oob_out_ch0 => open, + ff_txfullclk => open, + ff_txhalfclk => ff_txhalfclk, + refck2core => refck2core, + ffs_plol => link_error(5) + ); + end generate; + gen_serdes_1 : if SERDES_NUM = 1 generate + THE_SERDES: serdes_1 + port map( + core_txrefclk => clk, + core_rxrefclk => clk, + refclkp => SD_REFCLK_P_IN, + refclkn => SD_REFCLK_N_IN, + hdinp1 => sd_rxd_p_in, + hdinn1 => sd_rxd_n_in, + ff_rxiclk_ch1 => ff_rxhalfclk, + ff_txiclk_ch1 => ff_txhalfclk, + ff_ebrd_clk_1 => ff_rxhalfclk, -- not used, just for completeness + ff_txdata_ch1 => tx_data, + ff_tx_k_cntrl_ch1 => tx_k, + ff_force_disp_ch1 => "00", + ff_disp_sel_ch1 => "00", + ff_correct_disp_ch1 => "00", + ffc_rrst_ch1 => '0', + ffc_lane_tx_rst_ch1 => ffc_lane_tx_rst, + ffc_lane_rx_rst_ch1 => ffc_lane_rx_rst, + ffc_txpwdnb_ch1 => '1', + ffc_rxpwdnb_ch1 => '1', + ffc_macro_rst => '0', + ffc_quad_rst => ffc_quad_rst, + ffc_trst => '0', + hdoutp1 => sd_txd_p_out, + hdoutn1 => sd_txd_n_out, + ff_rxdata_ch1 => rx_data, --comb_rx_data, + ff_rx_k_cntrl_ch1 => rx_k, --comb_rx_k, + ff_rxfullclk_ch1 => open, + ff_rxhalfclk_ch1 => ff_rxhalfclk, + ff_disp_err_ch1 => open, + ff_cv_ch1 => link_error(7 downto 6), + ffs_rlos_lo_ch1 => link_error(8), + ffs_ls_sync_status_ch1 => link_ok(0), + ffs_cc_underrun_ch1 => link_error(0), + ffs_cc_overrun_ch1 => link_error(1), + ffs_txfbfifo_error_ch1 => link_error(2), + ffs_rxfbfifo_error_ch1 => link_error(3), + ffs_rlol_ch1 => link_error(4), + oob_out_ch1 => open, + ff_txfullclk => open, + ff_txhalfclk => ff_txhalfclk, + refck2core => refck2core, + ffs_plol => link_error(5) + ); + end generate; + gen_serdes_2 : if SERDES_NUM = 2 generate + THE_SERDES: serdes_2 + port map( + core_txrefclk => clk, + core_rxrefclk => clk, + hdinp2 => sd_rxd_p_in, + hdinn2 => sd_rxd_n_in, + ff_rxiclk_ch2 => ff_rxhalfclk, + ff_txiclk_ch2 => ff_txhalfclk, + ff_ebrd_clk_2 => ff_rxhalfclk, -- not used, just for completeness + ff_txdata_ch2 => tx_data, + ff_tx_k_cntrl_ch2 => tx_k, + ff_force_disp_ch2 => "00", + ff_disp_sel_ch2 => "00", + ff_correct_disp_ch2 => "00", + ffc_rrst_ch2 => '0', + ffc_lane_tx_rst_ch2 => ffc_lane_tx_rst, + ffc_lane_rx_rst_ch2 => ffc_lane_rx_rst, + ffc_txpwdnb_ch2 => '1', + ffc_rxpwdnb_ch2 => '1', + ffc_macro_rst => '0', + ffc_quad_rst => ffc_quad_rst, + ffc_trst => '0', + hdoutp2 => sd_txd_p_out, + hdoutn2 => sd_txd_n_out, + ff_rxdata_ch2 => rx_data, --comb_rx_data, + ff_rx_k_cntrl_ch2 => rx_k, --comb_rx_k, + ff_rxfullclk_ch2 => open, + ff_rxhalfclk_ch2 => ff_rxhalfclk, + ff_disp_err_ch2 => open, + ff_cv_ch2 => link_error(7 downto 6), + ffs_rlos_lo_ch2 => link_error(8), + ffs_ls_sync_status_ch2 => link_ok(0), + ffs_cc_underrun_ch2 => link_error(0), + ffs_cc_overrun_ch2 => link_error(1), + ffs_txfbfifo_error_ch2 => link_error(2), + ffs_rxfbfifo_error_ch2 => link_error(3), + ffs_rlol_ch2 => link_error(4), + oob_out_ch2 => open, + ff_txfullclk => open, + ff_txhalfclk => ff_txhalfclk, + refck2core => refck2core, + ffs_plol => link_error(5) + ); + end generate; + gen_serdes_3 : if SERDES_NUM = 3 generate + THE_SERDES: serdes_3 + port map( + core_txrefclk => clk, + core_rxrefclk => clk, + hdinp3 => sd_rxd_p_in, + hdinn3 => sd_rxd_n_in, + ff_rxiclk_ch3 => ff_rxhalfclk, + ff_txiclk_ch3 => ff_txhalfclk, + ff_ebrd_clk_3 => ff_rxhalfclk, -- not used, just for completeness + ff_txdata_ch3 => tx_data, + ff_tx_k_cntrl_ch3 => tx_k, + ff_force_disp_ch3 => "00", + ff_disp_sel_ch3 => "00", + ff_correct_disp_ch3 => "00", + ffc_rrst_ch3 => '0', + ffc_lane_tx_rst_ch3 => ffc_lane_tx_rst, + ffc_lane_rx_rst_ch3 => ffc_lane_rx_rst, + ffc_txpwdnb_ch3 => '1', + ffc_rxpwdnb_ch3 => '1', + ffc_macro_rst => '0', + ffc_quad_rst => ffc_quad_rst, + ffc_trst => '0', + hdoutp3 => sd_txd_p_out, + hdoutn3 => sd_txd_n_out, + ff_rxdata_ch3 => rx_data, --comb_rx_data, + ff_rx_k_cntrl_ch3 => rx_k, --comb_rx_k, + ff_rxfullclk_ch3 => open, + ff_rxhalfclk_ch3 => ff_rxhalfclk, + ff_disp_err_ch3 => open, + ff_cv_ch3 => link_error(7 downto 6), + ffs_rlos_lo_ch3 => link_error(8), + ffs_ls_sync_status_ch3 => link_ok(0), + ffs_cc_underrun_ch3 => link_error(0), + ffs_cc_overrun_ch3 => link_error(1), + ffs_txfbfifo_error_ch3 => link_error(2), + ffs_rxfbfifo_error_ch3 => link_error(3), + ffs_rlol_ch3 => link_error(4), + oob_out_ch3 => open, + ff_txfullclk => open, + ff_txhalfclk => ff_txhalfclk, + refck2core => refck2core, + ffs_plol => link_error(5) + ); + end generate; + + +------------------------------------------------------------------------- +-- RX Fifo & Data output +------------------------------------------------------------------------- +THE_FIFO_SFP_TO_FPGA: trb_net_fifo_16bit_bram_dualport +generic map( + USE_STATUS_FLAGS => c_NO + ) +port map( read_clock_in => clock, + write_clock_in => ff_rxhalfclk, + read_enable_in => fifo_rx_rd_en, + write_enable_in => fifo_rx_wr_en, + fifo_gsr_in => fifo_rx_reset, + write_data_in => fifo_rx_din, + read_data_out => fifo_rx_dout, + full_out => fifo_rx_full, + empty_out => fifo_rx_empty + ); + +fifo_rx_reset <= RESET; +fifo_rx_rd_en <= '1'; + +-- Received bytes need to be swapped if the SerDes is "off by one" in its internal 8bit path +THE_BYTE_SWAP_PROC: process( ff_rxhalfclk ) +begin + if( rising_edge(ff_rxhalfclk) ) then + last_rx <= rx_k(1) & rx_data(15 downto 8); + if( swap_bytes = '0' ) then + fifo_rx_din <= rx_k(1) & rx_k(0) & rx_data(15 downto 8) & rx_data(7 downto 0); + fifo_rx_wr_en <= not rx_k(0) and rx_allow and link_ok(0); + else + fifo_rx_din <= rx_k(0) & last_rx(8) & rx_data(7 downto 0) & last_rx(7 downto 0); + fifo_rx_wr_en <= not last_rx(8) and rx_allow and link_ok(0); + end if; + end if; +end process THE_BYTE_SWAP_PROC; + +buf_med_data_out <= fifo_rx_dout(15 downto 0); +buf_med_dataready_out <= not fifo_rx_dout(17) and not fifo_rx_dout(16) and not last_fifo_rx_empty and rx_allow_q; +buf_med_packet_num_out <= rx_counter; +med_read_out <= tx_allow_q; + +THE_SYNC_PROC: process( clock ) +begin + if( rising_edge(clock) ) then + if RESET = '1' then + med_dataready_out <= '0'; + else + med_dataready_out <= buf_med_dataready_out; + med_data_out <= buf_med_data_out; + med_packet_num_out <= buf_med_packet_num_out; + end if; + end if; +end process THE_SYNC_PROC; + +--rx packet counter +--------------------- +THE_RX_PACKETS_PROC: process( clock ) +begin + if( rising_edge(clock) ) then + last_fifo_rx_empty <= fifo_rx_empty; + if RESET = '1' or rx_allow_q = '0' then + rx_counter <= c_H0; + else + if( buf_med_dataready_out = '1' ) then + if( rx_counter = c_max_word_number ) then + rx_counter <= (others => '0'); + else + rx_counter <= rx_counter + 1; + end if; + end if; + end if; + end if; +end process; + +--TX Fifo & Data output to Serdes +--------------------- +THE_FIFO_FPGA_TO_SFP: trb_net_fifo_16bit_bram_dualport +generic map( + USE_STATUS_FLAGS => c_NO + ) +port map( read_clock_in => ff_txhalfclk, + write_clock_in => clock, + read_enable_in => fifo_tx_rd_en, + write_enable_in => fifo_tx_wr_en, + fifo_gsr_in => fifo_tx_reset, + write_data_in => fifo_tx_din, + read_data_out => fifo_tx_dout, + full_out => fifo_tx_full, + empty_out => fifo_tx_empty + ); + +fifo_tx_reset <= reset; +fifo_tx_din <= med_packet_num_in(2) & med_packet_num_in(0)& med_data_in; +fifo_tx_wr_en <= med_dataready_in and tx_allow_q; +fifo_tx_rd_en <= tx_allow; + + +THE_SERDES_INPUT_PROC: process( ff_txhalfclk ) +begin + if( rising_edge(ff_txhalfclk) ) then + last_fifo_tx_empty <= fifo_tx_empty; + if( (last_fifo_tx_empty = '1') or (tx_allow = '0') ) then + tx_data <= x"c5bc"; + tx_k <= "01"; +-- elsif send_resync = '1' then +-- tx_data <= x"7F7F"; +-- tx_k <= "00"; + else + tx_data <= fifo_tx_dout(15 downto 0); + tx_k <= "00"; + end if; + end if; +end process THE_SERDES_INPUT_PROC; + +-- + + +--Generate LED signals +---------------------- +process(clock) + begin + if rising_edge(clock) then + led_counter <= led_counter + 1; + + if buf_med_dataready_out = '1' then + rx_led <= '1'; + elsif led_counter = 0 then + rx_led <= '0'; + end if; + + if tx_k(0) = '0' then -- tx_k clock domain crossing! + tx_led <= '1'; + elsif led_counter = 0 then + tx_led <= '0'; + end if; + + end if; + end process; + +stat_op(15 downto 12) <= buf_stat_op(15 downto 12); +stat_op(11) <= tx_led; --tx led +stat_op(10) <= rx_led; --rx led +stat_op(9 downto 0) <= buf_stat_op(9 downto 0); + +-- Debug output +stat_debug(3 downto 0) <= buf_stat_debug(3 downto 0); -- state_bits +stat_debug(4) <= buf_stat_debug(4); -- alignme +stat_debug(5) <= sfp_prsnt_n; +stat_debug(6) <= tx_k(0); +stat_debug(7) <= tx_k(1); +stat_debug(8) <= rx_k_q(0); +stat_debug(9) <= rx_k_q(1); +--stat_debug(9 downto 7) <= (others => '0'); +stat_debug(18 downto 10) <= link_error; +stat_debug(19) <= '0'; +stat_debug(20) <= link_ok(0); +stat_debug(38 downto 21) <= fifo_rx_din; +stat_debug(39) <= swap_bytes; +stat_debug(40) <= buf_stat_debug(7); -- sfp_missing_in +stat_debug(41) <= buf_stat_debug(8); -- sfp_los_in +stat_debug(42) <= buf_stat_debug(6); -- resync +stat_debug(59 downto 43) <= (others => '0'); +stat_debug(63 downto 60) <= link_error(3 downto 0); + +end architecture; \ No newline at end of file