Removed copy of FPGA source files.
Original-commit: fd3e84941de463fa1a7ebab0a69515b4bf2614cd
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
##################################################
|
||||
# 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 \
|
||||
))
|
||||
@@ -1,86 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
@@ -1,155 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
@@ -1,60 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
@@ -1,325 +0,0 @@
|
||||
//
|
||||
// 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_tlast_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_4k_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_4k_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
|
||||
Reference in New Issue
Block a user