diff --git a/intel/mii_gmii_io.vhd b/intel/mii_gmii_io.vhd new file mode 100644 index 0000000..a09b84d --- /dev/null +++ b/intel/mii_gmii_io.vhd @@ -0,0 +1,118 @@ +-- This file is part of the ethernet_mac project. +-- +-- For the full copyright and license information, please read the +-- LICENSE.md file that was distributed with this source code. +-- +-- Device-specific IO setup needed for communicating with the PHY +-- +-- Copyright (c) 2015, Philipp Kerling +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- * Redistributions of source code must retain the above copyright notice, this +-- list of conditions and the following disclaimer. +-- +-- * Redistributions in binary form must reproduce the above copyright notice, +-- this list of conditions and the following disclaimer in the documentation +-- and/or other materials provided with the distribution. +-- +-- * Neither the name of ethernet\_mac nor the names of its +-- contributors may be used to endorse or promote products derived from +-- this software without specific prior written permission. +-- +-- * Neither the source code, nor any derivative product, may be used for military +-- purposes. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- + +library ieee; +use ieee.std_logic_1164.all; + +use work.ethernet_types.all; + +entity mii_gmii_io is + port( + -- 125 MHz clock input (exact requirements can vary by implementation) + -- Spartan 6: clock should be unbuffered + clock_125_i : in std_ulogic; + + -- RX and TX clocks + clock_tx_o : out std_ulogic; + clock_rx_o : out std_ulogic; + + -- Speed selection for clock switch + speed_select_i : in t_ethernet_speed; + + -- Signals connected directly to external ports + -- MII + mii_tx_clk_i : in std_ulogic; + mii_tx_en_o : out std_ulogic; + mii_txd_o : out t_ethernet_data; + mii_rx_clk_i : in std_ulogic; + mii_rx_er_i : in std_ulogic; + mii_rx_dv_i : in std_ulogic; + mii_rxd_i : in t_ethernet_data; + + -- GMII + gmii_gtx_clk_o : out std_ulogic; + + -- Signals connected to the mii_gmii module + int_mii_tx_en_i : in std_ulogic; + int_mii_txd_i : in t_ethernet_data; + int_mii_rx_er_o : out std_ulogic; + int_mii_rx_dv_o : out std_ulogic; + int_mii_rxd_o : out t_ethernet_data + ); +end entity; + +architecture Behavioral of mii_gmii_io is + signal clock_tx : std_ulogic := '0'; + signal clock_rx : std_ulogic := '0'; +begin + -- set tx-clock: switch between 125 Mhz reference clock and MII_TX_CLK for TX process + with speed_select_i select clock_tx <= + clock_125_i when SPEED_1000MBPS, + mii_tx_clk_i when others; + -- set rx-clock + clock_rx <= mii_rx_clk_i; + + -- output 1000Mbps-clock only when running GMII to reduce switching noise + with speed_select_i select gmii_gtx_clk_o <= + clock_tx when SPEED_1000MBPS, + '0' when others; + + -- output rx/tx-clocks + clock_tx_o <= clock_tx; + clock_rx_o <= clock_rx; + + process (clock_tx) + begin + if rising_edge(clock_tx) then + -- output data to PHY + mii_tx_en_o <= int_mii_tx_en_i; + mii_txd_o <= int_mii_txd_i; + end if; + end process; + + process (clock_rx) + begin + if rising_edge(clock_rx) then + -- receive data from PHY + int_mii_rx_dv_o <= mii_rx_dv_i; + int_mii_rx_er_o <= mii_rx_er_i; + int_mii_rxd_o <= mii_rxd_i; + end if; + end process; +end architecture; diff --git a/intel/single_signal_synchronizer.vhd b/intel/single_signal_synchronizer.vhd new file mode 100644 index 0000000..bf3d296 --- /dev/null +++ b/intel/single_signal_synchronizer.vhd @@ -0,0 +1,68 @@ +-- This file is part of the ethernet_mac project. +-- +-- For the full copyright and license information, please read the +-- LICENSE.md file that was distributed with this source code. + +-- Synchronize a single bit from an arbitrary clock domain +-- into the clock_target domain +-- +-- Copyright (c) 2015, Philipp Kerling +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- * Redistributions of source code must retain the above copyright notice, this +-- list of conditions and the following disclaimer. +-- +-- * Redistributions in binary form must reproduce the above copyright notice, +-- this list of conditions and the following disclaimer in the documentation +-- and/or other materials provided with the distribution. +-- +-- * Neither the name of ethernet\_mac nor the names of its +-- contributors may be used to endorse or promote products derived from +-- this software without specific prior written permission. +-- +-- * Neither the source code, nor any derivative product, may be used for military +-- purposes. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +library ieee; +use ieee.std_logic_1164.all; + +entity single_signal_synchronizer is + port( + clock_target_i : in std_ulogic; + -- Asynchronous preset of the output and synchronizer flip-flops + preset_i : in std_ulogic := '0'; + -- Asynchronous signal input + signal_i : in std_ulogic; + -- Synchronous signal output + signal_o : out std_ulogic + ); +end entity; + +architecture simple of single_signal_synchronizer is + signal signal_tmp : std_ulogic := '0'; +begin + process(clock_target_i, preset_i) + begin + if preset_i = '1' then + signal_tmp <= '1'; + signal_o <= '1'; + elsif rising_edge(clock_target_i) then + signal_tmp <= signal_i; + signal_o <= signal_tmp; + end if; + end process; +end architecture; diff --git a/intel/utility.vhd b/intel/utility.vhd new file mode 100644 index 0000000..0c52d06 --- /dev/null +++ b/intel/utility.vhd @@ -0,0 +1,120 @@ +-- This file is part of the ethernet_mac project. +-- +-- For the full copyright and license information, please read the +-- LICENSE.md file that was distributed with this source code. + +-- Utility functions +-- +-- Copyright (c) 2015, Philipp Kerling +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- * Redistributions of source code must retain the above copyright notice, this +-- list of conditions and the following disclaimer. +-- +-- * Redistributions in binary form must reproduce the above copyright notice, +-- this list of conditions and the following disclaimer in the documentation +-- and/or other materials provided with the distribution. +-- +-- * Neither the name of ethernet\_mac nor the names of its +-- contributors may be used to endorse or promote products derived from +-- this software without specific prior written permission. +-- +-- * Neither the source code, nor any derivative product, may be used for military +-- purposes. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +library ieee; +use ieee.std_logic_1164.all; + +package utility is + -- Return the reverse of the given vector + function reverse_vector(vec : in std_ulogic_vector) return std_ulogic_vector; + -- Return a vector with the bytes in opposite order but the content of the bytes unchanged (e.g. for big/little endian conversion) + function reverse_bytes(vec : in std_ulogic_vector) return std_ulogic_vector; + -- Extract a byte out of a vector + function extract_byte(vec : in std_ulogic_vector; byteno : in natural) return std_ulogic_vector; + -- Set a byte in a vector + procedure set_byte(vec : inout std_ulogic_vector; byteno : in natural; value : in std_ulogic_vector(7 downto 0)); +end package; + +package body utility is + function reverse_vector(vec : in std_ulogic_vector) return std_ulogic_vector is + variable result : std_ulogic_vector(vec'range); + alias rev_vec : std_ulogic_vector(vec'reverse_range) is vec; + begin + for i in rev_vec'range loop + result(i) := rev_vec(i); + end loop; + return result; + end function; + + function reverse_bytes(vec : in std_ulogic_vector) return std_ulogic_vector is + variable result : std_ulogic_vector(vec'range); + begin + assert vec'length mod 8 = 0 report "Vector length must be a multiple of 8 for byte reversal" severity failure; + assert vec'low = 0 report "Vector must start at 0 for byte reversal" severity failure; + for byte in 0 to vec'high / 8 loop + set_byte(result, vec'high / 8 - byte, extract_byte(vec, byte)); + end loop; + return result; + end function; + + function extract_byte(vec : in std_ulogic_vector; byteno : in natural) return std_ulogic_vector is + begin + -- Support both vector directions + if vec'ascending then + --return vec(byteno * 8 to (byteno + 1) * 8 - 1); -- quartus cannot synthesize this + if (byteno = 0) then + return vec(0 to 7); + elsif (byteno = 1) then + return vec(8 to 15); + elsif (byteno = 2) then + return vec(16 to 23); + elsif (byteno = 3) then + return vec(24 to 31); + elsif (byteno = 4) then + return vec(32 to 39); + else + return vec(40 to 47); + end if; + else + --return vec((byteno + 1) * 8 - 1 downto byteno * 8); -- quartus cannot synthesize this + if (byteno = 0) then + return vec(7 downto 0); + elsif (byteno = 1) then + return vec(15 downto 8); + elsif (byteno = 2) then + return vec(23 downto 16); + elsif (byteno = 3) then + return vec(31 downto 24); + elsif (byteno = 4) then + return vec(39 downto 32); + else + return vec(47 downto 40); + end if; + end if; + end function; + + procedure set_byte(vec : inout std_ulogic_vector; byteno : in natural; value : in std_ulogic_vector(7 downto 0)) is + begin + -- Support both vector directions + if vec'ascending then + vec(byteno * 8 to (byteno + 1) * 8 - 1) := value; + else + vec((byteno + 1) * 8 - 1 downto byteno * 8) := value; + end if; + end procedure; +end package body;