aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/packet_proc/eth_dispatch.v
diff options
context:
space:
mode:
authorBen Hilburn <ben.hilburn@ettus.com>2014-05-14 11:42:19 -0700
committerBen Hilburn <ben.hilburn@ettus.com>2014-05-14 11:42:19 -0700
commit00711ba213dde8aa0a099d2b18d3da0a33e6af79 (patch)
tree612f616ebbf8080b5dc9cb5d64a8062e9aa3a498 /fpga/usrp3/lib/packet_proc/eth_dispatch.v
parent5de0bfce3f03cc45a1eed93dc1b8df1b188b5040 (diff)
downloaduhd-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.v937
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