summaryrefslogtreecommitdiff
path: root/lib/ethernet/components/rmii_phy_to_mii_mac.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ethernet/components/rmii_phy_to_mii_mac.vhd')
-rw-r--r--lib/ethernet/components/rmii_phy_to_mii_mac.vhd217
1 files changed, 217 insertions, 0 deletions
diff --git a/lib/ethernet/components/rmii_phy_to_mii_mac.vhd b/lib/ethernet/components/rmii_phy_to_mii_mac.vhd
new file mode 100644
index 0000000..09227c6
--- /dev/null
+++ b/lib/ethernet/components/rmii_phy_to_mii_mac.vhd
@@ -0,0 +1,217 @@
+------------------------------------------------------------------
+-- _____ ______ _____ -
+-- |_ _| | ____|/ ____| -
+-- | | _ __ | |__ | (___ 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;