------------------------------------------------------------------ -- _____ ______ _____ - -- |_ _| | ____|/ ____| - -- | | _ __ | |__ | (___ Institute of Embedded Systems - -- | | | '_ \| __| \___ \ Zuercher Hochschule Winterthur - -- _| |_| | | | |____ ____) | (University of Applied Sciences) - -- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - ------------------------------------------------------------------ -- -- Project : SInet -- Description : Connects the data interface of a PHY in RMMI Mode and a MAC -- in MII Mode -- $LastChangedDate: 2006-11-14 12:14:54 +0100 (Tue, 14 Nov 2006) $ -- $Rev: 1358 $ -- $Author: beut $ ----------------------------------------------------------------- -- -- Change History -- Date |Name |Modification ------------|----------|----------------------------------------- -- 20.02.09 | beut | file ceated ----------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; package rmii_phy_to_mii_mac_pkg is component rmii_phy_to_mii_mac port ( reset_n_i : in std_logic; clk_25_i : in std_logic; clk_50_i : in std_logic; rmii_crs_i : in std_logic; -- Transmit Path mii_tx_en_i : in std_logic; mii_txd_i : in std_logic_vector(3 downto 0); rmii_tx_en_o : out std_logic; rmii_txd_o : out std_logic_vector(1 downto 0); -- Receive Path rmii_rx_dv_i : in std_logic; rmii_rxd_i : in std_logic_vector(1 downto 0); mii_rx_dv_o : out std_logic; mii_rxd_o : out std_logic_vector(3 downto 0) ); end component rmii_phy_to_mii_mac; end package rmii_phy_to_mii_mac_pkg; library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity rmii_phy_to_mii_mac is port ( reset_n_i : in std_logic; clk_25_i : in std_logic; clk_50_i : in std_logic; rmii_crs_i : in std_logic; -- Transmit Path mii_tx_en_i : in std_logic; mii_txd_i : in std_logic_vector(3 downto 0); rmii_tx_en_o : out std_logic; rmii_txd_o : out std_logic_vector(1 downto 0); -- Receive Path rmii_rx_dv_i : in std_logic; rmii_rxd_i : in std_logic_vector(1 downto 0); mii_rx_dv_o : out std_logic; mii_rxd_o : out std_logic_vector(3 downto 0) ); end rmii_phy_to_mii_mac; architecture behavior of rmii_phy_to_mii_mac is signal rmii_txd_next, rmii_txd_curr : std_logic; signal clk_25_sync_to_data : std_logic; signal clk_25_toggle, clk_50_toggle : std_logic; signal rmii_rxd_buffer : std_logic_vector(5 downto 0); signal mii_txd_buffer : std_logic_vector(3 downto 0); signal buffer_cnt : integer range 0 to 1; signal clk_50_en : std_logic; signal rmii_rx_dv_f : std_logic; signal mii_rx_dv_f : std_logic; signal mii_rx_dv_ff : std_logic; signal rmii_valid_sof : std_logic; begin ----------------------------------------------------------------- -- Clock 50 Enable Gnerating (is high if clock 25Mhz and Clock 50 MHz are rising ----------------------------------------------------------------- clock_25_proc: process (clk_25_i) begin if rising_edge(clk_25_i) then clk_25_toggle <= not clk_25_toggle; end if; end process; -- The clock enable muxes data in 25MHz freqency and has the same timing like data and not the clock! clock_50_proc: process (reset_n_i, clk_50_i) begin if reset_n_i = '0' then clk_50_toggle <= '0'; clk_50_en <= '0'; elsif rising_edge(clk_50_i) then clk_50_toggle <= clk_25_toggle; -- edge detection clk_50_en <= clk_25_toggle xor clk_50_toggle; --25 MHz clk sync to data of 50MHz end if; end process; ----------------------------------------------------------------- ----------------------------------------------------------------- -- Data Muxing from MAC to PHY ----------------------------------------------------------------- mii_to_rmii_proc : process (clk_50_en, mii_txd_i, mii_txd_buffer) begin if clk_50_en = '0' then rmii_txd_o <= mii_txd_buffer(1 downto 0); else rmii_txd_o <= mii_txd_buffer(3 downto 2); end if; end process; rmii_tx_en_proc: process (reset_n_i, clk_50_i) begin if reset_n_i = '0' then rmii_tx_en_o <= '0'; elsif rising_edge(clk_50_i) then if clk_50_en = '1' then -- data changes after a beginning of 25MHz cycle mii_txd_buffer <= mii_txd_i; rmii_tx_en_o <= mii_tx_en_i; end if; end if; end process; ----------------------------------------------------------------- ----------------------------------------------------------------- -- Data Muxing from PHY to MAC ----------------------------------------------------------------- -- Data buffern buffer_proc: process (reset_n_i, clk_50_i) begin if reset_n_i = '0' then rmii_rxd_buffer <= (others => '0'); elsif rising_edge(clk_50_i) then rmii_rxd_buffer(1 downto 0) <= rmii_rxd_buffer(3 downto 2); rmii_rxd_buffer(3 downto 2) <= rmii_rxd_buffer(5 downto 4); rmii_rxd_buffer(5 downto 4) <= rmii_rxd_i; end if; end process; rmii_rx_dv_proc: process (reset_n_i, clk_50_i) begin if reset_n_i = '0' then mii_rx_dv_f <= '0'; mii_rx_dv_ff <= '0'; mii_rxd_o <= (others => '0'); elsif rising_edge(clk_50_i) then if clk_50_en = '1' then if rmii_valid_sof = '1' then --only valid if the packet from phy is valid mii_rx_dv_f <= rmii_rx_dv_i; mii_rx_dv_ff <= mii_rx_dv_f; -- valid is two 25 MHz clockcycles later end if; if buffer_cnt = 1 then -- depends on the rmii dv signal mii_rxd_o <= rmii_rxd_buffer(3 downto 0); -- Three step buffer else mii_rxd_o <= rmii_rxd_buffer(5 downto 2); -- Two step buffer end if; end if; end if; end process; mii_rx_dv_o <= mii_rx_dv_ff ; -- counts the 50MHz clocks before rmii dv signal goes high before a 25MHZ Clock buffer_cnt_proc: process (reset_n_i, clk_50_i) begin if reset_n_i = '0' then buffer_cnt <= 0; elsif rising_edge(clk_50_i) then if (rmii_rx_dv_i = '1' and rmii_rx_dv_f = '0') and clk_50_en = '0' then buffer_cnt <= 1; elsif (rmii_rx_dv_i = '1' and rmii_rx_dv_f = '0') and clk_50_en = '1' then buffer_cnt <= 0; end if; end if; end process; rmii_valid_sof_proc: process (reset_n_i, clk_50_i) begin if reset_n_i = '0' then rmii_valid_sof <= '0'; rmii_rx_dv_f <= '0'; elsif rising_edge(clk_50_i) then rmii_rx_dv_f <= rmii_rx_dv_i; if rmii_crs_i = '1' and rmii_rx_dv_f = '0' and rmii_rx_dv_i = '1' then -- start of a valid frame rmii_valid_sof <= '1'; end if; end if; end process; end behavior;