library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity mdio is port ( clk125 : in std_logic; reset125 : in std_logic; command : in std_logic_vector(0 to 27); -- operation(2) & phyaddr(5) & devaddr(5) & data_in(16) data_out : out std_logic_vector(0 to 15); enable : in std_logic; done : out std_logic; mdio_in : in std_logic; mdio_out : out std_logic; mdio_Z : out std_logic; mdc : out std_logic; phy_reset_n : out std_logic; total_count : out std_logic_vector(31 downto 0); address_count : out std_logic_vector(31 downto 0); write_count : out std_logic_vector(31 downto 0); read_count : out std_logic_vector(31 downto 0); read_incr_count : out std_logic_vector(31 downto 0) ); end mdio; architecture arch of mdio is type state_t is (state_idle, state_preamble, state_start, state_operation, state_phyaddr, state_devaddr, state_turnaround, state_data); signal state : state_t; signal state_count : natural range 0 to 32; signal operation : std_logic_vector(0 to 1); signal phyaddr : std_logic_vector(0 to 4); signal devaddr : std_logic_vector(0 to 4); signal data_in : std_logic_vector(0 to 15); signal mdc_count : natural range 0 to 25; signal mdc_i : std_logic; signal total_count_i : unsigned(31 downto 0); signal address_count_i : unsigned(31 downto 0); signal write_count_i : unsigned(31 downto 0); signal read_count_i : unsigned(31 downto 0); signal read_incr_count_i : unsigned(31 downto 0); signal done_i : std_logic; begin phy_reset_n <= not reset125; mdc <= mdc_i; operation <= command(0 to 1); phyaddr <= command(2 to 6); devaddr <= command(7 to 11); data_in <= command(12 to 27); done <= done_i; process (clk125, reset125) begin if reset125 = '1' then mdc_i <= '0'; mdc_count <= 0; done_i <= '0'; elsif rising_edge(clk125) then done_i <= '0'; if mdc_count = 25 - 1 then mdc_count <= 0; mdc_i <= not mdc_i; -- 2.5 MHz if mdc_i = '0' then -- rising edge if state = state_data and state_count = 15 then done_i <= '1'; end if; end if; else mdc_count <= mdc_count + 1; end if; end if; end process; process (mdc_i, reset125) begin if reset125 = '1' then state <= state_idle; state_count <= 0; data_out <= (others => '0'); elsif rising_edge(mdc_i) then state_count <= state_count + 1; if state = state_preamble then if state_count = 31 then state <= state_start; state_count <= 0; end if; elsif state = state_start then if state_count = 1 then state <= state_operation; state_count <= 0; end if; elsif state = state_operation then if state_count = 1 then state <= state_phyaddr; state_count <= 0; end if; elsif state = state_phyaddr then if state_count = 4 then state <= state_devaddr; state_count <= 0; end if; elsif state = state_devaddr then if state_count = 4 then state <= state_turnaround; state_count <= 0; end if; elsif state = state_turnaround then if state_count = 1 then state <= state_data; state_count <= 0; end if; elsif state = state_data then data_out(state_count) <= mdio_in; if state_count = 15 then state <= state_idle; state_count <= 0; end if; else -- state = state_idle if enable = '1' then state <= state_preamble; state_count <= 0; end if; end if; end if; end process; process (mdc_i, reset125) begin if reset125 = '1' then mdio_out <= '0'; mdio_Z <= '1'; elsif falling_edge(mdc_i) then mdio_out <= '0'; mdio_Z <= '1'; if state = state_preamble then mdio_out <= '1'; mdio_Z <= '0'; elsif state = state_start then mdio_out <= '0'; mdio_Z <= '0'; elsif state = state_operation then mdio_out <= operation(state_count); mdio_Z <= '0'; elsif state = state_phyaddr then mdio_out <= phyaddr(state_count); mdio_Z <= '0'; elsif state = state_devaddr then mdio_out <= devaddr(state_count); mdio_Z <= '0'; elsif state = state_turnaround then if operation(0) = '0' then -- write or address mdio_Z <= '0'; if state_count = 0 then mdio_out <= '1'; else mdio_out <= '0'; end if; end if; elsif state = state_data then if operation(0) = '0' then -- write or address mdio_Z <= '0'; mdio_out <= data_in(state_count); end if; end if; end if; end process; total_count <= std_logic_vector(total_count_i); address_count <= std_logic_vector(address_count_i); write_count <= std_logic_vector(write_count_i); read_count <= std_logic_vector(read_count_i); read_incr_count <= std_logic_vector(read_incr_count_i); process (clk125, reset125) begin if reset125 = '1' then total_count_i <= (others => '0'); address_count_i <= (others => '0'); write_count_i <= (others => '0'); read_count_i <= (others => '0'); read_incr_count_i <= (others => '0'); elsif rising_edge(clk125) then if done_i = '1' then total_count_i <= total_count_i + 1; if operation = "00" then address_count_i <= address_count_i + 1; end if; if operation = "01" then write_count_i <= write_count_i + 1; end if; if operation = "11" then read_count_i <= read_count_i + 1; end if; if operation = "10" then read_incr_count_i <= read_incr_count_i + 1; end if; end if; end if; end process; end arch;