156 lines
3.8 KiB
Verilog
156 lines
3.8 KiB
Verilog
//
|
|
// 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
|
|
|