From 33ec6fd9fe13127154fa70202b433ce5547f1801 Mon Sep 17 00:00:00 2001 From: Michael Boehmer Date: Thu, 2 Dec 2021 15:18:58 +0100 Subject: [PATCH] progress. reset handling can be considered a pain in the ass, again. --- media_interfaces/med_ecp3_sfp_sync_all_RS.vhd | 19 +- media_interfaces/sync/med_sync_control_RS.vhd | 75 ++-- media_interfaces/sync/med_sync_define_RS.vhd | 322 +++++++++--------- media_interfaces/sync/rx_rsl.vhd | 195 +++++++++++ 4 files changed, 419 insertions(+), 192 deletions(-) create mode 100644 media_interfaces/sync/rx_rsl.vhd diff --git a/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd b/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd index 063dff9..0065776 100644 --- a/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd +++ b/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd @@ -11,6 +11,7 @@ use work.med_sync_define_RS.all; entity med_ecp3_sfp_sync_all_RS is generic( + SERDES_NUM : integer := 3; SIM_MODE : integer := 0; IS_MODE : int_array_t(0 to 3) := (c_IS_UNUSED, c_IS_UNUSED, c_IS_UNUSED, c_IS_UNUSED); IS_WAP_ZERO : integer := 1 @@ -132,6 +133,7 @@ architecture med_ecp3_sfp_sync_all_RS_arch of med_ecp3_sfp_sync_all_RS is signal tx_reset_i : std_logic_vector(3 downto 0); signal master_reset_sel : std_logic; + signal pll_lol_i : std_logic; signal quad_mode : integer range 0 to 100; @@ -154,7 +156,7 @@ begin assert not ((quad_mode >= 1) and (quad_mode <= 4)) report "Note: QUAD with only master ports detected" severity note; assert not (quad_mode = 8) report "Note: QUAD with one slave port detected" severity note; assert not ((quad_mode >= 9) and (quad_mode <= 11)) report "Note: mixed master/slave QUAD detected" severity note; - + ------------------------------------------------- -- only used SerDes are activated ------------------------------------------------- @@ -227,6 +229,7 @@ begin ------------------------------------------------- -- Serdes ------------------------------------------------- + gen_pcs3: if SERDES_NUM = 3 generate THE_SERDES : entity work.serdes_sync_all_RS port map( hdinp_ch0 => hdinp(0), @@ -366,13 +369,15 @@ begin fpga_txrefclk => MASTER_CLK_IN, -- reference TX clock tx_serdes_rst_c => '0', - tx_pll_lol_qd_s => TX_PLL_LOL_OUT, + tx_pll_lol_qd_s => pll_lol_i, rst_qd_c => master_reset_sel, --RST_QUAD_IN, -- deadlock caused by this... 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 @@ -397,6 +402,9 @@ 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, -- control signals to SerDes @@ -477,6 +485,9 @@ 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); end architecture; diff --git a/media_interfaces/sync/med_sync_control_RS.vhd b/media_interfaces/sync/med_sync_control_RS.vhd index e94cb38..92b1299 100644 --- a/media_interfaces/sync/med_sync_control_RS.vhd +++ b/media_interfaces/sync/med_sync_control_RS.vhd @@ -29,6 +29,9 @@ entity med_sync_control_RS is 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; WA_POSITION_IN : in std_logic_vector(3 downto 0); -- WordAlignment Position LINK_TX_READY_IN : in std_logic; -- control signals to SerDes @@ -70,10 +73,10 @@ architecture med_sync_control_arch of med_sync_control_RS is signal led_rx, last_led_rx : std_logic; signal led_tx, last_led_tx : std_logic; signal timer : unsigned(20 downto 0); - signal sd_los_qsys : std_logic; + signal sd_los_q : std_logic; signal reset_i : std_logic; - signal reset_rx_fsm_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; @@ -100,47 +103,49 @@ begin ) port map( RESET => '0', - CLK0 => CLK_SYS, - CLK1 => CLK_SYS, + CLK0 => CLK_REF, + CLK1 => CLK_REF, D_IN(0) => SFP_LOS_IN, - D_OUT(0) => sd_los_qsys + 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 <= (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 - reset_rx_fsm_i <= (CLEAR or RESET or sd_los_qsys); +-- clrn_rx_fsm_i <= not (CLEAR or RESET or sd_los_q); + clr_rx_fsm_i <= sd_los_q; + + MASTER_RESET_OUT <= sd_los_q; -- TX_CONTROL and RX_CONTROL reset - reset_i <= (RESET or sd_los_qsys) when (IS_MODE = c_IS_SLAVE) + reset_i <= (RESET or sd_los_q) when (IS_MODE = c_IS_SLAVE) else (RESET); ------------------------------------------------- -- Reset RX FSM ------------------------------------------------- - THE_RX_RST_FSM: main_rx_reset_RS -- OK - generic map( - SIM_MODE => SIM_MODE, - IS_WAP_ZERO => IS_WAP_ZERO, - IS_MODE => IS_MODE - ) + THE_RX_RST_FSM: rx_rsl port map( - CLEAR => reset_rx_fsm_i, - LOCALCLK => CLK_REF, - TX_PLL_LOL_IN => '0', -- TX and RX channel are independent - RX_CDR_LOL_IN => RX_CDR_LOL_IN, -- internally synced - RX_LOS_LOW_IN => RX_LOS_IN, -- internally synced - WA_POSITION_IN => WA_POSITION_IN, -- internally synced - SFP_LOS_IN => SFP_LOS_IN, -- internally synced - RX_PCS_RST_CH_C_OUT => rx_pcs_rst_i, - RX_SERDES_RST_CH_C_OUT => rx_serdes_rst_i, - LINK_RX_READY_OUT => link_rx_ready_i, - MASTER_RESET_OUT => MASTER_RESET_OUT, -- not necessary??? - STATE_OUT => rx_fsm_state + CLEAR => clr_rx_fsm_i, + REFCLK => CLK_REF, + pll_lol => PLL_LOL_IN, + cdr_lol => RX_CDR_LOL_IN, + cv => CV_IN, + lsm => LSM_IN, + los => RX_LOS_IN, + -- outputs + rx_serdes_rst => rx_serdes_rst_i, + rx_pcs_rst => rx_pcs_rst_i, + state_out => rx_fsm_state ); + + link_rx_ready_i <= '0'; -- BUG + -- reset signals for RX SerDes need to be sync'ed to real RX clock SYNC_RST_SIGS: entity work.signal_sync generic map( WIDTH => 2 ) @@ -253,7 +258,7 @@ begin ------------------------------------------------- led_ok <= link_full_done_i when rising_edge(CLK_SYS); led_rx <= (media_med2int_i.dataready or led_rx) and not timer(20) when rising_edge(CLK_SYS); - led_tx <= (MEDIA_INT2MED.dataready or led_tx or sd_los_qsys) and not timer(20) when rising_edge(CLK_SYS); + led_tx <= (MEDIA_INT2MED.dataready or led_tx or sd_los_q) and not timer(20) when rising_edge(CLK_SYS); ROC_TIMER_PROC: process( CLK_SYS, RESET ) begin @@ -292,12 +297,12 @@ 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) <= link_rx_ready_i; - DEBUG_OUT(6) <= link_half_done_i; - DEBUG_OUT(7) <= link_full_done_i; - DEBUG_OUT(8) <= LINK_TX_READY_IN; - DEBUG_OUT(9) <= is_wap_zero_i; - DEBUG_OUT(10) <= reset_rx_fsm_i; + DEBUG_OUT(5) <= CV_IN;--link_rx_ready_i; + DEBUG_OUT(6) <= LSM_IN;--link_half_done_i; + DEBUG_OUT(7) <= PLL_LOL_IN;--link_full_done_i; + DEBUG_OUT(8) <= RESET;--LINK_TX_READY_IN; + DEBUG_OUT(9) <= CLEAR;--is_wap_zero_i; + DEBUG_OUT(10) <= clr_rx_fsm_i; DEBUG_OUT(11) <= reset_i; DEBUG_OUT(15 downto 12) <= rx_fsm_state; DEBUG_OUT(21 downto 16) <= debug_tx_control_i(5 downto 0); diff --git a/media_interfaces/sync/med_sync_define_RS.vhd b/media_interfaces/sync/med_sync_define_RS.vhd index a71751e..5b44a85 100644 --- a/media_interfaces/sync/med_sync_define_RS.vhd +++ b/media_interfaces/sync/med_sync_define_RS.vhd @@ -1,11 +1,11 @@ -library ieee; -USE IEEE.std_logic_1164.ALL; -USE IEEE.std_logic_ARITH.ALL; -USE IEEE.std_logic_UNSIGNED.ALL; - -use work.trb_net_std.all; - -package med_sync_define_RS is +library ieee; +USE IEEE.std_logic_1164.ALL; +USE IEEE.std_logic_ARITH.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +use work.trb_net_std.all; + +package med_sync_define_RS is -- These idles are available constant K_BGN : std_logic_vector(7 downto 0) := x"1c"; -- K28.0 -- reserved for retransmission @@ -22,157 +22,173 @@ constant K_EOP : std_logic_vector(7 downto 0) := x"fd"; -- K29.7 -- reserved constant K_RST : std_logic_vector(7 downto 0) := x"fe"; -- K30.7 -- used for reset -- data char for idle -constant D_IDLE0 : std_logic_vector(7 downto 0) := x"C5"; -- D5.6 -constant D_IDLE1 : std_logic_vector(7 downto 0) := x"50"; -- D16.2 - -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_ecp3_fifo_18x16_dualport_oreg - port( - Data : in std_logic_vector(17 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(17 downto 0); - Empty : out std_logic; - Full : out std_logic; - AlmostFull : out std_logic - ); -end component; +constant D_IDLE0 : std_logic_vector(7 downto 0) := x"C5"; -- D5.6 +constant D_IDLE1 : std_logic_vector(7 downto 0) := x"50"; -- D16.2 + +component rx_rsl is + port ( + CLEAR : in std_logic; + refclk : in std_logic; + pll_lol : in std_logic; + cdr_lol : in std_logic; + cv : in std_logic; + lsm : in std_logic; + los : in std_logic; + -- outputs + rx_serdes_rst : out std_logic; + rx_pcs_rst : out std_logic; + state_out : out std_logic_vector(3 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 main_rx_reset_RS is - generic( - SIM_MODE : integer := 0; - IS_WAP_ZERO : integer := 0; - IS_MODE : integer := c_IS_SLAVE - ); - port( - CLEAR : in std_logic; -- async reset, active high - LOCALCLK : in std_logic; -- CDR reference clock - TX_PLL_LOL_IN : in std_logic; -- TX_PLOL form AUX channel - RX_CDR_LOL_IN : in std_logic; -- CDR LOL - RX_LOS_LOW_IN : in std_logic; -- RX LOS - WA_POSITION_IN : in std_logic_vector(3 downto 0); - SFP_LOS_IN : in std_logic; -- SFP LOS signal - RX_PCS_RST_CH_C_OUT : out std_logic; - RX_SERDES_RST_CH_C_OUT : out std_logic; - LINK_RX_READY_OUT : out std_logic; -- RX SerDes is fully operational - MASTER_RESET_OUT : out std_logic; -- can be used as master reset if sourced from Slave port - STATE_OUT : out std_logic_vector(3 downto 0) - ); +component lattice_ecp3_fifo_18x16_dualport_oreg + port( + Data : in std_logic_vector(17 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(17 downto 0); + Empty : out std_logic; + Full : out std_logic; + AlmostFull : out std_logic + ); end component; -component main_tx_reset_RS is - generic( - SIM_MODE : integer := 0 - ); - port( - CLEAR : in std_logic; -- async reset - 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_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 - STATE_OUT : out std_logic_vector(3 downto 0) - ); +--component main_rx_reset_RS is +-- generic( +-- SIM_MODE : integer := 0; +-- IS_WAP_ZERO : integer := 0; +-- IS_MODE : integer := c_IS_SLAVE +-- ); +-- port( +-- CLEAR : in std_logic; -- async reset, active high +-- LOCALCLK : in std_logic; -- CDR reference clock +-- TX_PLL_LOL_IN : in std_logic; -- TX_PLOL form AUX channel +-- RX_CDR_LOL_IN : in std_logic; -- CDR LOL +-- RX_LOS_LOW_IN : in std_logic; -- RX LOS +-- WA_POSITION_IN : in std_logic_vector(3 downto 0); +-- SFP_LOS_IN : in std_logic; -- SFP LOS signal +-- RX_PCS_RST_CH_C_OUT : out std_logic; +-- RX_SERDES_RST_CH_C_OUT : out std_logic; +-- LINK_RX_READY_OUT : out std_logic; -- RX SerDes is fully operational +-- MASTER_RESET_OUT : out std_logic; -- can be used as master reset if sourced from Slave port +-- STATE_OUT : out std_logic_vector(3 downto 0) +-- ); +--end component; + +component main_tx_reset_RS is + generic( + SIM_MODE : integer := 0 + ); + port( + CLEAR : in std_logic; -- async reset + 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_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 + STATE_OUT : out std_logic_vector(3 downto 0) + ); end component; -component rx_control_RS is - generic( - SIM_MODE : integer := 0 - ); - port( - CLK_RXI : in std_logic; - CLK_SYS : in std_logic; - RESET : in std_logic; -- synchronous to RXI - -- Media Interface - 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; - -- SerDex data stream - RX_DATA_IN : in std_logic_vector(7 downto 0); - RX_K_IN : in std_logic; - -- synchronous link signals - WORD_SYNC_OUT : out std_logic; - RX_DLM_OUT : out std_logic; - RX_DLM_WORD_OUT : out std_logic_vector(7 downto 0); - RX_RST_OUT : out std_logic; - RX_RST_WORD_OUT : out std_logic_vector(7 downto 0); - -- link status signals - LINK_RX_READY_IN : in std_logic; - LINK_TX_READY_IN : in std_logic; - LINK_HALF_DONE_IN : in std_logic; - LINK_FULL_DONE_IN : in std_logic; - -- debug - DEBUG_OUT : out std_logic_vector(31 downto 0); - STAT_REG_OUT : out std_logic_vector(31 downto 0) - ); -end component; +component rx_control_RS is + generic( + SIM_MODE : integer := 0 + ); + port( + CLK_RXI : in std_logic; + CLK_SYS : in std_logic; + RESET : in std_logic; -- synchronous to RXI + -- Media Interface + 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; + -- SerDex data stream + RX_DATA_IN : in std_logic_vector(7 downto 0); + RX_K_IN : in std_logic; + -- synchronous link signals + WORD_SYNC_OUT : out std_logic; + RX_DLM_OUT : out std_logic; + RX_DLM_WORD_OUT : out std_logic_vector(7 downto 0); + RX_RST_OUT : out std_logic; + RX_RST_WORD_OUT : out std_logic_vector(7 downto 0); + -- link status signals + LINK_RX_READY_IN : in std_logic; + LINK_TX_READY_IN : in std_logic; + LINK_HALF_DONE_IN : in std_logic; + LINK_FULL_DONE_IN : in std_logic; + -- debug + DEBUG_OUT : out std_logic_vector(31 downto 0); + STAT_REG_OUT : out std_logic_vector(31 downto 0) + ); +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 - 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) - ); +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 + 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 component; -component tx_control_RS is - generic( - SIM_MODE : integer := 0; - IS_MODE : integer := c_IS_UNUSED - ); - port( - CLK_TX : in std_logic; - CLK_SYS : in std_logic; - RESET : in std_logic; -- async/sync reset - -- Media Interface - TX_DATA_IN : in std_logic_vector(15 downto 0); -- media interface - TX_PACKET_NUMBER_IN : in std_logic_vector(2 downto 0); -- media interface - TX_WRITE_IN : in std_logic; -- media interface - TX_READ_OUT : out std_logic; -- media interface - -- SerDes data stream - TX_DATA_OUT : out std_logic_vector(7 downto 0); -- to TX SerDes - TX_K_OUT : out std_logic; -- to TX SerDes - -- synchronous signals - WORD_SYNC_IN : in std_logic; -- byte/word sync - SEND_DLM_IN : in std_logic; - SEND_DLM_WORD_IN : in std_logic_vector(7 downto 0); - SEND_RST_IN : in std_logic; - SEND_RST_WORD_IN : in std_logic_vector(7 downto 0); - -- link status signals, internally synced - LINK_TX_READY_IN : in std_logic; -- local ref clock - LINK_RX_READY_IN : in std_logic; -- local ref clock - LINK_HALF_DONE_IN : in std_logic; -- recovered RX clock - LINK_FULL_DONE_IN : in std_logic; -- recovered RX clock - -- debug - DEBUG_OUT : out std_logic_vector(31 downto 0); - STAT_REG_OUT : out std_logic_vector(31 downto 0) - ); +component tx_control_RS is + generic( + SIM_MODE : integer := 0; + IS_MODE : integer := c_IS_UNUSED + ); + port( + CLK_TX : in std_logic; + CLK_SYS : in std_logic; + RESET : in std_logic; -- async/sync reset + -- Media Interface + TX_DATA_IN : in std_logic_vector(15 downto 0); -- media interface + TX_PACKET_NUMBER_IN : in std_logic_vector(2 downto 0); -- media interface + TX_WRITE_IN : in std_logic; -- media interface + TX_READ_OUT : out std_logic; -- media interface + -- SerDes data stream + TX_DATA_OUT : out std_logic_vector(7 downto 0); -- to TX SerDes + TX_K_OUT : out std_logic; -- to TX SerDes + -- synchronous signals + WORD_SYNC_IN : in std_logic; -- byte/word sync + SEND_DLM_IN : in std_logic; + SEND_DLM_WORD_IN : in std_logic_vector(7 downto 0); + SEND_RST_IN : in std_logic; + SEND_RST_WORD_IN : in std_logic_vector(7 downto 0); + -- link status signals, internally synced + LINK_TX_READY_IN : in std_logic; -- local ref clock + LINK_RX_READY_IN : in std_logic; -- local ref clock + LINK_HALF_DONE_IN : in std_logic; -- recovered RX clock + LINK_FULL_DONE_IN : in std_logic; -- recovered RX clock + -- debug + DEBUG_OUT : out std_logic_vector(31 downto 0); + STAT_REG_OUT : out std_logic_vector(31 downto 0) + ); end component; - -end package; + +end package; diff --git a/media_interfaces/sync/rx_rsl.vhd b/media_interfaces/sync/rx_rsl.vhd new file mode 100644 index 0000000..90af3c8 --- /dev/null +++ b/media_interfaces/sync/rx_rsl.vhd @@ -0,0 +1,195 @@ +library ieee; +use ieee.std_logic_1164.all; +use IEEE.std_logic_unsigned.all; +use IEEE.std_logic_arith.all; + +entity rx_rsl is + port ( + CLEAR : in std_logic; + refclk : in std_logic; + pll_lol : in std_logic; + cdr_lol : in std_logic; + cv : in std_logic; + lsm : in std_logic; + los : in std_logic; + -- outputs + rx_serdes_rst : out std_logic; + rx_pcs_rst : out std_logic; + state_out : out std_logic_vector(3 downto 0) + ); +end rx_rsl; + +architecture rx_rsl_arc of rx_rsl is + +attribute syn_keep : boolean; + +------------------------------------------------------------------ +-- Constants Declaration -- +------------------------------------------------------------------ + +--@125MHz 100ms + +constant Tplol : std_logic_vector (31 downto 0):=x"00BEBC20"; +constant Tcdr : std_logic_vector (31 downto 0):=x"00BEBC20"; +constant Tviol : std_logic_vector (31 downto 0):=x"00BEBC20"; + +------------------------------------------------------------------ +-- Internal Variables -- +------------------------------------------------------------------ +signal pll_lol_s : std_logic; +signal cdr_lol_s : std_logic; +signal cv_s : std_logic; +signal lsm_s : std_logic; +signal los_s : std_logic; + +signal cnt : std_logic_vector (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); +signal rx_sm : rx_sm_state; +attribute syn_keep of rx_sm : signal is true; + +begin +------------------------------------------------------------------ +-- Components Instantiation -- +------------------------------------------------------------------ + +------------------------------------------------------------------ +-- Begin Of The Design -- +------------------------------------------------------------------ + +-- Remark: on ECP3, rx_serdes_rst sets RX_CDR_LOL. + +------------------------------------------------------------------ +rx_reset_proc : process (CLEAR, refclk) +begin + if( CLEAR = '1' ) then + pll_lol_s <= '1'; + cdr_lol_s <= '1'; + cv_s <= '1'; + lsm_s <= '0'; + los_s <= '1'; + + rx_serdes_rst <= '1'; + rx_pcs_rst <= '1'; + + rx_sm <= powerup; + cnt <= (others => '0'); + elsif( rising_edge(refclk) ) then + pll_lol_s <= pll_lol; + cdr_lol_s <= cdr_lol; + cv_s <= cv; + lsm_s <= lsm; + los_s <= los; + + case rx_sm is + when powerup => + state_out <= x"0"; +-- rx_serdes_rst <= '1'; -- bad idea + rx_serdes_rst <= '0'; + rx_pcs_rst <= '1'; + if( (pll_lol_s = '1') or (los_s = '1') ) then + cnt <= (others => '0'); + else + if( cnt = Tplol ) then + cnt <= (others => '0'); + rx_sm <= apply_cdr_rst; + else + cnt <= cnt + '1'; + end if; + end if; + + when apply_cdr_rst => + state_out <= x"1"; + rx_serdes_rst <= '1'; + rx_pcs_rst <= '1'; + if( cnt = x"00000007" ) then + cnt <= (others => '0'); + rx_sm <= wait_cdr_lock; + else + cnt <= cnt + '1'; + end if; + + when wait_cdr_lock => + state_out <= x"2"; + rx_serdes_rst <= '0'; + rx_pcs_rst <= '1'; + if( cnt = Tcdr ) then + cnt <= (others => '0'); + rx_sm <= test_cdr; + else + cnt <= cnt + '1'; + end if; + + when test_cdr => + state_out <= x"3"; + rx_serdes_rst <= '0'; + rx_pcs_rst <= '1'; + if( cdr_lol_s = '1' ) then + cnt <= (others => '0'); + rx_sm <= apply_cdr_rst; + else + if( cnt = Tcdr ) then + cnt <= (others => '0'); + rx_sm <= apply_rxpcs_rst; + else + cnt <= cnt + '1'; + end if; + end if; + when apply_rxpcs_rst => + state_out <= x"4"; + rx_serdes_rst <= '0'; + rx_pcs_rst <= '1'; + if (cnt = x"00000007") then + cnt <= (others => '0'); + rx_sm <= wait_rxpcs_lock; + else + cnt <= cnt + '1'; + end if; + + when wait_rxpcs_lock => + state_out <= x"5"; + rx_serdes_rst <= '0'; + rx_pcs_rst <= '0'; + if (cnt = Tviol) then + cnt <= (others => '0'); + rx_sm <= test_rxpcs; + else + cnt <= cnt + '1'; + end if; + when test_rxpcs => + state_out <= x"6"; + rx_serdes_rst <= '0'; + rx_pcs_rst <= '0'; + if (lsm_s = '0') or (cv_s = '1') then + cnt <= (others => '0'); + rx_sm <= apply_rxpcs_rst; + else + if (cnt = Tviol) then + cnt <= (others => '0'); + rx_sm <= idle; + else + cnt <= cnt + '1'; + end if; + end if; + + when idle => + state_out <= x"7"; + rx_serdes_rst <= '0'; + rx_pcs_rst <= '0'; + if (lsm_s = '0') or (cv_s = '1') then + rx_sm <= apply_rxpcs_rst; + cnt <= (others => '0'); + end if; + end case; + +------------------------------------------------ +-- if (pll_lol_s = '1') or (los_s = '1') then + if (pll_lol_s = '1') then + rx_sm <= powerup; + cnt <= (others => '0'); + end if; + +end if; +end process rx_reset_proc; + +end rx_rsl_arc; -- 2.43.0