From 643d40c1c4d154e0ac922402663349521c372e3a Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 2 Aug 2010 11:00:08 +0200 Subject: Add packages needed for TSE MAC --- lib/ethernet/components/rmii_in_out.vhd | 339 ++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 lib/ethernet/components/rmii_in_out.vhd (limited to 'lib/ethernet/components/rmii_in_out.vhd') diff --git a/lib/ethernet/components/rmii_in_out.vhd b/lib/ethernet/components/rmii_in_out.vhd new file mode 100644 index 0000000..13db067 --- /dev/null +++ b/lib/ethernet/components/rmii_in_out.vhd @@ -0,0 +1,339 @@ +------------------------------------------------------------------ +-- _____ ______ _____ - +-- |_ _| | ____|/ ____| Institute of Embedded Systems - +-- | | _ __ | |__ | (___ Zuercher Hochschule fuer - +-- | | | '_ \| __| \___ \ angewandte Wissenschaften - +-- _| |_| | | | |____ ____) | (University of Applied Sciences) - +-- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - +------------------------------------------------------------------ +-- +-- Project : SInet +-- Module : synthesis library ines_ethernet +--! \file +--! \brief RMII to byte stream converter +-- +-- $LastChangedDate: 2010-04-14 15:27:24 +0200 (Wed, 14 Apr 2010) $ +-- $Rev: 3244 $ +-- $Author: beut $ +----------------------------------------------------------------- +-- +-- Change History +-- Date |Name |Modification +----------------------------------------------------------------- +-- 13.02.07 | GLC | file created +----------------------------------------------------------------- +-- 02.11.07 | ffar | adaptation for SInet +----------------------------------------------------------------- +-- 20.06.08 | beut | preambel and SFD Generator added +----------------------------------------------------------------- +-- 14.04.10 | beut | Interframe gap counter added +----------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +--! \brief This packages provides an interface to an RMII 100BaseTX phy +package rmii_in_out_pkg is + component rmii_in_out + generic( + G_AMOUNT_OF_PREAMBEL_AND_SFD_BYTES : natural := 4; + G_IFG_CLOCKS : natural := 48 -- 96 Bit ==> 960ns @ 100Mbit ==> IFG = 48 @ 20ns Clockperiode + ); + port ( + clk_i : in std_logic; -- 50 Mhz + reset_n_i : in std_logic; + -- RMII in + rxd_i : in std_logic_vector(1 downto 0); + rx_dv_i : in std_logic; + crs_dv_i : in std_logic; + col_i : in std_logic; + -- RMII out + txd_o : out std_logic_vector(1 downto 0); + tx_en_o : out std_logic; + -- Data out + rx_data_o : out std_logic_vector(7 downto 0); + rx_stb_o : out std_logic; + rx_dv_o : out std_logic; + -- Data in + tx_data_i : in std_logic_vector(7 downto 0); + tx_en_i : in std_logic; + tx_ack_o : out std_logic; + -- Other + get_time_o : out std_logic; + frame_start_o : out std_logic; + frame_end_o : out std_logic + ); + end component rmii_in_out; +end package rmii_in_out_pkg; + + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + + +--! \brief Interface to RMII 100BaseTX phy +--! \details This interface is a bidirectional converter between byte stream +--! interface and RMII. It also provides start of frame and end of +--! frame signals. +--! Because of generic byte stream interface it can be easily +--! replaced by coresponding MII interface. +entity rmii_in_out is + generic( + G_AMOUNT_OF_PREAMBEL_AND_SFD_BYTES : natural := 4; --! number of preamble bytes which are sent + G_IFG_CLOCKS : natural := 48 -- 96 Bit ==> 960ns @ 100Mbit ==> IFG = 48 @ 20ns Clockperiode + ); + port ( + --!@name Clock and reset inputs + --@{ + clk_i : in std_logic; --! This clock must run at 50 Mhz + reset_n_i : in std_logic; --! negative, asynchronous reset + --!@} + + --!@name RMII input (from Network) + --@{ + rxd_i : in std_logic_vector(1 downto 0); --! Data input + rx_dv_i : in std_logic; --! Receive data valid + crs_dv_i : in std_logic; --! carrier sense (not used) + col_i : in std_logic; --! collision detected (not used) + --!@} + + --!@name RMII out (to Network) + --@{ + txd_o : out std_logic_vector(1 downto 0); --! Transmit data out + tx_en_o : out std_logic; --! Transmit data enable + --!@} + + --!@name Data out to FPGA + --@{ + rx_data_o : out std_logic_vector(7 downto 0); --! Receive data + rx_stb_o : out std_logic; --! Receive data strobe + rx_dv_o : out std_logic; --! Receive data valid + --!@} + + --!@name Data in from FPGA + --@{ + tx_data_i : in std_logic_vector(7 downto 0); --! Transmit data out + tx_en_i : in std_logic; --! Transmit data enable + tx_ack_o : out std_logic; --! Transmit data acknowledge + --!@} + + --!@name Additional information signals + --@{ + get_time_o : out std_logic; --! Frame start in preamble detected --> take 1588 time stamp + frame_start_o : out std_logic; --! Pulse at frame start, after preamble + frame_end_o : out std_logic --! Pulse at frame end + --!@} + ); +end rmii_in_out; + +--! \brief The pincount optimised RMII interface is converted to 8 Bit byte stream interface +--! \details Data are received at 50MHz from phy. There is no separate clock signal between +--! phy and FPGA. Instead of using a separate clock signal, both chips are connected to +--! the same clock source. The output data stream which is delivered to the FPGA internal +--! components is 8 Bit wide, with clock signal. The send path does the oposite. +architecture rtl of rmii_in_out is + + --! \name Receive signals + --!@{ + --! receive fsm states enumeration + type states is (Wait_For_Start_Of_Frame, Wait_For_End_Of_Frame, + Preamble, Sfd, Frame, Toggle_Or_End_Of_Frame); + --! receive fsm states + signal state : states; + --! Used for edge detection at end of frame + signal rx_dv_i_f : std_logic; + --! shows active frame stream (same as rx_dv_o) + signal frame_in : std_logic; + --! frame_in edge pulse + signal frame_in_f : std_logic; + --! parallelise the 2 bit input stream to 8 bit + signal data_buffer : std_logic_vector(7 downto 0); + --! pointer to data_buffer + signal data_i_position : integer range 0 to 3; + --!@} + + --! \name Transmit signals + --!@{ + --! pointer to tx_data + signal nibble_cnt : integer range 0 to 3 := 3; + --! transmit data + signal tx_data : std_logic_vector(7 downto 0); + --! transmit enable + signal tx_en : std_logic; + --! transmit enable one clock delayed + signal tx_en_f : std_logic; + --! preamble byte counter + signal preamble_cnt : integer range 0 to 7; + --!@} + + --! \name IFG signals + --!@{ + --! counts the IFG + signal ifg_cnt : natural range 0 to G_IFG_CLOCKS; + --!@} + +begin + + rx_dv_o <= frame_in; + + frame_start_o <= frame_in and (not frame_in_f); + frame_end_o <= (not frame_in) and frame_in_f; + tx_en_o <= tx_en; + + --! receive frames and cut off pramble + rmii_in_out_proc : process (reset_n_i, clk_i) + begin + if (reset_n_i = '0') then + get_time_o <= '0'; + rx_dv_i_f <= '0'; + frame_in <= '0'; + state <= Wait_For_Start_Of_Frame; + elsif (clk_i'event and clk_i = '1') then + + rx_dv_i_f <= rx_dv_i; + + case state is + when Wait_For_Start_Of_Frame => + get_time_o <= '0'; + if rx_dv_i = '1' then + state <= Preamble; + else + state <= Wait_For_Start_Of_Frame; + end if; + + when Preamble => + if rx_dv_i /= '1' then + state <= Wait_For_End_Of_Frame; + elsif rxd_i = "01" then -- preamble detected + state <= Sfd; + else + state <= Preamble; + end if; + + when Sfd => + if rx_dv_i /= '1' then + state <= Wait_For_End_Of_Frame; + elsif rxd_i = "11" then -- SFD detected + get_time_o <= '1'; + state <= Frame; + else + state <= Sfd; + end if; + + when Frame => + frame_in <= '1'; + if rx_dv_i /= '1' then + state <= Wait_For_End_Of_Frame; + else + state <= Frame; + end if; + + when Wait_For_End_Of_Frame => + if (rx_dv_i /= '1' and rx_dv_i_f /= '1') then + get_time_o <= '0'; + frame_in <= '0'; + state <= Wait_For_Start_Of_Frame; + else + state <= Wait_For_End_Of_Frame; + end if; + + when others => + state <= Wait_For_End_Of_Frame; + + end case; + end if; + end process; + + --! converts 2 bit RMII data to bytes + conv_2_to_8bit_proc : process (reset_n_i, clk_i) + begin + + if (reset_n_i = '0') then + rx_stb_o <= '0'; + rx_data_o <= (others => '0'); + data_buffer <= (others => '0'); + data_i_position <= 0; + frame_in_f <= '0'; + elsif (clk_i'event and clk_i = '1') then + + rx_stb_o <= '0'; + frame_in_f <= frame_in; + + data_buffer(5 downto 0) <= data_buffer(7 downto 2); + data_buffer(7 downto 6) <= rxd_i; + + if rx_dv_i = '1' and rx_dv_i_f = '0' then -- reset at start of frame + data_i_position <= 0; + rx_data_o <= (others => '0'); + elsif frame_in = '1' then -- store data + + if data_i_position < 3 then + data_i_position <= data_i_position + 1; + else + data_i_position <= 0; + rx_data_o <= data_buffer; + rx_stb_o <= '1'; -- indicates a valid byte + end if; + + end if; + end if; + end process; + + txd_o <= tx_data(1 downto 0); + + --! send frames and generate preamble + rmii_out_proc : process (reset_n_i, clk_i) + begin + if (reset_n_i = '0') then + tx_data <= (others => '0'); + tx_en <= '0'; + tx_ack_o <= '0'; + nibble_cnt <= 3; + preamble_cnt <= 0; + elsif (clk_i'event and clk_i = '1') then + tx_ack_o <= '0'; + if (tx_en_i = '1' or nibble_cnt < 3) and ifg_cnt = 0 then -- framestart or send last nibble + tx_en <= '1'; -- start + if nibble_cnt < 3 then -- continute byte + tx_data(5 downto 0) <= tx_data(7 downto 2); + tx_data(7 downto 6) <= "00"; + nibble_cnt <= nibble_cnt + 1; + elsif preamble_cnt + 1 < G_AMOUNT_OF_PREAMBEL_AND_SFD_BYTES then -- send preamble + tx_data <= b"0101_0101"; + preamble_cnt <= preamble_cnt + 1; + nibble_cnt <= 0; + elsif preamble_cnt + 1 = G_AMOUNT_OF_PREAMBEL_AND_SFD_BYTES then -- send sfd + tx_data <= b"1101_0101"; + preamble_cnt <= preamble_cnt + 1; + nibble_cnt <= 0; + else -- send data + tx_data <= tx_data_i; + tx_ack_o <= '1'; + nibble_cnt <= 0; + end if; + else -- stop + tx_en <= '0'; + preamble_cnt <= 0; + nibble_cnt <= 3; + end if; + end if; + end process; + + --! Interframe Gap Counter + ifg_counter : process(clk_i, reset_n_i) + begin + if reset_n_i = '0' then + ifg_cnt <= 0; + tx_en_f <= '0'; + elsif clk_i'event and clk_i = '1' then + tx_en_f <= tx_en; -- tx_en one clock delayed + if tx_en = '0' and tx_en_f = '1' then -- end of frame + ifg_cnt <= G_IFG_CLOCKS; + elsif ifg_cnt > 0 then + ifg_cnt <= ifg_cnt -1; + end if; + end if; + end process ifg_counter; + +end rtl; \ No newline at end of file -- cgit v1.2.3-54-g00ecf