From 389de3140b3d630f5d996b0d3e5e8fd0d280dfb4 Mon Sep 17 00:00:00 2001 From: Jan Michel Date: Fri, 11 Aug 2017 16:25:16 +0200 Subject: [PATCH] Add better sync of media interface control signals. Disable Lattice ECP5 link state machine --- media_interfaces/med_ecp5_sfp_sync.vhd | 12 +++-- media_interfaces/sync/med_sync_control.vhd | 53 +++++++++++++------ media_interfaces/sync/med_sync_define.vhd | 5 +- media_interfaces/sync/rx_control.vhd | 15 +++--- media_interfaces/sync/rx_reset_fsm.vhd | 61 +++++++++------------- media_interfaces/sync/tx_control.vhd | 30 +++++++---- media_interfaces/sync/tx_reset_fsm.vhd | 24 +++++---- 7 files changed, 118 insertions(+), 82 deletions(-) diff --git a/media_interfaces/med_ecp5_sfp_sync.vhd b/media_interfaces/med_ecp5_sfp_sync.vhd index 9c9b892..033e235 100644 --- a/media_interfaces/med_ecp5_sfp_sync.vhd +++ b/media_interfaces/med_ecp5_sfp_sync.vhd @@ -176,8 +176,8 @@ gen_pcs0 : if SERDES_NUM = 0 generate serdes_sync_0_pll_refclki => clk_200_ref, -- sli_rst => '0', serdes_sync_0_pll_lol => tx_pll_lol, - serdes_sync_0_rsl_disable => '0', - serdes_sync_0_rsl_rst => CLEAR, + serdes_sync_0_rsl_disable => '1', + serdes_sync_0_rsl_rst => '0', --CLEAR, serdes_sync_0_rsl_rx_rdy => rx_ready, serdes_sync_0_rsl_tx_rdy => tx_ready ); @@ -198,7 +198,7 @@ THE_MED_CONTROL : entity work.med_sync_control CLK_SYS => SYSCLK, CLK_RXI => clk_rx_full, --clk_rx_full, CLK_RXHALF => '0', - CLK_TXI => clk_200_ref, --clk_200_internal, --clk_tx_full, JM150706 + CLK_TXI => clk_tx_full, --clk_200_ref, --clk_200_internal, --clk_tx_full, JM150706 CLK_REF => clk_200_ref, --CLK_INTERNAL_FULL, RESET => RESET, CLEAR => CLEAR, @@ -227,6 +227,9 @@ THE_MED_CONTROL : entity work.med_sync_control RX_DLM_WORD => RX_DLM_WORD, RX_DLM => RX_DLM, + SERDES_RX_READY_IN => rx_ready, + SERDES_TX_READY_IN => tx_ready, + STAT_TX_CONTROL => stat_tx_control_i, STAT_RX_CONTROL => stat_rx_control_i, DEBUG_TX_CONTROL => debug_tx_control_i, @@ -283,7 +286,8 @@ stat_med(5) <= rx_cdr_lol; stat_med(6) <= rx_los_low; stat_med(7) <= rx_ready; stat_med(8) <= tx_ready; -stat_med(31 downto 9) <= (others => '0'); +stat_med(9) <= lsm_status; +stat_med(31 downto 10) <= (others => '0'); end architecture; diff --git a/media_interfaces/sync/med_sync_control.vhd b/media_interfaces/sync/med_sync_control.vhd index 56cca26..4ab938b 100644 --- a/media_interfaces/sync/med_sync_control.vhd +++ b/media_interfaces/sync/med_sync_control.vhd @@ -45,6 +45,9 @@ entity med_sync_control is RX_DLM_WORD : out std_logic_vector(7 downto 0); RX_DLM : out std_logic; + SERDES_RX_READY_IN : in std_logic := '1'; + SERDES_TX_READY_IN : in std_logic := '1'; + STAT_TX_CONTROL : out std_logic_vector(31 downto 0); STAT_RX_CONTROL : out std_logic_vector(31 downto 0); DEBUG_TX_CONTROL : out std_logic_vector(31 downto 0); @@ -86,6 +89,8 @@ signal send_link_reset_real_i : std_logic := '0'; signal reset_i, rst_n, rst_n_tx : std_logic; signal media_med2int_i : MED2INT; +signal finished_reset_rx, finished_reset_rx_q : std_logic; +signal finished_reset_tx, finished_reset_tx_q : std_logic; begin @@ -106,25 +111,27 @@ media_med2int_i.clk_full <= CLK_RXI; ------------------------------------------------- THE_RX_FSM : rx_reset_fsm port map( - RST_N => rst_n, - RX_REFCLK => CLK_REF, - TX_PLL_LOL_QD_S => TX_LOL, - RX_SERDES_RST_CH_C => RX_SERDES_RST, - RX_CDR_LOL_CH_S => RX_CDR_LOL, - RX_LOS_LOW_CH_S => RX_LOS, - RX_PCS_RST_CH_C => RX_PCS_RST, - WA_POSITION => wa_position_rx, - STATE_OUT => rx_fsm_state + RST_N => rst_n, + RX_REFCLK => CLK_REF, + TX_PLL_LOL_QD_S => TX_LOL, + RX_SERDES_RST_CH_C => RX_SERDES_RST, + RX_CDR_LOL_CH_S => RX_CDR_LOL, + RX_LOS_LOW_CH_S => RX_LOS, + RX_PCS_RST_CH_C => RX_PCS_RST, + WA_POSITION => wa_position_rx, + NORMAL_OPERATION_OUT => finished_reset_rx, + STATE_OUT => rx_fsm_state ); THE_TX_FSM : tx_reset_fsm port map( - RST_N => rst_n_tx, - TX_REFCLK => CLK_REF, - TX_PLL_LOL_QD_S => TX_LOL, - RST_QD_C => QUAD_RST, - TX_PCS_RST_CH_C => TX_PCS_RST, - STATE_OUT => tx_fsm_state + RST_N => rst_n_tx, + TX_REFCLK => CLK_REF, + TX_PLL_LOL_QD_S => TX_LOL, + RST_QD_C => QUAD_RST, + TX_PCS_RST_CH_C => TX_PCS_RST, + NORMAL_OPERATION_OUT => finished_reset_tx, + STATE_OUT => tx_fsm_state ); @@ -143,12 +150,15 @@ end process; --Slave enables RX/TX when sync is done, Master waits additional time to make sure link is stable PROC_ALLOW : process begin wait until rising_edge(CLK_SYS); - if rx_fsm_state = x"6" and (IS_SYNC_SLAVE = 1 or start_timer(start_timer'left) = '1') then + if finished_reset_rx_q = '1' --SERDES_RX_READY_IN= '1' --and + and (IS_SYNC_SLAVE = 1 or start_timer(start_timer'left) = '1') then rx_allow <= '1'; else rx_allow <= '0'; end if; - if tx_fsm_state = x"5" and rx_fsm_state = x"6" and (IS_SYNC_SLAVE = 1 or start_timer(start_timer'left) = '1') then + if --SERDES_RX_READY_IN = '1' and SERDES_TX_READY_IN = '1' + finished_reset_tx_q = '1' and finished_reset_rx_q = '1' + and (IS_SYNC_SLAVE = 1 or start_timer(start_timer'left) = '1') then tx_allow <= '1'; else tx_allow <= '0'; @@ -156,6 +166,14 @@ PROC_ALLOW : process begin end process; + link_reset_fin_tx : signal_sync port map(RESET => '0',CLK0 => CLK_SYS, CLK1 => CLK_SYS, + D_IN(0) => finished_reset_tx, + D_OUT(0) => finished_reset_tx_q); + link_reset_fin_rx : signal_sync port map(RESET => '0',CLK0 => CLK_SYS, CLK1 => CLK_SYS, + D_IN(0) => finished_reset_rx, + D_OUT(0) => finished_reset_rx_q); + + PROC_START_TIMER : process begin wait until rising_edge(CLK_SYS); if got_link_ready_i = '1' then @@ -232,6 +250,7 @@ THE_RX_CONTROL : rx_control SEND_LINK_RESET_OUT => send_link_reset_i, MAKE_RESET_OUT => make_link_reset_i, RX_ALLOW_IN => rx_allow, + RX_RESET_FINISHED => finished_reset_rx, GOT_LINK_READY => got_link_ready_i, DEBUG_OUT => DEBUG_RX_CONTROL, diff --git a/media_interfaces/sync/med_sync_define.vhd b/media_interfaces/sync/med_sync_define.vhd index 85a6730..c5cf348 100644 --- a/media_interfaces/sync/med_sync_define.vhd +++ b/media_interfaces/sync/med_sync_define.vhd @@ -43,6 +43,7 @@ component rx_control is SEND_LINK_RESET_OUT : out std_logic := '0'; MAKE_RESET_OUT : out std_logic := '0'; RX_ALLOW_IN : in std_logic := '0'; + RX_RESET_FINISHED : in std_logic := '0'; GOT_LINK_READY : out std_logic := '0'; DEBUG_OUT : out std_logic_vector(31 downto 0); @@ -96,6 +97,7 @@ component rx_reset_fsm is RX_PCS_RST_CH_C : out std_logic; --fix word alignment position to 0 for non-slave links! WA_POSITION : in std_logic_vector(3 downto 0) := x"0"; + NORMAL_OPERATION_OUT : out std_logic; STATE_OUT : out std_logic_vector(3 downto 0) ); end component; @@ -107,6 +109,7 @@ component tx_reset_fsm is TX_PLL_LOL_QD_S : in std_logic; RST_QD_C : out std_logic; TX_PCS_RST_CH_C : out std_logic; + NORMAL_OPERATION_OUT : out std_logic; STATE_OUT : out std_logic_vector(3 downto 0) ); end component; @@ -182,4 +185,4 @@ end component; -end package; \ No newline at end of file +end package; diff --git a/media_interfaces/sync/rx_control.vhd b/media_interfaces/sync/rx_control.vhd index 12af875..ccc72b0 100644 --- a/media_interfaces/sync/rx_control.vhd +++ b/media_interfaces/sync/rx_control.vhd @@ -13,11 +13,12 @@ entity rx_control is CLK_100 : in std_logic; RESET_IN : in std_logic; +--clk_sys signals RX_DATA_OUT : out std_logic_vector(15 downto 0); RX_PACKET_NUMBER_OUT : out std_logic_vector(2 downto 0); RX_WRITE_OUT : out std_logic; --- RX_READ_IN : in std_logic; +-- clk_rx signals RX_DATA_IN : in std_logic_vector( 7 downto 0); RX_K_IN : in std_logic; @@ -31,10 +32,12 @@ entity rx_control is RX_DLM : out std_logic := '0'; RX_DLM_WORD : out std_logic_vector( 7 downto 0) := (others => '0'); - SEND_LINK_RESET_OUT : out std_logic := '0'; - MAKE_RESET_OUT : out std_logic := '0'; - RX_ALLOW_IN : in std_logic := '0'; - GOT_LINK_READY : out std_logic := '0'; +--other signals + SEND_LINK_RESET_OUT : out std_logic := '0'; --clk_rx + MAKE_RESET_OUT : out std_logic := '0'; --clk_rx + RX_ALLOW_IN : in std_logic := '0'; --clk_sys + RX_RESET_FINISHED : in std_logic := '0'; --clk_rx + GOT_LINK_READY : out std_logic := '0'; --clk_rx DEBUG_OUT : out std_logic_vector(31 downto 0); STAT_REG_OUT : out std_logic_vector(31 downto 0) @@ -231,7 +234,7 @@ PROC_RX_FSM : process begin end case; - if RESET_IN = '1' then + if RESET_IN = '1' or RX_RESET_FINISHED = '0' then rx_state <= SLEEP; make_reset_i <= '0'; send_link_reset_i <= '0'; diff --git a/media_interfaces/sync/rx_reset_fsm.vhd b/media_interfaces/sync/rx_reset_fsm.vhd index b9d4040..7fc3aec 100644 --- a/media_interfaces/sync/rx_reset_fsm.vhd +++ b/media_interfaces/sync/rx_reset_fsm.vhd @@ -17,6 +17,7 @@ entity rx_reset_fsm is RX_PCS_RST_CH_C : out std_logic; --fix word alignment position to 0 for non-slave links! WA_POSITION : in std_logic_vector(3 downto 0) := x"0"; + NORMAL_OPERATION_OUT : out std_logic; STATE_OUT : out std_logic_vector(3 downto 0) ); end entity ; @@ -29,9 +30,9 @@ type statetype is (WAIT_FOR_PLOL, RX_SERDES_RESET, WAIT_FOR_timer1, CHECK_LOL_LO signal cs: statetype; -- current state of lsm signal ns: statetype; -- next state of lsm -signal tx_pll_lol_qd_s_int: std_logic; -signal rx_los_low_int: std_logic; -signal plol_los_int: std_logic; +signal tx_pll_lol_qd_q: std_logic; +signal rx_cdr_lol_ch_q: std_logic; +signal rx_los_low_ch_q: std_logic; signal rx_lol_los : std_logic; signal rx_lol_los_int: std_logic; signal rx_lol_los_del: std_logic; @@ -49,7 +50,7 @@ signal timer2 : std_logic; begin -rx_lol_los <= rx_cdr_lol_ch_s or rx_los_low_ch_s ; +rx_lol_los <= rx_cdr_lol_ch_q or rx_los_low_ch_q ; process(RX_REFCLK) begin @@ -58,39 +59,29 @@ begin cs <= WAIT_FOR_PLOL; rx_lol_los_int <= '1'; rx_lol_los_del <= '1'; - tx_pll_lol_qd_s_int <= '1'; RX_PCS_RST_CH_C <= '1'; RX_SERDES_RST_CH_C <= '0'; - rx_los_low_int <= '1'; else cs <= ns; rx_lol_los_del <= rx_lol_los; rx_lol_los_int <= rx_lol_los_del; - tx_pll_lol_qd_s_int <= tx_pll_lol_qd_s; RX_PCS_RST_CH_C <= rx_pcs_rst_ch_c_int; RX_SERDES_RST_CH_C <= rx_serdes_rst_ch_c_int; - rx_los_low_int <= rx_los_low_ch_s; end if; end if; end process; ---timer1 = 3NS; ---Fastest REFCLK = 312 MHz, or 3ns. We need 1 REFCLK cycles or 2 REFCLKDIV2 cycles ---A 1 bit counter counts 2 cycles, so a 2 bit ([1:0]) counter will do if we set timer1 = bit[1] --- process begin --- wait until rising_edge(RX_REFCLK); --- if reset_timer1 = '1' then --- counter1 <= "00"; --- timer1 <= '0'; --- else --- if counter1(1) = '1' then --- timer1 <='1'; --- else --- timer1 <='0'; --- counter1 <= counter1 + 1 ; --- end if; --- end if; --- end process; + sync_sfp_sigs : entity work.signal_sync + generic map(WIDTH => 3) + port map(RESET => '0',CLK0 => RX_REFCLK, CLK1 => RX_REFCLK, + D_IN(0) => TX_PLL_LOL_QD_S, + D_IN(1) => RX_CDR_LOL_CH_S, + D_IN(2) => RX_LOS_LOW_CH_S, + D_OUT(0) => tx_pll_lol_qd_q, + D_OUT(1) => rx_cdr_lol_ch_q, + D_OUT(2) => rx_los_low_ch_q + ); + --timer2 = 400,000 Refclk cycles or 200,000 REFCLKDIV2 cycles --An 18 bit counter ([17:0]) counts 262144 cycles, so a 19 bit ([18:0]) counter will do if we set timer2 = bit[18] @@ -110,16 +101,17 @@ end process; end process; -process(cs, tx_pll_lol_qd_s_int, rx_los_low_int, timer1, rx_lol_los_int, timer2, wa_position, rx_lol_los_del) +process(cs, tx_pll_lol_qd_q, rx_los_low_ch_q, timer1, rx_lol_los_int, timer2, wa_position, rx_lol_los_del) begin --- reset_timer1 <= '0'; - reset_timer2 <= '0'; - STATE_OUT <= x"F"; + reset_timer2 <= '0'; + STATE_OUT <= x"F"; + NORMAL_OPERATION_OUT <= '0'; + case cs is when WAIT_FOR_PLOL => rx_pcs_rst_ch_c_int <= '1'; rx_serdes_rst_ch_c_int <= '0'; - if (tx_pll_lol_qd_s_int = '1' or rx_los_low_int = '1') then --Also make sure A Signal + if (tx_pll_lol_qd_q = '1' or rx_los_low_ch_q = '1') then --Also make sure A Signal ns <= WAIT_FOR_PLOL; --is Present prior to moving to the next else ns <= RX_SERDES_RESET; @@ -137,11 +129,7 @@ begin when WAIT_FOR_timer1 => rx_pcs_rst_ch_c_int <= '1'; rx_serdes_rst_ch_c_int <= '1'; --- if timer1 = '1' then - ns <= CHECK_LOL_LOS; --- else --- ns <= WAIT_FOR_timer1; --- end if; + ns <= CHECK_LOL_LOS; STATE_OUT <= x"3"; when CHECK_LOL_LOS => @@ -176,6 +164,7 @@ begin if rx_lol_los_int = '1' or WA_POSITION /= x"0" then ns <= WAIT_FOR_PLOL; else + NORMAL_OPERATION_OUT <= '1'; ns <= NORMAL; end if; STATE_OUT <= x"6"; @@ -190,4 +179,4 @@ end process; -end architecture; \ No newline at end of file +end architecture; diff --git a/media_interfaces/sync/tx_control.vhd b/media_interfaces/sync/tx_control.vhd index 313b015..8cdbcd8 100644 --- a/media_interfaces/sync/tx_control.vhd +++ b/media_interfaces/sync/tx_control.vhd @@ -337,7 +337,7 @@ begin if (current_state = SEND_START_H or current_state = SEND_IDLE_H or current_state = SEND_DATA_H or current_state = SEND_DLM_H or current_state = SEND_REQUEST_H or current_state = SEND_CHKSUM_H) and ram_empty = '0' and tx_allow_qtx = '1' and send_link_reset_qtx = '0' - and make_request_i = '0' and make_restart_i = '0' and send_dlm_i = '0' then + and make_request_i = '0' and make_restart_i = '0' and send_dlm_i = '0' then --TODO: Sync these 3 signals ram_read <= '1'; else ram_read <= '0'; @@ -351,11 +351,19 @@ begin -- ---------------------------------------------------------------------- -tx_allow_qtx <= TX_ALLOW_IN when rising_edge(CLK_200); -rx_allow_qtx <= RX_ALLOW_IN when rising_edge(CLK_200); + txallow_sync : signal_sync port map(RESET => '0',CLK0 => CLK_200, CLK1 => CLK_200, + D_IN(0) => TX_ALLOW_IN, + D_OUT(0) => tx_allow_qtx); + rxallow_sync : signal_sync port map(RESET => '0',CLK0 => CLK_200, CLK1 => CLK_200, + D_IN(0) => RX_ALLOW_IN, + D_OUT(0) => rx_allow_qtx); + sendres_sync : signal_sync port map(RESET => '0',CLK0 => CLK_200, CLK1 => CLK_200, + D_IN(0) => SEND_LINK_RESET_IN, + D_OUT(0) => send_link_reset_qtx); + txallow_sync2 : signal_sync port map(RESET => '0',CLK0 => CLK_100, CLK1 => CLK_100, + D_IN(0) => tx_allow_qtx, + D_OUT(0) => tx_allow_q); -send_link_reset_qtx <= SEND_LINK_RESET_IN when rising_edge(CLK_200); -tx_allow_q <= tx_allow_qtx when rising_edge(CLK_100); THE_RETRANSMIT_PULSE_SYNC_1 : pulse_sync port map( @@ -501,10 +509,14 @@ tx_allow_q <= tx_allow_qtx when rising_edge(CLK_100); begin if rising_edge(CLK_100) then STAT_REG_OUT <= (others => '0'); - STAT_REG_OUT(7 downto 0) <= std_logic_vector(ram_fill_level); - STAT_REG_OUT(15 downto 8) <= std_logic_vector(ram_read_addr); +-- STAT_REG_OUT(7 downto 0) <= std_logic_vector(ram_fill_level); + STAT_REG_OUT(3 downto 0) <= state_bits; + + STAT_REG_OUT(7) <= TX_K_OUT; + STAT_REG_OUT(15 downto 8) <= TX_DATA_OUT; +-- STAT_REG_OUT(15 downto 8) <= std_logic_vector(ram_read_addr); -- STAT_REG_OUT(16) <= ram_afull; --- STAT_REG_OUT(17) <= ram_empty; + STAT_REG_OUT(17) <= ram_empty; STAT_REG_OUT(18) <= tx_allow_qtx; STAT_REG_OUT(19) <= TX_ALLOW_IN; STAT_REG_OUT(20) <= make_restart_i; @@ -538,4 +550,4 @@ state_bits <= x"0" when current_state = SEND_IDLE_L else x"c" when current_state = SEND_RESET else x"F"; -end architecture; \ No newline at end of file +end architecture; diff --git a/media_interfaces/sync/tx_reset_fsm.vhd b/media_interfaces/sync/tx_reset_fsm.vhd index 0d8d22c..b10d8e1 100644 --- a/media_interfaces/sync/tx_reset_fsm.vhd +++ b/media_interfaces/sync/tx_reset_fsm.vhd @@ -13,6 +13,7 @@ port ( TX_PLL_LOL_QD_S : in std_logic; RST_QD_C : out std_logic; TX_PCS_RST_CH_C : out std_logic; + NORMAL_OPERATION_OUT : out std_logic; STATE_OUT : out std_logic_vector(3 downto 0) ); @@ -45,17 +46,21 @@ process (TX_REFCLK, RST_N) begin if RST_N = '0' then cs <= QUAD_RESET; - tx_pll_lol_qd_s_int <= '1'; tx_pcs_rst_ch_c <= '1'; RST_QD_C <= '1'; else if rising_edge(TX_REFCLK) then cs <= ns; - tx_pll_lol_qd_s_int <= tx_pll_lol_qd_s; tx_pcs_rst_ch_c <= tx_pcs_rst_ch_c_int; RST_QD_C <= RST_QD_C_int; end if; end if; end process; + + sync_sfp_sigs : entity work.signal_sync port map(RESET => '0',CLK0 => TX_REFCLK, CLK1 => TX_REFCLK, + D_IN(0) => TX_PLL_LOL_QD_S, + D_OUT(0) => tx_pll_lol_qd_s_int); + + --TIMER1 = 20ns; --Fastest REFLCK =312 MHZ, or 3 ns. We need 8 REFCLK cycles or 4 REFCLKDIV2 cycles -- A 2 bit counter ([1:0]) counts 4 cycles, so a 3 bit ([2:0]) counter will do if we set TIMER1 = bit[2] @@ -106,11 +111,11 @@ end process; process(cs, TIMER1, TIMER2, tx_pll_lol_qd_s_int) begin - - reset_timer1 <= '0'; - reset_timer2 <= '0'; - STATE_OUT <= x"F"; - + reset_timer1 <= '0'; + reset_timer2 <= '0'; + STATE_OUT <= x"F"; + NORMAL_OPERATION_OUT <= '0'; + case cs is when QUAD_RESET => @@ -158,8 +163,9 @@ begin if tx_pll_lol_qd_s_int = '1' then ns <= QUAD_RESET; else + NORMAL_OPERATION_OUT <= '1'; ns <= NORMAL; - end if; + end if; when others => ns <= QUAD_RESET; @@ -168,4 +174,4 @@ begin end process; -end architecture; \ No newline at end of file +end architecture; -- 2.43.0