// // 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