---------------------------------------------------------------------------------- -- Company: University of Connecticut -- Engineer: Igor Senderovich -- -- Create Date: 04:14:41 10/01/2007 -- Design Name: -- Module Name: Receiver - behavioral -- Dependencies: Runs through the packet header and first two bytes to either -- 1. Discard packet not meant for this address -- 2. Save the source MAC address in RAM -- 3. Parse the packet contents if valid -- -- PC->FPGA Packet Format: -------------------------------------------------------------------------------- -- Standard ethernet packet header: -------------------------------------------------------------------------------- -- 6 bytes - destination MAC address (this device or broadcast/multicast) -- 6 bytes - source MAC address (address of command/control device) -- ---------- optional section, much check if present --------------------- -- 2 bytes - 0x9100 (TPID value here indicates this section is present) -- 2 bytes - TCI (VLAN id, QOS info, can be ignored by receiver) -- ---------- optional section, much check if present --------------------- -- 2 bytes - 0x8100 (TPID value here indicates this section is present) -- 2 bytes - TCI (VLAN id, QOS info, can be ignored by receiver) -- ---------- end of optional section ------------------------------------- -- 2 bytes - packet length, valid range is 64..1500, discard otherwise -------------------------------------------------------------------------------- -- Packet payload -------------------------------------------------------------------------------- -- 1 byte - LocStamp for this board, or 0xFF for custom multicast -- 1 byte - packet type, see below for choices -- N bytes - depends on packet type, see decoders for details -------------------------------------------------------------------------------- -- -- PC->FPGA Packet Types: ------------------------------------------------------------------------ -- Type Hex Meaning Decoder ------------------------------------------------------------------------ -- P 0x50 Set new DAC values PacketReader -- Q 0x51 Request T, ADC values none -- R 0x52 Request hard reset none -- R' 0xD2 Request soft reset SoftReset ------------------------------------------------------------------------ library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; library FPGA_BasicComp; use FPGA_BasicComp.BasicComp.all; entity Receiver is Port ( Clk : in std_logic; Go : in std_logic; Done : out std_logic; LocStamp : in std_logic_vector (7 downto 0); PktType : out std_logic_vector (7 downto 0); -- RAM control lines RAM_EN : out std_logic; RAM_ADDR_tri : out std_logic_vector (9 downto 0); RAM_WE_tri : out std_logic_vector (1 downto 0); RAM_DI_tri : out std_logic_vector (15 downto 0); RAM_DO : in std_logic_vector (15 downto 0); --Transceiver control lines TxRx_Go : out std_logic; TxRx_A_tri : out std_logic_vector (7 downto 0); TxRx_D_tri : out std_logic_vector (7 downto 0); TxRx_Rd_tri : out std_logic; TxRx_Q : in std_logic_vector (7 downto 0); TxRx_Done : in std_logic); -- Serial port lines --Ser_Go : out std_logic; --Ser_D_tri : out std_logic_vector (7 downto 0); --Ser_Done : in std_logic; --Debug : out std_logic end Receiver; architecture behavioral of Receiver is component ReadPpacket is port ( Clk : in std_logic; Go : in std_logic; Done : out std_logic; RAM_EN : out std_logic; RAM_ADDR_tri : out std_logic_vector (9 downto 0); RAM_WE_tri : out std_logic_vector (1 downto 0); RAM_DI_tri : out std_logic_vector (15 downto 0); RAM_DO : in std_logic_vector (15 downto 0); TxRx_Go : out std_logic; TxRx_Rd_tri : out std_logic; TxRx_A_tri : out std_logic_vector (7 downto 0); TxRx_D_tri : out std_logic_vector (7 downto 0); TxRx_Q : in std_logic_vector (7 downto 0); TxRx_Done : in std_logic); end component; constant P_Packet : std_logic_vector (7 downto 0) := X"50"; constant Q_Packet : std_logic_vector (7 downto 0) := X"51"; constant R_Packet : std_logic_vector (7 downto 0) := X"52"; constant Rx_Packet : std_logic_vector (7 downto 0) := X"D2"; type stage_t is (S0,S1,S2,S3,S4,S5,S6,S7,S8,S9,SA,SB,SC,SD,SE,SX); --,SS); signal stage : stage_t := S0; signal counter_4b : std_logic_vector (3 downto 0); signal match_bits : std_logic_vector (7 downto 0); signal request_stamp : std_logic_vector (7 downto 0); type packet_len_t is array (0 to 1) of std_logic_vector (7 downto 0); signal packet_len : packet_len_t; signal Go_PPR : std_logic := '0'; signal Done_PPR : std_logic; signal Done_reg : std_logic := '0'; signal PktType_reg : std_logic_vector (7 downto 0) := (others => '0'); signal RAM_EN_PPR : std_logic; signal RAM_ADDR_PPR : std_logic_vector (9 downto 0); signal RAM_WE_PPR : std_logic_vector (1 downto 0); signal RAM_DI_PPR : std_logic_vector (15 downto 0); signal RAM_EN_reg : std_logic := '0'; signal RAM_ADDR_reg : std_logic_vector (9 downto 0) := (others => '0'); signal RAM_WE_reg : std_logic_vector (1 downto 0) := (others => '0'); signal RAM_DI_reg : std_logic_vector (15 downto 0) := (others => '0'); signal TxRx_Go_PPR : std_logic := '0'; signal TxRx_A_PPR : std_logic_vector (7 downto 0); signal TxRx_D_PPR : std_logic_vector (7 downto 0); signal TxRx_Rd_PPR : std_logic; signal TxRx_Go_reg : std_logic := '0'; signal TxRx_A_reg : std_logic_vector (7 downto 0) := (others => '0'); signal TxRx_D_reg : std_logic_vector (7 downto 0) := (others => '0'); signal TxRx_Rd_reg : std_logic := '0'; --signal Ser_Go_reg : std_logic := '0'; --signal Ser_D_reg : std_logic_vector (7 downto 0) := (others => '0'); --signal Debug_reg : std_logic := '0'; begin RAM_EN <= RAM_EN_reg or RAM_EN_PPR; RAM_ADDR_tri <= RAM_ADDR_PPR when (RAM_EN_PPR = '1') else RAM_ADDR_reg when (RAM_EN_reg = '1') else (others => 'Z'); RAM_WE_tri <= RAM_WE_PPR when (RAM_EN_PPR = '1') else RAM_WE_reg when (RAM_EN_reg = '1') else (others => 'Z'); RAM_DI_tri <= RAM_DI_PPR when (RAM_EN_PPR = '1') else RAM_DI_reg when (RAM_EN_reg = '1') else (others => 'Z'); TxRx_Go <= TxRx_Go_reg or TxRx_Go_PPR; TxRx_A_tri <= TxRx_A_PPR when (TxRx_Go_PPR = '1') else TxRx_A_reg when (TxRx_Go_reg = '1') else (others => 'Z'); TxRx_D_tri <= TxRx_D_PPR when (TxRx_Go_PPR = '1') else TxRx_D_reg when (TxRx_Go_reg = '1') else (others => 'Z'); TxRx_Rd_tri <= TxRx_Rd_PPR when (TxRx_Go_PPR = '1') else TxRx_Rd_reg when (TxRx_Go_reg = '1') else 'Z'; PktType <= PktType_reg; PpacketReader : ReadPpacket port map ( Clk => Clk, Go => Go_PPR, Done => Done_PPR, RAM_EN => RAM_EN_PPR, RAM_ADDR_tri => RAM_ADDR_PPR, RAM_WE_tri => RAM_WE_PPR, RAM_DI_tri => RAM_DI_PPR, RAM_DO => RAM_DO, TxRx_Go => TxRx_Go_PPR, TxRx_Rd_tri => TxRx_Rd_PPR, TxRx_A_tri => TxRx_A_PPR, TxRx_D_tri => TxRx_D_PPR, TxRx_Q => TxRx_Q, TxRx_Done => TxRx_Done ); PacketScanner : process (Clk) variable addr_byte_var : std_logic_vector (7 downto 0); variable op_complete_var : std_logic; constant Stage_X : std_logic_vector (7 downto 0) := X"6F"; constant Stage_Ok : std_logic_vector (7 downto 0) := X"70"; constant Stage_Done : std_logic_vector (7 downto 0) := X"80"; begin if rising_edge(Clk) then stage <= stage; counter_4b <= (others => '0'); match_bits <= match_bits; packet_len <= packet_len; request_stamp <= request_stamp; PktType_reg <= PktType_reg; Go_PPR <= '0'; Done_reg <= '0'; -- disable the RAM lines when not in use RAM_EN_reg <= '0'; RAM_ADDR_reg <= RAM_ADDR_reg; RAM_WE_reg <= RAM_WE_reg; RAM_DI_reg <= RAM_DI_reg; -- disable the MuxIntel lines when not in use TxRx_Go_reg <= '0'; TxRx_Rd_reg <= '0'; TxRx_A_reg <= (others => '0'); TxRx_D_reg <= (others => '0'); -- disable the serial port when not in use --Ser_Go_reg <= '0'; --Ser_D_reg <= (others => '0'); --Debug_reg <= '0'; op_complete_var := TxRx_Go_reg and TxRx_Done; case stage is when S0 => if (Go = '1') then stage <= S1; end if; ------------------------------------------------------------- -- The MAC on this ethernet interface only checks the first -- 5 bytes of the destination address against the local one. -- Check if this packet was eroneously received because it -- was sent to another address that differs from the local -- one only in the last address byte. Use the AUTORD -- interface of the ethernet controller to scan the packet. ------------------------------------------------------------- when S1 => counter_4b <= X"6"; match_bits <= (others => '0'); stage <= S2; when S2 => RAM_EN_reg <= '1'; RAM_WE_reg <= "00"; RAM_ADDR_reg <= "0000010" & counter_4b(3 downto 1); -- RAM_DO is not valid until the second clock in S2, but -- that is ok because it is only needed after TxRx_Done. if (counter_4b(0) = '0') then addr_byte_var := RAM_DO(15 downto 8); else addr_byte_var := RAM_DO(7 downto 0); end if; TxRx_A_reg <= X"01"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; if (TxRx_Q = addr_byte_var) then match_bits(conv_integer(counter_4b(2 downto 0))) <= '1'; else match_bits(conv_integer(counter_4b(2 downto 0))) <= '0'; end if; counter_4b <= counter_4b; if (op_complete_var = '1') then counter_4b <= counter_4b + 1; if (counter_4b = X"B") then stage <= S3; end if; end if; when S3 => if (match_bits = "11000111") then PktType_reg <= X"72"; -- x means rejected packet stage <= SX; else stage <= S4; end if; ------------------------------------------------------------- -- Next in the read buffer is the source address of the -- sender. Save this in RAM for later, when we need to -- send a response packet to the sender. ------------------------------------------------------------- when S4 => RAM_ADDR_reg <= "0000010" & counter_4b(3 downto 1); RAM_WE_reg <= not counter_4b(0) & counter_4b(0); RAM_DI_reg <= TxRx_Q & TxRx_Q; RAM_EN_reg <= op_complete_var; TxRx_A_reg <= X"01"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; counter_4b <= counter_4b; if (op_complete_var = '1') then counter_4b <= counter_4b + 1; if (counter_4b = X"5") then stage <= S5; end if; end if; ------------------------------------------------------------- -- Next in the read buffer is the packet length word. If it -- is the value 0x8100 or 0x9100 or 0x9200 or 0x9300 then -- this is an 802.1Q tagged packet, so skip the next 2 bytes, -- then read the packet length. ------------------------------------------------------------- when S5 => counter_4b <= X"0"; stage <= S6; when S6 => TxRx_A_reg <= X"01"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; packet_len(conv_integer(counter_4b(0))) <= TxRx_Q; counter_4b <= counter_4b; if (op_complete_var = '1') then counter_4b <= counter_4b + 1; if (counter_4b(0) = '1') then stage <= S7; end if; end if; when S7 => if (packet_len(0)(7 downto 5) = "100") then counter_4b <= counter_4b; stage <= S8; else stage <= S9; end if; when S8 => TxRx_A_reg <= X"01"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; counter_4b <= counter_4b; if (op_complete_var = '1') then counter_4b <= X"0"; if (counter_4b(1) = '0') then stage <= S6; end if; end if; when S9 => if (packet_len(0)(7 downto 2) /= "000000") then PktType_reg <= X"72"; -- x means rejected packet stage <= SX; else stage <= SA; end if; ------------------------------------------------------------- -- Next in the read buffer is the LocStamp value for the -- board that is the target for this packet. Either this -- must agree with the local value, or it must be 0xFF -- which indicates that the packet is being sent to any -- board that is able to receive it. ------------------------------------------------------------- when SA => TxRx_A_reg <= X"01"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; request_stamp <= TxRx_Q; if (op_complete_var = '1') then stage <= SB; end if; when SB => if (request_stamp /= LocStamp and request_stamp /= X"FF") then PktType_reg <= X"72"; -- x means rejected packet stage <= SX; else stage <= SC; end if; ------------------------------------------------------------- -- Finally read the packet type. If the packet is of type -- P then read its contents into RAM first, then flush it. -- All incoming packets are flushed from the buffer here. ------------------------------------------------------------- when SC => TxRx_A_reg <= X"01"; TxRx_Rd_reg <= '1'; TxRx_Go_reg <= not TxRx_Done; PktType_reg <= TxRx_Q; if (op_complete_var = '1') then stage <= SD; end if; when SD => case PktType_reg is when X"50" => Go_PPR <= not Done_PPR; op_complete_var := Go_PPR and Done_PPR; if (op_complete_var = '1') then stage <= SX; end if; when X"51" | X"52" | X"D2" => stage <= SX; when others => PktType_reg <= X"72"; -- x means rejected packet stage <= SX; end case; --------------------------------------------- -- Skip any remaining bytes in the current -- packet, and get set up read the next one. --------------------------------------------- when SX => TxRx_A_reg <= X"11"; TxRx_D_reg <= "00000010"; TxRx_Rd_reg <= '0'; TxRx_Go_reg <= not TxRx_Done; if (op_complete_var = '1') then stage <= SE; end if; ------------------------------------------------ -- Send one character out the serial port -- representing the packet type for valid, -- and "x" for invalid packets. ------------------------------------------------ -- when SS => -- Ser_D_reg <= PktType_reg; -- Ser_Go_reg <= not Ser_Done; -- op_complete_var := Ser_Go_reg and Ser_Done; -- if (op_complete_var = '1') then -- stage <= SF; -- end if; when SE => if (Go = '1') then Done_reg <= '1'; else stage <= S0; end if; end case; else stage <= stage; Done_reg <= Done_reg; counter_4b <= counter_4b; match_bits <= match_bits; packet_len <= packet_len; request_stamp <= request_stamp; PktType_reg <= PktType_reg; RAM_EN_reg <= RAM_EN_reg; RAM_ADDR_reg <= RAM_ADDR_reg; RAM_WE_reg <= RAM_WE_reg; RAM_DI_reg <= RAM_DI_reg; TxRx_Go_reg <= TxRx_Go_reg; TxRx_Rd_reg <= TxRx_Rd_reg; TxRx_A_reg <= TxRx_A_reg; TxRx_D_reg <= TxRx_D_reg; --Ser_Go_reg <= Ser_Go_reg; --Ser_D_reg <= Ser_D_reg; --Debug_reg <= Debug_reg; end if; end process; --Ser_Go <= Ser_Go_reg; --Ser_D_tri <= Ser_D_reg when (Ser_Go_reg = '1') else (others => 'Z'); --Debug <= Debug_reg; Done <= Done_reg; end behavioral;