--- /dev/null
+-- 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
--- /dev/null
+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
--- /dev/null
+--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