diff options
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/xport/eth_interface.v')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/xport/eth_interface.v | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/xport/eth_interface.v b/fpga/usrp3/lib/rfnoc/xport/eth_interface.v new file mode 100644 index 000000000..21e8b809d --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/xport/eth_interface.v @@ -0,0 +1,252 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Adapts from internal VITA to ethernet packets. Also handles CPU and ethernet crossover interfaces. + +module eth_interface #( + parameter [15:0] PROTOVER = {8'd1, 8'd0}, + parameter MTU = 10, + parameter NODE_INST = 0, + parameter RT_TBL_SIZE = 6, + parameter REG_AWIDTH = 14, + parameter BASE = 0 +) ( + input clk, + input reset, + input [15:0] device_id, + + // Register port: Write port (domain: clk) + input reg_wr_req, + input [REG_AWIDTH-1:0] reg_wr_addr, + input [31:0] reg_wr_data, + + // Register port: Read port (domain: clk) + input reg_rd_req, + input [REG_AWIDTH-1:0] reg_rd_addr, + output reg reg_rd_resp, + output reg [31:0] reg_rd_data, + + // Status ports (domain: clk) + output [47:0] my_mac, + output [31:0] my_ip, + output [15:0] my_udp_port, + + // Ethernet ports + output [63:0] eth_tx_tdata, + output [3:0] eth_tx_tuser, + output eth_tx_tlast, + output eth_tx_tvalid, + input eth_tx_tready, + input [63:0] eth_rx_tdata, + input [3:0] eth_rx_tuser, + input eth_rx_tlast, + input eth_rx_tvalid, + output eth_rx_tready, + + // 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 [3:0] e2c_tuser, + output e2c_tlast, + output e2c_tvalid, + input e2c_tready, + input [63:0] c2e_tdata, + input [3:0] c2e_tuser, + input c2e_tlast, + input c2e_tvalid, + output c2e_tready +); + + localparam [47:0] DEFAULT_MAC_ADDR = {8'h00, 8'h80, 8'h2f, 8'h16, 8'hc5, 8'h2f}; + localparam [31:0] DEFAULT_IP_ADDR = {8'd192, 8'd168, 8'd10, 8'd2}; + localparam [31:0] DEFAULT_UDP_PORT = 16'd49153; + + //--------------------------------------------------------- + // Registers + //--------------------------------------------------------- + + // Allocate one full page for MAC + localparam [REG_AWIDTH-1:0] REG_MAC_LSB = BASE + 'h0000; + localparam [REG_AWIDTH-1:0] REG_MAC_MSB = BASE + 'h0004; + + // Source IP address + localparam [REG_AWIDTH-1:0] REG_IP = BASE + 'h1000; + // Source UDP Port + localparam [REG_AWIDTH-1:0] REG_UDP = BASE + 'h1004; + + // Registers for Internal/Bridge Network Mode in CPU + localparam [REG_AWIDTH-1:0] REG_BRIDGE_MAC_LSB = BASE + 'h1010; + localparam [REG_AWIDTH-1:0] REG_BRIDGE_MAC_MSB = BASE + 'h1014; + localparam [REG_AWIDTH-1:0] REG_BRIDGE_IP = BASE + 'h1018; + localparam [REG_AWIDTH-1:0] REG_BRIDGE_UDP = BASE + 'h101c; + localparam [REG_AWIDTH-1:0] REG_BRIDGE_ENABLE = BASE + 'h1020; + + // MAC address for the dispatcher module. + // This value is used to determine if the packet is meant + // for this device should be consumed + // IP address for the dispatcher module. + // This value is used to determine if the packet is addressed + // to this device + // This module supports two destination ports + reg [47:0] mac_reg; + reg [31:0] ip_reg; + reg [15:0] udp_port; + reg [47:0] bridge_mac_reg; + reg [31:0] bridge_ip_reg; + reg [15:0] bridge_udp_port; + reg bridge_en; + + assign my_mac = bridge_en ? bridge_mac_reg : mac_reg; + assign my_ip = bridge_en ? bridge_ip_reg : ip_reg; + assign my_udp_port = bridge_en ? bridge_udp_port : udp_port; + + always @(posedge clk) begin + if (reset) begin + mac_reg <= DEFAULT_MAC_ADDR; + ip_reg <= DEFAULT_IP_ADDR; + udp_port <= DEFAULT_UDP_PORT; + bridge_en <= 1'b0; + bridge_mac_reg <= DEFAULT_MAC_ADDR; + bridge_ip_reg <= DEFAULT_IP_ADDR; + bridge_udp_port <= DEFAULT_UDP_PORT; + end + else begin + if (reg_wr_req) + case (reg_wr_addr) + + REG_MAC_LSB: + mac_reg[31:0] <= reg_wr_data; + + REG_MAC_MSB: + mac_reg[47:32] <= reg_wr_data[15:0]; + + REG_IP: + ip_reg <= reg_wr_data; + + REG_UDP: + udp_port <= reg_wr_data[15:0]; + + REG_BRIDGE_MAC_LSB: + bridge_mac_reg[31:0] <= reg_wr_data; + + REG_BRIDGE_MAC_MSB: + bridge_mac_reg[47:32] <= reg_wr_data[15:0]; + + REG_BRIDGE_IP: + bridge_ip_reg <= reg_wr_data; + + REG_BRIDGE_UDP: + bridge_udp_port <= reg_wr_data[15:0]; + + REG_BRIDGE_ENABLE: + bridge_en <= reg_wr_data[0]; + endcase + end + end + + always @ (posedge clk) begin + // No reset handling required for readback + if (reg_rd_req) begin + // Assert read response one cycle after read request + reg_rd_resp <= 1'b1; + case (reg_rd_addr) + REG_MAC_LSB: + reg_rd_data <= mac_reg[31:0]; + + REG_MAC_MSB: + reg_rd_data <= {16'b0,mac_reg[47:32]}; + + REG_IP: + reg_rd_data <= ip_reg; + + REG_UDP: + reg_rd_data <= {16'b0, udp_port}; + + REG_BRIDGE_MAC_LSB: + reg_rd_data <= bridge_mac_reg[31:0]; + + REG_BRIDGE_MAC_MSB: + reg_rd_data <= {16'b0,bridge_mac_reg[47:32]}; + + REG_BRIDGE_IP: + reg_rd_data <= bridge_ip_reg; + + REG_BRIDGE_UDP: + reg_rd_data <= {16'b0, bridge_udp_port}; + + REG_BRIDGE_ENABLE: + reg_rd_data <= {31'b0,bridge_en}; + + default: + reg_rd_resp <= 1'b0; + endcase + end + // Deassert read response after one clock cycle + if (reg_rd_resp) begin + reg_rd_resp <= 1'b0; + end + end + + // 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_switch is the numbier of valid bytes + + eth_ipv4_chdr64_adapter #( + .PROTOVER (PROTOVER), + .MTU (MTU), + .CPU_FIFO_SIZE (MTU), + .RT_TBL_SIZE (RT_TBL_SIZE), + .NODE_INST (NODE_INST), + .DROP_UNKNOWN_MAC(0), + .IS_CPU_ARM (1) + ) eth_adapter_i ( + .clk (clk ), + .rst (reset ), + .device_id (device_id ), + .s_mac_tdata (eth_rx_tdata ), + .s_mac_tuser (eth_rx_tuser ), + .s_mac_tlast (eth_rx_tlast ), + .s_mac_tvalid (eth_rx_tvalid), + .s_mac_tready (eth_rx_tready), + .m_mac_tdata (eth_tx_tdata ), + .m_mac_tuser (eth_tx_tuser ), + .m_mac_tlast (eth_tx_tlast ), + .m_mac_tvalid (eth_tx_tvalid), + .m_mac_tready (eth_tx_tready), + .s_chdr_tdata (v2e_tdata ), + .s_chdr_tlast (v2e_tlast ), + .s_chdr_tvalid (v2e_tvalid ), + .s_chdr_tready (v2e_tready ), + .m_chdr_tdata (e2v_tdata ), + .m_chdr_tlast (e2v_tlast ), + .m_chdr_tvalid (e2v_tvalid ), + .m_chdr_tready (e2v_tready ), + .s_cpu_tdata (c2e_tdata ), + .s_cpu_tuser (c2e_tuser ), + .s_cpu_tlast (c2e_tlast ), + .s_cpu_tvalid (c2e_tvalid ), + .s_cpu_tready (c2e_tready ), + .m_cpu_tdata (e2c_tdata ), + .m_cpu_tuser (e2c_tuser ), + .m_cpu_tlast (e2c_tlast ), + .m_cpu_tvalid (e2c_tvalid ), + .m_cpu_tready (e2c_tready ), + .my_eth_addr (my_mac ), + .my_ipv4_addr (my_ip ), + .my_udp_chdr_port(my_udp_port ) + ); + + +endmodule // eth_interface |