diff options
Diffstat (limited to 'netfpga10g/hdl/mdio.vhd')
| -rw-r--r-- | netfpga10g/hdl/mdio.vhd | 223 | 
1 files changed, 223 insertions, 0 deletions
diff --git a/netfpga10g/hdl/mdio.vhd b/netfpga10g/hdl/mdio.vhd new file mode 100644 index 0000000..1cb34fa --- /dev/null +++ b/netfpga10g/hdl/mdio.vhd @@ -0,0 +1,223 @@ + +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;  | 
