aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/xge_interface
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/xge_interface')
-rw-r--r--fpga/usrp3/lib/xge_interface/Makefile.srcs10
-rw-r--r--fpga/usrp3/lib/xge_interface/axi64_to_xge64.v86
-rw-r--r--fpga/usrp3/lib/xge_interface/axi_count_packets_in_fifo.v155
-rw-r--r--fpga/usrp3/lib/xge_interface/xge64_to_axi64.v309
-rw-r--r--fpga/usrp3/lib/xge_interface/xge_handshake.v60
-rw-r--r--fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v325
6 files changed, 945 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/xge_interface/Makefile.srcs b/fpga/usrp3/lib/xge_interface/Makefile.srcs
new file mode 100644
index 000000000..63cef065d
--- /dev/null
+++ b/fpga/usrp3/lib/xge_interface/Makefile.srcs
@@ -0,0 +1,10 @@
+##################################################
+# Logic to interface to Opencores 10G MAC
+##################################################
+XGE_INTERFACE_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/xge_interface/, \
+axi64_to_xge64.v \
+axi_count_packets_in_fifo.v \
+xge64_to_axi64.v \
+xge_handshake.v \
+xge_mac_wrapper.v \
+))
diff --git a/fpga/usrp3/lib/xge_interface/axi64_to_xge64.v b/fpga/usrp3/lib/xge_interface/axi64_to_xge64.v
new file mode 100644
index 000000000..4bb9d200b
--- /dev/null
+++ b/fpga/usrp3/lib/xge_interface/axi64_to_xge64.v
@@ -0,0 +1,86 @@
+//
+// Copyright 2013 Ettus Research LLC
+//
+
+
+//
+// Removes 6 alignment bytes at the beginning of every packet.
+// This gives us proper alignment to the IP/UDP header.
+//
+// Place an SOF indication in bit[3] of the output tuser.
+//
+
+module axi64_to_xge64
+ (
+ input clk,
+ input reset,
+ input clear,
+ input [63:0] s_axis_tdata,
+ input [3:0] s_axis_tuser,
+ input s_axis_tlast,
+ input s_axis_tvalid,
+ output s_axis_tready,
+ output [63:0] m_axis_tdata,
+ output [3:0] m_axis_tuser,
+ output m_axis_tlast,
+ output m_axis_tvalid,
+ input m_axis_tready
+ );
+
+ localparam STORE_FIRST = 0;
+ localparam FORWARD_FULL = 1;
+ localparam RELEASE_LAST = 2;
+
+ reg [1:0] state;
+ reg [15:0] saved;
+ reg [2:0] last_occ;
+ reg last_sof;
+
+ //on last line when eof and not finishing with 7 or 8 bytes as last word.
+ wire last_line = (s_axis_tlast && !(s_axis_tuser[2:0] == 3'b111 || s_axis_tuser[2:0] == 3'b000));
+
+ always @(posedge clk) begin
+ if(reset | clear) begin
+ last_sof <= 0;
+ last_occ <= 0;
+ state <= STORE_FIRST;
+ end
+ else begin
+ if (s_axis_tvalid && s_axis_tready) begin
+ saved <= s_axis_tdata[15:0];
+ last_occ <= s_axis_tuser[2:0];
+ last_sof <= (state == STORE_FIRST) ;
+ end
+
+ case(state)
+
+ STORE_FIRST: begin
+ if (s_axis_tvalid && s_axis_tready) begin
+ state <= FORWARD_FULL;
+ end
+ end
+
+ FORWARD_FULL: begin
+ if (s_axis_tvalid && s_axis_tready && s_axis_tlast) begin
+ state <= last_line? STORE_FIRST : RELEASE_LAST;
+ end
+ end
+
+ RELEASE_LAST: begin
+ if (m_axis_tvalid && m_axis_tready) begin
+ state <= STORE_FIRST;
+ end
+ end
+
+ endcase //state
+ end
+ end
+
+ assign m_axis_tdata[63:0] = {saved, s_axis_tdata[63:16]};
+ assign m_axis_tuser[3] = last_sof;
+ assign m_axis_tlast = (state == RELEASE_LAST)? 1'b1 : last_line;
+ assign m_axis_tuser[2:0] = ((state == RELEASE_LAST)? last_occ : (last_line? s_axis_tuser[2:0] : 3'b110)) + 3'b010;
+ assign m_axis_tvalid = (state == STORE_FIRST)? 0 : ((state == RELEASE_LAST)? 1 : s_axis_tvalid);
+ assign s_axis_tready = (state == STORE_FIRST)? 1 : ((state == RELEASE_LAST)? 0 : m_axis_tready);
+
+endmodule //fifo69_txrealign
diff --git a/fpga/usrp3/lib/xge_interface/axi_count_packets_in_fifo.v b/fpga/usrp3/lib/xge_interface/axi_count_packets_in_fifo.v
new file mode 100644
index 000000000..45eae42c0
--- /dev/null
+++ b/fpga/usrp3/lib/xge_interface/axi_count_packets_in_fifo.v
@@ -0,0 +1,155 @@
+//
+// Copyright 2013 Ettus Research LLC
+//
+
+
+//
+// Tracks the number of complete packets in an AXI FIFO so that
+// the XGE MAC can commit to transmitting a packet.
+//
+
+module axi_count_packets_in_fifo
+ (
+ input clk,
+ input reset,
+ input in_axis_tvalid,
+ input in_axis_tready,
+ input in_axis_tlast,
+ input out_axis_tvalid,
+ input out_axis_tready,
+ input out_axis_tlast,
+ input pkt_tx_full,
+ output enable_tx
+ );
+
+ localparam WAIT_SOF = 0;
+ localparam WAIT_EOF = 1;
+
+ localparam WAIT_FULL = 0;
+ localparam DELAY_TO_EOF = 0;
+ localparam WAIT_SPACE = 2;
+
+
+ reg in_state, out_state;
+ reg [1:0] full_state;
+ reg pause_tx;
+
+ reg [7:0] pkt_count;
+
+
+ //
+ // Count packets arriving into large FIFO
+ //
+ always @(posedge clk)
+ if (reset) begin
+ in_state <= WAIT_SOF;
+ end else
+ case(in_state)
+ WAIT_SOF:
+ if (in_axis_tvalid && in_axis_tready) begin
+ in_state <= WAIT_EOF;
+ end else begin
+ in_state <= WAIT_SOF;
+ end
+ WAIT_EOF:
+ if (in_axis_tlast && in_axis_tvalid && in_axis_tready) begin
+ in_state <= WAIT_SOF;
+ end else begin
+ in_state <= WAIT_EOF;
+ end
+ endcase // case(in_state)
+
+
+ //
+ // Count packets leaving large FIFO
+ //
+ always @(posedge clk)
+ if (reset) begin
+ out_state <= WAIT_SOF;
+ end else
+ case(out_state)
+ WAIT_SOF:
+ if (out_axis_tvalid && out_axis_tready) begin
+ out_state <= WAIT_EOF;
+ end else begin
+ out_state <= WAIT_SOF;
+ end
+ WAIT_EOF:
+ if (out_axis_tlast && out_axis_tvalid && out_axis_tready) begin
+ out_state <= WAIT_SOF;
+ end else begin
+ out_state <= WAIT_EOF;
+ end
+ endcase // case(in_state)
+
+
+ //
+ // Count packets in FIFO.
+ // No protection on counter wrap,
+ // unclear how such an error could occur or how to gracefully deal with it.
+ //
+ always @(posedge clk)
+ if (reset)
+ pkt_count <= 0;
+ else if (((out_state==WAIT_EOF) && out_axis_tlast && out_axis_tvalid && out_axis_tready)
+ && ((in_state==WAIT_EOF) && in_axis_tlast && in_axis_tvalid && in_axis_tready))
+ pkt_count <= pkt_count;
+ else if ((out_state==WAIT_EOF) && out_axis_tlast && out_axis_tvalid && out_axis_tready)
+ pkt_count <= pkt_count - 1;
+ else if ((in_state==WAIT_EOF) && in_axis_tlast && in_axis_tvalid && in_axis_tready)
+ pkt_count <= pkt_count + 1;
+
+
+ //
+ // Guard against Tx MAC overflow (as indicated by pkt_tx_full)
+ //
+ always @(posedge clk)
+ if (reset) begin
+ pause_tx <= 0;
+ full_state <= WAIT_FULL;
+ end
+ else begin
+ pause_tx <= 0;
+ case(full_state)
+ WAIT_FULL:
+ // Search for pkt_tx_full going asserted
+ if (pkt_tx_full && (out_state == WAIT_SOF)) begin
+ full_state <= WAIT_SPACE;
+ pause_tx <= 1;
+ end else if (pkt_tx_full && (out_state == WAIT_EOF)) begin
+ full_state <= DELAY_TO_EOF;
+ end
+
+ DELAY_TO_EOF:
+ // pkt_tx_full has gone asserted during Tx of a packet from FIFO.
+ // Wait until either FIFO has space again and transition direct to WAIT_FULL
+ // or at EOF if pkt_tx_full is still asserted the transition to WAIT_SPACE until
+ // MAC flags there is space again.
+ if (pkt_tx_full && out_axis_tlast && out_axis_tvalid && out_axis_tready) begin
+ full_state <= WAIT_SPACE;
+ pause_tx <= 1;
+ end else if (pkt_tx_full) begin
+ full_state <= DELAY_TO_EOF;
+ end else
+ full_state <= WAIT_FULL;
+
+ WAIT_SPACE:
+ // Wait for MAC to flag space in internal Tx FIFO again then transition to WAIT_FULL.
+ if (pkt_tx_full) begin
+ full_state <= WAIT_SPACE;
+ pause_tx <= 1;
+ end else
+ full_state <= WAIT_FULL;
+
+ endcase // case(full_state)
+ end
+
+
+ // Enable Tx to MAC
+ assign enable_tx = (pkt_count != 0) && ~pause_tx;
+
+
+
+
+endmodule // count_tx_packets
+
diff --git a/fpga/usrp3/lib/xge_interface/xge64_to_axi64.v b/fpga/usrp3/lib/xge_interface/xge64_to_axi64.v
new file mode 100644
index 000000000..1ff4af748
--- /dev/null
+++ b/fpga/usrp3/lib/xge_interface/xge64_to_axi64.v
@@ -0,0 +1,309 @@
+//
+// Copyright 2013 Ettus Research LLC
+//
+
+
+// Adds 6 bytes at the beginning of every packet
+// This gives us good32/64bit alignment of IP/UDP headers.
+//
+// The 6 bytes added include an octet passed as a parameter allowing a label to
+// be added as metatdata in the header padding. This is typically the ingress
+// port to be tagged in the packet as metadata.
+//
+// bit[65] EOF
+// bit[64] SOF
+// bit[68:66] occ
+//
+// This design will break if downstream can not be guarenteed to be ready to accept data.
+// XGE MAC expects to be able to stream whole packet with no handshaking.
+// We force downstream packet gate to discard packet by signalling error with tlast and
+// resynchronizing with upstream.
+//
+
+module xge64_to_axi64
+ #(parameter LABEL=0)
+ (
+ input clk,
+ input reset,
+ input clear,
+ input [63:0] datain,
+ input [2:0] occ,
+ input sof,
+ input eof,
+ input err,
+ input valid,
+ output reg [63:0] axis_tdata,
+ output reg [3:0] axis_tuser,
+ output reg axis_tlast,
+ output reg axis_tvalid, // Signal data avilable to downstream
+ input axis_tready
+ );
+
+ localparam EMPTY = 0;
+ localparam IN_USE = 1;
+ localparam FLUSHING3 = 2;
+ localparam FLUSHING4 = 3;
+ localparam FLUSHING5 = 4;
+ localparam FLUSHING6 = 5;
+ localparam FLUSHING7 = 6;
+ localparam FLUSHING8 = 7;
+ localparam ERROR1 = 8;
+
+
+ localparam EOF1 = 3'b001;
+ localparam EOF2 = 3'b010;
+ localparam EOF3 = 3'b011;
+ localparam EOF4 = 3'b100;
+ localparam EOF5 = 3'b101;
+ localparam EOF6 = 3'b110;
+ localparam EOF7 = 3'b111;
+ localparam EOF8 = 3'b000;
+
+ reg [3:0] state;
+ reg err_reg;
+ reg [47:0] holding_reg;
+
+ always @(posedge clk)
+ if(reset | clear) begin
+ state <= EMPTY;
+ axis_tdata <= 0;
+ holding_reg <= 0;
+ axis_tvalid <= 0;
+ end else begin
+ // Defaults
+ axis_tvalid <= 0;
+ axis_tuser <= 0;
+ axis_tlast <= 0;
+ err_reg <= 0;
+
+ case(state)
+ EMPTY: begin
+ if (valid & axis_tready & sof) begin
+ // Start of packet should always be received in this state.
+ // It should NEVER be possible to get a packet from the MAC with EOF also set in
+ // the first 64 bits so not designed for.
+ // Add pad. Store last 6 octets into holding, change state to show data in holding.
+ state <= IN_USE;
+ axis_tvalid <= 1;
+ end
+ else if (valid & ~axis_tready)
+ // Assert on this condition, add H/W to deal with overflow later.
+ $display("ERROR: xge64_to_axi64, valid & ~axis_tready");
+
+ holding_reg <= datain[47:0];
+ axis_tdata[63:56] <= LABEL; // Tag packet with label
+ axis_tdata[55:16] <= 40'h0;
+ axis_tdata[15:0] <= datain[63:48];
+ end
+
+ IN_USE: begin
+ if (valid & axis_tready & (eof | err)) begin
+ // End of packet should always be received in this state.
+ // If Error is asserted from MAC, immediate EOF is forced,
+ // and the error flag set in tuser. State machine will return to WAIT
+ // state and search for new SOF thereby discarding anything left of error packet.
+ //
+ // In the case of 3 through 8 valid octets in the final 64bits input,
+ // we must run another cycle afterwards since we have 6 more bytes still in holding.
+ err_reg <= err;
+ holding_reg[47:0] <= datain[47:0];
+ axis_tdata[63:16] <= holding_reg[47:0];
+ axis_tdata[15:0] <= datain[63:48];
+ axis_tvalid <= 1;
+
+ case(occ[2:0])
+ // 8 valid Octets in last word of packet, finish next cycle
+ 0: begin
+ state <= FLUSHING8;
+ end
+ // 7 valid Octets in last word of packet, finish next cycle
+ 7: begin
+ state <= FLUSHING7;
+ end
+ // 6 valid octets in last word of packet, finish next cycle
+ 6: begin
+ state <= FLUSHING6;
+ end
+ // 5 valid octets in last word of packet, finish next cycle
+ 5: begin
+ state <= FLUSHING5;
+ end
+ // 4 valid octets in last word of packet, finish next cycle
+ 4: begin
+ state <= FLUSHING4;
+ end
+ // 3 valid octets in last word of packet, finish next cycle
+ 3: begin
+ state <= FLUSHING3;
+ end
+ // 2 valid octets in last word of packet, finish this cycle
+ 2: begin
+ axis_tuser <= {err,EOF8};
+ state <= EMPTY;
+ axis_tlast <= 1;
+ end
+ // 1 valid octets in last word of packet, finish this cycle
+ 1: begin
+ axis_tuser <= {err,EOF7};
+ state <= EMPTY;
+ axis_tlast <= 1;
+ end
+ endcase // case (occ[2:0])
+ end // if (valid & axis_tready & eof)
+ else if (valid & axis_tready) begin
+ // No EOF indication so in packet payload somewhere still.
+ state <= IN_USE;
+ holding_reg[47:0] <= datain[47:0];
+ axis_tdata[63:16] <= holding_reg[47:0];
+ axis_tdata[15:0] <= datain[63:48];
+ axis_tvalid <= 1;
+ end
+ else if (valid & ~axis_tready) begin
+ // Assert on this condition
+ $display("ERROR: xge64_to_axi64, valid & ~axis_tready");
+ // Keep error state asserted ready for downstream to accept
+ state <= ERROR1;
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end else if (~valid) begin
+ // Assert on this condition, don't expect the MAC to ever throtle dataflow intra-packet.
+ $display("ERROR: xge64_to_axi64, ~valid ");
+ state <= ERROR1;
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end
+ end // case: IN_USE
+
+ FLUSHING3: begin
+ if (axis_tready) begin
+ // EOF has been received last cycle.
+ // Ethernet interframe gap means we don't have to search for back-to-back EOF-SOF here.
+ // 1 valid Octets to finish
+ state <= EMPTY;
+ axis_tlast <= 1;
+ axis_tuser <= {err_reg, EOF1};
+ axis_tdata[63:16] <= holding_reg[47:0];
+ axis_tvalid <= 1;
+ end else begin
+ state <= ERROR1;
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end // else: !if(axis_tready)
+ end
+
+ FLUSHING4: begin
+ if (axis_tready) begin
+ // EOF has been received last cycle.
+ // Ethernet interframe gap means we don't have to search for back-to-back EOF-SOF here.
+ // 2 valid Octets to finish
+ state <= EMPTY;
+ axis_tlast <= 1;
+ axis_tuser <= {err_reg, EOF2};
+ axis_tdata[63:16] <= holding_reg[47:0];
+ axis_tvalid <= 1;
+ end else begin
+ state <= ERROR1;
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end // else: !if(axis_tready)
+ end
+
+ FLUSHING5: begin
+ if (axis_tready) begin
+ // EOF has been received last cycle.
+ // Ethernet interframe gap means we don't have to search for back-to-back EOF-SOF here.
+ // 3 valid Octets to finish
+ state <= EMPTY;
+ axis_tlast <= 1;
+ axis_tuser <= {err_reg, EOF3};
+ axis_tdata[63:16] <= holding_reg[47:0];
+ axis_tvalid <= 1;
+ end else begin
+ state <= ERROR1;
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end // else: !if(axis_tready)
+ end
+
+ FLUSHING6: begin
+ if (axis_tready) begin
+ // EOF has been received last cycle.
+ // Ethernet interframe gap means we don't have to search for back-to-back EOF-SOF here.
+ // 4 valid Octets to finish
+ state <= EMPTY;
+ axis_tlast <= 1;
+ axis_tuser <= {err_reg, EOF4};
+ axis_tdata[63:16] <= holding_reg[47:0];
+ axis_tvalid <= 1;
+ end else begin
+ state <= ERROR1;
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end // else: !if(axis_tready)
+ end
+
+ FLUSHING7: begin
+ if (axis_tready) begin
+ // EOF has been received last cycle.
+ // Ethernet interframe gap means we don't have to search for back-to-back EOF-SOF here.
+ // 5 valid Octets to finish
+ state <= EMPTY;
+ axis_tlast <= 1;
+ axis_tuser <= {err_reg, EOF5};
+ axis_tdata[63:16] <= holding_reg[47:0];
+ axis_tvalid <= 1;
+ end else begin
+ state <= ERROR1;
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end // else: !if(axis_tready)
+ end
+
+ FLUSHING8: begin
+ if (axis_tready) begin
+ // EOF has been received last cycle.
+ // Ethernet interframe gap means we don't have to search for back-to-back EOF-SOF here.
+ // 6 valid Octets to finish
+ state <= EMPTY;
+ axis_tlast <= 1;
+ axis_tuser <= {err_reg, EOF6};
+ axis_tdata[63:16] <= holding_reg[47:0];
+ axis_tvalid <= 1;
+ end else begin
+ state <= ERROR1;
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end // else: !if(axis_tready)
+ end
+
+ ERROR1: begin
+ // We were already actively receiving a packet from the upstream MAC and the downstream
+ // signaled not ready by de-asserting tready. Since we can't back pressure the MAC we have to
+ // abandon the current packet, discarding any data already sent down stream by sending an asserted error
+ // with a tlast when ever tready becomes asserted again. Meanwhile we start dropping arriving MAC
+ // data on the floor since there is nothing useful we can do with it currently.
+ if (axis_tready)
+ begin
+ // OK tready is asserted again so tlast is geting accepted this cycle along with an asserted error.
+ state <= EMPTY;
+ end else begin
+ // Keep error state asserted ready for downstream to accept
+ axis_tlast <= 1;
+ axis_tvalid <= 1;
+ axis_tuser <= {1'b1, EOF8}; // Force error in this packet.
+ end
+ end // case: ERROR1
+
+
+ endcase // case(state)
+ end // else: !if(reset | clear)
+
+endmodule
diff --git a/fpga/usrp3/lib/xge_interface/xge_handshake.v b/fpga/usrp3/lib/xge_interface/xge_handshake.v
new file mode 100644
index 000000000..251099f57
--- /dev/null
+++ b/fpga/usrp3/lib/xge_interface/xge_handshake.v
@@ -0,0 +1,60 @@
+//
+// Copyright 2013 Ettus Research LLC
+//
+
+//
+//
+// Provide required handshake to Opencores XGE MAC to initiate Rx of one available packet
+//
+//
+
+
+module xge_handshake
+ (
+ input clk,
+ input reset,
+ output reg pkt_rx_ren,
+ input pkt_rx_avail,
+ input pkt_rx_eop
+ );
+
+ localparam IDLE=0;
+ localparam RX=1;
+
+ reg state;
+
+
+ always @(posedge clk)
+ if (reset) begin
+ pkt_rx_ren <= 0;
+ state <= IDLE;
+ end else begin
+ case (state)
+ //
+ // Wait for pkt_rx_avail to be asserted, then assert pkt_rx_ren next cycle
+ //
+ IDLE: begin
+ if (pkt_rx_avail) begin
+ pkt_rx_ren <= 1;
+ state <= RX;
+ end else begin
+ pkt_rx_ren <= 0;
+ state <= IDLE;
+ end
+ end
+ //
+ // Keep pkt_rx_ren asserted until EOF received.
+ //
+ RX: begin
+ if (pkt_rx_eop) begin
+ pkt_rx_ren <= 0;
+ state <= IDLE;
+ end else begin
+ pkt_rx_ren <= 1;
+ state <= RX;
+ end
+ end
+
+ endcase // case(state)
+ end // else: !if(reset)
+endmodule // xge_handshake
diff --git a/fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v b/fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v
new file mode 100644
index 000000000..21c71ba37
--- /dev/null
+++ b/fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v
@@ -0,0 +1,325 @@
+//
+// Copyright 2013 Ettus Research LLC
+//
+
+
+//
+// Wrap XGE MAC so that:
+//
+// *) Signals are crossed between the MAC's own 156.25MHz clock domain and the
+// main FPGA clock domain.
+// *) 6 byte Padding is added at RX, including metadata so that IP headers become aligned.
+// *) 6 Byte padding is stripped at TX, so that Eth header data starts immediately.
+// *) TX & RX can buffer at least an MTU sized packet
+// *) On TX, to not start an Ethernet Tx until a complete packet is present in the
+// last Tx FIFO so that the MAC doesn't underrun.
+//
+
+module xge_mac_wrapper
+ #(parameter PORTNUM=8'd0)
+
+ (
+ // XGMII
+ input xgmii_clk,
+ output [63:0] xgmii_txd,
+ output [7:0] xgmii_txc,
+ input [63:0] xgmii_rxd,
+ input [7:0] xgmii_rxc,
+ // MDIO
+ output mdc,
+ output mdio_in,
+ input mdio_out,
+ // Wishbone I/F
+ input [7:0] wb_adr_i, // To wishbone_if0 of wishbone_if.v
+ input wb_clk_i, // To sync_clk_wb0 of sync_clk_wb.v, ...
+ input wb_cyc_i, // To wishbone_if0 of wishbone_if.v
+ input [31:0] wb_dat_i, // To wishbone_if0 of wishbone_if.v
+ input wb_rst_i, // To sync_clk_wb0 of sync_clk_wb.v, ...
+ input wb_stb_i, // To wishbone_if0 of wishbone_if.v
+ input wb_we_i, // To wishbone_if0 of wishbone_if.v
+ output wb_ack_o, // From wishbone_if0 of wishbone_if.v
+ output [31:0] wb_dat_o, // From wishbone_if0 of wishbone_if.v
+ output wb_int_o, // From wishbone_if0 of wishbone_if.v
+ // Client FIFO Interfaces
+ input sys_clk,
+ input reset, // From sys_clk domain.
+ output [63:0] rx_tdata,
+ output [3:0] rx_tuser,
+ output rx_tlast,
+ output rx_tvalid,
+ input rx_tready,
+ input [63:0] tx_tdata,
+ input [3:0] tx_tuser, // Bit[3] (error) is ignored for now.
+ input tx_tlast,
+ input tx_tvalid,
+ output tx_tready,
+ // Other
+ input phy_ready,
+ // Debug
+ output [31:0] debug_rx,
+ output [31:0] debug_tx);
+
+
+
+ (* ASYNC_REG = "TRUE" *)
+ reg xgmii_reset_r1;
+ reg xgmii_reset;
+
+ //
+ // Generate 156MHz synchronized reset localy
+ //
+ always @(posedge xgmii_clk or posedge reset)
+ begin
+ if (reset) begin
+ xgmii_reset_r1 <= 1'b1;
+ xgmii_reset <= 1'b1;
+ end
+ else begin
+ xgmii_reset_r1 <= 1'b0; // IJB. Was PLL lock here.
+ xgmii_reset <= xgmii_reset_r1;
+ end
+ end // always @ (posedge xgmii_clk or posedge reset)
+
+ //
+ // 10G MAC
+ //
+ wire [63:0] eth_rx_data;
+ wire eth_rx_avail;
+ wire eth_rx_eof;
+ wire eth_rx_err;
+ wire [2:0] eth_rx_occ;
+ wire eth_rx_sof;
+ wire eth_rx_valid;
+ wire eth_rx_ren;
+
+ wire eth_tx_full;
+ wire [63:0] eth_tx_data;
+ wire eth_tx_eof;
+ wire [2:0] eth_tx_occ;
+ wire eth_tx_sof;
+ wire eth_tx_valid;
+
+ xge_mac xge_mac
+ (
+ // Outputs
+ .pkt_rx_avail (eth_rx_avail),
+ .pkt_rx_data (eth_rx_data),
+ .pkt_rx_eop (eth_rx_eof),
+ .pkt_rx_err (eth_rx_err),
+ .pkt_rx_mod (eth_rx_occ),
+ .pkt_rx_sop (eth_rx_sof),
+ .pkt_rx_val (eth_rx_valid),
+ .pkt_tx_full (eth_tx_full),
+ .wb_ack_o (wb_ack_o),
+ .wb_dat_o (wb_dat_o),
+ .wb_int_o (xge_int),
+ .xgmii_txc (xgmii_txc[7:0]),
+ .xgmii_txd (xgmii_txd[63:0]),
+ .mdc (mdc),
+ .mdio_out (mdio_in),// Switch sense of in and out here for master and slave.
+ .mdio_tri (mdio_tri),
+ .xge_gpo ( ),
+ // Inputs
+ .clk_156m25 (xgmii_clk),
+ .clk_xgmii_rx (xgmii_clk),
+ .clk_xgmii_tx (xgmii_clk),
+ .pkt_rx_ren (eth_rx_ren),
+ .pkt_tx_data (eth_tx_data),
+ .pkt_tx_eop (eth_tx_eof),
+ .pkt_tx_mod (eth_tx_occ),
+ .pkt_tx_sop (eth_tx_sof),
+ .pkt_tx_val (eth_tx_valid),
+ .reset_156m25_n (~xgmii_reset),
+ .reset_xgmii_rx_n (~xgmii_reset),
+ .reset_xgmii_tx_n (~xgmii_reset),
+ .wb_adr_i (wb_adr_i[7:0]),
+ .wb_clk_i (wb_clk_i),
+ .wb_cyc_i (wb_cyc_i),
+ .wb_dat_i (wb_dat_i),
+ .wb_rst_i (wb_rst_i),
+ .wb_stb_i (wb_stb_i),
+ .wb_we_i (wb_we_i),
+ .xgmii_rxc (xgmii_rxc[7:0]),
+ .xgmii_rxd (xgmii_rxd[63:0]),
+ .mdio_in (mdio_out), // Switch sense of in and out here for master and slave.
+ .xge_gpi (/*{2'b00,align_status,mgt_tx_ready,sync_status[3:0]}*/0)
+ );
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////
+ // RX FIFO Chain
+ ///////////////////////////////////////////////////////////////////////////////////////
+ wire [63:0] rx_tdata_int;
+ wire [3:0] rx_tuser_int;
+ wire rx_talst_int;
+ wire rx_tvalid_int;
+ wire rx_tready_int;
+
+ //
+ // Logic to drive pkt_rx_ren on XGE MAC
+ //
+ xge_handshake xge_handshake
+ (
+ .clk(xgmii_clk),
+ .reset(xgmii_reset),
+ .pkt_rx_ren(eth_rx_ren),
+ .pkt_rx_avail(eth_rx_avail),
+ .pkt_rx_eop(eth_rx_eof)
+ );
+
+ //
+ // Add pad of 6 empty bytes before MAC addresses of new Rxed packet so that IP
+ // headers are alligned. Also put metadata in first octet of pad that shows
+ // ingress port.
+ //
+ xge64_to_axi64 #(.LABEL(PORTNUM)) xge64_to_axi64
+ (
+ .clk(xgmii_clk),
+ .reset(xgmii_reset),
+ .clear(clear),
+ .datain(eth_rx_data),
+ .occ(eth_rx_occ),
+ .sof(eth_rx_sof),
+ .eof(eth_rx_eof),
+ .err(eth_rx_err),
+ .valid(eth_rx_valid),
+ .axis_tdata(rx_tdata_int),
+ .axis_tuser(rx_tuser_int),
+ .axis_tlast(rx_tlast_int),
+ .axis_tvalid(rx_tvalid_int),
+ .axis_tready(rx_tready_int)
+ );
+
+ //
+ // Large FIFO must be able to run input side at 64b@156MHz to sustain 10Gb Rx.
+ //
+
+ axi64_8k_2clk_fifo rxfifo_2clk
+ (
+ .s_aresetn(~xgmii_reset),
+ .s_aclk(xgmii_clk),
+ .s_axis_tvalid(rx_tvalid_int),
+ .s_axis_tready(rx_tready_int),
+ .s_axis_tdata(rx_tdata_int),
+ .s_axis_tlast(rx_tlast_int),
+ .s_axis_tuser(rx_tuser_int),
+ .axis_wr_data_count(),
+
+ .m_aclk(sys_clk),
+ .m_axis_tvalid(rx_tvalid),
+ .m_axis_tready(rx_tready),
+ .m_axis_tdata(rx_tdata),
+ .m_axis_tlast(rx_tlast),
+ .m_axis_tuser(rx_tuser),
+ .axis_rd_data_count() );
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////
+ // TX FIFO Chain
+ ///////////////////////////////////////////////////////////////////////////////////////
+
+ wire [63:0] tx_tdata_int;
+ wire [3:0] tx_tuser_int;
+ wire tx_tlast_int;
+ wire tx_tvalid_int;
+ wire tx_tready_int;
+
+ wire [63:0] tx_tdata_int2;
+ wire [3:0] tx_tuser_int2;
+ wire tx_tlast_int2;
+ wire tx_tvalid_int2;
+ wire tx_tready_int2;
+
+ wire tx_tvalid_int3;
+ wire tx_tready_int3;
+ wire tx_sof_int3;
+
+
+ axi64_8k_2clk_fifo txfifo_2clk_1x
+ (
+ .s_aresetn(~xgmii_reset),
+ .s_aclk(sys_clk),
+ .s_axis_tvalid(tx_tvalid),
+ .s_axis_tready(tx_tready),
+ .s_axis_tdata(tx_tdata),
+ .s_axis_tlast(tx_tlast),
+ .s_axis_tuser(tx_tuser),
+ .axis_wr_data_count(),
+
+ .m_aclk(xgmii_clk),
+ .m_axis_tvalid(tx_tvalid_int),
+ .m_axis_tready(tx_tready_int),
+ .m_axis_tdata(tx_tdata_int),
+ .m_axis_tlast(tx_tlast_int),
+ .m_axis_tuser(tx_tuser_int),
+ .axis_rd_data_count() );
+
+ //
+ // Strip the 6 octet ethernet padding we used internally.
+ // Put SOF into bit[3] of tuser.
+ //
+ axi64_to_xge64 axi64_to_xge64
+ (
+ .clk(xgmii_clk),
+ .reset(xgmii_reset),
+ .clear(clear),
+ .s_axis_tdata(tx_tdata_int),
+ .s_axis_tuser(tx_tuser_int),
+ .s_axis_tlast(tx_tlast_int),
+ .s_axis_tvalid(tx_tvalid_int),
+ .s_axis_tready(tx_tready_int),
+ .m_axis_tdata(tx_tdata_int2),
+ .m_axis_tuser(tx_tuser_int2),
+ .m_axis_tlast(tx_tlast_int2),
+ .m_axis_tvalid(tx_tvalid_int2),
+ .m_axis_tready(tx_tready_int2)
+ );
+
+ //
+ // Large FIFO can hold a max sized ethernet packet.
+ //
+ axi64_8k_2clk_fifo txfifo_2clk_2
+ (
+ .s_aresetn(~xgmii_reset),
+ .s_aclk(xgmii_clk),
+ .s_axis_tvalid(tx_tvalid_int2),
+ .s_axis_tready(tx_tready_int2),
+ .s_axis_tdata(tx_tdata_int2),
+ .s_axis_tlast(tx_tlast_int2),
+ .s_axis_tuser(tx_tuser_int2),
+ .axis_wr_data_count(),
+
+ .m_aclk(xgmii_clk),
+ .m_axis_tvalid(tx_tvalid_int3),
+ .m_axis_tready(tx_tready_int3),
+ .m_axis_tdata(eth_tx_data),
+ .m_axis_tlast(eth_tx_eof),
+ .m_axis_tuser({tx_sof_int3,eth_tx_occ}),
+ .axis_rd_data_count() );
+
+ //
+ // Monitor number of Ethernet packets in tx_fifo2
+ //
+ axi_count_packets_in_fifo axi_count_packets_in_fifo
+ (
+ .clk(xgmii_clk),
+ .reset(xgmii_reset),
+ .in_axis_tvalid(tx_tvalid_int2),
+ .in_axis_tready(tx_tready_int2),
+ .in_axis_tlast(tx_tlast_int2),
+ .out_axis_tvalid(tx_tvalid_int3),
+ .out_axis_tready(tx_tready_int3),
+ .out_axis_tlast(eth_tx_eof),
+ .pkt_tx_full(eth_tx_full),
+ .enable_tx(enable_tx) );
+
+ //
+ //
+ // Supress FIFO flags to stop overflow of MAC in Tx direction
+ //
+ assign eth_tx_valid = tx_tvalid_int3 & enable_tx;
+ assign tx_tready_int3 = enable_tx;
+ assign eth_tx_sof = tx_sof_int3 & enable_tx;
+
+
+endmodule