diff options
Diffstat (limited to 'fpga/usrp3/top/e320/n3xx_sfp_wrapper.v')
-rw-r--r-- | fpga/usrp3/top/e320/n3xx_sfp_wrapper.v | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/fpga/usrp3/top/e320/n3xx_sfp_wrapper.v b/fpga/usrp3/top/e320/n3xx_sfp_wrapper.v new file mode 100644 index 000000000..5067b1727 --- /dev/null +++ b/fpga/usrp3/top/e320/n3xx_sfp_wrapper.v @@ -0,0 +1,484 @@ +/////////////////////////////////////////////////////////////////// +// +// Copyright 2017 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: n3xx_sfp_wrapper +// Description: +// Reduces clutter at top level. +// - Aurora: wraps up sfpp_io, axil_regport and axi_dummy +// - 1/10G: wrapper around network interface +// +////////////////////////////////////////////////////////////////////// + +module n3xx_sfp_wrapper #( + parameter PROTOCOL = "10GbE", // Must be {10GbE, 1GbE, Aurora, Disabled} + parameter DWIDTH = 32, + parameter AWIDTH = 14, + parameter [7:0] PORTNUM = 8'd0, + parameter MDIO_EN = 0, + parameter [4:0] MDIO_PHYADDR = 5'd0, + parameter [15:0] RFNOC_PROTOVER = {8'd1, 8'd0} +)( + // Resets + input areset, + input bus_rst, + + // Clocks + input gt_refclk, + input gb_refclk, + input misc_clk, + input bus_clk, + // FIXME: Merge E320 and N310 files + input user_clk, + input sync_clk, + + //Axi-lite + input s_axi_aclk, + input s_axi_aresetn, + input [AWIDTH-1:0] s_axi_awaddr, + input s_axi_awvalid, + output s_axi_awready, + + input [DWIDTH-1:0] s_axi_wdata, + input [DWIDTH/8-1:0] s_axi_wstrb, + input s_axi_wvalid, + output s_axi_wready, + + output [1:0] s_axi_bresp, + output s_axi_bvalid, + input s_axi_bready, + + input [AWIDTH-1:0] s_axi_araddr, + input s_axi_arvalid, + output s_axi_arready, + + output [DWIDTH-1:0] s_axi_rdata, + output [1:0] s_axi_rresp, + output s_axi_rvalid, + input s_axi_rready, + + // SFP high-speed IO + output txp, + output txn, + input rxp, + input rxn, + + // SFP low-speed IO + input sfpp_present_n, + input sfpp_rxlos, + input sfpp_tx_fault, + output sfpp_tx_disable, + + //GT Common + input qpllrefclklost, + input qplllock, + input qplloutclk, + input qplloutrefclk, + output qpllreset, + + //Aurora MMCM + input mmcm_locked, + output gt_pll_lock, + output gt_tx_out_clk_unbuf, + + // Vita router interface + output [63:0] e2v_tdata, + output e2v_tlast, + output e2v_tvalid, + input e2v_tready, + + input [63:0] v2e_tdata, + input v2e_tlast, + input v2e_tvalid, + output v2e_tready, + + // CPU + output [63:0] e2c_tdata, + output [7:0] e2c_tkeep, + output e2c_tlast, + output e2c_tvalid, + input e2c_tready, + + input [63:0] c2e_tdata, + input [7:0] c2e_tkeep, + input c2e_tlast, + input c2e_tvalid, + output c2e_tready, + + // MISC + output [31:0] port_info, + input [15:0] device_id, + + // Timebase Outputs + output sfp_pps, + output sfp_refclk, + + // Sideband White Rabbit Control + input wr_reset_n, + input wr_refclk, + + output wr_dac_sclk, + output wr_dac_din, + output wr_dac_clr_n, + output wr_dac_cs_n, + output wr_dac_ldac_n, + + output wr_eeprom_scl_o, + input wr_eeprom_scl_i, + output wr_eeprom_sda_o, + input wr_eeprom_sda_i, + + input wr_uart_rx, + output wr_uart_tx, + + // WR AXI Control + output wr_axi_aclk, + input wr_axi_aresetn, + input [31:0] wr_axi_awaddr, + input wr_axi_awvalid, + output wr_axi_awready, + input [DWIDTH-1:0] wr_axi_wdata, + input [DWIDTH/8-1:0] wr_axi_wstrb, + input wr_axi_wvalid, + output wr_axi_wready, + output [1:0] wr_axi_bresp, + output wr_axi_bvalid, + input wr_axi_bready, + input [31:0] wr_axi_araddr, + input wr_axi_arvalid, + output wr_axi_arready, + output [DWIDTH-1:0] wr_axi_rdata, + output [1:0] wr_axi_rresp, + output wr_axi_rvalid, + input wr_axi_rready, + output wr_axi_rlast, + + output link_up, + output activity + +); + + localparam REG_BASE_SFP_IO = 14'h0; + localparam REG_BASE_ETH_SWITCH = 14'h1000; + + // AXI4-Lite to RegPort (PS to PL Register Access) + wire reg_wr_req; + wire [AWIDTH-1:0] reg_wr_addr; + wire [DWIDTH-1:0] reg_wr_data; + wire reg_rd_req; + wire [AWIDTH-1:0] reg_rd_addr; + wire reg_rd_resp, reg_rd_resp_io, reg_rd_resp_eth_if; + wire [DWIDTH-1:0] reg_rd_data, reg_rd_data_io, reg_rd_data_eth_if; + + axil_regport_master #( + .DWIDTH (DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .AWIDTH (AWIDTH), // Width of the address bus + .WRBASE (0), // Write address base + .RDBASE (0), // Read address base + .TIMEOUT (10) // log2(timeout). Read will timeout after (2^TIMEOUT - 1) cycles + ) sfp_reg_mst_i ( + // Clock and reset + .s_axi_aclk (s_axi_aclk), + .s_axi_aresetn (s_axi_aresetn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr (s_axi_awaddr), + .s_axi_awvalid (s_axi_awvalid), + .s_axi_awready (s_axi_awready), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata (s_axi_wdata), + .s_axi_wstrb (s_axi_wstrb), + .s_axi_wvalid (s_axi_wvalid), + .s_axi_wready (s_axi_wready), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp (s_axi_bresp), + .s_axi_bvalid (s_axi_bvalid), + .s_axi_bready (s_axi_bready), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr (s_axi_araddr), + .s_axi_arvalid (s_axi_arvalid), + .s_axi_arready (s_axi_arready), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata (s_axi_rdata), + .s_axi_rresp (s_axi_rresp), + .s_axi_rvalid (s_axi_rvalid), + .s_axi_rready (s_axi_rready), + // Register port: Write port (domain: reg_clk) + .reg_clk (bus_clk), + .reg_wr_req (reg_wr_req), + .reg_wr_addr (reg_wr_addr), + .reg_wr_data (reg_wr_data), + // Register port: Read port (domain: reg_clk) + .reg_rd_req (reg_rd_req), + .reg_rd_addr (reg_rd_addr), + .reg_rd_resp (reg_rd_resp), + .reg_rd_data (reg_rd_data) + ); + + // Regport Mux for response + regport_resp_mux #( + .WIDTH (DWIDTH), + .NUM_SLAVES (2) + ) reg_resp_mux_i ( + .clk(bus_clk), .reset(bus_rst), + .sla_rd_resp({reg_rd_resp_eth_if, reg_rd_resp_io}), + .sla_rd_data({reg_rd_data_eth_if, reg_rd_data_io}), + .mst_rd_resp(reg_rd_resp), .mst_rd_data(reg_rd_data) + ); + + wire [63:0] sfpo_tdata, sfpi_tdata; + wire [3:0] sfpo_tuser, sfpi_tuser; + wire sfpo_tlast, sfpi_tlast, sfpo_tvalid, sfpi_tvalid, sfpo_tready, sfpi_tready; + + generate + if (PROTOCOL != "WhiteRabbit") begin + n3xx_mgt_io_core #( + .PROTOCOL (PROTOCOL), + .REG_BASE (REG_BASE_SFP_IO), + .REG_DWIDTH (DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH (AWIDTH), // Width of the address bus + .MDIO_EN (MDIO_EN), + .MDIO_PHYADDR (MDIO_PHYADDR), + .PORTNUM (PORTNUM) + ) mgt_io_i ( + //must reset all channels on quad when sfp1 gtx core is reset + .areset (areset), + .gt_refclk (gt_refclk), + .gb_refclk (gb_refclk), + .misc_clk (misc_clk), + + .bus_rst (bus_rst), + .bus_clk (bus_clk), + + .txp (txp), + .txn (txn), + .rxp (rxp), + .rxn (rxn), + + .sfpp_rxlos (sfpp_rxlos), + .sfpp_tx_fault (sfpp_tx_fault), + .sfpp_tx_disable(sfpp_tx_disable), + + //RegPort + .reg_wr_req (reg_wr_req), + .reg_wr_addr (reg_wr_addr), + .reg_wr_data (reg_wr_data), + .reg_rd_req (reg_rd_req), + .reg_rd_addr (reg_rd_addr), + .reg_rd_resp (reg_rd_resp_io), + .reg_rd_data (reg_rd_data_io), + + // Vita to Ethernet + .s_axis_tdata (sfpi_tdata), + .s_axis_tuser (sfpi_tuser), + .s_axis_tlast (sfpi_tlast), + .s_axis_tvalid (sfpi_tvalid), + .s_axis_tready (sfpi_tready), + + // Ethernet to Vita + .m_axis_tdata (sfpo_tdata), + .m_axis_tuser (sfpo_tuser), + .m_axis_tlast (sfpo_tlast), + .m_axis_tvalid (sfpo_tvalid), + .m_axis_tready (sfpo_tready), + + .port_info (port_info), + .link_up (link_up), + .activity (activity) + ); + + end else begin + //--------------------------------------------------------------------------------- + // White Rabbit + //--------------------------------------------------------------------------------- + + wire wr_sfp_scl, wr_sfp_sda_o, wr_sfp_sda_i; + + n3xx_wr_top #( + .g_simulation(1'b0), // in std_logic + .g_dpram_size(131072/4), + .g_dpram_initf("../../../../bin/wrpc/wrc_phy16.bram") + ) wr_inst ( + .areset_n_i (wr_reset_n), // in std_logic; -- active low reset, optional + .wr_refclk_buf_i (wr_refclk), // in std_logic; -- 20MHz VCXO after IBUFGDS + .gige_refclk_buf_i (gt_refclk), // in std_logic; -- 125 MHz MGT Ref after IBUFDS_GTE2 + .dac_sclk_o (wr_dac_sclk), // out std_logic; -- N3xx cWB-DAC-SCLK + .dac_din_o (wr_dac_din), // out std_logic; -- N3xx cWB-DAC-DIN + .dac_clr_n_o (wr_dac_clr_n), // out std_logic; -- N3xx cWB-DAC-nCLR + .dac_cs_n_o (wr_dac_cs_n), // out std_logic; -- N3xx cWB-DAC-nSYNC + .dac_ldac_n_o (wr_dac_ldac_n), // out std_logic; -- N3xx cWB-DAC-nLDAC + .LED_ACT (activity), // out std_logic; -- connect to SFP+ ACT + .LED_LINK (link_up), // out std_logic; -- connect to SFP+ LINK + .sfp_txp_o (txp), // out std_logic; + .sfp_txn_o (txn), // out std_logic; + .sfp_rxp_i (rxp), // in std_logic; + .sfp_rxn_i (rxn), // in std_logic; + .sfp_mod_def0_b (sfpp_present_n), // in std_logic; - sfp detect + .eeprom_scl_o (wr_eeprom_scl_o), + .eeprom_scl_i (wr_eeprom_scl_i), + .eeprom_sda_o (wr_eeprom_sda_o), + .eeprom_sda_i (wr_eeprom_sda_i), + .sfp_scl_o (wr_sfp_scl), + .sfp_scl_i (wr_sfp_scl), + .sfp_sda_o (wr_sfp_sda_o), + .sfp_sda_i (wr_sfp_sda_i), + .sfp_tx_fault_i (sfpp_tx_fault), // in std_logic; + .sfp_tx_disable_o (sfpp_tx_disable), // out std_logic; + .sfp_los_i (sfpp_rxlos), // in std_logic; + .wr_uart_rxd (wr_uart_rx), // in std_logic; + .wr_uart_txd (wr_uart_tx), // out std_logic; + + .s00_axi_aclk_o (wr_axi_aclk), + .s00_axi_aresetn (wr_axi_aresetn), + .s00_axi_awaddr (wr_axi_awaddr), + .s00_axi_awprot (3'b0), + .s00_axi_awvalid (wr_axi_awvalid), + .s00_axi_awready (wr_axi_awready), + .s00_axi_wdata (wr_axi_wdata), + .s00_axi_wstrb (wr_axi_wstrb), + .s00_axi_wvalid (wr_axi_wvalid), + .s00_axi_wready (wr_axi_wready), + .s00_axi_bresp (wr_axi_bresp), + .s00_axi_bvalid (wr_axi_bvalid), + .s00_axi_bready (wr_axi_bready), + .s00_axi_araddr (wr_axi_araddr), + .s00_axi_arprot (3'b0), + .s00_axi_arvalid (wr_axi_arvalid), + .s00_axi_arready (wr_axi_arready), + .s00_axi_rdata (wr_axi_rdata), + .s00_axi_rresp (wr_axi_rresp), + .s00_axi_rvalid (wr_axi_rvalid), + .s00_axi_rready (wr_axi_rready), + .s00_axi_rlast (wr_axi_rlast), + .axi_int_o (), + + .pps_o (sfp_pps), // out std_logic; + .clk_pps_o (sfp_refclk), // out std_logic; + .link_ok_o (), // out std_logic; + .clk_sys_locked_o (), // out std_logic; + .clk_dmtd_locked_o (), // out std_logic); + .wr_debug0_o (), + .wr_debug1_o () + ); + + // TEMPORARY mimic the AXGE SFP EEROM + sfp_eeprom sfp_eeprom_i ( + .clk_i(bus_clk), + .sfp_scl(wr_sfp_scl), + .sfp_sda_i(wr_sfp_sda_o), + .sfp_sda_o(wr_sfp_sda_i)); + + // Assign the port_info vector similarly to mgt_io_core + localparam [7:0] COMPAT_NUM = 8'd2; + localparam [7:0] MGT_PROTOCOL = 8'd4; + assign port_info = {COMPAT_NUM, 6'h0, activity, link_up, MGT_PROTOCOL, PORTNUM}; + + // Tie off unused outputs. + assign gt_pll_lock = 1'b0; + assign gt_tx_out_clk_unbuf = 1'b0; + end + endgenerate + + generate + // Tie off the Ethernet switch for these protocols that do not use it. + if(PROTOCOL == "Aurora" || PROTOCOL == "Disabled" || PROTOCOL == "WhiteRabbit") begin + + //set unused wires to default value + assign e2c_tdata = 64'h0; + assign e2c_tkeep = 8'h0; + assign e2c_tlast = 1'b0; + assign e2c_tvalid = 1'b0; + assign c2e_tready = 1'b1; + + assign reg_rd_resp_eth_if = 1'b0; + assign reg_rd_data_eth_if = 'h0; + + end else begin + + wire [3:0] e2c_tuser; + wire [3:0] c2e_tuser; + + // In AXI Stream, tkeep is the byte qualifier that indicates + // whether the content of the associated byte + // of TDATA is processed as part of the data stream. + // tuser as used in eth_interface is the number of valid bytes + + // Converting tuser to tkeep for ingress packets + assign e2c_tkeep = ~e2c_tlast ? 8'b1111_1111 + : (e2c_tuser == 4'd0) ? 8'b1111_1111 + : (e2c_tuser == 4'd1) ? 8'b0000_0001 + : (e2c_tuser == 4'd2) ? 8'b0000_0011 + : (e2c_tuser == 4'd3) ? 8'b0000_0111 + : (e2c_tuser == 4'd4) ? 8'b0000_1111 + : (e2c_tuser == 4'd5) ? 8'b0001_1111 + : (e2c_tuser == 4'd6) ? 8'b0011_1111 + : 8'b0111_1111; + + // Converting tkeep to tuser for egress packets + assign c2e_tuser = ~c2e_tlast ? 4'd0 + : (c2e_tkeep == 8'b1111_1111) ? 4'd0 + : (c2e_tkeep == 8'b0111_1111) ? 4'd7 + : (c2e_tkeep == 8'b0011_1111) ? 4'd6 + : (c2e_tkeep == 8'b0001_1111) ? 4'd5 + : (c2e_tkeep == 8'b0000_1111) ? 4'd4 + : (c2e_tkeep == 8'b0000_0111) ? 4'd3 + : (c2e_tkeep == 8'b0000_0011) ? 4'd2 + : (c2e_tkeep == 8'b0000_0001) ? 4'd1 + : 4'd0; + + + eth_interface #( + .PROTOVER (RFNOC_PROTOVER), + .MTU (10), + .NODE_INST (0), + .REG_AWIDTH (AWIDTH), + .BASE (REG_BASE_ETH_SWITCH) + ) eth_interface ( + .clk (bus_clk), + .reset (bus_rst), + .device_id (device_id), + .reg_wr_req (reg_wr_req), + .reg_wr_addr (reg_wr_addr), + .reg_wr_data (reg_wr_data), + .reg_rd_req (reg_rd_req), + .reg_rd_addr (reg_rd_addr), + .reg_rd_resp (reg_rd_resp_eth_if), + .reg_rd_data (reg_rd_data_eth_if), + .my_mac (), + .my_ip (), + .my_udp_port (), + .eth_tx_tdata (sfpi_tdata), + .eth_tx_tuser (sfpi_tuser), + .eth_tx_tlast (sfpi_tlast), + .eth_tx_tvalid (sfpi_tvalid), + .eth_tx_tready (sfpi_tready), + .eth_rx_tdata (sfpo_tdata), + .eth_rx_tuser (sfpo_tuser), + .eth_rx_tlast (sfpo_tlast), + .eth_rx_tvalid (sfpo_tvalid), + .eth_rx_tready (sfpo_tready), + .e2v_tdata (e2v_tdata), + .e2v_tlast (e2v_tlast), + .e2v_tvalid (e2v_tvalid), + .e2v_tready (e2v_tready), + .v2e_tdata (v2e_tdata), + .v2e_tlast (v2e_tlast), + .v2e_tvalid (v2e_tvalid), + .v2e_tready (v2e_tready), + .e2c_tdata (e2c_tdata), + .e2c_tuser (e2c_tuser), + .e2c_tlast (e2c_tlast), + .e2c_tvalid (e2c_tvalid), + .e2c_tready (e2c_tready), + .c2e_tdata (c2e_tdata), + .c2e_tuser (c2e_tuser), + .c2e_tlast (c2e_tlast), + .c2e_tvalid (c2e_tvalid), + .c2e_tready (c2e_tready) + ); + + end + endgenerate + +endmodule // n310_sfp_wrapper |