1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
//
// Copyright 2013 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
//
// 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 = 1;
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
|