1// 2// Copyright 2020 Ettus Research, a National Instruments Brand 3// 4// SPDX-License-Identifier: LGPL-3.0-or-later 5// Module: eth_ipv4_interface 6// 7// Description: 8// Adapts from internal CHDR to UDP/IPV4 Ethernet packets. 9// Packets not specifically addressed to CHDR are routed 10// to the CPU 11// 12// Parameters: 13// - PROTOVER: RFNoC protocol version {8'd<major>, 8'd<minor>} 14// - CPU_FIFO_SIZE: Log2 of the FIFO depth (in bytes) for the CPU egress path 15// - CHDR_FIFO_SIZE: Log2 of the FIFO depth (in bytes) for the CHDR egress path 16// - RT_TBL_SIZE: Log2 of the depth of the return-address routing table 17// - NODE_INST: The node type to return for a node-info discovery 18// - DROP_UNKNOWN_MAC: Drop packets not addressed to us? 19// - DROP_MIN_PACKET: Drop packets smaller than 64 bytes? 20// - PREAMBLE_BYTES: Number of bytes of Preamble expected 21// - ADD_SOF: Add a SOF indication into the tuser field of e2c 22// - SYNC: Set if MAC is not the same as bus_clk 23// - ENET_W: Width of the link to the Ethernet MAC 24// - CPU_W: Width of the CPU interface 25// - CHDR_W: Width of the CHDR interface 26// 27 28module eth_ipv4_interface #( 29 logic [15:0] PROTOVER = {8'd1, 8'd0}, 30 int CPU_FIFO_SIZE = $clog2(8*1024), 31 int CHDR_FIFO_SIZE = $clog2(8*1024), 32 int NODE_INST = 0, 33 int RT_TBL_SIZE = 6, 34 int REG_AWIDTH = 14, 35 int BASE = 0, 36 bit DROP_UNKNOWN_MAC = 0, 37 bit DROP_MIN_PACKET = 0, 38 int PREAMBLE_BYTES = 6, 39 bit ADD_SOF = 1, 40 bit SYNC = 0, 41 int ENET_W = 64, 42 int CPU_W = 64, 43 int CHDR_W = 64 44) ( 45 input logic bus_clk, 46 input logic bus_rst, 47 input logic [15:0] device_id, 48 49 // Register port: Write port (domain: bus_clk) 50 input logic reg_wr_req, 51 input logic [REG_AWIDTH-1:0] reg_wr_addr, 52 input logic [31:0] reg_wr_data, 53 54 // Register port: Read port (domain: bus_clk) 55 input logic reg_rd_req, 56 input logic [REG_AWIDTH-1:0] reg_rd_addr, 57 output logic reg_rd_resp, 58 output logic [31:0] reg_rd_data, 59 60 // Status ports (domain: bus_clk) 61 output logic [47:0] my_mac, 62 output logic [31:0] my_ip, 63 output logic [15:0] my_udp_chdr_port, 64 65 // Ethernet MAC 66 AxiStreamIf.master eth_tx, // tUser = {1'b0,trailing bytes}; 67 AxiStreamIf.slave eth_rx, // tUser = {error,trailing bytes}; 68 // CHDR router interface 69 AxiStreamIf.master e2v, // tUser = {*not used*}; 70 AxiStreamIf.slave v2e, // tUser = {*not used*}; 71 // CPU DMA 72 AxiStreamIf.master e2c, // tUser = {sof,trailing bytes}; 73 AxiStreamIf.slave c2e // tUser = {1'b0,trailing bytes}; 74 75 ); 76 77 localparam [47:0] DEFAULT_MAC_ADDR = {8'h00, 8'h80, 8'h2f, 8'h16, 8'hc5, 8'h2f}; 78 localparam [31:0] DEFAULT_IP_ADDR = {8'd192, 8'd168, 8'd10, 8'd2}; 79 localparam [31:0] DEFAULT_UDP_PORT = 16'd49153; 80 81 //--------------------------------------------------------- 82 // Registers 83 //--------------------------------------------------------- 84 // Include for register offsets 85 `include "eth_regs.vh" 86 // Allocate one full page for M 87 // mac_reg: MAC address for the dispatcher module. This value is used to 88 // determine if the packet is meant for this device and should be consumed. 89 // 90 // ip_reg: IP address for the dispatcher module. This value is used to 91 // determine if the packet is addressed to this device 92 // 93 // This module supports two destination ports. 94 logic [47:0] mac_reg = DEFAULT_MAC_ADDR; 95 logic [31:0] ip_reg = DEFAULT_IP_ADDR; 96 logic [15:0] udp_port = DEFAULT_UDP_PORT; 97 logic [47:0] bridge_mac_reg = DEFAULT_MAC_ADDR; 98 logic [31:0] bridge_ip_reg = DEFAULT_IP_ADDR; 99 logic [15:0] bridge_udp_port = DEFAULT_UDP_PORT; 100 logic bridge_en; 101 logic cpu_dropped; 102 logic chdr_dropped; 103 logic [31:0] chdr_drop_count = 0; 104 logic [31:0] cpu_drop_count = 0; 105 106 always_comb begin : bridge_mux 107 my_mac = bridge_en ? bridge_mac_reg : mac_reg; 108 my_ip = bridge_en ? bridge_ip_reg : ip_reg; 109 my_udp_chdr_port = bridge_en ? bridge_udp_port : udp_port; 110 end 111 112 always_ff @(posedge bus_clk) begin : reg_wr_ff 113 if (bus_rst) begin 114 mac_reg <= DEFAULT_MAC_ADDR; 115 ip_reg <= DEFAULT_IP_ADDR; 116 udp_port <= DEFAULT_UDP_PORT; 117 bridge_en <= 1'b0; 118 bridge_mac_reg <= DEFAULT_MAC_ADDR; 119 bridge_ip_reg <= DEFAULT_IP_ADDR; 120 bridge_udp_port <= DEFAULT_UDP_PORT; 121 end 122 else begin 123 if (reg_wr_req) 124 case (reg_wr_addr) 125 126 REG_MAC_LSB: 127 mac_reg[31:0] <= reg_wr_data; 128 129 REG_MAC_MSB: 130 mac_reg[47:32] <= reg_wr_data[15:0]; 131 132 REG_IP: 133 ip_reg <= reg_wr_data; 134 135 REG_UDP: 136 udp_port <= reg_wr_data[15:0]; 137 138 REG_BRIDGE_MAC_LSB: 139 bridge_mac_reg[31:0] <= reg_wr_data; 140 141 REG_BRIDGE_MAC_MSB: 142 bridge_mac_reg[47:32] <= reg_wr_data[15:0]; 143 144 REG_BRIDGE_IP: 145 bridge_ip_reg <= reg_wr_data; 146 147 REG_BRIDGE_UDP: 148 bridge_udp_port <= reg_wr_data[15:0]; 149 150 REG_BRIDGE_ENABLE: 151 bridge_en <= reg_wr_data[0]; 152 endcase 153 end 154 end 155 156 always_ff @ (posedge bus_clk) begin : reg_rd_ff 157 if (bus_rst) begin 158 reg_rd_resp <= 1'b0; 159 reg_rd_data <= 32'd0; 160 chdr_drop_count <= 32'd0; 161 cpu_drop_count <= 32'd0; 162 end 163 else begin 164 if (chdr_dropped) begin 165 chdr_drop_count <= chdr_drop_count+1; 166 end 167 if (cpu_dropped) begin 168 cpu_drop_count <= cpu_drop_count+1; 169 end 170 if (reg_rd_req) begin 171 // Assert read response one cycle after read request 172 reg_rd_resp <= 1'b1; 173 case (reg_rd_addr) 174 REG_MAC_LSB: 175 reg_rd_data <= mac_reg[31:0]; 176 177 REG_MAC_MSB: 178 reg_rd_data <= {16'b0,mac_reg[47:32]}; 179 180 REG_IP: 181 reg_rd_data <= ip_reg; 182 183 REG_UDP: 184 reg_rd_data <= {16'b0, udp_port}; 185 186 REG_BRIDGE_MAC_LSB: 187 reg_rd_data <= bridge_mac_reg[31:0]; 188 189 REG_BRIDGE_MAC_MSB: 190 reg_rd_data <= {16'b0,bridge_mac_reg[47:32]}; 191 192 REG_BRIDGE_IP: 193 reg_rd_data <= bridge_ip_reg; 194 195 REG_BRIDGE_UDP: 196 reg_rd_data <= {16'b0, bridge_udp_port}; 197 198 REG_BRIDGE_ENABLE: 199 reg_rd_data <= {31'b0,bridge_en}; 200 // Drop counts are used to debug situations 201 // Where the incoming data goes faster than 202 // chdr can consume it 203 REG_CHDR_DROPPED: 204 begin 205 reg_rd_data <= chdr_drop_count; 206 chdr_drop_count <= 0; // clear when read 207 end 208 REG_CPU_DROPPED: 209 begin 210 reg_rd_data <= cpu_drop_count; 211 cpu_drop_count <= 0; // clear when read 212 end 213 default: 214 reg_rd_resp <= 1'b0; 215 endcase 216 end 217 // Deassert read response after one clock cycle 218 if (reg_rd_resp) begin 219 reg_rd_resp <= 1'b0; 220 end 221 end 222 end 223 224 logic b_dropped_valid; 225 logic e_cpu_dropped, b_cpu_dropped; 226 logic e_chdr_dropped, b_chdr_dropped; 227 // push over the clock domain 228 // Sized to fit into 2 SRL's 229 axi_fifo_2clk #(.WIDTH(2), .SIZE(4)) fifo_i ( 230 .reset(eth_rx.rst), 231 .i_aclk(eth_rx.clk), 232 .i_tdata({e_cpu_dropped, e_chdr_dropped}), 233 .i_tvalid(e_cpu_dropped || e_chdr_dropped), .i_tready(/*not used*/), 234 .o_aclk(bus_clk), 235 .o_tdata({b_cpu_dropped, b_chdr_dropped}), 236 .o_tvalid(b_dropped_valid), .o_tready(1'b1) 237 ); 238 239 always_comb begin 240 cpu_dropped = b_cpu_dropped && b_dropped_valid; 241 chdr_dropped = b_chdr_dropped && b_dropped_valid; 242 end 243 244 eth_ipv4_chdr_adapter #( 245 .PROTOVER (PROTOVER), 246 .CPU_FIFO_SIZE (CPU_FIFO_SIZE), 247 .CHDR_FIFO_SIZE (CHDR_FIFO_SIZE), 248 .RT_TBL_SIZE (RT_TBL_SIZE), 249 .NODE_INST (NODE_INST), 250 .DROP_UNKNOWN_MAC(DROP_UNKNOWN_MAC), 251 .DROP_MIN_PACKET (DROP_MIN_PACKET), 252 .PREAMBLE_BYTES (PREAMBLE_BYTES), 253 .ADD_SOF (ADD_SOF), 254 .SYNC (SYNC), 255 .ENET_W (ENET_W), 256 .CPU_W (CPU_W), 257 .CHDR_W (CHDR_W) 258 ) eth_adapter_i ( 259 .eth_rx (eth_rx ), 260 .eth_tx (eth_tx ), 261 .v2e (v2e ), 262 .e2v (e2v ), 263 .c2e (c2e ), 264 .e2c (e2c ), 265 .device_id (device_id), 266 .my_mac (my_mac ), 267 .my_ip (my_ip ), 268 .my_udp_chdr_port(my_udp_chdr_port), 269 .chdr_dropped (e_chdr_dropped), 270 .cpu_dropped (e_cpu_dropped) 271 ); 272 273 274endmodule : eth_ipv4_interface 275