-- $Log: eth_receive.vhd,v $ -- Revision 1.9 1998/11/26 22:29:30 scaplan -- Final Revision for implementation, CRC removed. -- -- Revision 1.8 1998/11/20 02:42:02 scaplan -- Cleaned DOS ^M's that had gotten tagged along in last revision. -- -- Revision 1.6 1998/11/11 06:11:25 scaplan -- Fixed: Had introduced an off by one error on length shift in previous revision. -- This is now fixed, but we've gained some logic cells .. Ack! -- Other: Cleaned up comments, added some constants and removed magic numbers. -- -- Revision 1.5 1998/11/11 05:41:43 scaplan -- Fixed: Length size bug (was reading bits instead of bytes -- Added: Collision routines. Will no longer allow a frame to start -- if the remote e-net is already reading data. Additionally, -- when a collision is detected on either interface, the receiver -- will reset, and await a new, clean packet. -- Added: Boundary checking on length field. Current Max = 12144, Min = 8. -- Min will need to be changed to 384 for real implementation. Has -- been left smaller to facilitate simulation. -- -- Revision 1.3 1998/11/09 22:25:46 scaplan -- Added eth_recv_frame_full to replace eth_recv_frame. -- eth_recv_frame is now high from start of frame until end of data, -- so it is now LOW during CRC. This is because Paul is the evil -- overload of all things, so details like this must be done in -- accordance with his wished rather than in a sane and logical -- manner, like holding eth_recv_frame high while the frame -- is being recieved. :-) -- -- Revision 1.2 1998/11/09 06:39:12 psomogyi -- Fixed compile error. -- -- Revision 1.1 1998/11/08 09:27:12 scaplan -- Split ethernet into transmit and receive. -- -- Log: ethernet.vhd -- Revision 1.6 1998/10/28 22:32:29 scaplan -- Updated state tables. -> fully functional reciever (12% chip) -- -- Revision 1.5 1998/10/26 23:03:20 scaplan -- Optimized for chip size, testing for +/- errors on counters -- -- Revision 1.4 1998/10/25 03:14:18 scaplan -- More state ethernet state table and simulation. -- -- Revision 1.3 1998/10/24 23:25:29 scaplan -- More state tables, receiver routines. -- -- Revision 1.2 1998/10/24 18:50:14 scaplan -- Began work on receive state table. -- -- Revision 1.1 1998/10/24 18:30:18 gargus -- initial revision. -- -- -- Compile Status: OK -- Simulation Status: OK -- Cell Usage: 139 -- Bugs: possible off-by-one counter issues -- only matches last byte of preamble and start delimiter. -- - this is considered acceptable behavior, considering that -- the only other option is a 64 bit pattern matcher (big) ... -- haven't implemented "proper" Altera state tables library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity eth_receive is port ( -- To ethernet tranciever (external signals) -- some network status send_state : buffer std_logic_vector(3 downto 0); COL : in std_logic; -- Collision Detect: -- Active high when collision detected (TX or RX) CRS : in std_logic; -- Carrier Sense: -- Asserted on first valid high-low transmission on -- recieve pair. COL_remote : in std_logic; CRS_remote : in std_logic; -- Collision and Carrier sense from the OTHER ethernet device. -- Since we're not buffering, we need to know the state of the -- other device. RxD : in std_logic; -- Recieve Data RxC : in std_logic; -- Recieve Data Clock -- To recieve buffer eth_recv_frame : buffer std_logic; -- Hold high while receiving data eth_recv_clock : out std_logic; -- clock for data eth_recv_data : out std_logic; -- Recieve data eth_recv_frame_data : buffer std_logic); end entity eth_receive; architecture receiver of eth_receive is constant length_size : std_logic_vector := conv_std_logic_vector(16,15); constant address_size : std_logic_vector := conv_std_logic_vector(96,15); constant crc_size : std_logic_vector := conv_std_logic_vector(32,15); constant one : std_logic_vector := conv_std_logic_vector(1,15); -- Min length should actually be 384, but to keep our simulations small, we're using 8. constant min_length : std_logic_vector := conv_std_logic_vector(384,14); constant max_length : std_logic_vector := conv_std_logic_vector(12144,14); signal count :std_logic_vector(3 downto 0); -- name states after bit pattern already seen type state_type is (recv_null, recv1, recv10, recv101, recv1010, recv10101, recv101010, recv1010101, frame_address, frame_length, frame_data, frame_crc); signal recv_state, next_recv_state : state_type; --signal part, next_part : frame_state_type; signal eth_recv_frame_address, eth_recv_frame_length, length_error, eth_recv_frame_full : std_logic; begin receive_state : process(recv_state, RxD) begin case recv_state is when recv_null => eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; eth_recv_frame_data <= '0'; eth_recv_frame_length <= '0'; if RxD = '1' then next_recv_state <= recv1; else next_recv_state <= recv_null; end if; -- Die network die -- next_recv_state <= frame_address; when recv1 => if send_state < "0001" then send_state <= "0001"; end if; eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; if RxD = '0' then next_recv_state <= recv10; else next_recv_state <= recv_null; end if; when recv10 => if send_state < "0010" then send_state <= "0010"; end if; eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; if RxD = '1' then next_recv_state <= recv101; else next_recv_state <= recv_null; end if; when recv101 => if send_state < "0011" then send_state <= "0011"; end if; eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; if RxD = '0' then next_recv_state <= recv1010; else next_recv_state <= recv_null; end if; when recv1010 => if send_state < "0100" then send_state <= "0100"; end if; eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; if RxD = '1' then next_recv_state <= recv10101; else next_recv_state <= recv_null; end if; when recv10101 => if send_state < "0101" then send_state <= "0101"; end if; eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; if RxD = '0' then next_recv_state <= recv101010; else next_recv_state <= recv_null; end if; when recv101010 => if send_state < "0110" then send_state <= "0110"; end if; eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; if RxD = '1' then next_recv_state <= recv1010101; else next_recv_state <= recv_null; end if; when recv1010101 => if send_state < "0111" then send_state <= "0111"; end if; eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; if RxD = '1' then next_recv_state <= frame_address; else next_recv_state <= recv_null; end if; when frame_address => -- if send_state < "1000" then -- send_state <= "1000"; -- end if; eth_recv_frame <= '1'; eth_recv_frame_full <= '1'; next_recv_state <= frame_length; when frame_length => eth_recv_frame_length <= '1'; eth_recv_frame <= '1'; eth_recv_frame_full <= '1'; next_recv_state <= frame_data; when frame_data => eth_recv_frame <= '1'; eth_recv_frame_full <= '1'; eth_recv_frame_length <= '0'; eth_recv_frame_data <= '1'; if length_error = '1' then next_recv_state <= recv_null; else next_recv_state <= frame_crc; end if; when frame_crc => eth_recv_frame <= '0'; eth_recv_frame_full <= '1'; eth_recv_frame_data <= '0'; eth_recv_frame_length <= '0'; next_recv_state <= recv_null; when others => next_recv_state <= recv_null; eth_recv_frame <= '0'; eth_recv_frame_full <= '0'; eth_recv_frame_length <= '0'; eth_recv_frame_data <= '0'; end case; end process receive_state; receive :process(RxC) variable recv_count : std_logic_vector (15 downto 0); variable length : std_logic_vector(15 downto 0); variable count2 : std_logic_vector(3 downto 0); begin eth_recv_clock <= RxC; eth_recv_data <= RxD; -- send_state <= count; if rising_edge(RxC) then if CRS = '1' then --or CRS_remote = '0' or COL = '1' or COL_remote = '1' then -- Resets the system when local CRS = '1' recv_state <= recv_null; elsif eth_recv_frame_full = '0' then -- network test -- if count2 < 4 then -- count <= count(2 downto 0) & RxD; -- count2 := count2 +1; -- end if; -- advance to next state recv_state <= next_recv_state; -- initialize our counter and shift register recv_count := address_size; length := (others => '0'); length_error <= '0'; elsif eth_recv_frame_full = '1' then recv_count := recv_count - 1; if eth_recv_frame_length = '1' then -- Shift data into 2^3 (8's) so we're counting bits length(15 downto 3) := length(14 downto 3) & RxD; end if; if recv_count = 0 then if next_recv_state = frame_length then recv_count := length_size; elsif next_recv_state = frame_data then if length > max_length then -- Something stinks here length data is invalid. -- Data width must equal to or less than 12144 bits (1518 bytes) recv_count := one; elsif length < min_length then -- Data size is smaller than minimum, that means there's -- padding in this frame, so set counter to minimum frame -- length. length_error <= '1'; recv_count := min_length; -- Note: No worries about encrypting padding, since it will -- be decryped before it is unpadded. else recv_count := length; end if; elsif next_recv_state = frame_crc then recv_count := crc_size; else recv_count := address_size; end if; recv_state <= next_recv_state; end if; end if; -- recv_frame = 1 end if; -- clock end process receive; end receiver;