// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: CERN-OHL-S-2.0 #include "hls_jfjoch.h" void ethernet(AXI_STREAM ð_in, AXI_STREAM &ip_out, AXI_STREAM &arp_out, AXI_STREAM &ptp_out, ap_uint<48> fpga_mac_addr, ap_uint<1> enable, ap_uint<1> direct, uint64_t& counter, volatile ap_uint<1> &in_clear_counters) { // direct - don't enforce MAC address // enable - allows packets to go through #pragma HLS INTERFACE ap_ctrl_none port=return #pragma HLS INTERFACE axis register both port=eth_in #pragma HLS INTERFACE axis register both port=ip_out #pragma HLS INTERFACE axis register both port=arp_out #pragma HLS INTERFACE axis register both port=ptp_out #pragma HLS INTERFACE ap_none register port=fpga_mac_addr #pragma HLS INTERFACE ap_none register port=direct #pragma HLS INTERFACE ap_none register port=enable #pragma HLS INTERFACE ap_vld register port=counter #pragma HLS INTERFACE ap_none register port=in_clear_counters #pragma HLS PIPELINE II=1 style=flp enum eth_dest {DEST_IP = 0, DEST_ARP = 1, DEST_IGNORE = 2, DEST_PTP = 3}; enum eth_state {INSPECT_HEADER, FORWARD, DISCARD}; static eth_state state = INSPECT_HEADER; static eth_dest dest; static uint64_t internal_counter = 0; ap_uint<1> tmp = in_clear_counters; if (tmp) internal_counter = 0; #pragma HLS RESET variable=state #pragma HLS RESET variable=internal_counter packet_512_t packet_in; if (eth_in.read_nb(packet_in)) { if (state == INSPECT_HEADER) { dest = DEST_IGNORE; if (enable) { ap_uint<48> dest_mac = packet_in.data(47, 0); ap_uint<48> src_mac = packet_in.data(95, 48); ap_uint<16> ether_type = get_header_field_16(packet_in.data, 12 * 8); bool multicast = (dest_mac(47, 40) == 0x01 && dest_mac(39, 32) == 0x00 && dest_mac(31, 24) == 0x5e); if (((dest_mac == fpga_mac_addr) || (dest_mac == MAC_BROADCAST) || multicast || direct) && (ether_type == ETHER_PTP)) { state = FORWARD; dest = DEST_PTP; } else if (((dest_mac == fpga_mac_addr) || (dest_mac == MAC_BROADCAST) || multicast || direct) && (ether_type == ETHER_IP)) { state = FORWARD; dest = DEST_IP; internal_counter++; } else if ((dest_mac == MAC_BROADCAST) && (ether_type == ETHER_ARP) && (packet_in.last)) { state = FORWARD; dest = DEST_ARP; } } } switch (dest) { case DEST_IP: ip_out.write(packet_in); break; case DEST_ARP: arp_out.write(packet_in); break; case DEST_PTP: ptp_out.write(packet_in); break; default: break; } if (packet_in.last) { state = INSPECT_HEADER; } } counter = internal_counter; }