diff options
| author | Ben Hilburn <ben.hilburn@ettus.com> | 2014-02-14 12:05:07 -0800 | 
|---|---|---|
| committer | Ben Hilburn <ben.hilburn@ettus.com> | 2014-02-14 12:05:07 -0800 | 
| commit | ff1546f8137f7f92bb250f685561b0c34cc0e053 (patch) | |
| tree | 7fa6fd05c8828df256a1b20e2935bd3ba9899e2c /fpga/usrp3/lib/xge_interface | |
| parent | 4f691d88123784c2b405816925f1a1aef69d18c1 (diff) | |
| download | uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.tar.gz uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.tar.bz2 uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.zip  | |
Pushing the bulk of UHD-3.7.0 code.
Diffstat (limited to 'fpga/usrp3/lib/xge_interface')
| -rw-r--r-- | fpga/usrp3/lib/xge_interface/Makefile.srcs | 10 | ||||
| -rw-r--r-- | fpga/usrp3/lib/xge_interface/axi64_to_xge64.v | 86 | ||||
| -rw-r--r-- | fpga/usrp3/lib/xge_interface/axi_count_packets_in_fifo.v | 155 | ||||
| -rw-r--r-- | fpga/usrp3/lib/xge_interface/xge64_to_axi64.v | 309 | ||||
| -rw-r--r-- | fpga/usrp3/lib/xge_interface/xge_handshake.v | 60 | ||||
| -rw-r--r-- | fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v | 325 | 
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  | 
