diff --git a/library/util_gmii_to_rgmii/mdc_mdio.v b/library/util_gmii_to_rgmii/mdc_mdio.v new file mode 100644 index 000000000..fa7bab93d --- /dev/null +++ b/library/util_gmii_to_rgmii/mdc_mdio.v @@ -0,0 +1,112 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2011(c) Analog Devices, Inc. +// +// 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 Analog Devices, Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// - The use of this software may or may not infringe the patent rights +// of one or more patent holders. This license does not release you +// from the requirement that you obtain separate licenses from these +// patent holders to use this software. +// - Use of the software either in source or binary form, must be run +// on or directly connected to an Analog Devices Inc. component. +// +// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. +// +// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +// RIGHTS, 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. +// *************************************************************************** +// *************************************************************************** + +module mdc_mdio ( + + mdio_mdc, + mdio_in_w, + mdio_in_r, + + speed_select, + duplex_mode); + + parameter PHY_AD = 5'b10000; + + input mdio_mdc; + input mdio_in_w; + input mdio_in_r; + output [ 1:0] speed_select; + output duplex_mode; + + localparam IDLE = 2'b01; + localparam ACQUIRE = 2'b10; + + wire preamble; + + reg [ 1:0] current_state = IDLE; + reg [ 1:0] next_state = IDLE; + reg [31:0] data_in = 32'h0; + reg [31:0] data_in_r = 32'h0; + reg [ 5:0] data_counter = 6'h0; + reg [ 1:0] speed_select = 2'h0; + reg duplex_mode = 1'h0; + + assign preamble = &data_in; + + always @(posedge mdio_mdc) begin + current_state <= next_state; + data_in <= {data_in[30:0], mdio_in_w}; + if (current_state == ACQUIRE) begin + data_counter <= data_counter + 1; + end else begin + data_counter <= 0; + end + if (data_counter == 6'h1f) begin + if (data_in[31] == 1'b0 && data_in[29:28]==2'b10 && data_in[27:23] == PHY_AD && data_in[22:18] == 5'h11) begin + speed_select <= data_in_r[16:15] ; + duplex_mode <= data_in_r[14]; + end + end + end + + always @(negedge mdio_mdc) begin + data_in_r <= {data_in_r[30:0], mdio_in_r}; + end + + always @(*) begin + case (current_state) + IDLE: begin + if (preamble == 1 && mdio_in_w == 0) begin + next_state <= ACQUIRE; + end else begin + next_state <= IDLE; + end + end + ACQUIRE: begin + if (data_counter == 6'h1f) begin + next_state <= IDLE; + end else begin + next_state <= ACQUIRE; + end + end + default: begin + next_state <= IDLE; + end + endcase + end + +endmodule diff --git a/library/util_gmii_to_rgmii/util_gmii_to_rgmii.v b/library/util_gmii_to_rgmii/util_gmii_to_rgmii.v new file mode 100644 index 000000000..3ad00a845 --- /dev/null +++ b/library/util_gmii_to_rgmii/util_gmii_to_rgmii.v @@ -0,0 +1,314 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2011(c) Analog Devices, Inc. +// +// 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 Analog Devices, Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// - The use of this software may or may not infringe the patent rights +// of one or more patent holders. This license does not release you +// from the requirement that you obtain separate licenses from these +// patent holders to use this software. +// - Use of the software either in source or binary form, must be run +// on or directly connected to an Analog Devices Inc. component. +// +// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. +// +// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +// RIGHTS, 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. +// *************************************************************************** +// *************************************************************************** +// based on XILINX xapp692 +// specific for MOTCON2 ADI board +// works correctly if the PHY is set with Autonegotiation on + +module util_gmii_to_rgmii ( + + clk_20m, + clk_25m, + clk_125m, + + reset, + + rgmii_td, + rgmii_tx_ctl, + rgmii_txc, + rgmii_rd, + rgmii_rx_ctl, + rgmii_rxc, + + mdio_mdc, + mdio_in_w, + mdio_in_r, + + gmii_txd, + gmii_tx_en, + gmii_tx_er, + gmii_tx_clk, + gmii_crs, + gmii_col, + gmii_rxd, + gmii_rx_dv, + gmii_rx_er, + gmii_rx_clk); + + parameter PHY_AD = 5'b10000; + + input clk_20m; + input clk_25m; + input clk_125m; + + input reset; + + output [ 3:0] rgmii_td; + output rgmii_tx_ctl; + output rgmii_txc; + input [ 3:0] rgmii_rd; + input rgmii_rx_ctl; + input rgmii_rxc; + + input mdio_mdc; + input mdio_in_w; + input mdio_in_r; + + input [ 7:0] gmii_txd; + input gmii_tx_en; + input gmii_tx_er; + output gmii_tx_clk; + output gmii_crs; + output gmii_col; + output [ 7:0] gmii_rxd; + output gmii_rx_dv; + output gmii_rx_er; + output gmii_rx_clk; + + // wires + wire clk_2_5m; + wire clk_100msps; + wire [ 3:0] rgmii_rd_delay; + wire [ 7:0] gmii_rxd_s; + wire rgmii_rx_ctl_delay; + wire rgmii_rx_ctl_s; + + wire [ 1:0] speed_selection; // 1x gigabit, 01 100Mbps, 00 10mbps + wire duplex_mode; // 1 full, 0 half + + // registers + reg tx_reset_d1; + reg tx_reset_sync; + reg rx_reset_d1; + reg [ 7:0] gmii_txd_r; + reg gmii_tx_en_r; + reg gmii_tx_er_r; + reg [ 7:0] gmii_txd_r_d1; + reg gmii_tx_en_r_d1; + reg gmii_tx_er_r_d1; + + reg rgmii_tx_ctl_r; + reg [ 3:0] gmii_txd_low; + reg gmii_col; + reg gmii_crs; + + reg [ 7:0] gmii_rxd; + reg gmii_rx_dv; + reg gmii_rx_er; + + assign gigabit = speed_selection [1]; + assign gmii_tx_clk = gmii_tx_clk_s; + + always @(posedge gmii_rx_clk) + begin + gmii_rxd = gmii_rxd_s; + gmii_rx_dv = gmii_rx_dv_s; + gmii_rx_er = gmii_rx_dv_s ^ rgmii_rx_ctl_s; + end + + always @(posedge gmii_tx_clk_s) begin + tx_reset_d1 <= reset; + tx_reset_sync <= tx_reset_d1; + end + + always @(posedge gmii_tx_clk_s) + begin + rgmii_tx_ctl_r = gmii_tx_en_r ^ gmii_tx_er_r; + gmii_txd_low = gigabit ? gmii_txd_r[7:4] : gmii_txd_r[3:0]; + gmii_col = duplex_mode ? 1'b0 : (gmii_tx_en_r| gmii_tx_er_r) & ( gmii_rx_dv | gmii_rx_er) ; + gmii_crs = duplex_mode ? 1'b0 : (gmii_tx_en_r| gmii_tx_er_r| gmii_rx_dv | gmii_rx_er); + end + + always @(posedge gmii_tx_clk_s) begin + if (tx_reset_sync == 1'b1) begin + gmii_txd_r <= 8'h0; + gmii_tx_en_r <= 1'b0; + gmii_tx_er_r <= 1'b0; + end + else + begin + gmii_txd_r <= gmii_txd; + gmii_tx_en_r <= gmii_tx_en; + gmii_tx_er_r <= gmii_tx_er; + gmii_txd_r_d1 <= gmii_txd_r; + gmii_tx_en_r_d1 <= gmii_tx_en_r; + gmii_tx_er_r_d1 <= gmii_tx_er_r; + end + end + + BUFR #( + .BUFR_DIVIDE("8"), + .SIM_DEVICE("7SERIES") + ) clk_2_5_divide ( + .I(clk_20m), + .CE(1), + .CLR(0), + .O(clk_2_5m)); + + BUFGMUX #( + .CLK_SEL_TYPE ("SYNC") + ) clk_tx_mux0 ( + .S(speed_selection[0]), + .I0(clk_2_5m), + .I1(clk_25m), + .O(clk_100msps)); + + BUFGMUX #( + .CLK_SEL_TYPE ("SYNC") + ) clk_tx_mux1 ( + .S(speed_selection[1]), + .I0(clk_100msps), + .I1(clk_125m), + .O(gmii_tx_clk_s)); + + ODDR #( + .DDR_CLK_EDGE("SAME_EDGE") + ) rgmii_txc_out ( + .Q (rgmii_txc), + .C (gmii_tx_clk_s), + .CE(1), + .D1(1), + .D2(0), + .R(tx_reset_sync), + .S(0)); + + generate + genvar i; + for (i = 0; i < 4; i = i + 1) begin : gen_tx_data + ODDR #( + .DDR_CLK_EDGE("SAME_EDGE") + ) rgmii_td_out ( + .Q (rgmii_td[i]), + .C (gmii_tx_clk_s), + .CE(1), + .D1(gmii_txd_r_d1[i]), + .D2(gmii_txd_low[i]), + .R(tx_reset_sync), + .S(0)); + end + endgenerate + + ODDR #( + .DDR_CLK_EDGE("SAME_EDGE") + ) rgmii_tx_ctl_out ( + .Q (rgmii_tx_ctl), + .C (gmii_tx_clk_s), + .CE(1), + .D1(gmii_tx_en_r_d1), + .D2(rgmii_tx_ctl_r), + .R(tx_reset_sync), + .S(0)); + + BUFG bufmr_rgmii_rxc( + .I(rgmii_rxc), + .O(gmii_rx_clk)); + + IDELAYE2 #( + .IDELAY_TYPE("FIXED"), + .HIGH_PERFORMANCE_MODE("TRUE"), + .REFCLK_FREQUENCY(200.0), + .SIGNAL_PATTERN("DATA"), + .DELAY_SRC("IDATAIN") + ) delay_rgmii_rx_ctl ( + .IDATAIN(rgmii_rx_ctl), + .DATAOUT(rgmii_rx_ctl_delay), + .DATAIN(0), + .C(0), + .CE(0), + .INC(0), + .CINVCTRL(0), + .CNTVALUEOUT(), + .LD(0), + .LDPIPEEN(0), + .CNTVALUEIN(0), + .REGRST(0)); + + generate + for (i = 0; i < 4; i = i + 1) begin + IDELAYE2 #( + .IDELAY_TYPE("FIXED"), + .HIGH_PERFORMANCE_MODE("TRUE"), + .REFCLK_FREQUENCY(200.0), + .SIGNAL_PATTERN("DATA"), + .DELAY_SRC("IDATAIN") + ) delay_rgmii_rd ( + .IDATAIN(rgmii_rd[i]), + .DATAOUT(rgmii_rd_delay[i]), + .DATAIN(0), + .C(0), + .CE(0), + .INC(0), + .CINVCTRL(0), + .CNTVALUEOUT(), + .LD(0), + .LDPIPEEN(0), + .CNTVALUEIN(0), + .REGRST(0)); + + IDDR #( + .DDR_CLK_EDGE("SAME_EDGE_PIPELINED") + ) rgmii_rx_iddr ( + .Q1(gmii_rxd_s[i]), + .Q2(gmii_rxd_s[i+4]), + .C(gmii_rx_clk), + .CE(1), + .D(rgmii_rd_delay[i]), + .R(0), + .S(0)); + end + endgenerate + + IDDR #( + .DDR_CLK_EDGE("SAME_EDGE_PIPELINED") + ) rgmii_rx_ctl_iddr ( + .Q1(gmii_rx_dv_s), + .Q2(rgmii_rx_ctl_s), + .C(gmii_rx_clk), + .CE(1), + .D(rgmii_rx_ctl_delay), + .R(0), + .S(0)); + + mdc_mdio #( + .PHY_AD(PHY_AD) + ) mdc_mdio_in( + .mdio_mdc(mdio_mdc), + .mdio_in_w(mdio_in_w), + .mdio_in_r(mdio_in_r), + .speed_select(speed_selection), + .duplex_mode(duplex_mode)); + +endmodule diff --git a/library/util_gmii_to_rgmii/util_gmii_to_rgmii_ip.tcl b/library/util_gmii_to_rgmii/util_gmii_to_rgmii_ip.tcl new file mode 100644 index 000000000..53feee61d --- /dev/null +++ b/library/util_gmii_to_rgmii/util_gmii_to_rgmii_ip.tcl @@ -0,0 +1,18 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create util_gmii_to_rgmii +adi_ip_files util_gmii_to_rgmii [list \ + "mdc_mdio.v" \ + "util_gmii_to_rgmii.v" ] + +adi_ip_properties_lite util_gmii_to_rgmii + +ipx::infer_bus_interface {gmii_tx_clk gmii_txd gmii_tx_en gmii_tx_er gmii_crs gmii_col gmii_rx_clk gmii_rxd gmii_rx_dv gmii_rx_er} xilinx.com:interface:gmii_rtl:1.0 [ipx::current_core] +set_property name {gmii} [ipx::get_bus_interface gmii_rtl_1 [ipx::current_core]] +ipx::infer_bus_interface {rgmii_td rgmii_tx_ctl rgmii_txc rgmii_rd rgmii_rx_ctl rgmii_rxc} xilinx.com:interface:rgmii_rtl:1.0 [ipx::current_core] +set_property value ACTIVE_HIGH [ipx::get_bus_parameters POLARITY -of_objects [ipx::get_bus_interfaces signal_reset -of_objects [ipx::current_core]]] + +ipx::save_core [ipx::current_core]