-------------------------------------------------------------
-- MSS copyright 2010-2013
--	Filename:  PHYSIM_GMII_MII.VHD
-- Author: Alain Zarembowitch / MSS
--	Version: 2
--	Date last modified: 8/21/13
-- Inheritance: 	N/A
--
-- description:  simulation of a PHY with GMII/MII interface.
-- User to set SPEED.
-- It loops tx back to rx after a fixed delay.
-- 
-- Rev 2 8/21/13 AZ
-- Corrected support for 1Gbps/125 MHz clock.
---------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity PHYSIM_GMII_MII is
    Port ( 
	 
		--// PHY GMII/MII Interface ----------------------------------------------------------------
		-- Connect directly to FPGA pins
		TX_CLK: out std_logic;  
			-- MII tx clock from PHY. Continuous clock. (10/100 Mbps only) 
			-- 25 MHz (100 Mbps), or 2.5 MHz (10 Mbps) depending on speed
			-- accuracy: +/- 100ppm (MII)
			-- duty cycle between 35% and 65% inclusive (MII).
		GTX_CLK: in std_logic;  
			-- GMII tx clock to PHY. Continuous clock. 125MHz (1000 Mbps only)
			-- 2ns delay inside (user adjustable).
		TXD: in std_logic_vector(7 downto 0);  
			-- tx data (when TX_EN = '1' and TX_ER = '0') or special codes otherwise (carrier extend, 
			-- carrier extend error, transmit error propagation). See 802.3 table 35-1 for definitions.
		TX_EN: in std_logic;  
			-- 
		TX_ER: in std_logic;  
			-- to deliberately corrupt the contents of the frame (so as to be detected as such by the receiver)
		
		RX_CLK: out std_logic;  
			-- continuous receive reference clock recovered by the PHY from the received signal
			-- 125/25/2.5 MHz +/- 50 ppm. 
			-- Duty cycle better than 35%/65% (MII)
			-- 125 MHz must be delayed by 1.5 to 2.1 ns to prevent glitches (TBC. true for RGMII, but for GMII TOO???)
			
		RXD: out std_logic_vector(7 downto 0);  
			-- rx data. 8-bit when 1000 Mbps. 4-bit nibble (3:0) when 10/100 Mbps.
		RX_DV: out std_logic;  
		RX_ER: out std_logic;  
		CRS: out std_logic;  
			-- carrier sense
		COL: out std_logic;  
			-- collision detection
	 
		RESET_N: IN std_logic;
			-- PHY reset
		SPEED: in std_logic_vector(1 downto 0);
			-- 00 = force 10 Mbps
			-- 01 = force 100 Mbps
			-- 10 = force 1000 Mbps
			-- 11 = auto-negotiation (default)
		MCLK: IN std_logic;
		MDIO: INOUT std_logic;  -- (tri-state)
			-- serial interface
		CLK125_NDO: OUT std_logic
			-- clean 125 MHz clock
			
		
 );
end entity;

architecture Behavioral of PHYSIM_GMII_MII is
--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
signal RXC: std_logic := '0';
signal TX_CLK_LOCAL: std_logic := '0';
signal RX_DV_local: std_logic := '0';


  constant CLK125_NDO_period : time := 8 ns;  -- 125 MHz

--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin

   CLK125G_process :process
   begin
		CLK125_NDO <= '0';
		wait for CLK125_NDO_period/2;
		CLK125_NDO <= '1';
		wait for CLK125_NDO_period/2;
   end process;
	
--// RX ------------------------------------------------------


-- loopback after a specified delay
RXD <= transport TXD after 36 ns;
RX_DV_local <= transport TX_EN after 36 ns;
RX_DV <= RX_DV_local;
RX_ER <= '0';
RX_CLK <= transport TX_CLK_LOCAL after 36 ns ; -- loopback 


	
--// TX ------------------------------------------------------
process
begin
	TX_CLK_LOCAL <= '0';
	if(SPEED = "00") then
		wait for 200 ns;	-- 10 Mbps => 2.5 MHz
	elsif(SPEED = "01") then
		wait for 200 ns;	-- 100 Mbps => 25 MHz
	else
		wait for 4 ns;		-- 1Gbps => 125 MHz
	end if;
	TX_CLK_LOCAL <= '1';
	if(SPEED = "00") then
		wait for 200 ns;	-- 10 Mbps => 2.5 MHz
	elsif(SPEED = "01") then
		wait for 200 ns;	-- 100 Mbps => 25 MHz
	else
		wait for 4 ns;		-- 1Gbps => 125 MHz
	end if;
end process;
TX_CLK <= TX_CLK_LOCAL;

COL <= '0';  -- no collision when phy loopback test
CRS <= '1' when (RX_DV_local = '1') or (TX_EN = '1') else '0';


end Behavioral;

