OpenCores
URL https://opencores.org/ocsvn/gigabit_udp_mac/gigabit_udp_mac/trunk

Subversion Repositories gigabit_udp_mac

[/] [gigabit_udp_mac/] [trunk/] [MAC/] [MII_MI _V6.vhd] - Rev 2

Compare with Previous | Blame | View Log

-------------------------------------------------------------
--	Filename:  MII_MI_V5.VHD
--	Version: 1
--	Date last modified: 1-30-11
-- Inheritance: 	MII_MI.VHD rev1 1-30-11 
--
-- description:  MII management interface.
-- Writes and read registers to/from the PHY IC through 
-- the MDC & MDIO serial interface.
-- The MCLK clock speed is set as a constant within (integer division of the reference clock CLK).
-- USAGE: adjust the constant MCLK_COUNTER_DIV within to meet the MDC/MDIO timing requirements (see PHY specs).
-- Virtex-5 use.
---------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity MII_MI_V6 is
	generic (
		PHY_ADDR: std_logic_vector(4 downto 0)
			-- PHY Address
	);
    Port ( 
		--// CLK, RESET
		SYNC_RESET: in std_logic;
		CLK: in std_logic;
 
		MI_REGAD: in std_logic_vector(4 downto 0);	
			-- 32 register address space for the PHY (ieee 802.3)
			--  0 - 15 are standard PHY registers as per IEEE specification.
			-- 16 - 31 are vendor-specific registers
		MI_TX_DATA: in std_logic_vector(15 downto 0);
		MI_RX_DATA: out std_logic_vector(15 downto 0);	
		MI_READ_START: in std_logic;
			-- 1 CLK wide pulse to start read transaction
			-- will be ignored if the previous transaction is yet to be completed.
			-- For reliable operation, the user must check MI_TRANSACTION_COMPLETE first.
		MI_WRITE_START: in std_logic;
			-- 1 CLK wide pulse to start write transaction
			-- will be ignored if the previous transaction is yet to be completed.
			-- For reliable operation, the user must check MI_TRANSACTION_COMPLETE first.
 
		MI_TRANSACTION_COMPLETE: out std_logic;
			-- '1' when transaction is complete 
 
		--// serial interface. connect to PHY 
		MCLK: out std_logic;
		MDI: in std_logic;  -- MDIO input
		MDO: out std_logic;  -- MDIO output
		MDT: out std_logic  -- MDIO tri-state
 
 );
end entity;
 
architecture Behavioral of MII_MI_V6 is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
signal STATE: std_logic_vector(7 downto 0) := x"00";   -- 0 is idle
signal TXRX_FRAME: std_logic_vector(63 downto 0); --32-bit idle sequence + 32-bit MI serial port frame + 2 end bit
signal MCLK_LOCAL: std_logic := '0';
signal MCLK_LOCAL_D: std_logic := '0';
signal MDOE: std_logic := '1';
signal MDI_DATA: std_logic := '0';
signal MDI_SAMPLE_CLK: std_logic := '0';
constant MCLK_COUNTER_DIV: std_logic_vector(7 downto 0) := x"17";  
	-- divide CLK by this 2*(value + 1) to generate a slower MCLK
	-- MCLK period (typ): 400 ns [Micrel KSZ9021]
	-- Example: 120 MHz clock, 400ns MCLK period => MCLK_COUNTER_DIV = 23
signal MCLK_COUNTER: std_logic_vector(7 downto 0) := x"00";
signal MI_SAMPLE_REQ: std_logic;
 
--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin
 
------------------------------------------------------
-- MCLK GENERATION
------------------------------------------------------
-- Divide CLK by MCLK_COUNTER_DIV
MCLK_GEN_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			MCLK_COUNTER <= (others => '0');
			MI_SAMPLE_REQ <= '0';
		elsif(STATE = 0) then
			-- idle. awaiting a start of transaction.
			MI_SAMPLE_REQ <= '0';
			if(MI_WRITE_START = '1') or (MI_READ_START = '1') then
				-- get started. reset MCLK phase.
				MCLK_COUNTER <= (others => '0');
			end if;
		else
			-- read/write transaction in progress
			if(MCLK_COUNTER = MCLK_COUNTER_DIV) then 
				-- next sample
				MI_SAMPLE_REQ <= '1';
				MCLK_COUNTER <= (others => '0');
			else
				MI_SAMPLE_REQ <= '0';
				MCLK_COUNTER <= MCLK_COUNTER + 1;
			end if;
		end if;
	end if;
end process;
 
------------------------------------------------------
-- OUTPUT TO PHY
------------------------------------------------------
 
STATE_GEN_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			STATE <= (others => '0');
			MCLK_LOCAL <= '0';
			MDOE <= '0';
		elsif(STATE = 0) then
			if (MI_WRITE_START = '1') then
				-- was idle. start of write transaction. start counting 
				STATE <= x"01";
				MCLK_LOCAL <= '0';
				MDOE <= '1';
			elsif (MI_READ_START = '1') then
				-- was idle. start of read transaction. start counting 
				STATE <= x"81";
				MCLK_LOCAL <= '0';
				MDOE <= '1';
			end if;
		elsif (MI_SAMPLE_REQ = '1') then
			if (STATE = 128) then
				-- write transaction complete. set output enable to high impedance
				STATE <= x"00";
				MCLK_LOCAL <= '0';
				MDOE <= '0';
			elsif (STATE = 220) then
				-- read transaction: finished writing addresses. switch to read mode
				STATE <= STATE + 1;
				MCLK_LOCAL <= not MCLK_LOCAL;
				MDOE <= '0';
			elsif (STATE = 255) then
				-- read transaction complete. reset state.
				STATE <= x"00";
				MCLK_LOCAL <= '0';
				MI_RX_DATA <= TXRX_FRAME(15 downto 0);  -- complete word read from PHY
			else
				STATE <= STATE + 1;
				MCLK_LOCAL <= not MCLK_LOCAL;
			end if;
		end if;
	end if;
end process;
 
-- immediate turn off the 'available' message as soon as a new transaction is triggered.
MI_TRANSACTION_COMPLETE <= '0' when (STATE > 0) else
									'0' when (MI_WRITE_START = '1') else
									'0' when (MI_READ_START = '1') else
									'1';
 
-- send MCLK to output
MCLK <= MCLK_LOCAL;
 
TXRX_FRAME_GEN: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			TXRX_FRAME <= (others => '0');
		elsif(MI_WRITE_START = '1') then
			-- start of write transaction. 
			-- Note: transmission sequence starts at bit 63 
			TXRX_FRAME(63 downto 32) <= x"FFFFFFFF";	-- preamble: idle sequence 32 '1's
			TXRX_FRAME(31 downto 23)  <= "0101" & PHY_ADDR;  
			TXRX_FRAME(22 downto 18) <= MI_REGAD;
			TXRX_FRAME(17 downto 16) <= "10";
			TXRX_FRAME(15 downto 0) <= MI_TX_DATA;
		elsif(MI_READ_START = '1') then
			-- start of read transaction. 
			-- Note: transmission sequence starts at bit 63 
			TXRX_FRAME(63 downto 32) <= x"FFFFFFFF";	-- preamble: idle sequence 32 '1's
			TXRX_FRAME(31 downto 23)  <= "0110" & PHY_ADDR; 
			TXRX_FRAME(22 downto 18) <= MI_REGAD;
		elsif(MI_SAMPLE_REQ = '1') and (STATE /= 0) and (STATE(0) = '0') and (MDOE = '1') then
			-- shift TXRX_FRAME 1 bit left every two clocks
			TXRX_FRAME(63 downto 1) <= TXRX_FRAME(62 downto 0);
		elsif(MDI_SAMPLE_CLK = '1') and (STATE /= 0) and (STATE(0) = '1') and (MDOE = '0') then
			-- shift MDIO into TXRX_FRAME 1 bit left every two clocks (read at the falling edge of MCLK)
			-- do this 16 times to collect the 16-bit response from the PHY.
			TXRX_FRAME(63 downto 1) <= TXRX_FRAME(62 downto 0);
			TXRX_FRAME(0) <= MDI_DATA;
	 	end if;
  end if;
end process;
 
-- select output bit. 
MDO <= TXRX_FRAME(63);
MDT <= not MDOE;
 
------------------------------------------------------
-- INPUT FROM PHY
------------------------------------------------------
 
 
-- reclock MDI input at the falling edge of MCLK
RX_RECLOCK_001: process(CLK)
begin
	if rising_edge(CLK) then
		MCLK_LOCAL_D <= MCLK_LOCAL;
 
		if(MCLK_LOCAL = '0') and (MCLK_LOCAL_D = '1') then
			MDI_DATA <= MDI;
			MDI_SAMPLE_CLK <= '1';
		else
			MDI_SAMPLE_CLK <= '0';
		end if;
	end if;
end process;
 
 
end Behavioral;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.