diff options
author | Ben Hilburn <ben.hilburn@ettus.com> | 2014-05-14 11:42:19 -0700 |
---|---|---|
committer | Ben Hilburn <ben.hilburn@ettus.com> | 2014-05-14 11:42:19 -0700 |
commit | 00711ba213dde8aa0a099d2b18d3da0a33e6af79 (patch) | |
tree | 612f616ebbf8080b5dc9cb5d64a8062e9aa3a498 /fpga/usrp3/lib/packet_proc/eth_dispatch.v | |
parent | 5de0bfce3f03cc45a1eed93dc1b8df1b188b5040 (diff) | |
download | uhd-00711ba213dde8aa0a099d2b18d3da0a33e6af79.tar.gz uhd-00711ba213dde8aa0a099d2b18d3da0a33e6af79.tar.bz2 uhd-00711ba213dde8aa0a099d2b18d3da0a33e6af79.zip |
fpga: updating b200 and x300 FPGA source code for latest images
Diffstat (limited to 'fpga/usrp3/lib/packet_proc/eth_dispatch.v')
-rw-r--r-- | fpga/usrp3/lib/packet_proc/eth_dispatch.v | 937 |
1 files changed, 468 insertions, 469 deletions
diff --git a/fpga/usrp3/lib/packet_proc/eth_dispatch.v b/fpga/usrp3/lib/packet_proc/eth_dispatch.v index 7068d5a77..07f40d50e 100644 --- a/fpga/usrp3/lib/packet_proc/eth_dispatch.v +++ b/fpga/usrp3/lib/packet_proc/eth_dispatch.v @@ -11,7 +11,7 @@ // 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. +// 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. // @@ -40,148 +40,148 @@ module eth_dispatch #(parameter BASE=0) ( // Clocking and reset interface - input clk, - input reset, - input clear, + input clk, + input reset, + input clear, // Setting register interface - input set_stb, - input [15:0] set_addr, + 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, + 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, + 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, + 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, + 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; - reg drop_this_packet; - - 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 - // - - 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()); - - 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()); - - 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()); - - 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()); - - 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()); + // + // 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; + reg drop_this_packet; + + 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 + // + + 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()); + + 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()); + + 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()); + + 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()); + + 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()); assign debug = { @@ -194,347 +194,346 @@ module eth_dispatch }; - // - // Packet Forwarding State machine. - // - - always @(posedge clk) - if (reset || clear) begin - state <= WAIT_PACKET; - header_ram_addr <= 0; - drop_this_packet <= 0; - fwd_input <= 0; - end else begin - // Defaults. - drop_this_packet <= 0; - - 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) begin - header_ram_addr <= 0; - state <= forward_ndest? FORWARD_XO : 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 if (drop_this_packet) begin - header_ram_addr <= HEADER_RAM_SIZE-1; - state <= DROP_PACKET; - 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. - // - 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; - - // space_in_fifo <= 0; - // is_there_fifo_space <= 1; - // packet_length <= 0; - 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) || - (state == DROP_PACKET) || - (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_tuser,zpu_pre_tdata} = ((state == FORWARD_ZPU_AND_XO) || (state == FORWARD_ZPU)) ? - {out_tuser,out_tdata} : 0; - - assign {xo_pre_tuser,xo_pre_tdata} = ((state == FORWARD_ZPU_AND_XO) || (state == FORWARD_XO)) ? - {out_tuser,out_tdata} : 0; - - assign {vita_pre_tuser,vita_pre_tdata} = (state == FORWARD_RADIO_CORE) ? {out_tuser,out_tdata} : 0; - - assign zpu_pre_tlast = out_tlast && ((state == FORWARD_ZPU) || (state == FORWARD_ZPU_AND_XO)); - - assign xo_pre_tlast = out_tlast && ((state == FORWARD_XO) || (state == FORWARD_ZPU_AND_XO)); - - assign vita_pre_tlast = out_tlast && (state == FORWARD_RADIO_CORE); - - // - // Egress FIFO's (Large) - // - 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() - ); - - assign debug_flags = {vita_pre_tready,xo_pre_tready,zpu_pre_tready}; - - - + // + // Packet Forwarding State machine. + // + + always @(posedge clk) + if (reset || clear) begin + state <= WAIT_PACKET; + header_ram_addr <= 0; + drop_this_packet <= 0; + fwd_input <= 0; + end else begin + // Defaults. + drop_this_packet <= 0; + + 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) begin + header_ram_addr <= 0; + state <= forward_ndest? FORWARD_XO : 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 if (drop_this_packet) begin + header_ram_addr <= HEADER_RAM_SIZE-1; + state <= DROP_PACKET; + 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. + // + 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; + + //space_in_fifo <= 0; + //is_there_fifo_space <= 1; + //packet_length <= 0; + 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_tuser,zpu_pre_tdata} = ((state == FORWARD_ZPU_AND_XO) || (state == FORWARD_ZPU)) ? + {out_tuser,out_tdata} : 0; + + assign {xo_pre_tuser,xo_pre_tdata} = ((state == FORWARD_ZPU_AND_XO) || (state == FORWARD_XO)) ? + {out_tuser,out_tdata} : 0; + + assign {vita_pre_tuser,vita_pre_tdata} = (state == FORWARD_RADIO_CORE) ? {out_tuser,out_tdata} : 0; + + assign zpu_pre_tlast = out_tlast && ((state == FORWARD_ZPU) || (state == FORWARD_ZPU_AND_XO)); + + assign xo_pre_tlast = out_tlast && ((state == FORWARD_XO) || (state == FORWARD_ZPU_AND_XO)); + + assign vita_pre_tlast = out_tlast && (state == FORWARD_RADIO_CORE); + + // + // Egress FIFO's (Large) + // + 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() + ); + + assign debug_flags = {vita_pre_tready,xo_pre_tready,zpu_pre_tready}; + + + /* -----\/----- EXCLUDED -----\/----- - + wire vready, zready, oready; wire vvalid, zvalid, ovalid; - + reg [2:0] ed_state; localparam ED_IDLE = 3'd0; localparam ED_IN_HDR = 3'd1; @@ -556,22 +555,22 @@ module eth_dispatch ; endcase // case (ed_state) */ - + /* -----\/----- EXCLUDED -----\/----- axi_packet_gate #(.WIDTH(64), .SIZE(10)) vita_gate (.clk(clk), .reset(reset), .clear(clear), .i_tdata(in_tdata), .i_tlast(), .i_terror(), .i_tvalid(1'b0), .i_tready(vready), .o_tdata(vita_tdata), .o_tlast(vita_tlast), .o_tvalid(vita_tvalid), .o_tready(vita_tready)); - + axi_packet_gate #(.WIDTH(68), .SIZE(10)) zpu_gate (.clk(clk), .reset(reset), .clear(clear), .i_tdata({in_tuser,in_tdata}), .i_tlast(in_tlast), .i_terror(in_tuser[3]), .i_tvalid(in_tvalid), .i_tready(in_tready), .o_tdata({zpu_tuser,zpu_tdata}), .o_tlast(zpu_tlast), .o_tvalid(zpu_tvalid), .o_tready(zpu_tready)); - + axi_packet_gate #(.WIDTH(68), .SIZE(10)) out_gate (.clk(clk), .reset(reset), .clear(clear), .i_tdata({in_tuser,in_tdata}), .i_tlast(), .i_terror(), .i_tvalid(1'b0), .i_tready(oready), .o_tdata({out_tuser,out_tdata}), .o_tlast(out_tlast), .o_tvalid(out_tvalid), .o_tready(out_tready)); -----/\----- EXCLUDED -----/\----- */ - + endmodule // eth_dispatch |