--------------------------------------------------------------------------------------------------------------- -- RISA Project -- Author: A.Greensted -- Module: -- Description: -- History: --------------------------------------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library SnapLib; use SnapLib.SnapPkg.all; entity SnapLinkRx is port ( clk : in std_logic; enable : in std_logic; nReset : in std_logic; sampleEn : in std_logic; rxReset : in std_logic; dataBits : in SNAPTYPE_SNAPLINK_DATABITS; newData : out std_logic; parityError : out std_logic; rxData : out std_logic_vector(17 downto 0); serialRxIn : in std_logic); end SnapLinkRx; architecture General of SnapLinkRx is signal decoderReg : std_logic_vector(0 to 6); signal bitValue : std_logic; signal validStartBit : std_logic; type RX_STATES is (IDLE, RX_WAIT, RX_DATA, RX_PARITY, RX_STOP_BIT); signal state : RX_STATES; signal parityBit : std_logic; signal bitCount : unsigned(4 downto 0); signal dataReg : std_logic_vector(17 downto 0); signal runCounter : std_logic; signal delayCount : unsigned(2 downto 0); signal nextBit : std_logic; begin rxData <= dataReg; -- Decoder ---------------------------------------------------------------------------------------------------- -- High rate data sampling, detects start bit and performs vote in each data bit --------------------------------------------------------------------------------------------------------------- Decoder : process(clk) begin if (clk'event and clk='1') then if (nReset='0') then decoderReg <= (others => '1'); elsif (enable='1') then if (rxReset='1') then decoderReg <= (others => '1'); elsif (sampleEn='1') then -- Feeds data into (6) and shifts towards (0) decoderReg <= decoderReg(1 to 6) & serialRxIn; -- NB. Note direction of decoder Reg (0 to 6) end if; end if; end if; end process; bitValue <= (decoderReg(4) and decoderReg(5)) or (decoderReg(5) and decoderReg(6)) or (decoderReg(4) and decoderReg(6)); validStartBit <= decoderReg(0) and not (decoderReg(1)) and (not bitValue); -- DelayCounter ----------------------------------------------------------------------------------------------- -- Times the delay between packet bits (8 sampleEn pulses) --------------------------------------------------------------------------------------------------------------- DelayCounter : process (clk) begin if (clk'event and clk = '1') then if (nReset='0') then delayCount <= b"000"; elsif (enable='1') then if (runCounter = '0' or rxReset='1') then delayCount <= b"000"; elsif (sampleEn = '1') then delayCount <= delayCount + 1; end if; end if; end if; end process DelayCounter; nextBit <= '1' when (delayCount=b"111" and sampleEn='1' and runCounter='1') else '0'; -- StateDecode ------------------------------------------------------------------------------------------------ -- Generates various signals that are derived from the state machine's state --------------------------------------------------------------------------------------------------------------- StateDecode : process(state) begin case state is when IDLE => runCounter <= '0'; when RX_WAIT => runCounter <= '0'; when RX_DATA => runCounter <= '1'; when RX_PARITY => runCounter <= '1'; when RX_STOP_BIT => runCounter <= '1'; end case; end process StateDecode; -- StateMachine ----------------------------------------------------------------------------------------------- -- State machine controlling the receiving process --------------------------------------------------------------------------------------------------------------- StateMachine: process (clk) variable newData_var : std_logic; variable parityError_var : std_logic; begin if (clk'event and clk = '1') then if (nReset='0') then parityBit <= '0'; bitCount <= (others => '0'); dataReg <= (others => '0'); state <= IDLE; parityError_var := '0'; newData_var := '0'; elsif (enable='1') then if (rxReset = '1') then parityBit <= '0'; bitCount <= (others => '0'); dataReg <= (others => '0'); state <= IDLE; parityError_var := '0'; newData_Var := '0'; else case state is when IDLE => parityBit <= '0'; case dataBits is when SNAP_SNAPLINK_16DATABITS => bitCount <= "01111"; when SNAP_SNAPLINK_17DATABITS => bitCount <= "10000"; when SNAP_SNAPLINK_18DATABITS => bitCount <= "10001"; end case; parityError_var := '0'; newData_var := '0'; if (validStartBit='1') then if (sampleEn='1') then state <= RX_DATA; else state <= RX_WAIT; end if; end if; when RX_WAIT => if (sampleEn='1') then state <= RX_DATA; end if; when RX_DATA => if (nextBit='1') then case dataBits is when SNAP_SNAPLINK_16DATABITS => dataReg(17 downto 16) <= (others => '0'); dataReg(15) <= bitValue; when SNAP_SNAPLINK_17DATABITS => dataReg(17) <= '0'; dataReg(16) <= bitValue; dataReg(15) <= dataReg(16); when SNAP_SNAPLINK_18DATABITS => dataReg(17) <= bitValue; dataReg(16 downto 15) <= dataReg(17 downto 16); end case; dataReg(14 downto 0) <= dataReg(15 downto 1); parityBit <= parityBit xor bitValue; bitCount <= bitCount - 1; if (bitCount="00000") then state <= RX_PARITY; end if; end if; when RX_PARITY => if (nextBit='1') then if (bitValue /= parityBit) then -- Check for parity error parityError_var := '1'; end if; state <= RX_STOP_BIT; end if; when RX_STOP_BIT => if (nextBit='1') then if (bitValue = '1') then -- Check for valid stop bit newData_var := '1'; end if; state <= IDLE; end if; end case; end if; end if; end if; parityError <= parityError_var; newData <= newData_var; end process StateMachine; end General;