diff options
Diffstat (limited to 'fpga/usrp3/lib/packet_proc/eth_dispatch.v')
-rw-r--r-- | fpga/usrp3/lib/packet_proc/eth_dispatch.v | 516 |
1 files changed, 0 insertions, 516 deletions
diff --git a/fpga/usrp3/lib/packet_proc/eth_dispatch.v b/fpga/usrp3/lib/packet_proc/eth_dispatch.v deleted file mode 100644 index c21c0b8cb..000000000 --- a/fpga/usrp3/lib/packet_proc/eth_dispatch.v +++ /dev/null @@ -1,516 +0,0 @@ - -// Ethernet dispatcher -// Incoming ethernet packets are examined and sent to the correct destination -// There are 3 destinations, ZPU, other ethernet port (out), and vita router -// Packets going to the vita router will have the ethernet/ip/udp headers stripped off. -// -// To make things simpler, we start out by sending all packets to zpu and out port. -// By the end of the eth/ip/udp headers, we can determine where the correct destination is. -// If the correct destination is vita, we send an error indication on the zpu and out ports, -// which will cause the axi_packet_gate to drop those packets, and send the vita frame to -// the vita port. -// -// If at the end of the headers we determine the packet should go to zpu, then we send an -// error indication on the out port, the rest of the packet to zpu and nothing on vita. -// If it should go to out, we send the error indication to zpu, the rest of the packet to out, -// and nothing on vita. -// -// Downstream we should have adequate fifo space, otherwise we could get backed up here. -// -// No tuser bits sent to vita, as vita assumes there are no errors and that occupancy is -// indicated by the length field of the vita header. - -// -// Rules for forwarding: -// -// Ethernet Broadcast (Dst MAC = ff:ff:ff:ff:ff:ff). Forward to both ZPU and XO MAC. -// ? Ethernet Multicast (Dst MAC = USRP_NEXT_HOP). Forward only to ZPU. -// ? Ethernet Multicast (Dst MAC = Unknown). Forward only to XO. -// Ethernet Unicast (Dst MAC = Unknown). Forward only to XO. -// Ethernet Unicast (Dst MAC = local). Look deeper...... -// IP Broadcast. Forward to both ZPU and XO MAC. (Should be coverd by Eth broadcast) -// IP Multicast. ? Unknow Action. -// IP Unicast (Dst IP = local). Look deeper.... -// UDP (Port = Listed) and its a VRLP packet. Forward only to VITA Radio Core. -// UDP (Port = Unknown). Forward only to ZPU. -// -// - -module eth_dispatch - #(parameter BASE=0) - ( - // Clocking and reset interface - input clk, - input reset, - input clear, - // Setting register interface - input set_stb, - input [15:0] set_addr, - input [31:0] set_data, - // Input 68bit AXI-Stream interface (from MAC) - input [63:0] in_tdata, - input [3:0] in_tuser, - input in_tlast, - input in_tvalid, - output in_tready, - // Output AXI-STream interface to VITA Radio Core - output [63:0] vita_tdata, - output [3:0] vita_tuser, - output vita_tlast, - output vita_tvalid, - input vita_tready, - // Output AXI-Stream interface to ZPU - output [63:0] zpu_tdata, - output [3:0] zpu_tuser, - output zpu_tlast, - output zpu_tvalid, - input zpu_tready, - // Output AXI-Stream interface to cross-over MAC - output [63:0] xo_tdata, - output [3:0] xo_tuser, - output xo_tlast, - output xo_tvalid, - input xo_tready, - // Debug - output [2:0] debug_flags, - output [31:0] debug - ); - - //--------------------------------------------------------- - // State machine declarations - //--------------------------------------------------------- - reg [2:0] state; - - localparam WAIT_PACKET = 0; - localparam READ_HEADER = 1; - localparam FORWARD_ZPU = 2; - localparam FORWARD_ZPU_AND_XO = 3; - localparam FORWARD_XO = 4; - localparam FORWARD_RADIO_CORE = 5; - localparam DROP_PACKET = 6; - localparam CLASSIFY_PACKET = 7; - - // Small RAM stores packet header during parsing. - // IJB consider changing HEADER_RAM_SIZE to 7 - localparam HEADER_RAM_SIZE = 9; - (*ram_style="distributed"*) reg [68:0] header_ram [HEADER_RAM_SIZE-1:0]; - - reg [3:0] header_ram_addr; - wire header_done = (header_ram_addr == HEADER_RAM_SIZE-1); - reg fwd_input; - - reg [63:0] in_tdata_reg; - - wire out_tvalid; - wire out_tready; - wire out_tlast; - wire [3:0] out_tuser; - wire [63:0] out_tdata; - - // Output AXI-Stream interface to VITA Radio Core - wire [63:0] vita_pre_tdata; - wire [3:0] vita_pre_tuser; - wire vita_pre_tlast; - wire vita_pre_tvalid; - wire vita_pre_tready; - // Output AXI-Stream interface to ZPU - wire [63:0] zpu_pre_tdata; - wire [3:0] zpu_pre_tuser; - wire zpu_pre_tlast; - wire zpu_pre_tvalid; - wire zpu_pre_tready; - // Output AXI-Stream interface to cross-over MAC - wire [63:0] xo_pre_tdata; - wire [3:0] xo_pre_tuser; - wire xo_pre_tlast; - wire xo_pre_tvalid; - wire xo_pre_tready; - - // Packet Parse Flags - reg is_eth_dst_addr; - reg is_eth_broadcast; - reg is_eth_type_ipv4; - reg is_ipv4_dst_addr; - reg is_ipv4_proto_udp; - reg is_ipv4_proto_icmp; - reg [1:0] is_udp_dst_ports; - reg is_icmp_no_fwd; - reg is_chdr; - - //--------------------------------------------------------- - // Settings regs - //--------------------------------------------------------- - - // MAC address for the dispatcher module. - // This value is used to determine if the packet is meant - // for this device should be consumed - wire [47:0] my_mac; - setting_reg #(.my_addr(BASE), .awidth(16), .width(32)) sr_my_mac_lsb - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(my_mac[31:0]),.changed()); - setting_reg #(.my_addr(BASE+1), .awidth(16), .width(16)) sr_my_mac_msb - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(my_mac[47:32]),.changed()); - - // IP address for the dispatcher module. - // This value is used to determine if the packet is addressed - // to this device - wire [31:0] my_ip; - setting_reg #(.my_addr(BASE+2), .awidth(16), .width(32)) sr_my_ip - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(my_ip[31:0]),.changed()); - - // This module supports two destination ports - wire [15:0] my_port0, my_port1; - setting_reg #(.my_addr(BASE+3), .awidth(16), .width(32)) sr_udp_port - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out({my_port1[15:0],my_port0[15:0]}),.changed()); - - // forward_ndest: Forward to crossover path if MAC Addr in packet - // does not match "my_mac" - // forward_bcast: Forward broadcasts to crossover path - wire forward_ndest, forward_bcast; - setting_reg #(.my_addr(BASE+4), .awidth(16), .width(2)) sr_forward_ctrl - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out({forward_ndest, forward_bcast}),.changed()); - - //ICMP Type and Code to forward packet to ZPU - wire [7:0] my_icmp_type, my_icmp_code; - setting_reg #(.my_addr(BASE+5), .awidth(16), .width(16)) sr_icmp_ctrl - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out({my_icmp_type, my_icmp_code}),.changed()); - - //--------------------------------------------------------- - // Packet Forwarding State machine. - //--------------------------------------------------------- - // Read input packet and store the header into a RAM for - // classification. A header is defined as HEADER_RAM_SIZE - // number of 64-bit words. - // Based on clasification results, output the packet to the - // VITA port, crossover(XO) port or the ZPU. Note that the - // XO and ZPU ports require fully framed Eth packets so data - // from the RAM has to be replayed on the output. The state - // machine will hold off input packets until the header is - // replayed. The state machine also supports dropping pkts. - - always @(posedge clk) - if (reset || clear) begin - state <= WAIT_PACKET; - header_ram_addr <= 0; - fwd_input <= 0; - end else begin - // Defaults. - case(state) - // - // Wait for start of a packet - // IJB: Add protection for a premature EOF here - // - WAIT_PACKET: begin - if (in_tvalid && in_tready) begin - header_ram[header_ram_addr] <= {in_tlast,in_tuser,in_tdata}; - header_ram_addr <= header_ram_addr + 1; - state <= READ_HEADER; - end - fwd_input <= 0; - end - // - // Continue to read full packet header into RAM. - // - READ_HEADER: begin - if (in_tvalid && in_tready) begin - header_ram[header_ram_addr] <= {in_tlast,in_tuser,in_tdata}; - // Have we reached end of fields we parse in header or got a short packet? - if (header_done || in_tlast) begin - // Make decision about where this packet is forwarded to. - state <= CLASSIFY_PACKET; - end // if (header_done || in_tlast) - else begin - header_ram_addr <= header_ram_addr + 1; - state <= READ_HEADER; - end // else: !if(header_done || in_tlast) - end // if (in_tvalid && in_tready) - end // case: READ_HEADER - - // - // Classify Packet - // - CLASSIFY_PACKET: begin - // Make decision about where this packet is forwarded to. - if (is_eth_type_ipv4 && is_ipv4_proto_icmp && is_icmp_no_fwd) begin - header_ram_addr <= 0; - state <= FORWARD_ZPU; - end else if (is_eth_broadcast) begin - header_ram_addr <= 0; - state <= forward_bcast? FORWARD_ZPU_AND_XO : FORWARD_ZPU; - end else if (!is_eth_dst_addr && forward_ndest) begin - header_ram_addr <= 0; - state <= FORWARD_XO; - end else if (!is_eth_dst_addr && !forward_ndest) begin - header_ram_addr <= HEADER_RAM_SIZE - 1; - state <= DROP_PACKET; - end else if ((is_udp_dst_ports != 0) && is_chdr) begin - header_ram_addr <= 6; // Jump to CHDR - state <= FORWARD_RADIO_CORE; - end else begin - header_ram_addr <= 0; - state <= FORWARD_ZPU; - end - end // case: CLASSIFY_PACKET - - // - // Forward this packet only to local ZPU - // - FORWARD_ZPU: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - // - // Forward this packet to both local ZPU and XO - // - FORWARD_ZPU_AND_XO: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - // - // Forward this packet to XO only - // - FORWARD_XO: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - // - // Forward this packet to the Radio Core only - // - FORWARD_RADIO_CORE: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - // - // Drop this packet on the ground - // - DROP_PACKET: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - endcase // case (state) - end // else: !if(reset || clear) - - //--------------------------------------------------------- - // Classifier State machine. - // Deep packet inspection during header ingress. - //--------------------------------------------------------- - // As the packet header is pushed into the RAM, set classification - // bits so that by the time the input state machine reaches the - // CLASSIFY_PACKET state, the packet has been fully identified. - - always @(posedge clk) - if (reset || clear) begin - is_eth_dst_addr <= 1'b0; - is_eth_broadcast <= 1'b0; - is_eth_type_ipv4 <= 1'b0; - is_ipv4_dst_addr <= 1'b0; - is_ipv4_proto_udp <= 1'b0; - is_ipv4_proto_icmp <= 1'b0; - is_udp_dst_ports <= 0; - is_icmp_no_fwd <= 0; - is_chdr <= 1'b0; - end else if (in_tvalid && in_tready) begin // if (reset || clear) - in_tdata_reg <= in_tdata; - - case (header_ram_addr) - // Pipelined, so nothing to look at first cycle. - // Reset all the flags here. - 0: begin - is_eth_dst_addr <= 1'b0; - is_eth_broadcast <= 1'b0; - is_eth_type_ipv4 <= 1'b0; - is_ipv4_dst_addr <= 1'b0; - is_ipv4_proto_udp <= 1'b0; - is_ipv4_proto_icmp <= 1'b0; - is_udp_dst_ports <= 0; - is_icmp_no_fwd <= 0; - is_chdr <= 1'b0; - end - 1: begin - // Look at upper 16bits of MAC Dst Addr. - if (in_tdata_reg[15:0] == 16'hFFFF) - is_eth_broadcast <= 1'b1; - if (in_tdata_reg[15:0] == my_mac[47:32]) - is_eth_dst_addr <= 1'b1; - end - 2: begin - // Look at lower 32bits of MAC Dst Addr. - if (is_eth_broadcast && (in_tdata_reg[63:32] == 32'hFFFFFFFF)) - is_eth_broadcast <= 1'b1; - else - is_eth_broadcast <= 1'b0; - if (is_eth_dst_addr && (in_tdata_reg[63:32] == my_mac[31:0])) - is_eth_dst_addr <= 1'b1; - else - is_eth_dst_addr <= 1'b0; - end // case: 2 - 3: begin - // Look at Ethertype - if (in_tdata_reg[47:32] == 16'h0800) - is_eth_type_ipv4 <= 1'b1; - // Extract Packet Length - // ADD THIS HERE. - end - 4: begin - // Look at protocol enapsulated by IPv4 - if ((in_tdata_reg[23:16] == 8'h11) && is_eth_type_ipv4) - is_ipv4_proto_udp <= 1'b1; - if ((in_tdata_reg[23:16] == 8'h01) && is_eth_type_ipv4) - is_ipv4_proto_icmp <= 1'b1; - end - 5: begin - // Look at IP DST Address. - if ((in_tdata_reg[31:0] == my_ip[31:0]) && is_eth_type_ipv4) - is_ipv4_dst_addr <= 1'b1; - end - 6: begin - // Look at UDP dest port - if ((in_tdata_reg[47:32] == my_port0[15:0]) && is_ipv4_proto_udp) - is_udp_dst_ports[0] <= 1'b1; - if ((in_tdata_reg[47:32] == my_port1[15:0]) && is_ipv4_proto_udp) - is_udp_dst_ports[1] <= 1'b1; - // Look at ICMP type and code - if (in_tdata_reg[63:48] == {my_icmp_type, my_icmp_code} && is_ipv4_proto_icmp) - is_icmp_no_fwd <= 1'b1; - end - 7: begin - // Look for a possible CHDR header string - // IJB. NOTE this is not a good test for a CHDR packet, we perhaps don;t need this state anyhow. - if (in_tdata_reg[63:32] != 32'h0) - is_chdr <= 1'b1; - end - 8: begin - // Check VRT Stream ID - // ADD THIS HERE. - // IJB. Perhaps delete this state. - end - endcase // case (header_ram_addr) - end // if (in_tvalid && in_tready) - - - //--------------------------------------------------------- - // Output (Egress) Interface muxing - //--------------------------------------------------------- - assign out_tready = - (state == DROP_PACKET) || - ((state == FORWARD_RADIO_CORE) && vita_pre_tready) || - ((state == FORWARD_XO) && xo_pre_tready) || - ((state == FORWARD_ZPU) && zpu_pre_tready) || - ((state == FORWARD_ZPU_AND_XO) && zpu_pre_tready && xo_pre_tready); - - assign out_tvalid = ((state == FORWARD_RADIO_CORE) || - (state == FORWARD_XO) || - (state == FORWARD_ZPU) || - (state == FORWARD_ZPU_AND_XO) || - (state == DROP_PACKET)) && (!fwd_input || in_tvalid); - - assign {out_tlast,out_tuser,out_tdata} = fwd_input ? {in_tlast,in_tuser,in_tdata} : header_ram[header_ram_addr]; - - assign in_tready = (state == WAIT_PACKET) || - (state == READ_HEADER) || - (out_tready && fwd_input); - - // - // Because we can forward to both the ZPU and XO FIFO's concurrently - // we have to make sure both can accept data in the same cycle. - // This makes it possible for either destination to block the other. - // Make sure (both) destination(s) can accept data before passing it. - // - assign xo_pre_tvalid = out_tvalid && - ((state == FORWARD_XO) || - ((state == FORWARD_ZPU_AND_XO) && zpu_pre_tready)); - assign zpu_pre_tvalid = out_tvalid && - ((state == FORWARD_ZPU) || - ((state == FORWARD_ZPU_AND_XO) && xo_pre_tready)); - assign vita_pre_tvalid = out_tvalid && - (state == FORWARD_RADIO_CORE); - - assign {zpu_pre_tlast, zpu_pre_tuser, zpu_pre_tdata} = {out_tlast, out_tuser, out_tdata}; - assign {xo_pre_tlast, xo_pre_tuser, xo_pre_tdata} = {out_tlast, out_tuser, out_tdata}; - assign {vita_pre_tlast, vita_pre_tuser, vita_pre_tdata} = {out_tlast, out_tuser, out_tdata}; - - //--------------------------------------------------------- - // Egress FIFO's - //--------------------------------------------------------- - // These FIFO's have to be fairly large to prevent any egress - // port from backpressuring the input state machine. - // The ZPU and XO ports are inherently slow consumers so they - // get a large buffer. The VITA port is fast but high throughput - // so even that needs a large FIFO. - - axi_fifo #(.WIDTH(69),.SIZE(10)) - axi_fifo_zpu ( - .clk(clk), - .reset(reset), - .clear(clear), - .i_tdata({zpu_pre_tlast,zpu_pre_tuser,zpu_pre_tdata}), - .i_tvalid(zpu_pre_tvalid), - .i_tready(zpu_pre_tready), - .o_tdata({zpu_tlast,zpu_tuser,zpu_tdata}), - .o_tvalid(zpu_tvalid), - .o_tready(zpu_tready), - .space(), - .occupied() - ); - - axi_fifo #(.WIDTH(69),.SIZE(10)) - axi_fifo_xo ( - .clk(clk), - .reset(reset), - .clear(clear), - .i_tdata({xo_pre_tlast,xo_pre_tuser,xo_pre_tdata}), - .i_tvalid(xo_pre_tvalid), - .i_tready(xo_pre_tready), - .o_tdata({xo_tlast,xo_tuser,xo_tdata}), - .o_tvalid(xo_tvalid), - .o_tready(xo_tready), - .space(), - .occupied() - ); - - axi_fifo #(.WIDTH(69),.SIZE(10)) - axi_fifo_vita ( - .clk(clk), - .reset(reset), - .clear(clear), - .i_tdata({vita_pre_tlast,vita_pre_tuser,vita_pre_tdata}), - .i_tvalid(vita_pre_tvalid), - .i_tready(vita_pre_tready), - .o_tdata({vita_tlast,vita_tuser,vita_tdata}), - .o_tvalid(vita_tvalid), - .o_tready(vita_tready), - .space(), - .occupied() - ); - -endmodule // eth_dispatch |