library ieee;\r
use ieee.std_logic_1164.all;\r
-use IEEE.std_logic_unsigned.all;\r
-use IEEE.std_logic_arith.all;\r
+USE IEEE.numeric_std.all;\r
\r
entity rx_rsl is\r
port (\r
- CLEAR : in std_logic;\r
- refclk : in std_logic;\r
- pll_lol : in std_logic;\r
- cdr_lol : in std_logic;\r
- cv : in std_logic;\r
- lsm : in std_logic;\r
- los : in std_logic;\r
+ CLEAR : in std_logic;\r
+ CLK_REF : in std_logic;\r
+ PLL_LOL_IN : in std_logic;\r
+ CDR_LOL_IN : in std_logic;\r
+ CV_IN : in std_logic;\r
+ LSM_IN : in std_logic;\r
+ LOS_IN : in std_logic;\r
-- outputs\r
- rx_serdes_rst : out std_logic;\r
- rx_pcs_rst : out std_logic;\r
- state_out : out std_logic_vector(3 downto 0)\r
+ RX_SERDES_RST_OUT : out std_logic;\r
+ RX_PCS_RST_OUT : out std_logic;\r
+ LINK_RX_READY_OUT : out std_logic;\r
+ STATE_OUT : out std_logic_vector(3 downto 0)\r
);\r
end rx_rsl; \r
\r
architecture rx_rsl_arc of rx_rsl is\r
\r
-attribute syn_keep : boolean;\r
+ attribute syn_keep : boolean;\r
\r
-------------------------------------------------------------------\r
--- Constants Declaration --\r
-------------------------------------------------------------------\r
+-- Remark: work of Christian Michel. Just re-edited to reflect necessary changes for ECP3.\r
+-- Without this piece of code, many things would have been a real pain.\r
\r
+ constant Tshort : unsigned(31 downto 0) := x"00000007";\r
--@125MHz 100ms\r
+ constant Tplol : unsigned(31 downto 0) := x"00BEBC20";\r
+ constant Tcdr : unsigned(31 downto 0) := x"00BEBC20";\r
+ constant Tviol : unsigned(31 downto 0) := x"00BEBC20";\r
\r
-constant Tplol : std_logic_vector (31 downto 0):=x"00BEBC20";\r
-constant Tcdr : std_logic_vector (31 downto 0):=x"00BEBC20";\r
-constant Tviol : std_logic_vector (31 downto 0):=x"00BEBC20";\r
+ signal pll_lol_s : std_logic;\r
+ signal cdr_lol_s : std_logic;\r
+ signal cv_s : std_logic;\r
+ signal lsm_s : std_logic;\r
+ signal los_s : std_logic;\r
\r
-------------------------------------------------------------------\r
--- Internal Variables --\r
-------------------------------------------------------------------\r
-signal pll_lol_s : std_logic;\r
-signal cdr_lol_s : std_logic;\r
-signal cv_s : std_logic;\r
-signal lsm_s : std_logic;\r
-signal los_s : std_logic;\r
+ signal cnt : unsigned(31 downto 0);\r
\r
-signal cnt : std_logic_vector (31 downto 0);\r
+ type rx_sm_state is (POWERUP, APPLY_CDR_RST, WAIT_CDR_LOCK, TEST_CDR, \r
+ APPLY_RXPCS_RST, WAIT_RXPCS_LOCK, TEST_RXPCS, IDLE);\r
\r
-type rx_sm_state is (powerup, apply_cdr_rst, wait_cdr_lock, test_cdr, apply_rxpcs_rst, wait_rxpcs_lock, test_rxpcs, idle);\r
-signal rx_sm : rx_sm_state;\r
-attribute syn_keep of rx_sm : signal is true;\r
+ signal rx_sm : rx_sm_state;\r
+ \r
+ attribute syn_keep of rx_sm : signal is true;\r
\r
begin\r
-------------------------------------------------------------------\r
--- Components Instantiation --\r
-------------------------------------------------------------------\r
\r
-------------------------------------------------------------------\r
--- Begin Of The Design --\r
-------------------------------------------------------------------\r
-\r
--- Remark: on ECP3, rx_serdes_rst sets RX_CDR_LOL.\r
+-- Remark: on ECP3, rx_serdes_rst sets RX_CDR_LOL. Deadlocks on POWERUP.\r
+-- Remark: RX_LOS is not necessary, as SFP_LOS keeps us safely in reset.\r
+-- Remark: syncing is done here by one FF only. Might be dangerous.\r
\r
------------------------------------------------------------------\r
-rx_reset_proc : process (CLEAR, refclk)\r
+RX_RESET_PROC : process( CLEAR, CLK_REF )\r
begin\r
if( CLEAR = '1' ) then\r
- pll_lol_s <= '1';\r
- cdr_lol_s <= '1';\r
- cv_s <= '1';\r
- lsm_s <= '0';\r
- los_s <= '1'; \r
- \r
- rx_serdes_rst <= '1';\r
- rx_pcs_rst <= '1';\r
+ pll_lol_s <= '1';\r
+ cdr_lol_s <= '1';\r
+ cv_s <= '1';\r
+ lsm_s <= '0';\r
+ los_s <= '1'; \r
+\r
+ RX_SERDES_RST_OUT <= '1';\r
+ RX_PCS_RST_OUT <= '1';\r
+ LINK_RX_READY_OUT <= '0';\r
\r
rx_sm <= powerup;\r
cnt <= (others => '0'); \r
- elsif( rising_edge(refclk) ) then\r
- pll_lol_s <= pll_lol;\r
- cdr_lol_s <= cdr_lol;\r
- cv_s <= cv; \r
- lsm_s <= lsm; \r
- los_s <= los; \r
+ elsif( rising_edge(CLK_REF) ) then\r
+ pll_lol_s <= PLL_LOL_IN;\r
+ cdr_lol_s <= CDR_LOL_IN;\r
+ cv_s <= CV_IN; \r
+ lsm_s <= LSM_IN; \r
+ los_s <= LOS_IN; \r
\r
case rx_sm is\r
- when powerup =>\r
- state_out <= x"0";\r
--- rx_serdes_rst <= '1'; -- bad idea\r
- rx_serdes_rst <= '0';\r
- rx_pcs_rst <= '1';\r
+ when POWERUP =>\r
+ STATE_OUT <= x"0";\r
+ RX_SERDES_RST_OUT <= '0'; -- needed for RX_LOS to be active\r
+ RX_PCS_RST_OUT <= '1';\r
+ LINK_RX_READY_OUT <= '0';\r
if( (pll_lol_s = '1') or (los_s = '1') ) then\r
- cnt <= (others => '0');\r
+ cnt <= (others => '0');\r
else\r
if( cnt = Tplol ) then\r
- cnt <= (others => '0');\r
- rx_sm <= apply_cdr_rst;\r
+ cnt <= (others => '0');\r
+ rx_sm <= APPLY_CDR_RST;\r
else\r
- cnt <= cnt + '1';\r
+ cnt <= cnt + 1;\r
end if;\r
end if;\r
\r
- when apply_cdr_rst =>\r
- state_out <= x"1";\r
- rx_serdes_rst <= '1';\r
- rx_pcs_rst <= '1';\r
- if( cnt = x"00000007" ) then\r
- cnt <= (others => '0');\r
- rx_sm <= wait_cdr_lock;\r
+ when APPLY_CDR_RST =>\r
+ STATE_OUT <= x"1";\r
+ RX_SERDES_RST_OUT <= '1';\r
+ RX_PCS_RST_OUT <= '1';\r
+ LINK_RX_READY_OUT <= '0';\r
+ if( cnt = Tshort ) then\r
+ cnt <= (others => '0');\r
+ rx_sm <= WAIT_CDR_LOCK;\r
else\r
- cnt <= cnt + '1'; \r
+ cnt <= cnt + 1; \r
end if;\r
\r
- when wait_cdr_lock =>\r
- state_out <= x"2";\r
- rx_serdes_rst <= '0';\r
- rx_pcs_rst <= '1';\r
+ when WAIT_CDR_LOCK =>\r
+ STATE_OUT <= x"2";\r
+ RX_SERDES_RST_OUT <= '0';\r
+ RX_PCS_RST_OUT <= '1';\r
+ LINK_RX_READY_OUT <= '0';\r
if( cnt = Tcdr ) then\r
- cnt <= (others => '0');\r
- rx_sm <= test_cdr;\r
+ cnt <= (others => '0');\r
+ rx_sm <= TEST_CDR;\r
else\r
- cnt <= cnt + '1'; \r
+ cnt <= cnt + 1; \r
end if;\r
\r
- when test_cdr =>\r
- state_out <= x"3";\r
- rx_serdes_rst <= '0';\r
- rx_pcs_rst <= '1';\r
+ when TEST_CDR =>\r
+ STATE_OUT <= x"3";\r
+ RX_SERDES_RST_OUT <= '0';\r
+ RX_PCS_RST_OUT <= '1';\r
+ LINK_RX_READY_OUT <= '0';\r
if( cdr_lol_s = '1' ) then\r
- cnt <= (others => '0');\r
- rx_sm <= apply_cdr_rst;\r
+ cnt <= (others => '0');\r
+ rx_sm <= APPLY_CDR_RST;\r
else\r
if( cnt = Tcdr ) then\r
- cnt <= (others => '0');\r
- rx_sm <= apply_rxpcs_rst;\r
+ cnt <= (others => '0');\r
+ rx_sm <= APPLY_RXPCS_RST;\r
else\r
- cnt <= cnt + '1';\r
+ cnt <= cnt + 1;\r
end if;\r
end if;\r
- when apply_rxpcs_rst =>\r
- state_out <= x"4";\r
- rx_serdes_rst <= '0';\r
- rx_pcs_rst <= '1';\r
- if (cnt = x"00000007") then\r
- cnt <= (others => '0');\r
- rx_sm <= wait_rxpcs_lock;\r
+\r
+ when APPLY_RXPCS_RST =>\r
+ STATE_OUT <= x"4";\r
+ RX_SERDES_RST_OUT <= '0';\r
+ RX_PCS_RST_OUT <= '1';\r
+ LINK_RX_READY_OUT <= '0';\r
+ if( cnt = Tshort ) then\r
+ cnt <= (others => '0');\r
+ rx_sm <= WAIT_RXPCS_LOCK;\r
else\r
- cnt <= cnt + '1'; \r
+ cnt <= cnt + 1; \r
end if;\r
\r
- when wait_rxpcs_lock =>\r
- state_out <= x"5";\r
- rx_serdes_rst <= '0';\r
- rx_pcs_rst <= '0';\r
- if (cnt = Tviol) then\r
- cnt <= (others => '0');\r
- rx_sm <= test_rxpcs;\r
+ when WAIT_RXPCS_LOCK =>\r
+ STATE_OUT <= x"5";\r
+ RX_SERDES_RST_OUT <= '0';\r
+ RX_PCS_RST_OUT <= '0';\r
+ LINK_RX_READY_OUT <= '0';\r
+ if( cnt = Tviol ) then\r
+ cnt <= (others => '0');\r
+ rx_sm <= TEST_RXPCS;\r
else\r
- cnt <= cnt + '1'; \r
- end if; \r
- when test_rxpcs =>\r
- state_out <= x"6";\r
- rx_serdes_rst <= '0';\r
- rx_pcs_rst <= '0';\r
- if (lsm_s = '0') or (cv_s = '1') then\r
- cnt <= (others => '0');\r
- rx_sm <= apply_rxpcs_rst;\r
+ cnt <= cnt + 1; \r
+ end if;\r
+\r
+ when TEST_RXPCS =>\r
+ STATE_OUT <= x"6";\r
+ RX_SERDES_RST_OUT <= '0';\r
+ RX_PCS_RST_OUT <= '0';\r
+ LINK_RX_READY_OUT <= '0';\r
+ if( (lsm_s = '0') or (cv_s = '1') ) then\r
+ cnt <= (others => '0');\r
+ rx_sm <= APPLY_RXPCS_RST;\r
else\r
- if (cnt = Tviol) then\r
- cnt <= (others => '0');\r
- rx_sm <= idle;\r
+ if( cnt = Tviol ) then\r
+ cnt <= (others => '0');\r
+ rx_sm <= IDLE;\r
else\r
- cnt <= cnt + '1';\r
+ cnt <= cnt + 1;\r
end if;\r
end if;\r
\r
when idle =>\r
- state_out <= x"7";\r
- rx_serdes_rst <= '0';\r
- rx_pcs_rst <= '0';\r
- if (lsm_s = '0') or (cv_s = '1') then\r
- rx_sm <= apply_rxpcs_rst; \r
- cnt <= (others => '0');\r
+ STATE_OUT <= x"7";\r
+ RX_SERDES_RST_OUT <= '0';\r
+ RX_PCS_RST_OUT <= '0';\r
+ LINK_RX_READY_OUT <= '1';\r
+ if( (lsm_s = '0') or (cv_s = '1') ) then\r
+ rx_sm <= APPLY_RXPCS_RST; \r
+ cnt <= (others => '0');\r
end if;\r
end case;\r
\r
------------------------------------------------\r
-- if (pll_lol_s = '1') or (los_s = '1') then\r
- if (pll_lol_s = '1') then\r
- rx_sm <= powerup; \r
- cnt <= (others => '0');\r
- end if;\r
+ if( pll_lol_s = '1' ) then\r
+ rx_sm <= POWERUP; \r
+ cnt <= (others => '0');\r
+ end if;\r
\r
-end if;\r
+ end if;\r
end process rx_reset_proc;\r
\r
end rx_rsl_arc;\r