---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 09:16:59 11/24/2012 -- Design Name: -- Module Name: EMAC_GXPCS - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.std_logic_misc.all; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. library UNISIM; use UNISIM.VComponents.all; entity XGbEPCS32 is Port ( reset : IN std_logic; clk2x : IN std_logic; -- 2xSFP_REFCLK 312.5MHz norminal clk : IN std_logic; TXUSRCLK : IN std_logic; TX_high : IN std_logic; -- in clk2x domain, TX_high = clk RXUSRCLK : IN std_logic; RXRESETDONE : IN std_logic; RESET_TXSync : IN std_logic; inh_TX : IN std_logic; GTX_TXD : out STD_LOGIC_VECTOR (31 downto 0) := (others => '0'); GTX_TXHEADER : out STD_LOGIC_VECTOR (1 downto 0) := (others => '0'); GTX_TX_PAUSE : IN std_logic; -- sequence counter = "011111" GTX_RXD : in STD_LOGIC_VECTOR (31 downto 0); GTX_RXDVLD : in STD_LOGIC; GTX_RXHEADER : in STD_LOGIC_VECTOR (1 downto 0); GTX_RXHEADERVLD : in STD_LOGIC; GTX_RXGOOD : out STD_LOGIC; GTX_RXGEARBOXSLIP_OUT : out STD_LOGIC := '0'; EmacPhyTxC : in STD_LOGIC_VECTOR (3 downto 0); EmacPhyTxD : in STD_LOGIC_VECTOR (31 downto 0); PhyEmacRxC : out STD_LOGIC_VECTOR (3 downto 0) := (others => '0'); PhyEmacRxD : out STD_LOGIC_VECTOR (31 downto 0) := (others => '0'); status : out STD_LOGIC_VECTOR (31 downto 0) ); end XGbEPCS32; architecture Behavioral of XGbEPCS32 is COMPONENT BLOCK_SYNC_SM PORT( RXHEADER_IN : IN std_logic_vector(2 downto 0); RXHEADERVALID_IN : IN std_logic; USER_CLK : IN std_logic; SYSTEM_RESET : IN std_logic; BLOCKSYNC_OUT : OUT std_logic; RXGEARBOXSLIP_OUT : OUT std_logic ); END COMPONENT; COMPONENT SCRAMBLER generic ( TX_DATA_WIDTH : integer := 32 ); PORT( UNSCRAMBLED_DATA_IN : IN std_logic_vector((TX_DATA_WIDTH-1) downto 0); DATA_VALID_IN : IN std_logic; USER_CLK : IN std_logic; SYSTEM_RESET : IN std_logic; SCRAMBLED_DATA_OUT : OUT std_logic_vector((TX_DATA_WIDTH-1) downto 0) ); END COMPONENT; COMPONENT DESCRAMBLER generic ( RX_DATA_WIDTH : integer := 32 ); PORT( SCRAMBLED_DATA_IN : IN std_logic_vector((RX_DATA_WIDTH-1) downto 0); DATA_VALID_IN : IN std_logic; USER_CLK : IN std_logic; SYSTEM_RESET : IN std_logic; UNSCRAMBLED_DATA_OUT : OUT std_logic_vector((RX_DATA_WIDTH-1) downto 0) ); END COMPONENT; constant EBLOCK : std_logic_vector(63 downto 0) := x"1e1e1e1e1e1e1e1e"; constant LBLOCK : std_logic_vector(63 downto 0) := x"0100000001000055"; constant R_FAULT : std_logic_vector(31 downto 0) := x"0200009c"; constant LBLOCK_R : std_logic_vector(71 downto 0) := x"0100009c10100009c1"; constant EBLOCK_R : std_logic_vector(71 downto 0) := x"fefefefeffefefefef"; type array37x32 is array(0 to 36) of bit_vector(31 downto 0); constant RxIdle : array37x32 := (x"ffff0000",x"ffff0000",x"ffff0000",x"ffff0000", x"ffff0000",x"ffff0000",x"ffff0000",x"00000000",x"00000000",x"00000000",x"00000000",x"00000000", x"ffff0000",x"ffff0000",x"ffff0000",x"00000000",x"00000000",x"00000000",x"00000000",x"00000000", x"ffff0000",x"ffff0000",x"ffff0000",x"00000000",x"00000000",x"00000000",x"00000000",x"00000000", x"ffff0000",x"ffff0000",x"ffff0000",x"00000000",x"00000000",x"00000000",x"00000000",x"00000000", x"00000000"); type state is (TX_INIT, TX_C, TX_D, TX_T, TX_E); signal T_state : state := TX_INIT; signal EmacPhyTxC_q : std_logic_vector(3 downto 0) := (others => '0'); signal EmacPhyTxD_q : std_logic_vector(31 downto 0) := (others => '0'); signal TxC : std_logic_vector(7 downto 0) := (others => '0'); signal TxD : std_logic_vector(63 downto 0) := (others => '0'); signal TxD_q : std_logic_vector(63 downto 0) := (others => '0'); signal c_coded : std_logic_vector(55 downto 0) := (others => '0'); signal tx_coded : std_logic_vector(65 downto 0) := (others => '0'); signal T_TYPE_C : std_logic := '0'; signal T_TYPE_D : std_logic := '0'; signal T_TYPE_S : std_logic := '0'; signal T_TYPE_T : std_logic := '0'; signal T_IS_D : std_logic := '0'; signal T_IS_O : std_logic_vector(1 downto 0) := (others => '0'); signal T_IS_S : std_logic_vector(1 downto 0) := (others => '0'); signal T_IS_C : std_logic_vector(7 downto 0) := (others => '0'); signal T_IS_E : std_logic_vector(7 downto 0) := (others => '0'); signal T_IS_T : std_logic_vector(7 downto 0) := (others => '0'); signal GTX_TX_PAUSE_q : std_logic := '0'; signal TX_FIFO_DI : std_logic_vector(33 downto 0) := (others => '0'); signal TX_FIFO_DO : std_logic_vector(33 downto 0) := (others => '0'); signal TX_FIFO_wa : std_logic_vector(3 downto 0) := (others => '0'); signal TX_FIFO_ra : std_logic_vector(3 downto 0) := (others => '0'); signal GTX_RXHEADER_IN : std_logic_vector(2 downto 0) := (others => '0'); signal BLOCK_LOCK : std_logic := '0'; signal BLOCK_SYNC_SM_RESET : std_logic := '0'; signal BLOCK_NOT_LOCK : std_logic := '0'; signal GTX_RXHEADERVLD_dl : std_logic_vector(1 downto 0) := (others => '0'); signal GTX_RXHEADER_dl0 : std_logic_vector(1 downto 0) := (others => '0'); signal TX_UNSCRAMBLED_DATA : std_logic_vector(65 downto 0) := (others => '0'); signal TX_UNSCRAMBLED_DATA_MUX : std_logic_vector(33 downto 0) := (others => '0'); signal RX_UNSCRAMBLED_DATA : std_logic_vector(63 downto 0) := (others => '0'); signal RX_UNSCRAMBLED_DATA_OUT : std_logic_vector(31 downto 0) := (others => '0'); signal RXHEADER : std_logic_vector(1 downto 0) := (others => '0'); type Rstate is (RX_INIT, RX_C, RX_D, RX_T, RX_E); signal R_state : Rstate := RX_INIT; signal RxC : std_logic_vector(7 downto 0) := (others => '0'); signal RxD : std_logic_vector(63 downto 0) := (others => '0'); signal c_raw : std_logic_vector(63 downto 0) := (others => '0'); signal rx_raw : std_logic_vector(71 downto 0) := (others => '0'); signal rx_raw_ps2 : std_logic_vector(71 downto 0) := (others => '0'); signal rx_raw_ps3 : std_logic_vector(71 downto 0) := (others => '0'); signal rx_raw_mux : std_logic_vector(35 downto 0) := (others => '0'); signal R_TYPE_C : std_logic := '0'; signal R_TYPE_D : std_logic := '0'; signal R_TYPE_S : std_logic := '0'; signal R_TYPE_T : std_logic := '0'; signal NEXT_TYPE_C : std_logic := '0'; signal NEXT_TYPE_D : std_logic := '0'; signal NEXT_TYPE_S : std_logic := '0'; signal NEXT_TYPE_T : std_logic := '0'; signal R_IS_D : std_logic := '0'; signal R_IS_T : std_logic := '0'; signal Legal_O : std_logic_vector(1 downto 0) := (others => '0'); signal R_IS_O : std_logic_vector(1 downto 0) := (others => '0'); signal R_IS_S : std_logic_vector(1 downto 0) := (others => '0'); signal R_IS_C : std_logic_vector(7 downto 0) := (others => '0'); signal R_IS_E : std_logic_vector(7 downto 0) := (others => '0'); signal RX_FIFO_DI : std_logic_vector(36 downto 0) := (others => '0'); signal RX_FIFO_DO : std_logic_vector(36 downto 0) := (others => '0'); signal RX_FIFO_WA : std_logic_vector(3 downto 0) := (others => '0'); signal RX_FIFO_RA : std_logic_vector(3 downto 0) := (others => '0'); signal RX_FIFO_RA_G : std_logic_vector(3 downto 0) := (others => '0'); signal RX_FIFO_RA_P : std_logic_vector(3 downto 0) := (others => '0'); signal RX_FIFO_WA_RA_D : std_logic_vector(3 downto 0) := (others => '0'); signal RX_FIFO_RA_G0SyncRegs : std_logic_vector(2 downto 0) := (others => '0'); signal RX_FIFO_RA_G1SyncRegs : std_logic_vector(2 downto 0) := (others => '0'); signal RX_FIFO_RA_G2SyncRegs : std_logic_vector(2 downto 0) := (others => '0'); signal RX_FIFO_RA_G3SyncRegs : std_logic_vector(2 downto 0) := (others => '0'); signal RX_FIFO_WE : std_logic := '0'; signal GTX_RXDVLD_q : std_logic := '0'; signal skip_RX_FIFO_WE : std_logic := '0'; signal ec_RX_FIFO_RAn : std_logic := '0'; signal insert_IDLE : std_logic := '0'; signal delete_IDLE : std_logic := '0'; signal insert_IDLE_l : std_logic := '0'; signal delete_IDLE_l : std_logic := '0'; signal R_IS_RF : std_logic_vector(6 downto 0) := (others => '0'); signal R_IS_LF : std_logic_vector(6 downto 0) := (others => '0'); signal R_IS_IDLE : std_logic_vector(5 downto 0) := (others => '0'); signal en_DI : std_logic := '0'; signal en_II : std_logic := '0'; signal T4567 : std_logic := '0'; signal inh : std_logic := '0'; signal inh_cntr : std_logic_vector(3 downto 0) := (others => '0'); signal reset_RXSyncRegs : std_logic_vector(2 downto 0) := (others => '0'); signal RXRESETDONE_SyncRegs : std_logic_vector(3 downto 0) := (others => '0'); signal RXGOOD_cntr : std_logic_vector(4 downto 0) := (others => '0'); begin process(clk2x) begin if(clk2x'event and clk2x = '1')then if(TX_high = '0')then EmacPhyTxC_q <= EmacPhyTxC; EmacPhyTxD_q <= EmacPhyTxD; else TxC <= EmacPhyTxC & EmacPhyTxC_q; TxD <= EmacPhyTxD & EmacPhyTxD_q; end if; if(TX_high = '1')then TX_UNSCRAMBLED_DATA_MUX <= '1' & TX_UNSCRAMBLED_DATA(64) & TX_UNSCRAMBLED_DATA(31 downto 0); else TX_UNSCRAMBLED_DATA_MUX <= '0' & TX_UNSCRAMBLED_DATA(64 downto 32); end if; TX_FIFO_DI(33 downto 32) <= TX_UNSCRAMBLED_DATA_MUX(33 downto 32); end if; end process; process(clk) begin if(clk'event and clk = '1')then if(TxC(3 downto 0) = x"1" and TxD(31 downto 0) = R_FAULT)then T_IS_O(0) <= '1'; else T_IS_O(0) <= '0'; end if; if(TxC(7 downto 4) = x"1" and TxD(63 downto 32) = R_FAULT)then T_IS_O(1) <= '1'; else T_IS_O(1) <= '0'; end if; if(TxC = x"01" and TxD(7 downto 0) = x"fb")then T_IS_S(0) <= '1'; else T_IS_S(0) <= '0'; end if; if(TxC(7 downto 4) = x"1" and TxD(39 downto 32) = x"fb")then T_IS_S(1) <= '1'; else T_IS_S(1) <= '0'; end if; for i in 0 to 7 loop if(TxC(i) = '1' and TxD(i*8+7 downto i*8) = x"07")then T_IS_C(i) <= '1'; else T_IS_C(i) <= '0'; end if; if(TxC(i) = '1' and TxD(i*8+7 downto i*8) = x"fe")then T_IS_E(i) <= '1'; c_coded(I*7+6 downto i*7) <= "0011110"; else T_IS_E(i) <= '0'; c_coded(I*7+6 downto i*7) <= "0000000"; end if; end loop; if(TxC(0) = '1' and TxD(7 downto 0) = x"fd")then T_IS_T(0) <= '1'; else T_IS_T(0) <= '0'; end if; if(TxC(1 downto 0) = "10" and TxD(15 downto 8) = x"fd")then T_IS_T(1) <= '1'; else T_IS_T(1) <= '0'; end if; if(TxC(2 downto 0) = "100" and TxD(23 downto 16) = x"fd")then T_IS_T(2) <= '1'; else T_IS_T(2) <= '0'; end if; if(TxC(3 downto 0) = "1000" and TxD(31 downto 24) = x"fd")then T_IS_T(3) <= '1'; else T_IS_T(3) <= '0'; end if; if(TxC(4 downto 0) = "10000" and TxD(39 downto 32) = x"fd")then T_IS_T(4) <= '1'; else T_IS_T(4) <= '0'; end if; if(TxC(5 downto 0) = "100000" and TxD(47 downto 40) = x"fd")then T_IS_T(5) <= '1'; else T_IS_T(5) <= '0'; end if; if(TxC(6 downto 0) = "1000000" and TxD(55 downto 48) = x"fd")then T_IS_T(6) <= '1'; else T_IS_T(6) <= '0'; end if; if(TxC(7 downto 0) = "10000000" and TxD(63 downto 56) = x"fd")then T_IS_T(7) <= '1'; else T_IS_T(7) <= '0'; end if; T_IS_D <= not or_reduce(TxC); if(and_reduce(T_IS_C) = '1' or (T_IS_O(0) = '1' and T_IS_C(7 downto 4) = not T_IS_E(7 downto 4)) or (T_IS_O(1) = '1' and T_IS_C(3 downto 0) = not T_IS_E(3 downto 0)) or T_IS_O = "11")then T_TYPE_C <= '1'; else T_TYPE_C <= '0'; end if; if(T_IS_S(0) = '1' or (T_IS_S(1) = '1' and (T_IS_C(3 downto 0) = not T_IS_E(3 downto 0) or T_IS_O(0) = '1')))then T_TYPE_S <= '1'; else T_TYPE_S <= '0'; end if; T_TYPE_D <= T_IS_D; T_TYPE_T <= '0'; if(T_IS_T(0) = '1' and T_IS_C(7 downto 1) = not T_IS_E(7 downto 1))then T_TYPE_T <= '1'; end if; if(T_IS_T(1) = '1' and T_IS_C(7 downto 2) = not T_IS_E(7 downto 2))then T_TYPE_T <= '1'; end if; if(T_IS_T(2) = '1' and T_IS_C(7 downto 3) = not T_IS_E(7 downto 3))then T_TYPE_T <= '1'; end if; if(T_IS_T(3) = '1' and T_IS_C(7 downto 4) = not T_IS_E(7 downto 4))then T_TYPE_T <= '1'; end if; if(T_IS_T(4) = '1' and T_IS_C(7 downto 5) = not T_IS_E(7 downto 5))then T_TYPE_T <= '1'; end if; if(T_IS_T(5) = '1' and T_IS_C(7 downto 6) = not T_IS_E(7 downto 6))then T_TYPE_T <= '1'; end if; if(T_IS_T(6) = '1' and T_IS_C(7) = not T_IS_E(7))then T_TYPE_T <= '1'; end if; if(T_IS_T(7) = '1')then T_TYPE_T <= '1'; end if; TxD_q <= TxD; if(T_IS_C = x"ff")then tx_coded(63 downto 0) <= x"000000000000001e"; end if; if(T_IS_O(1) = '1' and T_IS_C(3 downto 0) = not T_IS_E(3 downto 0))then tx_coded(63 downto 0) <= TxD_q(63 downto 40) & x"0" & c_coded(27 downto 0) & x"2d"; end if; if(T_IS_S(1) = '1' and T_IS_C(3 downto 0) = not T_IS_E(3 downto 0))then tx_coded(63 downto 0) <= TxD_q(63 downto 40) & x"0" & c_coded(27 downto 0) & x"33"; end if; if(T_IS_O(0) = '1' and T_IS_C(7 downto 4) = not T_IS_E(7 downto 4))then tx_coded(63 downto 0) <= c_coded(55 downto 28) & x"0" & TxD_q(31 downto 8) & x"4b"; end if; if(T_IS_O = "11")then tx_coded(63 downto 0) <= TxD_q(63 downto 40) & x"00" & TxD_q(31 downto 8) & x"55"; end if; if(T_IS_S(1) = '1' and T_IS_O(0) = '1')then tx_coded(63 downto 0) <= TxD_q(63 downto 40) & TxD_q(31 downto 0) & x"66"; end if; if(T_IS_S(0) = '1')then tx_coded(63 downto 0) <= TxD_q(63 downto 8) & x"78"; end if; if(T_IS_T(0) = '1')then tx_coded(63 downto 0) <= c_coded(55 downto 7) & "0000000" & x"87"; end if; if(T_IS_T(1) = '1')then tx_coded(63 downto 0) <= c_coded(55 downto 14) & "000000" & TxD_q(7 downto 0) & x"99"; end if; if(T_IS_T(2) = '1')then tx_coded(63 downto 0) <= c_coded(55 downto 21) & "00000" & TxD_q(15 downto 0) & x"aa"; end if; if(T_IS_T(3) = '1')then tx_coded(63 downto 0) <= c_coded(55 downto 28) & "0000" & TxD_q(23 downto 0) & x"b4"; end if; if(T_IS_T(4) = '1')then tx_coded(63 downto 0) <= c_coded(55 downto 35) & "000" & TxD_q(31 downto 0) & x"cc"; end if; if(T_IS_T(5) = '1')then tx_coded(63 downto 0) <= c_coded(55 downto 42) & "00" & TxD_q(39 downto 0) & x"d2"; end if; if(T_IS_T(6) = '1')then tx_coded(63 downto 0) <= c_coded(55 downto 49) & '0' & TxD_q(47 downto 0) & x"e1"; end if; if(T_IS_T(7) = '1')then tx_coded(63 downto 0) <= TxD_q(55 downto 0) & x"ff"; end if; if(T_IS_D = '1')then tx_coded(63 downto 0) <= TxD_q; end if; if(T_IS_D = '1')then tx_coded(65 downto 64) <= "01"; else tx_coded(65 downto 64) <= "10"; end if; if(reset = '1')then T_state <= TX_INIT; TX_UNSCRAMBLED_DATA <= "10" & LBLOCK; else case T_state is when TX_INIT => TX_UNSCRAMBLED_DATA <= tx_coded; if(T_TYPE_C = '1')then T_state <= TX_C; elsif(T_TYPE_S = '1')then T_state <= TX_D; else T_state <= TX_E; TX_UNSCRAMBLED_DATA <= "10" & EBLOCK; end if; when TX_C => TX_UNSCRAMBLED_DATA <= tx_coded; if(T_TYPE_S = '1')then T_state <= TX_D; elsif(T_TYPE_C = '0')then T_state <= TX_E; TX_UNSCRAMBLED_DATA <= "10" & EBLOCK; end if; when TX_D => TX_UNSCRAMBLED_DATA <= tx_coded; if(T_TYPE_T = '1')then T_state <= TX_T; elsif(T_TYPE_D = '0')then T_state <= TX_E; TX_UNSCRAMBLED_DATA <= "10" & EBLOCK; end if; when TX_T => TX_UNSCRAMBLED_DATA <= tx_coded; if(T_TYPE_C = '1')then T_state <= TX_C; elsif(T_TYPE_S = '1')then T_state <= TX_D; else T_state <= TX_E; TX_UNSCRAMBLED_DATA <= "10" & EBLOCK; end if; when others => TX_UNSCRAMBLED_DATA <= tx_coded; if(T_TYPE_C = '1')then T_state <= TX_C; elsif(T_TYPE_D = '1')then T_state <= TX_D; elsif(T_TYPE_T = '1')then T_state <= TX_T; else TX_UNSCRAMBLED_DATA <= "10" & EBLOCK; end if; end case; end if; end if; end process; process(clk2x,reset_TXSync) begin if(reset_TXSync = '1')then TX_FIFO_WA <= x"8"; elsif(clk2x'event and clk2x = '1')then TX_FIFO_WA <= TX_FIFO_WA + 1; end if; end process; g_TX_FIFO: for i in 0 to 33 generate i_TX_FIFO : RAM32X1D port map ( DPO => TX_FIFO_DO(i), -- Read-only 1-bit data output SPO => open, -- R/W 1-bit data output A0 => TX_FIFO_WA(0), -- R/W address[0] input bit A1 => TX_FIFO_WA(1), -- R/W address[1] input bit A2 => TX_FIFO_WA(2), -- R/W address[2] input bit A3 => TX_FIFO_WA(3), -- R/W address[3] input bit A4 => '0', -- R/W address[4] input bit D => TX_FIFO_DI(i), -- Write 1-bit data input DPRA0 => TX_FIFO_RA(0), -- Read-only address[0] input bit DPRA1 => TX_FIFO_RA(1), -- Read-only address[1] input bit DPRA2 => TX_FIFO_RA(2), -- Read-only address[2] input bit DPRA3 => TX_FIFO_RA(3), -- Read-only address[3] input bit DPRA4 => '0', -- Read-only address[4] input bit WCLK => clk2x, -- Write clock input WE => '1' -- Write enable input ); end generate; process(TXUSRCLK) begin if(TXUSRCLK'event and TXUSRCLK = '1')then if(reset_TXSync = '1')then TX_FIFO_RA <= (others => '0'); elsif(GTX_TX_PAUSE = '0' or (TX_FIFO_DO(33) = '1' and GTX_TX_PAUSE_q = '0'))then TX_FIFO_RA <= TX_FIFO_RA + 1; end if; if(inh_TX = '1')then GTX_TXHEADER <= "00"; else GTX_TXHEADER <= not TX_FIFO_DO(32) & TX_FIFO_DO(32); end if; GTX_TX_PAUSE_q <= GTX_TX_PAUSE; if(inh_TX = '1')then GTX_TXD <= (others => '0'); else GTX_TXD <= TX_FIFO_DO(31 downto 0); end if; end if; end process; process(RXUSRCLK,RXRESETDONE) begin if(RXRESETDONE = '0')then RXRESETDONE_SyncRegs <= (others => '0'); elsif(RXUSRCLK'event and RXUSRCLK = '1')then RXRESETDONE_SyncRegs <= RXRESETDONE_SyncRegs(2 downto 0) & '1'; end if; end process; i_BLOCK_SYNC_SM: BLOCK_SYNC_SM PORT MAP( BLOCKSYNC_OUT => BLOCK_LOCK, RXGEARBOXSLIP_OUT => GTX_RXGEARBOXSLIP_OUT, RXHEADER_IN => GTX_RXHEADER_IN, RXHEADERVALID_IN => GTX_RXHEADERVLD, USER_CLK => RXUSRCLK, SYSTEM_RESET => BLOCK_SYNC_SM_RESET ); BLOCK_SYNC_SM_RESET <= not RXRESETDONE_SyncRegs(3); GTX_RXHEADER_IN <= '0' & GTX_RXHEADER; BLOCK_NOT_LOCK <= not BLOCK_LOCK; i_SCRAMBLER: SCRAMBLER PORT MAP( UNSCRAMBLED_DATA_IN => TX_UNSCRAMBLED_DATA_MUX(31 downto 0), SCRAMBLED_DATA_OUT => TX_FIFO_DI(31 downto 0), DATA_VALID_IN => '1', USER_CLK => clk2x, SYSTEM_RESET => RESET_TXSync ); -- Rx code follows i_DESCRAMBLER: DESCRAMBLER PORT MAP( SCRAMBLED_DATA_IN => GTX_RXD, UNSCRAMBLED_DATA_OUT => RX_UNSCRAMBLED_DATA_OUT, DATA_VALID_IN => GTX_RXDVLD, USER_CLK => RXUSRCLK, SYSTEM_RESET => BLOCK_NOT_LOCK ); process(RXUSRCLK) begin if(RXUSRCLK'event and RXUSRCLK = '1')then GTX_RXHEADERVLD_dl <= GTX_RXHEADERVLD_dl(0) & GTX_RXHEADERVLD; if(GTX_RXHEADERVLD = '1')then GTX_RXHEADER_dl0 <= GTX_RXHEADER; end if; if(GTX_RXHEADERVLD_dl(0) = '1')then RX_UNSCRAMBLED_DATA(31 downto 0) <= RX_UNSCRAMBLED_DATA_OUT; end if; if(GTX_RXHEADERVLD_dl(1) = '1')then RX_UNSCRAMBLED_DATA(63 downto 32) <= RX_UNSCRAMBLED_DATA_OUT; end if; if(GTX_RXHEADERVLD_dl(0) = '1')then if(reset_RXSyncRegs(2) = '1' or R_state = RX_E)then GTX_RXGOOD <= '0'; elsif(RXGOOD_cntr(4) = '1')then GTX_RXGOOD <= '1'; end if; if(reset_RXSyncRegs(2) = '1' or R_state = RX_E)then RXGOOD_cntr <= (others => '0'); elsif(RXGOOD_cntr(4) = '0')then RXGOOD_cntr <= RXGOOD_cntr + 1; end if; -- pipeline stage 1 RXHEADER <= GTX_RXHEADER_dl0; case RX_UNSCRAMBLED_DATA(3 downto 0) is when x"1" => RxC <= x"c0"; when x"2" => RxC <= x"e0"; when x"3" | x"d" => RxC <= x"1f"; when x"4" => RxC <= x"f8"; when x"5" | x"6" => RxC <= x"11"; when x"7" | x"e" => RxC <= x"ff"; when x"8" => RxC <= x"01"; when x"9" => RxC <= x"fe"; when x"a" => RxC <= x"fc"; when x"b" => RxC <= x"f1"; when x"c" => RxC <= x"f0"; when x"f" => RxC <= x"80"; when others => RxC <= x"00"; end case; RxD <= RX_UNSCRAMBLED_DATA; for i in 0 to 7 loop if(RX_UNSCRAMBLED_DATA(i*7+14 downto i*7+8) = "0000000")then R_IS_C(i) <= '1'; else R_IS_C(i) <= '0'; end if; if(RX_UNSCRAMBLED_DATA(i*7+14 downto i*7+8) = "0011110")then R_IS_E(i) <= '1'; c_raw(I*8+7 downto i*8) <= x"fe"; else R_IS_E(i) <= '0'; c_raw(I*8+7 downto i*8) <= x"07"; end if; end loop; if(RX_UNSCRAMBLED_DATA(35 downto 8) = x"0010000" or RX_UNSCRAMBLED_DATA(35 downto 8) = x"0020000")then Legal_O(0) <= '1'; else Legal_O(0) <= '0'; end if; if(RX_UNSCRAMBLED_DATA(63 downto 36) = x"0100000" or RX_UNSCRAMBLED_DATA(63 downto 36) = x"0200000")then Legal_O(1) <= '1'; else Legal_O(1) <= '0'; end if; if(RX_UNSCRAMBLED_DATA(7 downto 4) = x"4" or RX_UNSCRAMBLED_DATA(7 downto 4) = x"5" or RX_UNSCRAMBLED_DATA(7 downto 4) = x"6")then R_IS_O(0) <= '1'; else R_IS_O(0) <= '0'; end if; if(RX_UNSCRAMBLED_DATA(7 downto 4) = x"2" or RX_UNSCRAMBLED_DATA(7 downto 4) = x"5")then R_IS_O(1) <= '1'; else R_IS_O(1) <= '0'; end if; if(RX_UNSCRAMBLED_DATA(7 downto 4) = x"7")then R_IS_S(0) <= '1'; else R_IS_S(0) <= '0'; end if; if(RX_UNSCRAMBLED_DATA(7 downto 4) = x"3" or RX_UNSCRAMBLED_DATA(7 downto 4) = x"6")then R_IS_S(1) <= '1'; else R_IS_S(1) <= '0'; end if; if(RXHEADER = "01")then R_IS_D <= '1'; else R_IS_D <= '0'; end if; if(RX_UNSCRAMBLED_DATA(7) = '1')then case RX_UNSCRAMBLED_DATA(6 downto 4) is when "000" => R_IS_T <= not or_reduce(RX_UNSCRAMBLED_DATA(14 downto 8)); when "001" => R_IS_T <= not or_reduce(RX_UNSCRAMBLED_DATA(21 downto 16)); when "010" => R_IS_T <= not or_reduce(RX_UNSCRAMBLED_DATA(28 downto 24)); when "011" => R_IS_T <= not or_reduce(RX_UNSCRAMBLED_DATA(35 downto 32)); when "100" => R_IS_T <= not or_reduce(RX_UNSCRAMBLED_DATA(42 downto 40)); when "101" => R_IS_T <= not or_reduce(RX_UNSCRAMBLED_DATA(49 downto 48)); when "110" => R_IS_T <= not RX_UNSCRAMBLED_DATA(56); when others => R_IS_T <= '1'; end case; else R_IS_T <= '0'; end if; -- pipeline stage 2 if(R_IS_D = '1')then NEXT_TYPE_D <= '1'; NEXT_TYPE_C <= '0'; NEXT_TYPE_S <= '0'; NEXT_TYPE_T <= '0'; rx_raw_ps2 <= x"00" & RxD; R_IS_IDLE(1 downto 0) <= "00"; R_IS_RF(1 downto 0) <= "00"; R_IS_LF(1 downto 0) <= "00"; else R_IS_IDLE(0) <= and_reduce(RxC(3 downto 0)) and and_reduce(R_IS_C(3 downto 0)) and (not NEXT_TYPE_T or not T4567) and not R_IS_T; R_IS_IDLE(1) <= and_reduce(RxC(7 downto 4)) and and_reduce(R_IS_C(7 downto 4)) and not R_IS_T; R_IS_RF(0) <= R_IS_O(0) and Legal_O(0) and not RxD(24); R_IS_RF(1) <= R_IS_O(1) and Legal_O(1) and not RxD(56); R_IS_LF(0) <= R_IS_O(0) and Legal_O(0) and RxD(24); R_IS_LF(1) <= R_IS_O(1) and Legal_O(1) and RxD(56); NEXT_TYPE_D <= '0'; rx_raw_ps2(71 downto 64) <= RxC; if(RxC = x"ff" and R_IS_C = x"ff" and R_IS_T = '0')then NEXT_TYPE_C <= '1'; rx_raw_ps2(63 downto 0) <= c_raw; elsif(Legal_O(0) = '1' and R_IS_O(0) = '1' and R_IS_C(7 downto 4) = not R_IS_E(7 downto 4) and RxC(7 downto 4) = x"f")then NEXT_TYPE_C <= '1'; rx_raw_ps2(63 downto 0) <= c_raw(63 downto 32) & RxD(31 downto 8) & x"9c"; elsif(Legal_O(1) = '1' and R_IS_O(1) = '1' and R_IS_C(3 downto 0) = not R_IS_E(3 downto 0) and RxC(3 downto 0) = x"f")then NEXT_TYPE_C <= '1'; rx_raw_ps2(63 downto 0) <= RxD(63 downto 40) & x"9c" & c_raw(31 downto 0); elsif(Legal_O = "11" and R_IS_O = "11")then NEXT_TYPE_C <= '1'; rx_raw_ps2(63 downto 0) <= RxD(63 downto 40) & x"9c" & RxD(31 downto 8) & x"9c"; else NEXT_TYPE_C <= '0'; end if; if(R_IS_S(0) = '1')then NEXT_TYPE_S <= '1'; rx_raw_ps2(63 downto 0) <= RxD(63 downto 8) & x"fb"; elsif(R_IS_S(1) = '1' and R_IS_C(3 downto 0) = not R_IS_E(3 downto 0) and RxC(3 downto 0) = x"f")then NEXT_TYPE_S <= '1'; rx_raw_ps2(63 downto 0) <= RxD(63 downto 40) & x"fb" & c_raw(31 downto 0); elsif(R_IS_S(1) = '1' and Legal_O(1) = '1' and R_IS_O(1) = '1')then NEXT_TYPE_S <= '1'; rx_raw_ps2(63 downto 0) <= RxD(63 downto 40) & x"fb" & RxD(31 downto 8) & x"9c"; else NEXT_TYPE_S <= '0'; end if; if(R_IS_T = '1')then case RxD(6 downto 4) is when "000" => if(R_IS_C(7 downto 1) = not R_IS_E(7 downto 1))then NEXT_TYPE_T <= '1'; else NEXT_TYPE_T <= '0'; end if; rx_raw_ps2(63 downto 0) <= c_raw(63 downto 8) & x"fd"; when "001" => if(R_IS_C(7 downto 2) = not R_IS_E(7 downto 2))then NEXT_TYPE_T <= '1'; else NEXT_TYPE_T <= '0'; end if; rx_raw_ps2(63 downto 0) <= c_raw(63 downto 16) & x"fd" & RxD(15 downto 8); when "010" => if(R_IS_C(7 downto 3) = not R_IS_E(7 downto 3))then NEXT_TYPE_T <= '1'; else NEXT_TYPE_T <= '0'; end if; rx_raw_ps2(63 downto 0) <= c_raw(63 downto 24) & x"fd" & RxD(23 downto 8); when "011" => if(R_IS_C(7 downto 4) = not R_IS_E(7 downto 4))then NEXT_TYPE_T <= '1'; else NEXT_TYPE_T <= '0'; end if; rx_raw_ps2(63 downto 0) <= c_raw(63 downto 32) & x"fd" & RxD(31 downto 8); when "100" => if(R_IS_C(7 downto 5) = not R_IS_E(7 downto 5))then NEXT_TYPE_T <= '1'; else NEXT_TYPE_T <= '0'; end if; rx_raw_ps2(63 downto 0) <= c_raw(63 downto 40) & x"fd" & RxD(39 downto 8); when "101" => if(R_IS_C(7 downto 6) = not R_IS_E(7 downto 6))then NEXT_TYPE_T <= '1'; else NEXT_TYPE_T <= '0'; end if; rx_raw_ps2(63 downto 0) <= c_raw(63 downto 48) & x"fd" & RxD(47 downto 8); when "110" => if(R_IS_C(7) = not R_IS_E(7))then NEXT_TYPE_T <= '1'; else NEXT_TYPE_T <= '0'; end if; rx_raw_ps2(63 downto 0) <= c_raw(63 downto 56) & x"fd" & RxD(55 downto 8); when others => NEXT_TYPE_T <= '1'; rx_raw_ps2(63 downto 0) <= x"fd" & RxD(63 downto 8); end case; else NEXT_TYPE_T <= '0'; end if; end if; T4567 <= RxD(6); -- pipeline stage 3 R_TYPE_C <= NEXT_TYPE_C; R_TYPE_D <= NEXT_TYPE_D; R_TYPE_S <= NEXT_TYPE_S; R_TYPE_T <= NEXT_TYPE_T; rx_raw_ps3 <= rx_raw_ps2(63 downto 32) & rx_raw_ps2(71 downto 68) & rx_raw_ps2(31 downto 0) & rx_raw_ps2(67 downto 64); R_IS_IDLE(3 downto 2) <= R_IS_IDLE(1 downto 0); R_IS_RF(3 downto 2) <= R_IS_RF(1 downto 0); R_IS_LF(3 downto 2) <= R_IS_LF(1 downto 0); end if; -- pipeline stage 4 if(reset = '1' or BLOCK_LOCK = '0')then R_state <= RX_INIT; rx_raw <= LBLOCK_R; R_IS_LF(5 downto 4) <= "11"; R_IS_RF(5 downto 4) <= "00"; R_IS_IDLE(5 downto 4) <= "00"; elsif(GTX_RXHEADERVLD_dl(0) = '1')then case R_state is when RX_INIT => rx_raw <= rx_raw_ps3; R_IS_LF(5 downto 4) <= "11"; R_IS_RF(5 downto 4) <= "00"; R_IS_IDLE(5 downto 4) <= "00"; if(R_TYPE_C = '1')then R_state <= RX_C; elsif(R_TYPE_S = '1')then R_state <= RX_D; else R_state <= RX_E; rx_raw <= EBLOCK_R; end if; when RX_C => R_IS_LF(5 downto 4) <= R_IS_LF(3 downto 2); R_IS_RF(5 downto 4) <= R_IS_RF(3 downto 2); R_IS_IDLE(5 downto 4) <= R_IS_IDLE(3 downto 2); rx_raw <= rx_raw_ps3; if(R_TYPE_S = '1')then R_state <= RX_D; elsif(R_TYPE_C = '0')then R_state <= RX_E; rx_raw <= EBLOCK_R; end if; when RX_D => R_IS_LF(5 downto 4) <= R_IS_LF(3 downto 2); R_IS_RF(5 downto 4) <= R_IS_RF(3 downto 2); R_IS_IDLE(5 downto 4) <= R_IS_IDLE(3 downto 2); rx_raw <= rx_raw_ps3; if(R_TYPE_T = '1' and (NEXT_TYPE_C = '1' or NEXT_TYPE_S = '1'))then R_state <= RX_T; elsif(R_TYPE_D = '0')then R_state <= RX_E; rx_raw <= EBLOCK_R; end if; when RX_T => R_IS_LF(5 downto 4) <= R_IS_LF(3 downto 2); R_IS_RF(5 downto 4) <= R_IS_RF(3 downto 2); R_IS_IDLE(5 downto 4) <= R_IS_IDLE(3 downto 2); rx_raw <= rx_raw_ps3; if(R_TYPE_S = '1')then R_state <= RX_D; else R_state <= RX_C; end if; when others => rx_raw <= rx_raw_ps3; R_IS_LF(5 downto 4) <= "00"; R_IS_RF(5 downto 4) <= "00"; R_IS_IDLE(5 downto 4) <= "00"; if(R_TYPE_C = '1')then R_state <= RX_C; elsif(R_TYPE_D = '1')then R_state <= RX_D; elsif(R_TYPE_T = '1' and (NEXT_TYPE_C = '1' or NEXT_TYPE_S = '1'))then R_state <= RX_T; else rx_raw <= EBLOCK_R; end if; end case; end if; end if; end process; process(RXUSRCLK,reset) begin if(reset = '1')then reset_RXSyncRegs <= (others => '1'); en_II <= '1'; elsif(RXUSRCLK'event and RXUSRCLK = '1')then reset_RXSyncRegs <= reset_RXSyncRegs(1 downto 0) & '0'; if(BLOCK_LOCK = '0')then en_II <= '1'; elsif((GTX_RXHEADERVLD_dl(0) = '0' and and_reduce(rx_raw(3 downto 0)) = '0') or (GTX_RXHEADERVLD_dl(0) = '1' and and_reduce(rx_raw(39 downto 36)) = '0'))then en_II <= '0'; elsif((GTX_RXHEADERVLD_dl(0) = '0' and or_reduce(rx_raw(3 downto 0)) = '1') or (GTX_RXHEADERVLD_dl(0) = '1' and or_reduce(rx_raw(39 downto 36)) = '1'))then en_II <= '1'; end if; end if; end process; process(RXUSRCLK) begin if(RXUSRCLK'event and RXUSRCLK = '1')then GTX_RXDVLD_q <= GTX_RXDVLD; RX_FIFO_WE <= GTX_RXHEADERVLD_dl(1) or GTX_RXHEADERVLD_dl(0); if(GTX_RXHEADERVLD_dl(0) = '0')then rx_raw_mux <= rx_raw(35 downto 0); R_IS_LF(6) <= R_IS_LF(4); R_IS_RF(6) <= R_IS_RF(4); if(R_IS_IDLE(4) = '1' or (R_IS_RF(6) = '1' and R_IS_RF(4) = '1') or (R_IS_LF(6) = '1' and R_IS_LF(4) = '1'))then en_DI <= '1'; else en_DI <= '0'; end if; else rx_raw_mux <= rx_raw(71 downto 36); R_IS_LF(6) <= R_IS_LF(5); R_IS_RF(6) <= R_IS_RF(5); if(R_IS_IDLE(5) = '1' or (R_IS_RF(6) = '1' and R_IS_RF(5) = '1') or (R_IS_LF(6) = '1' and R_IS_LF(5) = '1'))then en_DI <= '1'; else en_DI <= '0'; end if; end if; RX_FIFO_DI(36) <= en_II and insert_IDLE_l and not(RX_FIFO_DI(36) and RX_FIFO_WE); RX_FIFO_DI(35 downto 0) <= rx_raw_mux; skip_RX_FIFO_WE <= not (RX_FIFO_WE and skip_RX_FIFO_WE) and en_DI and delete_IDLE_l; if(inh = '1' or (RX_FIFO_WE = '1' and skip_RX_FIFO_WE = '1'))then delete_IDLE_l <= '0'; elsif(GTX_RXDVLD_q = '1' and GTX_RXDVLD = '0')then delete_IDLE_l <= delete_IDLE; end if; if(inh = '1' or (RX_FIFO_WE = '1' and RX_FIFO_DI(36) = '1'))then insert_IDLE_l <= '0'; elsif(GTX_RXDVLD_q = '1' and GTX_RXDVLD = '0')then insert_IDLE_l <= insert_IDLE; end if; end if; end process; process(RXUSRCLK,reset) begin if(reset = '1')then RX_FIFO_WA <= x"8"; RX_FIFO_RA_G0SyncRegs <= (others => '0'); RX_FIFO_RA_G1SyncRegs <= (others => '0'); RX_FIFO_RA_G2SyncRegs <= (others => '0'); RX_FIFO_RA_G3SyncRegs <= (others => '0'); RX_FIFO_RA_P <= (others => '0'); RX_FIFO_WA_RA_D <= (others => '0'); inh <= '0'; elsif(RXUSRCLK'event and RXUSRCLK = '1')then if(RX_FIFO_WE = '1' and skip_RX_FIFO_WE = '0')then RX_FIFO_WA <= RX_FIFO_WA + 1; end if; RX_FIFO_RA_G0SyncRegs <= RX_FIFO_RA_G0SyncRegs(1 downto 0) & RX_FIFO_RA_G(0); RX_FIFO_RA_G1SyncRegs <= RX_FIFO_RA_G1SyncRegs(1 downto 0) & RX_FIFO_RA_G(1); RX_FIFO_RA_G2SyncRegs <= RX_FIFO_RA_G2SyncRegs(1 downto 0) & RX_FIFO_RA_G(2); RX_FIFO_RA_G3SyncRegs <= RX_FIFO_RA_G3SyncRegs(1 downto 0) & RX_FIFO_RA_G(3); RX_FIFO_RA_P(3) <= RX_FIFO_RA_G3SyncRegs(2); RX_FIFO_RA_P(2) <= RX_FIFO_RA_G3SyncRegs(2) xor RX_FIFO_RA_G2SyncRegs(2); RX_FIFO_RA_P(1) <= RX_FIFO_RA_G3SyncRegs(2) xor RX_FIFO_RA_G2SyncRegs(2) xor RX_FIFO_RA_G1SyncRegs(2); RX_FIFO_RA_P(0) <= RX_FIFO_RA_G3SyncRegs(2) xor RX_FIFO_RA_G2SyncRegs(2) xor RX_FIFO_RA_G1SyncRegs(2) xor RX_FIFO_RA_G0SyncRegs(2); RX_FIFO_WA_RA_D <= RX_FIFO_WA - RX_FIFO_RA_P; if(RX_FIFO_WE = '1' and (skip_RX_FIFO_WE = '1' or RX_FIFO_DI(36) = '1'))then inh <= '1'; elsif(inh_cntr(3) = '1')then inh <= '0'; end if; if(inh = '0')then inh_cntr <= (others => '0'); elsif(GTX_RXHEADERVLD_dl(0) = '1')then inh_cntr <= inh_cntr + 1; end if; end if; end process; i_delete_IDLE : ROM32X1 generic map ( INIT => X"0000c01f") port map ( O => delete_IDLE, -- ROM output A0 => RX_FIFO_WA_RA_D(0), -- ROM address[0] A1 => RX_FIFO_WA_RA_D(1), -- ROM address[1] A2 => RX_FIFO_WA_RA_D(2), -- ROM address[2] A3 => RX_FIFO_WA_RA_D(3), -- ROM address[3] A4 => '0' -- ROM address[4] ); i_insert_IDLE : ROM32X1 generic map ( INIT => X"00000fe0") port map ( O => insert_IDLE, -- ROM output A0 => RX_FIFO_WA_RA_D(0), -- ROM address[0] A1 => RX_FIFO_WA_RA_D(1), -- ROM address[1] A2 => RX_FIFO_WA_RA_D(2), -- ROM address[2] A3 => RX_FIFO_WA_RA_D(3), -- ROM address[3] A4 => '0' -- ROM address[4] ); g_RX_FIFO: for i in 0 to 36 generate i_RX_FIFO : RAM32X1D generic map ( INIT => RxIdle(i)) -- Initial contents of RAM port map ( DPO => RX_FIFO_DO(i), -- Read-only 1-bit data output SPO => open, -- R/W 1-bit data output A0 => RX_FIFO_WA(0), -- R/W address[0] input bit A1 => RX_FIFO_WA(1), -- R/W address[1] input bit A2 => RX_FIFO_WA(2), -- R/W address[2] input bit A3 => RX_FIFO_WA(3), -- R/W address[3] input bit A4 => '0', -- R/W address[4] input bit D => RX_FIFO_DI(i), -- Write 1-bit data input DPRA0 => RX_FIFO_RA(0), -- Read-only address[0] input bit DPRA1 => RX_FIFO_RA(1), -- Read-only address[1] input bit DPRA2 => RX_FIFO_RA(2), -- Read-only address[2] input bit DPRA3 => RX_FIFO_RA(3), -- Read-only address[3] input bit DPRA4 => ec_RX_FIFO_RAn, -- Read-only address[4] input bit WCLK => RXUSRCLK, -- Write clock input WE => RX_FIFO_WE -- Write enable input ); end generate; -- add or remove idle(Ordered set) will be decided at the RX_FIFO write side process(clk2x) begin if(clk2x'event and clk2x = '1')then ec_RX_FIFO_RAn <= RX_FIFO_DO(36); if(reset = '1')then RX_FIFO_RA <= (others => '0'); RX_FIFO_RA_G <= (others => '0'); else if(ec_RX_FIFO_RAn = '0')then RX_FIFO_RA <= RX_FIFO_RA +1; end if; RX_FIFO_RA_G(3) <= RX_FIFO_RA(3); RX_FIFO_RA_G(2) <= RX_FIFO_RA(3) xor RX_FIFO_RA(2); RX_FIFO_RA_G(1) <= RX_FIFO_RA(2) xor RX_FIFO_RA(1); RX_FIFO_RA_G(0) <= RX_FIFO_RA(1) xor RX_FIFO_RA(0); end if; PhyEmacRxC <= RX_FIFO_DO(3 downto 0); PhyEmacRxD <= RX_FIFO_DO(35 downto 4); end if; end process; end Behavioral;