From: Michael Boehmer Date: Fri, 3 Dec 2021 13:33:54 +0000 (+0100) Subject: WAPZ included, uplink seems to work now X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=35f88b7b3e238f70acb65de67da33735667f6896;p=trbnet.git WAPZ included, uplink seems to work now --- diff --git a/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd b/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd index 6dddfc7..2a493f4 100644 --- a/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd +++ b/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd @@ -25,7 +25,7 @@ entity med_ecp3_sfp_sync_all_RS is -- Media Interface TX/RX MEDIA_MED2INT : out med2int_array_t(0 to 3); MEDIA_INT2MED : in int2med_array_t(0 to 3); - -- Sync operation + -- komma operation RX_DLM_OUT : out std_logic_vector(3 downto 0); -- DLM received RX_DLM_WORD_OUT : out std_logic_vector(4*8-1 downto 0); TX_DLM_IN : in std_logic; @@ -34,18 +34,20 @@ entity med_ecp3_sfp_sync_all_RS is RX_RST_WORD_OUT : out std_logic_vector(7 downto 0); TX_RST_IN : in std_logic; TX_RST_WORD_IN : in std_logic_vector(7 downto 0); - WORD_SYNC_IN : in std_logic; - WORD_SYNC_OUT : out std_logic; + -- sync operation + WORD_SYNC_IN : in std_logic; -- byte alignment for DLM/RST forwarding (to master port) + WORD_SYNC_OUT : out std_logic; -- byte alignment for DLM/RST forwarding (from slave port) MASTER_CLK_IN : in std_logic; -- recovered RX clock in (only master ports in quad) MASTER_CLK_OUT : out std_logic; -- recovered RX clock out (slave port in quad) - MASTER_RESET_OUT : out std_logic; - DESTROY_LINK_IN : in std_logic_vector(3 downto 0); -- disable SFP transmitter - LINK_TX_READY_IN : in std_logic; -- TX PLLs are operational + GLOBAL_RESET_IN : in std_logic; -- needed for MI with master port(s) only + GLOBAL_RESET_OUT : out std_logic; -- only available on MI with slave port + TX_PLL_LOL_IN : in std_logic; -- and'ed TX PLL LOL to sync startup TX_PLL_LOL_OUT : out std_logic; -- status signal of TX PLL - TX_RESET_OUT : out std_logic; - SYNC_TX_PLL_IN : in std_logic; -- bit0 alignment for TX Serializer - RST_QUAD_IN : in std_logic; - RST_TX_PCS_IN : in std_logic; + TX_CLK_AVAIL_OUT : out std_logic; -- stable RX recovered clock available + TX_PCS_RST_IN : in std_logic; -- TX PCS reset signal + SYNC_TX_PLL_IN : in std_logic; -- bit0 alignment for TX serializer + LINK_TX_READY_IN : in std_logic; -- + DESTROY_LINK_IN : in std_logic_vector(3 downto 0); -- hard reset for links --SFP Connection SD_PRSNT_N_IN : in std_logic_vector(3 downto 0); -- SFP Present ('0' = SFP in place, '1' = no SFP mounted) SD_LOS_IN : in std_logic_vector(3 downto 0); -- SFP Loss Of Signal ('0' = OK, '1' = no signal) @@ -83,15 +85,13 @@ architecture med_ecp3_sfp_sync_all_RS_arch of med_ecp3_sfp_sync_all_RS is signal rx_k : std_logic_vector(3 downto 0); signal rx_error : std_logic_vector(3 downto 0); - signal rst_n : std_logic; signal rx_serdes_rst : std_logic_vector(3 downto 0); signal rx_pcs_rst : std_logic_vector(3 downto 0); - signal rst_qd : std_logic_vector(3 downto 0); + signal tx_pcs_rst : std_logic_vector(3 downto 0); signal rx_los_low : std_logic_vector(3 downto 0); signal lsm_status : std_logic_vector(3 downto 0); signal rx_cdr_lol : std_logic_vector(3 downto 0); - signal tx_pll_lol : std_logic; signal sci_ch_i : std_logic_vector(4 downto 0); signal sci_addr_i : std_logic_vector(5 downto 0); @@ -100,8 +100,9 @@ architecture med_ecp3_sfp_sync_all_RS_arch of med_ecp3_sfp_sync_all_RS is signal sci_read_i : std_logic; signal sci_write_i : std_logic; - signal wa_position : std_logic_vector(15 downto 0) := x"FFFF"; - + signal wa_position_i : std_logic_vector(15 downto 0) := x"FFFF"; + signal wa_read_i : std_logic; + signal stat_rx_control_i : std_logic_vector(4*32-1 downto 0); signal stat_tx_control_i : std_logic_vector(4*32-1 downto 0); signal debug_rx_control_i : std_logic_vector(4*32-1 downto 0); @@ -129,19 +130,20 @@ architecture med_ecp3_sfp_sync_all_RS_arch of med_ecp3_sfp_sync_all_RS is signal rx_rst_word_i : std_logic_vector(4*8-1 downto 0); signal rx_rst_i : std_logic_vector(3 downto 0); - signal master_reset_i : std_logic_vector(3 downto 0); - signal tx_reset_i : std_logic_vector(3 downto 0); + signal global_reset_i : std_logic_vector(3 downto 0); - signal master_reset_sel : std_logic; + signal global_reset_sel : std_logic; signal pll_lol_i : std_logic; + + signal link_rx_ready_i : std_logic_vector(3 downto 0); + signal tx_clk_avail_sel : std_logic; signal quad_mode : integer range 0 to 100; begin --- unused = 0 --- master = 1 --- slave = 8 +-- constants used as reminder +-- unused = 0, master = 1, slave = 8 ------------------------------------------------- -- check settings of media interface @@ -159,8 +161,9 @@ begin ------------------------------------------------- -- SFPs are disabled on unused SerDes channels -------------------------------------------------- - -- we can include the LINK_TX_READY_IN signal here for master ports +------------------------------------------------- +-- BUG: link_tx_ready(i) for master ports to be included +-- BUG: slave ports need also disable with link_tx_ready(i) SD_TXDIS_OUT(3) <= DESTROY_LINK_IN(3) when IS_MODE(3) = c_IS_MASTER else '1' when IS_MODE(3) = c_IS_UNUSED else '0'; @@ -176,6 +179,7 @@ begin ------------------------------------------------- -- TX ref clock +-- output only if a slave port is available in QUAD ------------------------------------------------- MASTER_CLK_OUT <= clk_rx_full(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else clk_rx_full(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else @@ -184,18 +188,31 @@ begin '0'; ------------------------------------------------- --- master reset +-- global reset +-- output only if a slave port is available in QUAD ------------------------------------------------- - master_reset_sel <= master_reset_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else - master_reset_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else - master_reset_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else - master_reset_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else - '0'; -- we need a master reset in! + global_reset_sel <= global_reset_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else + global_reset_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else + global_reset_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else + global_reset_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else + GLOBAL_RESET_IN; - MASTER_RESET_OUT <= master_reset_sel; + GLOBAL_RESET_OUT <= global_reset_sel; + +------------------------------------------------- +-- stable RX recovered clock available +------------------------------------------------- + tx_clk_avail_sel <= link_rx_ready_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else + link_rx_ready_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else + link_rx_ready_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else + link_rx_ready_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else + '1'; + + TX_CLK_AVAIL_OUT <= tx_clk_avail_sel; ------------------------------------------------- -- reset komma +-- output only if a slave port is available in QUAD ------------------------------------------------- RX_RST_OUT <= rx_rst_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else rx_rst_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else @@ -203,25 +220,16 @@ begin rx_rst_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else '0'; - RX_RST_WORD_OUT <= rx_rst_word_i(7 downto 0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else - rx_rst_word_i(15 downto 8) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else - rx_rst_word_i(23 downto 16) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else - rx_rst_word_i(31 downto 24) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else + RX_RST_WORD_OUT <= rx_rst_word_i(0*8+7 downto 0*8) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else + rx_rst_word_i(1*8+7 downto 1*8) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else + rx_rst_word_i(2*8+7 downto 2*8) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else + rx_rst_word_i(3*8+7 downto 3*8) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else x"00"; -------------------------------------------------- --- TX PLL reset -------------------------------------------------- - TX_RESET_OUT <= tx_reset_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else - tx_reset_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else - tx_reset_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else - tx_reset_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else - '0'; - ------------------------------------------------- -- Serdes ------------------------------------------------- - gen_pcs3: if SERDES_NUM = 3 generate + gen_pcs3: if SERDES_NUM = 3 generate -- needed for LPF constraints, should be changed THE_SERDES : entity work.serdes_sync_all_RS port map( hdinp_ch0 => hdinp(0), @@ -245,7 +253,7 @@ begin rx_serdes_rst_ch0_c => rx_serdes_rst(0), sb_felb_ch0_c => '0', sb_felb_rst_ch0_c => '0', - tx_pcs_rst_ch0_c => RST_TX_PCS_IN, -- was wrong + tx_pcs_rst_ch0_c => tx_pcs_rst(0), -- was wrong tx_pwrup_ch0_c => powerup_ch(0), -- new rx_pcs_rst_ch0_c => rx_pcs_rst(0), rx_pwrup_ch0_c => powerup_ch(0), -- new @@ -276,7 +284,7 @@ begin rx_serdes_rst_ch1_c => rx_serdes_rst(1), sb_felb_ch1_c => '0', sb_felb_rst_ch1_c => '0', - tx_pcs_rst_ch1_c => RST_TX_PCS_IN, -- was wrong + tx_pcs_rst_ch1_c => tx_pcs_rst(1), -- was wrong tx_pwrup_ch1_c => powerup_ch(1), -- new rx_pcs_rst_ch1_c => rx_pcs_rst(1), rx_pwrup_ch1_c => powerup_ch(1), -- new @@ -307,7 +315,7 @@ begin rx_serdes_rst_ch2_c => rx_serdes_rst(2), sb_felb_ch2_c => '0', sb_felb_rst_ch2_c => '0', - tx_pcs_rst_ch2_c => RST_TX_PCS_IN, -- was wrong + tx_pcs_rst_ch2_c => tx_pcs_rst(2), -- was wrong tx_pwrup_ch2_c => powerup_ch(2), -- new rx_pcs_rst_ch2_c => rx_pcs_rst(2), rx_pwrup_ch2_c => powerup_ch(2), -- new @@ -338,7 +346,7 @@ begin rx_serdes_rst_ch3_c => rx_serdes_rst(3), sb_felb_ch3_c => '0', sb_felb_rst_ch3_c => '0', - tx_pcs_rst_ch3_c => RST_TX_PCS_IN, -- was wrong + tx_pcs_rst_ch3_c => tx_pcs_rst(3), -- was wrong tx_pwrup_ch3_c => powerup_ch(3), -- new rx_pcs_rst_ch3_c => rx_pcs_rst(3), rx_pwrup_ch3_c => powerup_ch(3), -- new @@ -361,15 +369,13 @@ begin fpga_txrefclk => MASTER_CLK_IN, -- reference TX clock tx_serdes_rst_c => '0', - tx_pll_lol_qd_s => pll_lol_i, - rst_qd_c => master_reset_sel, --RST_QUAD_IN, -- deadlock caused by this... + tx_pll_lol_qd_s => TX_PLL_LOL_OUT, + rst_qd_c => GLOBAL_RESET_IN, serdes_rst_qd_c => '0', -- was wrong tx_sync_qd_c => SYNC_TX_PLL_IN ); end generate; - - TX_PLL_LOL_OUT <= '1'; - + gen_control : for i in 0 to 3 generate gen_used_control : if (IS_MODE(i) = c_IS_SLAVE) or (IS_MODE(i) = c_IS_MASTER) generate THE_MED_CONTROL : entity work.med_sync_control_RS @@ -394,14 +400,14 @@ gen_control : for i in 0 to 3 generate SFP_LOS_IN => SD_LOS_IN(i), RX_CDR_LOL_IN => rx_cdr_lol(i), RX_LOS_IN => rx_los_low(i), - CV_IN => rx_error(i), - LSM_IN => lsm_status(i), - PLL_LOL_IN => pll_lol_i, - WA_POSITION_IN => wa_position(i*4+3 downto i*4), - LINK_TX_READY_IN => LINK_TX_READY_IN, + RX_CV_IN => rx_error(i), + RX_LSM_IN => lsm_status(i), + TX_PLL_LOL_IN => TX_PLL_LOL_IN, + WA_POSITION_IN => wa_position_i(i*4+3 downto i*4), -- control signals to SerDes RX_SERDES_RST => rx_serdes_rst(i), RX_PCS_RST => rx_pcs_rst(i), + TX_PCS_RST => tx_pcs_rst(i), -- SerDes data streams TX_DATA_OUT => tx_data(i*8+7 downto i*8), TX_K_OUT => tx_k(i), @@ -410,6 +416,11 @@ gen_control : for i in 0 to 3 generate -- ports for synchronous operation WORD_SYNC_IN => WORD_SYNC_IN, WORD_SYNC_OUT => WORD_SYNC_OUT, + GLOBAL_RESET_IN => GLOBAL_RESET_IN, + GLOBAL_RESET_OUT => global_reset_i(i), + LINK_TX_READY_IN => LINK_TX_READY_IN, + LINK_RX_READY_OUT => link_rx_ready_i(i), + -- komma operation TX_DLM_IN => tx_dlm_i, TX_DLM_WORD_IN => tx_dlm_word_i, TX_RST_IN => tx_rst_i(i), @@ -418,8 +429,6 @@ gen_control : for i in 0 to 3 generate RX_DLM_WORD_OUT => RX_DLM_WORD_OUT(i*8+7 downto i*8), RX_RST_OUT => rx_rst_i(i), RX_RST_WORD_OUT => rx_rst_word_i(i*8+7 downto i*8), - MASTER_RESET_OUT => master_reset_i(i), - TX_RESET_OUT => tx_reset_i(i), -- Status and debug signals STAT_TX_CONTROL => stat_tx_control_i(i*32+31 downto i*32), STAT_RX_CONTROL => stat_rx_control_i(i*32+31 downto i*32), @@ -456,9 +465,9 @@ end generate; SCI_RD => sci_read_i, SCI_WR => sci_write_i, -- WAP - WA_POS_OUT => wa_position, - WA_READ_OUT => open, - LINK_RX_READY_IN => '0', + WA_POS_OUT => wa_position_i, + WA_READ_OUT => wa_read_i, --open, + LINK_RX_READY_IN => '0', -- BUG --Slowcontrol BUS_RX => BUS_RX, BUS_TX => BUS_TX, @@ -478,10 +487,12 @@ end generate; STAT_DEBUG(63 downto 0) <= (others => '0'); - DEBUG_OUT <= debug_i(3*32+31 downto 3*32); --- DEBUG_OUT(11 downto 0) <= debug_i(3*32+11 downto 3*32); --- DEBUG_OUT(15 downto 12) <= rx_los_low; --- DEBUG_OUT(31 downto 16) <= debug_i(3*32+31 downto 3*32+16); +-- DEBUG_OUT <= debug_i(3*32+31 downto 3*32); + DEBUG_OUT(8 downto 0) <= debug_i(3*32+8 downto 3*32); + DEBUG_OUT(9) <= wa_read_i; + DEBUG_OUT(10) <= tx_clk_avail_sel; + DEBUG_OUT(11) <= GLOBAL_RESET_IN; + DEBUG_OUT(31 downto 12) <= debug_i(3*32+31 downto 3*32+12); end architecture; diff --git a/media_interfaces/sync/main_tx_reset_RS.vhd b/media_interfaces/sync/main_tx_reset_RS.vhd index f5dedd2..0af2421 100644 --- a/media_interfaces/sync/main_tx_reset_RS.vhd +++ b/media_interfaces/sync/main_tx_reset_RS.vhd @@ -15,8 +15,8 @@ entity main_tx_reset_RS is TX_PLL_LOL_QD_B_IN : in std_logic; -- QUAD B TX_PLL_LOL_QD_C_IN : in std_logic; -- QUAD C TX_PLL_LOL_QD_D_IN : in std_logic; -- QUAD D + TX_PLL_LOL_OUT : out std_logic; -- wired'or for RX state machines TX_CLOCK_AVAIL_IN : in std_logic; -- recovered RX clock available (if needed) - RST_QD_C_OUT : out std_logic; -- full QUAD reset TX_PCS_RST_CH_C_OUT : out std_logic; -- PCS reset SYNC_TX_QUAD_OUT : out std_logic; -- sync all QUADs to TX bit 0 LINK_TX_READY_OUT : out std_logic; -- TX lane can use used now @@ -28,10 +28,9 @@ architecture main_tx_reset_RS_arch of main_tx_reset_RS is -- We use two different timing for simulation and real world. -- Using SIM_MODE for implementation will most likely kill the link. - constant count2_index : integer := 19 - (SIM_MODE * 12); -- end of timer2 - constant count1_index : integer := 3; -- end of timer1 + constant count_index : integer := 15 - (SIM_MODE * 9); -- end of timer - type statetype is ( QUAD_RESET, WAIT_FOR_TIMER1, CHECK_PLOL, WAIT_FOR_TIMER2, SYNC_ALL, NORMAL ); + type statetype is ( IDLE, WAIT_FOR_TIMER, SYNC_ALL, SYNC_DONE, NORMAL ); signal CURRENT_STATE : statetype; -- current state of lsm signal NEXT_STATE : statetype; -- next state of lsm @@ -46,13 +45,9 @@ architecture main_tx_reset_RS_arch of main_tx_reset_RS is signal tx_pll_lol_all_q : std_logic; -- synced signal tx_clock_avail_q : std_logic; -- synced - signal counter1 : unsigned(count1_index downto 0); - signal timer1 : std_logic; - signal reset_timer1 : std_logic; - - signal counter2 : unsigned(count2_index downto 0); - signal timer2 : std_logic; - signal reset_timer2 : std_logic; + signal counter : unsigned(count_index downto 0); + signal timer : std_logic; + signal reset_timer : std_logic; begin @@ -60,6 +55,9 @@ begin tx_pll_lol_all <= TX_PLL_LOL_QD_A_IN or TX_PLL_LOL_QD_B_IN or TX_PLL_LOL_QD_C_IN or TX_PLL_LOL_QD_D_IN; + + TX_PLL_LOL_OUT <= tx_pll_lol_all; + -- synchronize, just to be on the safe side SYNC_SFP_SIGS : entity work.signal_sync generic map( @@ -76,71 +74,43 @@ begin D_OUT(1) => tx_clock_avail_q ); --- TIMER1 = 20ns; --- Fastest REFLCK = 312 MHZ, or 3 ns. We need 8 REFCLK cycles. --- A 3 bit counter ([2:0]) counts 8 cycles, so a 4 bit ([3:0]) counter will do if we set TIMER1 = bit[3] --- Timer 1 - THE_TIMER1_PROC: process( LOCALCLK ) +-- Timer + THE_TIMER_PROC: process( LOCALCLK ) begin if( rising_edge(LOCALCLK) ) then - if( reset_timer1 = '1' ) then - counter1 <= (others => '0'); + if( reset_timer = '1' ) then + counter <= (others => '0'); else - if( counter1(count1_index) = '0' ) then - counter1 <= counter1 + 1 ; + if( counter(count_index) = '0' ) then + counter <= counter + 1 ; end if; end if; end if; - end process THE_TIMER1_PROC; - - timer1 <= counter1(count1_index); + end process THE_TIMER_PROC; --- TIMER2 = 1,400,000 UI; --- WORST CASE CYCLES is with smallest multipier factor. --- This would be with X8 clock multiplier in DIV2 mode --- IN this casse, 1 UI = 2/8 REFCLK CYCLES. --- SO 1,400,000 UI = 1,400,000/4 = 350,000 REFCLK CYCLES --- A 19 bit counter ([18:0]) counts 524288 cycles, so a 20 bit ([19:0]) counter will do if we set TIMER2 = bit[19] - - THE_TIMER2_PROC: process( LOCALCLK ) - begin - if( rising_edge(LOCALCLK) ) then - if( reset_timer2 = '1' ) then - counter2 <= (others => '0'); - else - if( counter2(count2_index) = '0' ) then - counter2 <= counter2 + 1 ; - end if; - end if; - end if; - end process THE_TIMER2_PROC; + timer <= counter(count_index); - timer2 <= counter2(count2_index); -- State machine clocked process THE_FSM_PROC: process( LOCALCLK, CLEAR ) begin if( CLEAR = '1' ) then - CURRENT_STATE <= QUAD_RESET; + CURRENT_STATE <= IDLE; TX_PCS_RST_CH_C_OUT <= '1'; - RST_QD_C_OUT <= '1'; LINK_TX_READY_OUT <= '0'; else if( rising_edge(LOCALCLK) ) then CURRENT_STATE <= NEXT_STATE; TX_PCS_RST_CH_C_OUT <= tx_pcs_rst_ch_c_int; - RST_QD_C_OUT <= rst_qd_c_int; LINK_TX_READY_OUT <= link_tx_ready_int; end if; end if; end process THE_FSM_PROC; - THE_FSM_DECODE_PROC: process( CURRENT_STATE, timer1, timer2, tx_pll_lol_all_q, tx_clock_avail_q ) + THE_FSM_DECODE_PROC: process( CURRENT_STATE, timer, tx_pll_lol_all_q, tx_clock_avail_q ) begin - reset_timer1 <= '0'; - reset_timer2 <= '0'; - rst_qd_c_int <= '0'; + reset_timer <= '0'; tx_pcs_rst_ch_c_int <= '0'; sync_tx_quad_int <= '0'; link_tx_ready_int <= '0'; @@ -148,71 +118,49 @@ begin case CURRENT_STATE is - when QUAD_RESET => + when IDLE => STATE_OUT <= x"1"; tx_pcs_rst_ch_c_int <= '1'; - rst_qd_c_int <= '1'; - reset_timer1 <= '1'; - reset_timer2 <= '1'; - NEXT_STATE <= WAIT_FOR_TIMER1; + reset_timer <= '1'; + NEXT_STATE <= WAIT_FOR_TIMER; - when WAIT_FOR_TIMER1 => + when WAIT_FOR_TIMER => STATE_OUT <= x"2"; tx_pcs_rst_ch_c_int <= '1'; - rst_qd_c_int <= '1'; - reset_timer2 <= '1'; - if( timer1 = '1' ) then - NEXT_STATE <= CHECK_PLOL; + if( timer = '1' ) then + NEXT_STATE <= SYNC_ALL; else - NEXT_STATE <= WAIT_FOR_TIMER1; + NEXT_STATE <= WAIT_FOR_TIMER; end if; - when CHECK_PLOL => + when SYNC_ALL => STATE_OUT <= x"3"; tx_pcs_rst_ch_c_int <= '1'; - reset_timer1 <= '1'; - reset_timer2 <= '1'; - NEXT_STATE <= WAIT_FOR_TIMER2; + reset_timer <= '1'; + NEXT_STATE <= SYNC_DONE; - when WAIT_FOR_TIMER2 => + when SYNC_DONE => STATE_OUT <= x"4"; - reset_timer1 <= '1'; - tx_pcs_rst_ch_c_int <= '1'; - if( timer2 = '1' ) then - if( (tx_pll_lol_all_q = '1') or (tx_clock_avail_q = '0') ) then - NEXT_STATE <= QUAD_RESET; - else - NEXT_STATE <= SYNC_ALL; - sync_tx_quad_int <= '1'; - end if; - else - NEXT_STATE <= WAIT_FOR_TIMER2; - end if; - - when SYNC_ALL => - STATE_OUT <= x"5"; - reset_timer2 <= '1'; - if( timer1 = '1' ) then + if( timer = '1' ) then NEXT_STATE <= NORMAL; else - NEXT_STATE <= SYNC_ALL; + NEXT_STATE <= SYNC_DONE; end if; when NORMAL => - STATE_OUT <= x"6"; + STATE_OUT <= x"5"; tx_pcs_rst_ch_c_int <= '0'; link_tx_ready_int <= '1'; - reset_timer1 <= '1'; - reset_timer2 <= '1'; + reset_timer <= '1'; if( (tx_pll_lol_all_q = '1') or (tx_clock_avail_q = '0') ) then - NEXT_STATE <= QUAD_RESET; + NEXT_STATE <= IDLE; else NEXT_STATE <= NORMAL; end if; when others => STATE_OUT <= x"f"; - NEXT_STATE <= QUAD_RESET; + NEXT_STATE <= IDLE; end case; diff --git a/media_interfaces/sync/med_sync_control_RS.vhd b/media_interfaces/sync/med_sync_control_RS.vhd index c762028..e28b7f8 100644 --- a/media_interfaces/sync/med_sync_control_RS.vhd +++ b/media_interfaces/sync/med_sync_control_RS.vhd @@ -23,20 +23,20 @@ entity med_sync_control_RS is RESET : in std_logic; CLEAR : in std_logic; -- Media Interface - MEDIA_MED2INT : out MED2INT; -- Media Interface IN - MEDIA_INT2MED : in INT2MED; -- Media Interface OUT + MEDIA_MED2INT : out MED2INT; -- Media Interface OUT + MEDIA_INT2MED : in INT2MED; -- Media Interface IN -- status signals from SerDes SFP_LOS_IN : in std_logic; -- SFP Loss Of Signal RX_CDR_LOL_IN : in std_logic; -- SerDes RX CDR status RX_LOS_IN : in std_logic; -- SerDes RX input signal status - CV_IN : in std_logic; - LSM_IN : in std_logic; - PLL_LOL_IN : in std_logic; + RX_CV_IN : in std_logic; -- SerDes RX CodeViolation status + RX_LSM_IN : in std_logic; -- SerDes TX LinkStateMachine status + TX_PLL_LOL_IN : in std_logic; -- wired'or from all QUADs WA_POSITION_IN : in std_logic_vector(3 downto 0); -- WordAlignment Position - LINK_TX_READY_IN : in std_logic; -- control signals to SerDes RX_SERDES_RST : out std_logic; -- reset RX (SerDes + CDR) RX_PCS_RST : out std_logic; -- reset RX (PCS) + TX_PCS_RST : out std_logic; -- MISSING!!! -- SerDes data streams TX_DATA_OUT : out std_logic_vector(7 downto 0); -- data to TX SerDes TX_K_OUT : out std_logic; -- komma designator to TS SerDes @@ -45,6 +45,11 @@ entity med_sync_control_RS is -- ports for synchronous operation WORD_SYNC_IN : in std_logic; -- sync signal for Byte/Word Alignment WORD_SYNC_OUT : out std_logic; + GLOBAL_RESET_IN : in std_logic; -- global reset to master ports + GLOBAL_RESET_OUT : out std_logic; -- global reset from slave port + LINK_TX_READY_IN : in std_logic; -- + LINK_RX_READY_OUT : out std_logic; -- + -- komma handling TX_DLM_IN : in std_logic; -- transmit one DLM komma TX_DLM_WORD_IN : in std_logic_vector(7 downto 0); TX_RST_IN : in std_logic; -- transmit one RST komma @@ -53,8 +58,6 @@ entity med_sync_control_RS is RX_DLM_WORD_OUT : out std_logic_vector(7 downto 0); RX_RST_OUT : out std_logic; -- one RST komma received RX_RST_WORD_OUT : out std_logic_vector(7 downto 0); - MASTER_RESET_OUT : out std_logic; -- master reset for FPGA - TX_RESET_OUT : out std_logic; -- reset main TX reset FSM -- Status and debug signals STAT_TX_CONTROL : out std_logic_vector(31 downto 0); STAT_RX_CONTROL : out std_logic_vector(31 downto 0); @@ -76,7 +79,6 @@ architecture med_sync_control_arch of med_sync_control_RS is signal sd_los_q : std_logic; signal reset_i : std_logic; - signal clr_rx_fsm_i : std_logic; signal link_rx_ready_i : std_logic; signal link_rx_ready_qsys : std_logic; signal link_half_done_i : std_logic; @@ -109,16 +111,9 @@ begin D_OUT(0) => sd_los_q ); --- obselete --- keep central TX reset FSM idle while no clock is present --- TX_RESET_OUT <= (CLEAR or RESET or not link_rx_ready_i) when (IS_MODE = c_IS_SLAVE) --- else (CLEAR or RESET); - TX_RESET_OUT <= '0'; - --- RX_RESET_FSM reset - clr_rx_fsm_i <= sd_los_q; - - MASTER_RESET_OUT <= sd_los_q; +-- we use uplink signal detection as global reset (slave port) +-- doesn't make sense to start while no link partner is available + GLOBAL_RESET_OUT <= sd_los_q; -- TX_CONTROL and RX_CONTROL reset reset_i <= (RESET or sd_los_q) when (IS_MODE = c_IS_SLAVE) @@ -129,20 +124,21 @@ begin ------------------------------------------------- THE_RX_RST_FSM: rx_rsl port map( - CLEAR => clr_rx_fsm_i, + CLEAR => GLOBAL_RESET_IN, CLK_REF => CLK_REF, - PLL_LOL_IN => PLL_LOL_IN, + PLL_LOL_IN => TX_PLL_LOL_IN, CDR_LOL_IN => RX_CDR_LOL_IN, - CV_IN => CV_IN, - LSM_IN => LSM_IN, + CV_IN => RX_CV_IN, + LSM_IN => RX_LSM_IN, LOS_IN => RX_LOS_IN, + WAP_ZERO_IN => is_wap_zero_i, -- outputs RX_SERDES_RST_OUT => rx_serdes_rst_i, RX_PCS_RST_OUT => rx_pcs_rst_i, LINK_RX_READY_OUT => link_rx_ready_i, STATE_OUT => rx_fsm_state ); - + -- reset signals for RX SerDes need to be sync'ed to real RX clock for ECP5 SYNC_RST_SIGS: entity work.signal_sync generic map( WIDTH => 2 ) @@ -157,7 +153,9 @@ begin ); is_wap_zero_i <= '1' when (WA_POSITION_IN = x"0") else '0'; - + + LINK_RX_READY_OUT <= link_rx_ready_i; + ------------------------------------------------- -- RX Data ------------------------------------------------- @@ -197,7 +195,7 @@ begin THE_RX_LSM: rx_lsm_RS port map( LINK_RX_READY_IN => link_rx_ready_i, - RXCLK => CLK_RXI, + CLK_RXI => CLK_RXI, RX_K_IN => RX_K_IN, RX_DATA_IN => RX_DATA_IN, LINK_HALF_DONE_OUT => link_half_done_i, @@ -237,7 +235,7 @@ begin SEND_RST_IN => TX_RST_IN, SEND_RST_WORD_IN => TX_RST_WORD_IN, -- link status signals, internally synced - LINK_TX_READY_IN => LINK_TX_READY_IN, + LINK_TX_READY_IN => '0', -- BUG LINK_RX_READY_IN => link_rx_ready_i, LINK_HALF_DONE_IN => link_half_done_i, LINK_FULL_DONE_IN => link_full_done_i, @@ -285,8 +283,10 @@ begin media_med2int_i.stat_op(10) <= led_rx or last_led_rx; media_med2int_i.stat_op(9) <= '0'; --led_ok media_med2int_i.stat_op(8 downto 5) <= (others => '0'); - media_med2int_i.stat_op(4) <= '0'; - media_med2int_i.stat_op(3 downto 0) <= x"0" when link_half_done_i = '1' and link_full_done_i = '1' else x"7"; +-- media_med2int_i.stat_op(5) <= link_tx_ready_i; + media_med2int_i.stat_op(4) <= link_rx_ready_i; + media_med2int_i.stat_op(3 downto 0) <= x"0" when link_half_done_i = '1' and link_full_done_i = '1' + else x"7"; -- TEST_LINE signals DEBUG_OUT(0) <= SFP_LOS_IN; @@ -294,16 +294,23 @@ begin DEBUG_OUT(2) <= RX_CDR_LOL_IN; DEBUG_OUT(3) <= rx_pcs_rst_i; DEBUG_OUT(4) <= rx_serdes_rst_i; - DEBUG_OUT(5) <= CV_IN; - DEBUG_OUT(6) <= LSM_IN; - DEBUG_OUT(7) <= PLL_LOL_IN; - DEBUG_OUT(8) <= link_rx_ready_i; - DEBUG_OUT(9) <= CLEAR; - DEBUG_OUT(10) <= clr_rx_fsm_i; - DEBUG_OUT(11) <= reset_i; + DEBUG_OUT(5) <= TX_PLL_LOL_IN; + DEBUG_OUT(6) <= is_wap_zero_i; + DEBUG_OUT(7) <= link_rx_ready_i; + DEBUG_OUT(8) <= LINK_TX_READY_IN; + DEBUG_OUT(9) <= '0'; + DEBUG_OUT(10) <= '0'; + DEBUG_OUT(11) <= '0'; DEBUG_OUT(15 downto 12) <= rx_fsm_state; DEBUG_OUT(21 downto 16) <= debug_tx_control_i(5 downto 0); DEBUG_OUT(31 downto 22) <= (others => '0'); -- DEBUG_OUT <= (others => '0'); +-- Some remarks on the SerDes issue: +-- - slave ports keep everything in global reset until SFP detects light on receiver (SFP_LOS = 0) +-- - master ports take the slave port global reset, if available, otherwise GSR is used +-- - the global reset connects to RST_QD_C to keep TX PLL in reset +-- - slave ports establish the uplink first, with all checks for link integrity and WAP_ZERO_IN +-- - + end architecture; diff --git a/media_interfaces/sync/med_sync_define_RS.vhd b/media_interfaces/sync/med_sync_define_RS.vhd index e3a8aa8..b52e551 100644 --- a/media_interfaces/sync/med_sync_define_RS.vhd +++ b/media_interfaces/sync/med_sync_define_RS.vhd @@ -34,6 +34,7 @@ component rx_rsl is CV_IN : in std_logic; LSM_IN : in std_logic; LOS_IN : in std_logic; + WAP_ZERO_IN : in std_logic; -- outputs RX_SERDES_RST_OUT : out std_logic; RX_PCS_RST_OUT : out std_logic; @@ -99,14 +100,14 @@ component main_tx_reset_RS is SIM_MODE : integer := 0 ); port( - CLEAR : in std_logic; -- async reset + CLEAR : in std_logic; -- async reset, active high LOCALCLK : in std_logic; -- usually RX_REFCLK, not TX_REFCLK! TX_PLL_LOL_QD_A_IN : in std_logic; -- QUAD A TX_PLL_LOL_QD_B_IN : in std_logic; -- QUAD B TX_PLL_LOL_QD_C_IN : in std_logic; -- QUAD C TX_PLL_LOL_QD_D_IN : in std_logic; -- QUAD D + TX_PLL_LOL_OUT : out std_logic; -- wired'or for RX state machines TX_CLOCK_AVAIL_IN : in std_logic; -- recovered RX clock available (if needed) - RST_QD_C_OUT : out std_logic; -- full QUAD reset TX_PCS_RST_CH_C_OUT : out std_logic; -- PCS reset SYNC_TX_QUAD_OUT : out std_logic; -- sync all QUADs to TX bit 0 LINK_TX_READY_OUT : out std_logic; -- TX lane can use used now @@ -149,7 +150,7 @@ end component; component rx_lsm_RS is port( LINK_RX_READY_IN : in std_logic; -- serves as async reset, active low - RXCLK : in std_logic; -- recovered RX clock + CLK_RXI : in std_logic; -- recovered RX clock RX_K_IN : in std_logic; RX_DATA_IN : in std_logic_vector(7 downto 0); LINK_HALF_DONE_OUT : out std_logic; diff --git a/media_interfaces/sync/rx_lsm_RS.vhd b/media_interfaces/sync/rx_lsm_RS.vhd index 7ad7264..7e9bbe7 100644 --- a/media_interfaces/sync/rx_lsm_RS.vhd +++ b/media_interfaces/sync/rx_lsm_RS.vhd @@ -1,82 +1,82 @@ -LIBRARY IEEE; -USE IEEE.std_logic_1164.ALL; -USE IEEE.numeric_std.all; +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.all; -library work; +library work; use work.med_sync_define_RS.all; - + entity rx_lsm_RS is - port( - LINK_RX_READY_IN : in std_logic; -- serves as async reset, active low - RXCLK : in std_logic; -- recovered RX clock - RX_K_IN : in std_logic; + port( + LINK_RX_READY_IN : in std_logic; -- serves as async reset, active low + CLK_RXI : in std_logic; -- recovered RX clock + RX_K_IN : in std_logic; RX_DATA_IN : in std_logic_vector(7 downto 0); LINK_HALF_DONE_OUT : out std_logic; - LINK_FULL_DONE_OUT : out std_logic; - STATE_OUT : out std_logic_vector(3 downto 0) - ); -end entity; - -architecture rx_lsm_arch of rx_lsm_RS is - - type statetype is ( IDLE, K1F, D1F, K2F, D2FT, D2FS ); - - signal CURRENT_STATE : statetype; -- current state of lsm - signal NEXT_STATE : statetype; -- next state of lsm + LINK_FULL_DONE_OUT : out std_logic; + STATE_OUT : out std_logic_vector(3 downto 0) + ); +end entity; + +architecture rx_lsm_arch of rx_lsm_RS is + + type statetype is ( IDLE, K1F, D1F, K2F, D2FT, D2FS ); + + signal CURRENT_STATE : statetype; -- current state of lsm + signal NEXT_STATE : statetype; -- next state of lsm signal reset_ctr_t : std_logic; - signal ce_ctr_t : std_logic; - signal ctr_t : unsigned(4 downto 0); - signal ctr_t_done : std_logic; + signal ce_ctr_t : std_logic; + signal ctr_t : unsigned(4 downto 0); + signal ctr_t_done : std_logic; signal reset_ctr_s : std_logic; - signal ce_ctr_s : std_logic; - signal ctr_s : unsigned(4 downto 0); - signal ctr_s_done : std_logic; + signal ce_ctr_s : std_logic; + signal ctr_s : unsigned(4 downto 0); + signal ctr_s_done : std_logic; signal link_toggling_int : std_logic; signal link_steady_int : std_logic; - -begin + +begin - THE_CTR_T_PROC: process( RXCLK, LINK_RX_READY_IN ) + THE_CTR_T_PROC: process( CLK_RXI, LINK_RX_READY_IN ) begin if ( LINK_RX_READY_IN <= '0' ) then - ctr_t <= (others => '0'); - elsif( rising_edge(RXCLK) ) then - if( reset_ctr_t = '1' ) then - ctr_t <= (others => '0'); - else - if( (ctr_t(4) = '0') and (ce_ctr_t = '1') ) then - ctr_t <= ctr_t + 1 ; - end if; - end if; - end if; - end process THE_CTR_T_PROC; + ctr_t <= (others => '0'); + elsif( rising_edge(CLK_RXI) ) then + if( reset_ctr_t = '1' ) then + ctr_t <= (others => '0'); + else + if( (ctr_t(4) = '0') and (ce_ctr_t = '1') ) then + ctr_t <= ctr_t + 1 ; + end if; + end if; + end if; + end process THE_CTR_T_PROC; ctr_t_done <= ctr_t(4); - THE_CTR_S_PROC: process( RXCLK, LINK_RX_READY_IN ) + THE_CTR_S_PROC: process( CLK_RXI, LINK_RX_READY_IN ) begin if ( LINK_RX_READY_IN = '0' ) then - ctr_s <= (others => '0'); - elsif( rising_edge(RXCLK) ) then - if( reset_ctr_s = '1' ) then - ctr_s <= (others => '0'); - else - if( (ctr_s(4) = '0') and (ce_ctr_s = '1') ) then - ctr_s <= ctr_s + 1 ; - end if; - end if; - end if; - end process THE_CTR_S_PROC; - - ctr_s_done <= ctr_s(4); + ctr_s <= (others => '0'); + elsif( rising_edge(CLK_RXI) ) then + if( reset_ctr_s = '1' ) then + ctr_s <= (others => '0'); + else + if( (ctr_s(4) = '0') and (ce_ctr_s = '1') and (ctr_t_done = '1') ) then -- added to make sure correct sequence is done + ctr_s <= ctr_s + 1 ; + end if; + end if; + end if; + end process THE_CTR_S_PROC; + + ctr_s_done <= ctr_s(4); -- toggling idles sequence detected - THE_TOGGLE_DETECTED_PROC: process( RXCLK, LINK_RX_READY_IN ) + THE_TOGGLE_DETECTED_PROC: process( CLK_RXI, LINK_RX_READY_IN ) begin if ( LINK_RX_READY_IN = '0' ) then link_toggling_int <= '0'; - elsif( rising_edge(RXCLK) ) then + elsif( rising_edge(CLK_RXI) ) then if( ctr_t_done = '1' ) then link_toggling_int <= '1'; end if; @@ -85,42 +85,42 @@ begin LINK_HALF_DONE_OUT <= link_toggling_int; - -- steady idles sequence detected - THE_STEADY_DETECTED_PROC: process( RXCLK, LINK_RX_READY_IN ) - begin - if ( LINK_RX_READY_IN = '0' ) then - link_steady_int <= '0'; - elsif( rising_edge(RXCLK) ) then - if( ctr_s_done = '1' ) then - link_steady_int <= '1'; - end if; - end if; - end process THE_STEADY_DETECTED_PROC; - - LINK_FULL_DONE_OUT <= link_steady_int; - - -- State machine clocked process - THE_FSM_PROC: process( RXCLK, LINK_RX_READY_IN ) - begin - if( LINK_RX_READY_IN = '0' ) then - CURRENT_STATE <= IDLE; + -- steady idles sequence detected + THE_STEADY_DETECTED_PROC: process( CLK_RXI, LINK_RX_READY_IN ) + begin + if ( LINK_RX_READY_IN = '0' ) then + link_steady_int <= '0'; + elsif( rising_edge(CLK_RXI) ) then + if( ctr_s_done = '1' ) then + link_steady_int <= '1'; + end if; + end if; + end process THE_STEADY_DETECTED_PROC; + + LINK_FULL_DONE_OUT <= link_steady_int; + + -- State machine clocked process + THE_FSM_PROC: process( CLK_RXI, LINK_RX_READY_IN ) + begin + if( LINK_RX_READY_IN = '0' ) then + CURRENT_STATE <= IDLE; else - if( rising_edge(RXCLK) ) then - CURRENT_STATE <= NEXT_STATE; - end if; - end if; - end process THE_FSM_PROC; - - -- State machine decoding processs - THE_FSM_DECODE_PROC: process( CURRENT_STATE, RX_K_IN, RX_DATA_IN ) - begin + if( rising_edge(CLK_RXI) ) then + CURRENT_STATE <= NEXT_STATE; + end if; + end if; + end process THE_FSM_PROC; + + -- State machine decoding processs + THE_FSM_DECODE_PROC: process( CURRENT_STATE, RX_K_IN, RX_DATA_IN ) + begin reset_ctr_t <= '0'; reset_ctr_s <= '0'; ce_ctr_t <= '0'; - ce_ctr_s <= '0'; - STATE_OUT <= x"F"; - - case CURRENT_STATE is + ce_ctr_s <= '0'; + STATE_OUT <= x"F"; + + case CURRENT_STATE is when IDLE => STATE_OUT <= x"0"; @@ -141,47 +141,47 @@ begin end if; when D1F => - STATE_OUT <= x"2"; - if( (RX_K_IN = '1') and (RX_DATA_IN = K_IDLE) ) then - NEXT_STATE <= K2F; - else - NEXT_STATE <= IDLE; - end if; + STATE_OUT <= x"2"; + if( (RX_K_IN = '1') and (RX_DATA_IN = K_IDLE) ) then + NEXT_STATE <= K2F; + else + NEXT_STATE <= IDLE; + end if; when K2F => - STATE_OUT <= x"3"; - if ( (RX_K_IN = '0') and (RX_DATA_IN = D_IDLE1) ) then - NEXT_STATE <= D2FS; - elsif( (RX_K_IN = '0') and (RX_DATA_IN = D_IDLE0) ) then - NEXT_STATE <= D2FT; - else - NEXT_STATE <= IDLE; - end if; + STATE_OUT <= x"3"; + if ( (RX_K_IN = '0') and (RX_DATA_IN = D_IDLE1) ) then + NEXT_STATE <= D2FS; + elsif( (RX_K_IN = '0') and (RX_DATA_IN = D_IDLE0) ) then + NEXT_STATE <= D2FT; + else + NEXT_STATE <= IDLE; + end if; when D2FT => - STATE_OUT <= x"4"; - if( (RX_K_IN = '1') and (RX_DATA_IN = K_IDLE) ) then + STATE_OUT <= x"4"; + if( (RX_K_IN = '1') and (RX_DATA_IN = K_IDLE) ) then NEXT_STATE <= K1F; - ce_ctr_t <= '1'; - else - NEXT_STATE <= IDLE; - end if; + ce_ctr_t <= '1'; + else + NEXT_STATE <= IDLE; + end if; when D2FS => - STATE_OUT <= x"5"; - if( (RX_K_IN = '1') and (RX_DATA_IN = K_IDLE) ) then + STATE_OUT <= x"5"; + if( (RX_K_IN = '1') and (RX_DATA_IN = K_IDLE) ) then NEXT_STATE <= K1F; - ce_ctr_s <= '1'; - else - NEXT_STATE <= IDLE; - end if; + ce_ctr_s <= '1'; + else + NEXT_STATE <= IDLE; + end if; when others => - STATE_OUT <= x"f"; + STATE_OUT <= x"f"; NEXT_STATE <= IDLE; - - end case; - - end process THE_FSM_DECODE_PROC; - -end architecture; + + end case; + + end process THE_FSM_DECODE_PROC; + +end architecture; diff --git a/media_interfaces/sync/rx_rsl.vhd b/media_interfaces/sync/rx_rsl.vhd index 0a2828d..0e3cabf 100644 --- a/media_interfaces/sync/rx_rsl.vhd +++ b/media_interfaces/sync/rx_rsl.vhd @@ -11,6 +11,7 @@ entity rx_rsl is CV_IN : in std_logic; LSM_IN : in std_logic; LOS_IN : in std_logic; + WAP_ZERO_IN : in std_logic; -- outputs RX_SERDES_RST_OUT : out std_logic; RX_PCS_RST_OUT : out std_logic; @@ -26,11 +27,11 @@ architecture rx_rsl_arc of rx_rsl is -- Remark: work of Christian Michel. Just re-edited to reflect necessary changes for ECP3. -- Without this piece of code, many things would have been a real pain. - constant Tshort : unsigned(31 downto 0) := x"00000007"; ---@125MHz 100ms - constant Tplol : unsigned(31 downto 0) := x"00BEBC20"; - constant Tcdr : unsigned(31 downto 0) := x"00BEBC20"; - constant Tviol : unsigned(31 downto 0) := x"00BEBC20"; + constant Tshort : unsigned(31 downto 0) := x"0000000a"; +-- @200MHz 100ms + constant Tplol : unsigned(31 downto 0) := x"003fffff"; --x"01312d00"; + constant Tcdr : unsigned(31 downto 0) := x"003fffff"; --x"01312d00"; + constant Tviol : unsigned(31 downto 0) := x"003fffff"; --x"01312d00"; signal pll_lol_s : std_logic; signal cdr_lol_s : std_logic; @@ -41,7 +42,8 @@ architecture rx_rsl_arc of rx_rsl is signal cnt : unsigned(31 downto 0); type rx_sm_state is (POWERUP, APPLY_CDR_RST, WAIT_CDR_LOCK, TEST_CDR, - APPLY_RXPCS_RST, WAIT_RXPCS_LOCK, TEST_RXPCS, IDLE); + APPLY_RXPCS_RST, WAIT_RXPCS_LOCK, TEST_RXPCS, + CHECK_WAP, TX_SYNC, NORMAL_OP); signal rx_sm : rx_sm_state; @@ -61,13 +63,14 @@ begin cdr_lol_s <= '1'; cv_s <= '1'; lsm_s <= '0'; - los_s <= '1'; + los_s <= '1'; RX_SERDES_RST_OUT <= '1'; RX_PCS_RST_OUT <= '1'; LINK_RX_READY_OUT <= '0'; - + rx_sm <= powerup; + STATE_OUT <= x"f"; cnt <= (others => '0'); elsif( rising_edge(CLK_REF) ) then pll_lol_s <= PLL_LOL_IN; @@ -169,21 +172,43 @@ begin else if( cnt = Tviol ) then cnt <= (others => '0'); - rx_sm <= IDLE; + rx_sm <= CHECK_WAP; else cnt <= cnt + 1; end if; end if; - - when idle => + + when CHECK_WAP => STATE_OUT <= x"7"; RX_SERDES_RST_OUT <= '0'; RX_PCS_RST_OUT <= '0'; + LINK_RX_READY_OUT <= '0'; + cnt <= (others => '0'); + if( WAP_ZERO_IN = '1' ) then + rx_sm <= NORMAL_OP; + else +-- rx_sm <= APPLY_RXPCS_RST; -- DOESNT WORK + rx_sm <= APPLY_CDR_RST; + end if; + + when NORMAL_OP => + STATE_OUT <= x"8"; + RX_SERDES_RST_OUT <= '0'; + RX_PCS_RST_OUT <= '0'; LINK_RX_READY_OUT <= '1'; + cnt <= (others => '0'); if( (lsm_s = '0') or (cv_s = '1') ) then rx_sm <= APPLY_RXPCS_RST; - cnt <= (others => '0'); end if; + + when others => + -- just in case + STATE_OUT <= x"f"; + RX_SERDES_RST_OUT <= '0'; + RX_PCS_RST_OUT <= '0'; + LINK_RX_READY_OUT <= '0'; + rx_sm <= POWERUP; + end case; ------------------------------------------------