----------------------------------------------------- -- ethernetRX.vhd -- -- High level receiver for ethernet. This file contains the -- state mahcine that identifies valid data (ignoring all the -- frame) from an ethernet packet, and outputs that data, along -- with a data enable, guaranteed to be high for a rising edge -- of master_clock (the global clock). The actual data rate -- will be 1.25 MHz (10 Mbits / 8 bits/bus write. -- -- This module is designed to interface to the MicroLinear ML2653 -- Ethernet controller. The following signals are used to interface -- to it: -- RxC : 10Mhz clock provided by 2653. -- RxE : Goes high when the 2653 is decoding a packet. -- RxD : Ethernet data (entire frame including preamble) decoded. -- Is shifted one bit at a time on the rising edges (can be specified) -- of RxC, with the first bit coming on the first edge of RxC. -- TxC : 10MHz clock provided to clock data out on. (Not used) -- TxD : Serial data output for packet transmission. Not used, so tie to 0 -- to avoid putting chip in unknoiwn state. -- TxE : Output enable for packet transmission. Not used, so tie to 0 -- to avoid putting chip in unknoiwn state or disabling transmission -- COL : Collision detection : rises high when a collision detected -- LPBK: Places device in loopback mode - all Tx data appears on Rx line -- FD : Feedback. Not implemented. -- -- Code Status : Working, tested on HW -- Known Problems : CRC is not completely shifted in, since RxC ceases before it moves -- through the pipeline. Not an issue for us, since we're not doing CRC checking -- but something to consider for groups using this code. -- -- EE 552 Spring 2001 -- Rob Behm (Author) -- Craig Joly -- Wendy Benbow library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ethernetRX is port ( master_clock : in std_logic; -- Master clock input : 25.175 Mhz RxC : in std_logic; -- RX clock from 2653 RxD : in std_logic; -- RX data from 2653 - clocked on RxC RxE : in std_logic; -- RX in progess indicator TxC : in std_logic; -- TX clock from 2653 - leave unused TxD : out std_logic; -- TX data to 2653 - drive low TxE : out std_logic; -- TX enable to 2653 - drive low col : in std_logic; -- Signal from 2653 see above lpbk : out std_logic; -- Signal from 2653 see above fd : out std_logic; -- Signal from 2653 see above nReset : in std_logic; -- Active low reset data_in : buffer std_logic_vector(7 downto 0);-- 8 bit bus data data_valid: out std_logic -- data valid on rising edge of master clock when '1' ); end ethernetRX; architecture test of ethernetRX is -- Some signals so we can use '0' and '1' in port maps signal one: std_logic; signal zero : std_logic; type ethernet_rx_state is( idle, -- Not receiving any packets preamble, -- Preamble : 7 bytes of 10101010 delimiter, -- Delimiter: 1 byte of 10101011 destaddr, -- DST_MAC : 6 bytes of dest addr FFFFFFFFFF is broadcast srcaddr, -- SRC_MAC : 6 bytes of src addr len1, -- Most significant byte of length of data area. len2, -- Least significant byte of length of data area data, -- actual data transger. LENGTH bytes. checksum1, -- Checksum 1st byte checksum2, -- Checksum 2nd byte checksum3, -- Checksum 3rd byte checksum4 -- Checksum 4th byte ); -- Component declaration for ethernet receiver, which gives us -- a stream of bytes and a data valid pulse component ethernetreceiver is port ( master_clock : in std_logic; reset : in std_logic; RxC : in std_logic; RxE : in std_logic; RxD : in std_logic; data_in : out std_logic_vector(7 downto 0); data_valid : out std_logic ); end component; -- Active high reset signal signal reset: std_logic; -- Pipeline for incoming data to match it with data valid signal pipe1 : std_logic_vector(7 downto 0); -- State of the state machine. See above for state assignments signal rxstate : ethernet_rx_state; -- Length of the data part of the packet. Max length is 1500 bytes, so we need 11 bits to store it signal length : std_logic_vector(10 downto 0); -- Buffer for data valid. signal data_valid_buf : std_logic; -- Enable for data valid - data_valid only enabled when data portion of packet is RXd signal data_valid_data : std_logic; begin -- We reset when we're not receiving a packet or when nReset asserted reset <= (not nReset) or (not RxE); -- Set some constant lines up zero <= '0'; one <= '1'; -- Drive these lines low, so we can use the chip without using these features. TxD <= zero; TxE <= zero; lpbk <= zero; fd <= zero; -- This process generates the data_valid signal only when we're receiving the data portion -- of the packet generate_datavalid: process (master_clock) begin if rising_edge(master_clock) then if rxstate = data and data_valid_buf = '1' then data_valid <= '1'; else data_valid <= '0'; end if; end if; end process; -- Instance of the ethernet receiver, which converts the bitstream into a bytestream with -- periodic data valid, mapped into data_valid_buf. RXH : ethernetreceiver port map ( reset => reset, master_clock => master_clock, RxC => RxC, RxE => RxE, RxD => RxD, data_in => pipe1, data_valid => data_valid_buf ); packet_parse : process (master_clock, reset) variable count : integer; variable statecount : integer; variable oldrxc : std_logic; begin if reset = '1' then rxstate <= idle; count := 7; length <= "00000000000"; elsif rising_edge (master_clock) then -- If we have a master clock edge, and a data_vlaid from the ethernet_receiver -- component, then if data_valid_buf = '1' then case rxstate is -- This is the catch all state. We really shouldn't be here very often, as long -- as data's coming in. when idle => -- Shouldn't get here if there's data statecount := 6; rxstate <= preamble; -- Preamble : 7 bytes of 10101010 when preamble => if statecount = 0 then rxstate <= delimiter; else statecount := statecount -1; end if; -- Delimiter: 1 byte of 10101011 when delimiter => statecount := 5; rxstate <= destaddr; -- DST_MAC : 6 bytes of dest addr when destaddr => if statecount = 0 then statecount := 5; rxstate <= srcaddr; else statecount := statecount -1; end if; -- SRC_MAC : 6 bytes of src addr when srcaddr => if statecount = 0 then rxstate <= len1; else statecount := statecount -1; end if; -- Most significant byte of length. Since data size is limited to 1500 bytes, -- the top five bits of this field are ignored, presumed to always be zero -- Note : network byte order is big endian - MSByte first when len1 => length(10 downto 8) <= pipe1(2 downto 0); rxstate <= len2; -- Least significant byte of data length when len2 => length(7 downto 0) <= pipe1; rxstate <= data; -- OK. Now we have the data portion of the packet, if all's going well. when data => -- end on length = 1 to allow last byte time to shift out. -- if we end on 0, then we get length + 1 bytes ... BAD if length = 1 then rxstate <= checksum1; else length <= length - 1; end if; when checksum1 => rxstate <= checksum2; when checksum2 => rxstate <= checksum3; when checksum3 => rxstate <= checksum4; when checksum4 => rxstate <= preamble; when others => rxstate <= idle; end case; count := 7; end if; end if; end process; -- Process the pipeline data_in <= pipe1; end test;