//------------------------------------------------------------------------------ // Project : Xilinx LogiCORE Virtex-6 Embedded Tri-Mode Ethernet MAC // File : v6_emac_v2_3_sgmii_example_design.v // Version : 2.3 //----------------------------------------------------------------------------- // // (c) Copyright 2004-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // // Description: This is the Verilog example design for the Virtex-6 // Embedded Tri-Mode Ethernet MAC. It is intended that this // example design can be quickly adapted and downloaded onto // an FPGA to provide a real hardware test environment. // // This level: // // * Instantiates the FIFO Block wrapper, containing the // block level wrapper and an RX and TX FIFO with an // AXI-S interface; // // * Instantiates a simple AXI-S example design, // providing an address swap and a simple // loopback function; // // * Instantiates transmitter clocking circuitry // -the User side of the FIFOs are clocked at gtx_clk // at all times // // // * Serializes the Statistics vectors to prevent logic being // optimized out // // * Ties unused inputs off to reduce the number of IO // // Please refer to the Datasheet, Getting Started Guide, and // the Virtex-6 Embedded Tri-Mode Ethernet MAC User Gude for // further information. // // // --------------------------------------------------------------------- // | EXAMPLE DESIGN WRAPPER | // | --------------------------------------------------------| // | |FIFO BLOCK WRAPPER | // | | | // | | | // | | -----------------------------------------| // | | | BLOCK LEVEL WRAPPER | // | | | --------------------- | // | | | | V6 EMAC CORE | | // | | | | | | // | | | | | | // | | | | | | // | | | | | | // | -------- | ---------- | | | | // | | | | | | | | | | // | | |->|->| |--|--->| Tx Tx |-------------->| // | | | | | | | | AXI-S PHY | | // | | ADDR | | | | | | I/F I/F | | // | | SWAP | | | AXI-S | | | | | // | | | | | FIFO | | | | | // | | | | | | | | | | // | | | | | | | | Rx Rx | | // | | | | | | | | AX)-S PHY | | // | | |<-|<-| |<-|----| I/F I/F |<--------------| // | | | | | | | | | | // | -------- | ---------- | --------------------- | // | | | | // | | -----------------------------------------| // | --------------------------------------------------------| // --------------------------------------------------------------------- // //------------------------------------------------------------------------------ `timescale 1 ps/1 ps //------------------------------------------------------------------------------ // The entity declaration for the example_design level wrapper. //------------------------------------------------------------------------------ module v6_emac_v2_3_sgmii_example_design ( // asynchronous reset input glbl_rst, // SGMII-transceiver clock buffer input input mgtclk_n, input mgtclk_p, output phy_resetn, // SGMII interface output txp, output txn, input rxp, input rxn, // MDIO Interface //--------------- inout mdio, input mdc_in, // Serialised statistics vectors //------------------------------ output tx_statistics_s, output rx_statistics_s, // Serialised Pause interface controls //------------------------------------ input pause_req_s, // Main example design controls //----------------------------- input [1:0] mac_speed, input update_speed, input serial_command, output syncacqstatus, input gen_tx_data, input chk_tx_data, input swap_address, input reset_error, output frame_error, output frame_errorn ); // control parameters parameter LOCAL_PHY_ADDR = 5'h1; parameter BOARD_PHY_ADDR = 5'h7; //---------------------------------------------------------------------------- // internal signals used in this top level wrapper. //---------------------------------------------------------------------------- // example design clocks (* KEEP = "TRUE" *) wire gtx_clk_bufg; (* KEEP = "TRUE" *) wire s_axi_aclk; reg phy_resetn_int; // resets (and reset generation) wire chk_reset_int; reg chk_pre_resetn = 0; reg chk_resetn = 0; wire gtx_clk_reset_int; reg gtx_pre_resetn = 0; reg gtx_resetn = 0; wire rx_reset; wire tx_reset; (* KEEP = "TRUE" *) wire clk125_out; wire resetdone_sync; reg [5:0] phy_reset_count; wire glbl_rst_intn; // USER side RX AXI-S interface wire rx_fifo_clock; wire rx_fifo_resetn; wire [7:0] rx_axis_fifo_tdata; wire rx_axis_fifo_tvalid; wire rx_axis_fifo_tlast; wire rx_axis_fifo_tready; // USER side TX AXI-S interface wire tx_fifo_clock; wire tx_fifo_resetn; wire [7:0] tx_axis_fifo_tdata; wire tx_axis_fifo_tvalid; wire tx_axis_fifo_tlast; wire tx_axis_fifo_tready; // RX Statistics serialisation signals (* KEEP = "TRUE" *) wire rx_statistics_valid; reg rx_statistics_valid_reg; (* KEEP = "TRUE" *) wire [27:0] rx_statistics_vector; reg [29:0] rx_stats_shift; // TX Statistics serialisation signals (* KEEP = "TRUE" *) wire tx_statistics_valid; reg tx_statistics_valid_reg; (* KEEP = "TRUE" *) wire [31:0] tx_statistics_vector; reg [33:0] tx_stats_shift; // Pause interface DESerialisation reg [18:0] pause_shift; reg pause_req; reg [15:0] pause_val; wire syncacqstatus_int; (* KEEP = "TRUE" *) wire [79:0] rx_configuration_vector; (* KEEP = "TRUE" *) wire [79:0] tx_configuration_vector; // signal tie offs wire [7:0] tx_ifg_delay = 0; // not used in this example assign frame_errorn = !frame_error; wire mdio_i; wire mdio_o; wire mdio_t; // want to infer an IOBUF on the mdio port assign mdio = mdio_t ? 1'bz : mdio_o; assign mdio_i = mdio; PULLUP mdio_pu ( .O (mdio_i) ); assign syncacqstatus = syncacqstatus_int; // Prevent XST from automatically adding a BUFG to MDC_IN IBUF mdc_in_ibuf ( .I (mdc_in), .O (mdc_in_i) ); //---------------------------------------------------------------------------- // Generate clock logic for the example design //---------------------------------------------------------------------------- // Generate the clock input to the transceiver // (clk_ds can be shared between multiple EMAC instances, including // multiple instantiations of the EMAC wrappers) IBUFDS_GTXE1 clkingen ( .I (mgtclk_p), .IB (mgtclk_n), .CEB (1'b0), .O (clk_ds), .ODIV2 () ); // The 125MHz clock from the transceiver is routed through a BUFG and // input to the MAC wrappers // (clk125 can be shared between multiple EMAC instances, including // multiple instantiations of the EMAC wrappers) BUFG bufg_clk125 ( .I (clk125_out), .O (gtx_clk_bufg) ); // Generate the axi4-lite clock BUFG bufg_axi ( .I (clk125_out), .O (s_axi_aclk) ); assign glbl_rst_intn = !glbl_rst; //---------------------------------------------------------------------------- // Generate the user side clocks for the axi fifos //---------------------------------------------------------------------------- assign tx_fifo_clock = gtx_clk_bufg; assign rx_fifo_clock = gtx_clk_bufg; //---------------------------------------------------------------------------- // Generate resets required for the fifo side signals etc //---------------------------------------------------------------------------- // in each case the async reset is first captured and then synchronised // synchronise the reset done from the GT sync_block syncresetdone ( .clk (gtx_clk_bufg), .data_in (resetdone), .data_out (resetdone_sync) ); //--------------- // gtx_clk reset reset_sync gtx_reset_gen ( .clk (gtx_clk_bufg), .enable (resetdone_sync), .reset_in (glbl_rst || rx_reset || tx_reset), .reset_out (gtx_clk_reset_int) ); // Create fully synchronous reset in the gtx_clk domain. always @(posedge gtx_clk_bufg) begin if (gtx_clk_reset_int) begin gtx_pre_resetn <= 0; gtx_resetn <= 0; end else begin gtx_pre_resetn <= 1; gtx_resetn <= gtx_pre_resetn; end end //--------------- // data check reset reset_sync chk_reset_gen ( .clk (gtx_clk_bufg), .enable (resetdone_sync), .reset_in (glbl_rst || reset_error), .reset_out (chk_reset_int) ); // Create fully synchronous reset in the gtx_clk domain. always @(posedge gtx_clk_bufg) begin if (chk_reset_int) begin chk_pre_resetn <= 0; chk_resetn <= 0; end else begin chk_pre_resetn <= 1; chk_resetn <= chk_pre_resetn; end end //--------------- // PHY reset // the phy reset output (active low) needs to be held for at least 10x25MHZ cycles // this is derived using the 125MHz available and a 6 bit counter always @(posedge gtx_clk_bufg) begin if (!glbl_rst_intn) begin phy_resetn_int <= 1'b0; phy_reset_count <= 6'd0; end else begin if (!(&phy_reset_count)) begin phy_reset_count <= phy_reset_count + 6'd1; end else begin phy_resetn_int <= 1'b1; end end end assign phy_resetn = phy_resetn_int; // generate the user side resets for the axi fifos assign tx_fifo_resetn = gtx_resetn; assign rx_fifo_resetn = gtx_resetn; //---------------------------------------------------------------------------- // Serialize the stats vectors // This is a single bit approach, retimed onto gtx_clk // this code is only present to prevent code being stripped.. //---------------------------------------------------------------------------- // RX STATS // when an update is txd load shifter (plus start/stop bit) // shifter always runs (no power concerns as this is an example design) always @(posedge gtx_clk_bufg) begin rx_statistics_valid_reg <= rx_statistics_valid; if (!rx_statistics_valid_reg & rx_statistics_valid) begin rx_stats_shift <= {1'b1, rx_statistics_vector, 1'b1}; end else begin rx_stats_shift <= {rx_stats_shift[28:0], 1'b0}; end end assign rx_statistics_s = rx_stats_shift[29]; // TX STATS // when an update is txd load shifter (plus start/stop bit) // shifter always runs (no power concerns as this is an example design) always @(posedge gtx_clk_bufg) begin tx_statistics_valid_reg <= tx_statistics_valid; if (!tx_statistics_valid_reg & tx_statistics_valid) begin tx_stats_shift <= {1'b1, tx_statistics_vector, 1'b1}; end else begin tx_stats_shift <= {tx_stats_shift[32:0], 1'b0}; end end assign tx_statistics_s = tx_stats_shift[33]; //---------------------------------------------------------------------------- // DESerialize the Pause interface // This is a single bit approach timed on gtx_clk // this code is only present to prevent code being stripped.. //---------------------------------------------------------------------------- // the serialized pause info has a start bit followed by the quanta and a stop bit // capture the quanta when the start bit hits the msb and the stop bit is in the lsb always @(posedge gtx_clk_bufg) begin pause_shift <= {pause_shift[17:0], pause_req_s}; end always @(posedge gtx_clk_bufg) begin if (pause_shift[18] === 1'b0 & pause_shift[17] === 1'b1 & pause_shift[0] === 1'b1) begin pause_req <= 1'b1; pause_val <= pause_shift[16:1]; end else begin pause_req <= 1'b0; pause_val <= 0; end end //---------------------------------------------------------------------------- // Instantiate the V6 Hard EMAC core fifo block wrapper //---------------------------------------------------------------------------- v6_emac_v2_3_sgmii_fifo_block v6emac_fifo_block ( .gtx_clk (gtx_clk_bufg), .clk125_out (clk125_out), // Receiver Statistics Interface //--------------------------------------- .rx_reset (rx_reset), .rx_statistics_vector (rx_statistics_vector), .rx_statistics_valid (rx_statistics_valid), // Receiver (AXI-S) Interface //---------------------------------------- .rx_fifo_clock (rx_fifo_clock), .rx_fifo_resetn (rx_fifo_resetn), .rx_axis_fifo_tdata (rx_axis_fifo_tdata), .rx_axis_fifo_tvalid (rx_axis_fifo_tvalid), .rx_axis_fifo_tready (rx_axis_fifo_tready), .rx_axis_fifo_tlast (rx_axis_fifo_tlast), // Transmitter Statistics Interface //------------------------------------------ .tx_reset (tx_reset), .tx_ifg_delay (tx_ifg_delay), .tx_statistics_vector (tx_statistics_vector), .tx_statistics_valid (tx_statistics_valid), // Transmitter (AXI-S) Interface //------------------------------------------- .tx_fifo_clock (tx_fifo_clock), .tx_fifo_resetn (tx_fifo_resetn), .tx_axis_fifo_tdata (tx_axis_fifo_tdata), .tx_axis_fifo_tvalid (tx_axis_fifo_tvalid), .tx_axis_fifo_tready (tx_axis_fifo_tready), .tx_axis_fifo_tlast (tx_axis_fifo_tlast), // MAC Control Interface //------------------------ .pause_req (pause_req), .pause_val (pause_val), // SGMII interface .txp (txp), .txn (txn), .rxp (rxp), .rxn (rxn), .phyad (LOCAL_PHY_ADDR), .resetdone (resetdone), .syncacqstatus (syncacqstatus_int), // SGMII transceiver clock buffer input .clk_ds (clk_ds), // MDIO Interface //----------------- .mdio_i (mdio_i), .mdio_o (mdio_o), .mdio_t (mdio_t), .mdc_in (mdc_in_i), // asynchronous reset .glbl_rstn (glbl_rst_intn), .rx_axi_rstn (1'b1), .tx_axi_rstn (1'b1) ); //---------------------------------------------------------------------------- // Instantiate the address swapping module and simple pattern generator //---------------------------------------------------------------------------- basic_pat_gen basic_pat_gen ( .axi_tclk (tx_fifo_clock), .axi_tresetn (tx_fifo_resetn), .check_resetn (chk_resetn), .enable_pat_gen (gen_tx_data), .enable_pat_chk (chk_tx_data), .enable_address_swap (swap_address), .rx_axis_fifo_tdata (rx_axis_fifo_tdata), .rx_axis_fifo_tvalid (rx_axis_fifo_tvalid), .rx_axis_fifo_tlast (rx_axis_fifo_tlast), .rx_axis_fifo_tready (rx_axis_fifo_tready), .tx_axis_fifo_tdata (tx_axis_fifo_tdata), .tx_axis_fifo_tvalid (tx_axis_fifo_tvalid), .tx_axis_fifo_tlast (tx_axis_fifo_tlast), .tx_axis_fifo_tready (tx_axis_fifo_tready), .frame_error (frame_error) ); endmodule