diff options
author | Martin Braun <martin.braun@ettus.com> | 2020-01-23 16:10:22 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2020-01-28 09:35:36 -0800 |
commit | bafa9d95453387814ef25e6b6256ba8db2df612f (patch) | |
tree | 39ba24b5b67072d354775272e687796bb511848d /fpga/usrp3/lib/rfnoc/xport/eth_internal.v | |
parent | 3075b981503002df3115d5f1d0b97d2619ba30f2 (diff) | |
download | uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2 uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip |
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce
the size of the repository. However, over the last half-decade, the
split between the repositories has proven more burdensome than it has
been helpful. By merging the FPGA code back, it will be possible to
create atomic commits that touch both FPGA and UHD codebases. Continuous
integration testing is also simplified by merging the repositories,
because it was previously difficult to automatically derive the correct
UHD branch when testing a feature branch on the FPGA repository.
This commit also updates the license files and paths therein.
We are therefore merging the repositories again. Future development for
FPGA code will happen in the same repository as the UHD host code and
MPM code.
== Original Codebase and Rebasing ==
The original FPGA repository will be hosted for the foreseeable future
at its original local location: https://github.com/EttusResearch/fpga/
It can be used for bisecting, reference, and a more detailed history.
The final commit from said repository to be merged here is
05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as
v4.0.0.0-pre-uhd-merge.
If you have changes in the FPGA repository that you want to rebase onto
the UHD repository, simply run the following commands:
- Create a directory to store patches (this should be an empty
directory):
mkdir ~/patches
- Now make sure that your FPGA codebase is based on the same state as
the code that was merged:
cd src/fpga # Or wherever your FPGA code is stored
git rebase v4.0.0.0-pre-uhd-merge
Note: The rebase command may look slightly different depending on what
exactly you're trying to rebase.
- Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge:
git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches
Note: Make sure that only patches are stored in your output directory.
It should otherwise be empty. Make sure that you picked the correct
range of commits, and only commits you wanted to rebase were exported
as patch files.
- Go to the UHD repository and apply the patches:
cd src/uhd # Or wherever your UHD repository is stored
git am --directory fpga ~/patches/*
rm -rf ~/patches # This is for cleanup
== Contributors ==
The following people have contributed mainly to these files (this list
is not complete):
Co-authored-by: Alex Williams <alex.williams@ni.com>
Co-authored-by: Andrej Rode <andrej.rode@ettus.com>
Co-authored-by: Ashish Chaudhari <ashish@ettus.com>
Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com>
Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Derek Kozel <derek.kozel@ettus.com>
Co-authored-by: EJ Kreinar <ej@he360.com>
Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com>
Co-authored-by: Ian Buckley <ian.buckley@gmail.com>
Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Jon Kiser <jon.kiser@ni.com>
Co-authored-by: Josh Blum <josh@joshknows.com>
Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com>
Co-authored-by: Martin Braun <martin.braun@ettus.com>
Co-authored-by: Matt Ettus <matt@ettus.com>
Co-authored-by: Michael West <michael.west@ettus.com>
Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com>
Co-authored-by: Nick Foster <nick@ettus.com>
Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Paul David <paul.david@ettus.com>
Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com>
Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com>
Co-authored-by: Sylvain Munaut <tnt@246tNt.com>
Co-authored-by: Trung Tran <trung.tran@ettus.com>
Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/xport/eth_internal.v')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/xport/eth_internal.v | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/xport/eth_internal.v b/fpga/usrp3/lib/rfnoc/xport/eth_internal.v new file mode 100644 index 000000000..49cf838a5 --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/xport/eth_internal.v @@ -0,0 +1,433 @@ +/////////////////////////////////////////////////////////////////// +// +// Copyright 2019 Ettus Research, a National Instruments brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: eth_internal +// Description: +// Reduces clutter at top level. +// - FPGA-internal Ethernet port +// - ARP responder instead of other CPU connection +// +////////////////////////////////////////////////////////////////////// + +`default_nettype none +module eth_internal #( + parameter DWIDTH = 32, + parameter AWIDTH = 14, + parameter [7:0] PORTNUM = 0, + parameter [15:0] RFNOC_PROTOVER = {8'd1, 8'd0} +)( + // Resets + input wire bus_rst, + + // Clocks + input wire bus_clk, + + //Axi-lite + input wire s_axi_aclk, + input wire s_axi_aresetn, + input wire [AWIDTH-1:0] s_axi_awaddr, + input wire s_axi_awvalid, + output wire s_axi_awready, + + input wire [DWIDTH-1:0] s_axi_wdata, + input wire [DWIDTH/8-1:0] s_axi_wstrb, + input wire s_axi_wvalid, + output wire s_axi_wready, + + output wire [1:0] s_axi_bresp, + output wire s_axi_bvalid, + input wire s_axi_bready, + + input wire [AWIDTH-1:0] s_axi_araddr, + input wire s_axi_arvalid, + output wire s_axi_arready, + + output wire [DWIDTH-1:0] s_axi_rdata, + output wire [1:0] s_axi_rresp, + output wire s_axi_rvalid, + input wire s_axi_rready, + + // Host-Ethernet DMA interface + output wire [63:0] e2h_tdata, + output wire [7:0] e2h_tkeep, + output wire e2h_tlast, + output wire e2h_tvalid, + input wire e2h_tready, + + input wire [63:0] h2e_tdata, + input wire [7:0] h2e_tkeep, + input wire h2e_tlast, + input wire h2e_tvalid, + output wire h2e_tready, + + // RFNoC interface + output wire [63:0] e2v_tdata, + output wire e2v_tlast, + output wire e2v_tvalid, + input wire e2v_tready, + + input wire [63:0] v2e_tdata, + input wire v2e_tlast, + input wire v2e_tvalid, + output wire v2e_tready, + + // MISC + output wire [31:0] port_info, + input wire [15:0] device_id, + + output wire link_up, + output reg activity + +); + + localparam REG_BASE_ETH_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_eth_if; + reg reg_rd_resp_io = 1'b0; + wire [DWIDTH-1:0] reg_rd_data, reg_rd_data_eth_if; + reg [DWIDTH-1:0] reg_rd_data_io = 'd0; + + 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 + ) eth_dma_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) + ); + + // ARP responder + wire [63:0] e2c_tdata; + wire [7:0] e2c_tkeep; + wire e2c_tlast; + wire e2c_tvalid; + wire e2c_tready; + + wire [63:0] c2e_tdata; + wire [7:0] c2e_tkeep; + wire c2e_tlast; + wire c2e_tvalid; + wire c2e_tready; + + wire [3:0] e2c_tuser; + wire [3:0] c2e_tuser; + + // ARM Host-to-Ethernet + wire [3:0] e2h_tuser; + wire [3:0] h2e_tuser; + + // Host Ethernet-to-CHDR + wire [63:0] h2e_chdr_tdata; + wire [3:0] h2e_chdr_tuser; + wire h2e_chdr_tlast; + wire h2e_chdr_tvalid; + wire h2e_chdr_tready; + wire [63:0] e2h_chdr_tdata; + wire [3:0] e2h_chdr_tuser; + wire e2h_chdr_tlast; + wire e2h_chdr_tvalid; + wire e2h_chdr_tready; + + + // 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; + + // Converting tuser to tkeep for ingress packets + assign e2h_tkeep = ~e2h_tlast ? 8'b1111_1111 + : (e2h_tuser == 4'd0) ? 8'b1111_1111 + : (e2h_tuser == 4'd1) ? 8'b0000_0001 + : (e2h_tuser == 4'd2) ? 8'b0000_0011 + : (e2h_tuser == 4'd3) ? 8'b0000_0111 + : (e2h_tuser == 4'd4) ? 8'b0000_1111 + : (e2h_tuser == 4'd5) ? 8'b0001_1111 + : (e2h_tuser == 4'd6) ? 8'b0011_1111 + : 8'b0111_1111; + + // Converting tkeep to tuser for egress packets + assign h2e_tuser = ~h2e_tlast ? 4'd0 + : (h2e_tkeep == 8'b1111_1111) ? 4'd0 + : (h2e_tkeep == 8'b0111_1111) ? 4'd7 + : (h2e_tkeep == 8'b0011_1111) ? 4'd6 + : (h2e_tkeep == 8'b0001_1111) ? 4'd5 + : (h2e_tkeep == 8'b0000_1111) ? 4'd4 + : (h2e_tkeep == 8'b0000_0111) ? 4'd3 + : (h2e_tkeep == 8'b0000_0011) ? 4'd2 + : (h2e_tkeep == 8'b0000_0001) ? 4'd1 + : 4'd0; + + // FPGA-side addresses for the ARP responder + wire [47:0] my_mac; + wire [31:0] my_ip; + wire [15:0] my_udp_port; + + arm_deframer arm_deframer_i ( + .clk(bus_clk), + .reset(bus_rst), + .clear(1'b0), + .s_axis_tdata(h2e_tdata), + .s_axis_tuser(h2e_tuser), + .s_axis_tlast(h2e_tlast), + .s_axis_tvalid(h2e_tvalid), + .s_axis_tready(h2e_tready), + .m_axis_tdata(h2e_chdr_tdata), + .m_axis_tuser(h2e_chdr_tuser), + .m_axis_tlast(h2e_chdr_tlast), + .m_axis_tvalid(h2e_chdr_tvalid), + .m_axis_tready(h2e_chdr_tready) + ); + + axi64_to_xge64 arm_framer ( + .clk(bus_clk), + .reset(bus_rst), + .clear(1'b0), + .s_axis_tdata(e2h_chdr_tdata), + .s_axis_tuser(e2h_chdr_tuser), + .s_axis_tlast(e2h_chdr_tlast), + .s_axis_tvalid(e2h_chdr_tvalid), + .s_axis_tready(e2h_chdr_tready), + .m_axis_tdata(e2h_tdata), + .m_axis_tuser(e2h_tuser), + .m_axis_tlast(e2h_tlast), + .m_axis_tvalid(e2h_tvalid), + .m_axis_tready(e2h_tready) + ); + + 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_mac), + .my_ip (my_ip), + .my_udp_port (my_udp_port), + .eth_tx_tdata (e2h_chdr_tdata), + .eth_tx_tuser (e2h_chdr_tuser), + .eth_tx_tlast (e2h_chdr_tlast), + .eth_tx_tvalid (e2h_chdr_tvalid), + .eth_tx_tready (e2h_chdr_tready), + .eth_rx_tdata (h2e_chdr_tdata), + .eth_rx_tuser (h2e_chdr_tuser), + .eth_rx_tlast (h2e_chdr_tlast), + .eth_rx_tvalid (h2e_chdr_tvalid), + .eth_rx_tready (h2e_chdr_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) + ); + + arp_responder arp_responder_i ( + .aclk (bus_clk), + .aresetn (~bus_rst), + .mac_addr (my_mac), + .ip_addr (my_ip), + .s_axis_tdata (e2c_tdata), + .s_axis_tvalid (e2c_tvalid), + .s_axis_tready (e2c_tready), + .s_axis_tkeep (e2c_tkeep), + .s_axis_tlast (e2c_tlast), + .s_axis_tuser (1'b0), + .m_axis_tdata (c2e_tdata), + .m_axis_tvalid (c2e_tvalid), + .m_axis_tready (c2e_tready), + .m_axis_tkeep (c2e_tkeep), + .m_axis_tlast (c2e_tlast), + .m_axis_tuser () + ); + + //----------------------------------------------------------------- + // "I/O" Registers + //----------------------------------------------------------------- + localparam [7:0] COMPAT_NUM = 8'd2; + localparam [7:0] MGT_PROTOCOL = 8'd4; // 10 GbE Internal (8'd2 is 10 GbE External) + + // Common registers + localparam REG_PORT_INFO = REG_BASE_ETH_IO + 'h0; + localparam REG_MAC_CTRL_STATUS = REG_BASE_ETH_IO + 'h4; + localparam REG_PHY_CTRL_STATUS = REG_BASE_ETH_IO + 'h8; + localparam REG_MAC_LED_CTL = REG_BASE_ETH_IO + 'hC; + + // Protocol specific constants + localparam [1:0] MAC_LED_CTL_RST_VAL = 2'h0; + + localparam [31:0] MAC_CTRL_RST_VAL = {31'h0, 1'b1}; // tx_enable on reset + localparam [31:0] PHY_CTRL_RST_VAL = 32'h0; + + // Writable registers + reg [31:0] mac_ctrl_reg = MAC_CTRL_RST_VAL; + reg [31:0] phy_ctrl_reg = PHY_CTRL_RST_VAL; + reg [1:0] mac_led_ctl = MAC_LED_CTL_RST_VAL; + + always @(posedge bus_clk) begin + if (bus_rst) begin + mac_ctrl_reg <= MAC_CTRL_RST_VAL; + phy_ctrl_reg <= PHY_CTRL_RST_VAL; + mac_led_ctl <= MAC_LED_CTL_RST_VAL; + end else if (reg_wr_req) begin + case(reg_wr_addr) + REG_MAC_CTRL_STATUS: + mac_ctrl_reg <= reg_wr_data; + REG_PHY_CTRL_STATUS: + phy_ctrl_reg <= reg_wr_data; + REG_MAC_LED_CTL: + mac_led_ctl <= reg_wr_data[1:0]; + endcase + end + end + + // Readable registers + wire [31:0] mac_status, phy_status; + + assign port_info = {COMPAT_NUM, 6'h0, activity, link_up, MGT_PROTOCOL, PORTNUM}; + + always @(posedge bus_clk) begin + // No reset handling needed for readback + if (reg_rd_req) begin + reg_rd_resp_io <= 1'b1; + case(reg_rd_addr) + REG_PORT_INFO: + reg_rd_data_io <= port_info; + REG_MAC_CTRL_STATUS: + reg_rd_data_io <= mac_status; + REG_PHY_CTRL_STATUS: + reg_rd_data_io <= phy_status; + REG_MAC_LED_CTL: + reg_rd_data_io <= {30'd0, mac_led_ctl}; + default: + reg_rd_resp_io <= 1'b0; + endcase + end if (reg_rd_resp_io) begin + reg_rd_resp_io <= 1'b0; + end + end + + assign mac_status = 'd0; + assign phy_status[31:8] = 24'h0; + assign link_up = 1'b1; + + wire identify_enable = mac_led_ctl[0]; + wire identify_value = mac_led_ctl[1]; + + //----------------------------------------------------------------- + // Activity detector + //----------------------------------------------------------------- + wire activity_int; + + pulse_stretch act_pulse_str_i ( + .clk(bus_clk), + .rst(bus_rst | ~link_up), + .pulse((h2e_tvalid & h2e_tready) | (e2h_tvalid & e2h_tready)), + .pulse_stretched(activity_int) + ); + + always @ (posedge bus_clk) activity <= identify_enable ? identify_value : activity_int; + +endmodule +`default_nettype wire |