-- $Log: eth_transmit.vhd,v $ -- Revision 1.11 1998/11/26 22:22:27 scaplan -- Final Revision, CRC Removed -- -- Revision 1.10 1998/11/20 02:42:03 scaplan -- Cleaned DOS ^M's that had gotten tagged along in last revision. -- -- Revision 1.8 1998/11/11 00:43:27 psomogyi -- Fixed off-by-one crc loading bug. -- -- Revision 1.7 1998/11/09 22:00:37 scaplan -- Added some useful comments. -- -- Revision 1.6 1998/11/09 21:50:58 scaplan -- Fixed missed bit on start of frame. Optimized down to 8% chip (94 cells). -- -- Revision 1.5 1998/11/09 06:40:41 psomogyi -- First integrated (ethernet-only) simulation. -- -- Revision 1.4 1998/11/09 01:33:52 scaplan -- Tried to make it smaller... Down to 11% chip, not too bad. -- However, had to hack up the "proper" altera state machine. It is smaller when -- not done the way Noah said ... -- -- Revision 1.3 1998/11/08 12:57:11 scaplan -- Remembered to add log header -- -- The Ethernet Transmit Interface -- Compile Status: OK -- Simulation Status: OK -- Bugs: Missed bit on start of frame. (SC - Fixed rev 1.6) -- Extra bits on end of frame. -- Possible off by one errors library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity eth_transmit is generic(buffersize : positive := 63; crcsize : positive := 31); port ( -- To ethernet tranciever (external signals) COL : in std_logic; -- Collision Detect: -- Active high when collision detected (TX or RX) TxC : in std_logic; -- Transmit Clock (10 MHz) TxD : out std_logic; -- Transmit Data: Sampled on rising edge of TxC TxE : buffer std_logic; -- Transmit Enable: Held high while sending data -- From send buffer -- eth_send_clear : out std_logic; -- clear to send eth_send_error : out std_logic; -- notify of TxD error eth_send_data : in std_logic; -- data to send eth_send_clock : out std_logic; -- send data clock eth_send_frame : in std_logic; --start and end of frame -- From crc -- crc_register : in std_logic_vector(crcsize downto 0)); end entity eth_transmit; architecture transmitter of eth_transmit is type statevariable is (wait_for_data, send_data, flush_buffer); signal state : statevariable; signal eth_send_current_bit, next_bit : std_logic; signal count : std_logic_vector(5 downto 0); signal eth_send_buffer : std_logic_vector(63 downto 0); begin transmit : process(TxC) constant preamble : std_logic_vector(63 downto 0) := "1010101010101010101010101010101010101010101010101010101010101011"; constant buffer_size : std_logic_vector(5 downto 0) := "111111"; constant crc_size : std_logic_vector(5 downto 0) := "011111"; begin eth_send_error <= COL; eth_send_clock <= TxC; --if COL = '1' then state <= wait_for_data; if (TxC'event and TxC = '1') then case state is when wait_for_data => -- Fill send buffer with ethernet preamble eth_send_buffer <= preamble; if eth_send_frame = '1' then -- Get ready to send a new frame -- Don't lose the first bit! (fix - V1.6) next_bit <= eth_send_data; state <= send_data; end if; when send_data => -- Shift data through the buffer -- Shift in new bit (LSB), MSB will be written to output eth_send_buffer <= eth_send_buffer(62 downto 0) & next_bit; next_bit <= eth_send_data; if eth_send_frame = '0' then -- No more input data, but we still need to flush the buffer. state <= flush_buffer; count <= buffer_size; end if; when flush_buffer => -- Run through 64 more clocks to empty the buffer -- Shift data through the buffer -- Shift in new bit (LSB), MSB will be written to output count <= count - 1; if count = 0 then -- Buffer is empty, but we still need to send the CRC. -- Die CRC Die! -- eth_send_buffer(63 downto 32) <= crc_register; -- count <= crc_size; -- state <= send_crc; state <= wait_for_data; else eth_send_buffer <= eth_send_buffer(62 downto 0) & next_bit; next_bit <= '0'; end if; -- Die CRC Die! -- when send_crc => -- CRC has been put into the top 32 bits of out buffer -- Run through 32 more clocks to transmit CRC -- eth_send_buffer <= eth_send_buffer(62 downto 0) & next_bit; -- next_bit <= '0'; -- count <= count - 1; -- if count = 0 then -- All done. -- state <= wait_for_data; -- end if; when others => if eth_send_frame = '0' then state <= wait_for_data; end if; end case; end if; end process transmit; with state select TxE <= '1' when send_data | flush_buffer, '0' when others; -- Trasnmit MSB from send_buffer when in send_data with state select TxD <= eth_send_buffer(63) when send_data | flush_buffer, '0' when others; end transmitter;