summaryrefslogtreecommitdiff
path: root/netfpga10g/hdl/mdio.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'netfpga10g/hdl/mdio.vhd')
-rw-r--r--netfpga10g/hdl/mdio.vhd223
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;