Skip to content

Commit 3d90e80

Browse files
committed
Fix frame FIFO full logic bug
1 parent f9a5e68 commit 3d90e80

File tree

2 files changed

+77
-71
lines changed

2 files changed

+77
-71
lines changed

rtl/axis_async_fifo.v

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ localparam WIDTH = USER_OFFSET + (USER_ENABLE ? USER_WIDTH : 0);
124124
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_next;
125125
reg [ADDR_WIDTH:0] wr_ptr_cur_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_cur_next;
126126
reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_gray_next;
127+
reg [ADDR_WIDTH:0] wr_ptr_cur_gray_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_cur_gray_next;
127128
reg [ADDR_WIDTH:0] wr_addr_reg = {ADDR_WIDTH+1{1'b0}};
128129
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
129130
reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_gray_next;
@@ -155,11 +156,14 @@ reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next;
155156
wire full = ((wr_ptr_gray_reg[ADDR_WIDTH] != rd_ptr_gray_sync2_reg[ADDR_WIDTH]) &&
156157
(wr_ptr_gray_reg[ADDR_WIDTH-1] != rd_ptr_gray_sync2_reg[ADDR_WIDTH-1]) &&
157158
(wr_ptr_gray_reg[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2_reg[ADDR_WIDTH-2:0]));
159+
wire full_cur = ((wr_ptr_cur_gray_reg[ADDR_WIDTH] != rd_ptr_gray_sync2_reg[ADDR_WIDTH]) &&
160+
(wr_ptr_cur_gray_reg[ADDR_WIDTH-1] != rd_ptr_gray_sync2_reg[ADDR_WIDTH-1]) &&
161+
(wr_ptr_cur_gray_reg[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2_reg[ADDR_WIDTH-2:0]));
158162
// empty when pointers match exactly
159163
wire empty = rd_ptr_gray_reg == wr_ptr_gray_sync2_reg;
160164
// overflow within packet
161-
wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
162-
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
165+
wire full_wr = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
166+
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
163167

164168
// control signals
165169
reg write;
@@ -184,7 +188,7 @@ reg good_frame_sync2_reg = 1'b0;
184188
reg good_frame_sync3_reg = 1'b0;
185189
reg good_frame_sync4_reg = 1'b0;
186190

187-
assign s_axis_tready = (!full || DROP_WHEN_FULL) && !s_rst_sync3_reg;
191+
assign s_axis_tready = (FRAME_FIFO ? (!full_cur || full_wr || DROP_WHEN_FULL) : !full) && !s_rst_sync3_reg;
188192

189193
generate
190194
assign s_axis[DATA_WIDTH-1:0] = s_axis_tdata;
@@ -249,41 +253,42 @@ always @* begin
249253
wr_ptr_next = wr_ptr_reg;
250254
wr_ptr_cur_next = wr_ptr_cur_reg;
251255
wr_ptr_gray_next = wr_ptr_gray_reg;
252-
253-
if (s_axis_tvalid) begin
254-
// input data valid
255-
if (!full || DROP_WHEN_FULL) begin
256-
// not full, perform write
257-
if (!FRAME_FIFO) begin
258-
// normal FIFO mode
259-
write = 1'b1;
260-
wr_ptr_next = wr_ptr_reg + 1;
261-
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
262-
end else if (full || full_cur || drop_frame_reg) begin
263-
// full, packet overflow, or currently dropping frame
264-
// drop frame
265-
drop_frame_next = 1'b1;
266-
if (s_axis_tlast) begin
267-
// end of frame, reset write pointer
256+
wr_ptr_cur_gray_next = wr_ptr_cur_gray_reg;
257+
258+
if (s_axis_tready && s_axis_tvalid) begin
259+
// transfer in
260+
if (!FRAME_FIFO) begin
261+
// normal FIFO mode
262+
write = 1'b1;
263+
wr_ptr_next = wr_ptr_reg + 1;
264+
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
265+
end else if (full_cur || full_wr || drop_frame_reg) begin
266+
// full, packet overflow, or currently dropping frame
267+
// drop frame
268+
drop_frame_next = 1'b1;
269+
if (s_axis_tlast) begin
270+
// end of frame, reset write pointer
271+
wr_ptr_cur_next = wr_ptr_reg;
272+
wr_ptr_cur_gray_next = wr_ptr_cur_next ^ (wr_ptr_cur_next >> 1);
273+
drop_frame_next = 1'b0;
274+
overflow_next = 1'b1;
275+
end
276+
end else begin
277+
write = 1'b1;
278+
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
279+
wr_ptr_cur_gray_next = wr_ptr_cur_next ^ (wr_ptr_cur_next >> 1);
280+
if (s_axis_tlast) begin
281+
// end of frame
282+
if (DROP_BAD_FRAME && (USER_BAD_FRAME_MASK & s_axis_tuser == USER_BAD_FRAME_VALUE)) begin
283+
// bad packet, reset write pointer
268284
wr_ptr_cur_next = wr_ptr_reg;
269-
drop_frame_next = 1'b0;
270-
overflow_next = 1'b1;
271-
end
272-
end else begin
273-
write = 1'b1;
274-
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
275-
if (s_axis_tlast) begin
276-
// end of frame
277-
if (DROP_BAD_FRAME && (USER_BAD_FRAME_MASK & s_axis_tuser == USER_BAD_FRAME_VALUE)) begin
278-
// bad packet, reset write pointer
279-
wr_ptr_cur_next = wr_ptr_reg;
280-
bad_frame_next = 1'b1;
281-
end else begin
282-
// good packet, update write pointer
283-
wr_ptr_next = wr_ptr_cur_reg + 1;
284-
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
285-
good_frame_next = 1'b1;
286-
end
285+
wr_ptr_cur_gray_next = wr_ptr_cur_next ^ (wr_ptr_cur_next >> 1);
286+
bad_frame_next = 1'b1;
287+
end else begin
288+
// good packet, update write pointer
289+
wr_ptr_next = wr_ptr_cur_reg + 1;
290+
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
291+
good_frame_next = 1'b1;
287292
end
288293
end
289294
end
@@ -295,6 +300,7 @@ always @(posedge s_clk) begin
295300
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
296301
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
297302
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
303+
wr_ptr_cur_gray_reg <= {ADDR_WIDTH+1{1'b0}};
298304

299305
drop_frame_reg <= 1'b0;
300306
overflow_reg <= 1'b0;
@@ -304,6 +310,7 @@ always @(posedge s_clk) begin
304310
wr_ptr_reg <= wr_ptr_next;
305311
wr_ptr_cur_reg <= wr_ptr_cur_next;
306312
wr_ptr_gray_reg <= wr_ptr_gray_next;
313+
wr_ptr_cur_gray_reg <= wr_ptr_cur_gray_next;
307314

308315
drop_frame_reg <= drop_frame_next;
309316
overflow_reg <= overflow_next;

rtl/axis_fifo.v

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,13 @@ reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next;
132132
// full when first MSB different but rest same
133133
wire full = ((wr_ptr_reg[ADDR_WIDTH] != rd_ptr_reg[ADDR_WIDTH]) &&
134134
(wr_ptr_reg[ADDR_WIDTH-1:0] == rd_ptr_reg[ADDR_WIDTH-1:0]));
135+
wire full_cur = ((wr_ptr_cur_reg[ADDR_WIDTH] != rd_ptr_reg[ADDR_WIDTH]) &&
136+
(wr_ptr_cur_reg[ADDR_WIDTH-1:0] == rd_ptr_reg[ADDR_WIDTH-1:0]));
135137
// empty when pointers match exactly
136138
wire empty = wr_ptr_reg == rd_ptr_reg;
137139
// overflow within packet
138-
wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
139-
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
140+
wire full_wr = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
141+
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
140142

141143
// control signals
142144
reg write;
@@ -148,7 +150,7 @@ reg overflow_reg = 1'b0, overflow_next;
148150
reg bad_frame_reg = 1'b0, bad_frame_next;
149151
reg good_frame_reg = 1'b0, good_frame_next;
150152

151-
assign s_axis_tready = (!full || DROP_WHEN_FULL);
153+
assign s_axis_tready = FRAME_FIFO ? (!full_cur || full_wr || DROP_WHEN_FULL) : !full;
152154

153155
generate
154156
assign s_axis[DATA_WIDTH-1:0] = s_axis_tdata;
@@ -184,38 +186,35 @@ always @* begin
184186
wr_ptr_next = wr_ptr_reg;
185187
wr_ptr_cur_next = wr_ptr_cur_reg;
186188

187-
if (s_axis_tvalid) begin
188-
// input data valid
189-
if (!full || DROP_WHEN_FULL) begin
190-
// not full, perform write
191-
if (!FRAME_FIFO) begin
192-
// normal FIFO mode
193-
write = 1'b1;
194-
wr_ptr_next = wr_ptr_reg + 1;
195-
end else if (full || full_cur || drop_frame_reg) begin
196-
// full, packet overflow, or currently dropping frame
197-
// drop frame
198-
drop_frame_next = 1'b1;
199-
if (s_axis_tlast) begin
200-
// end of frame, reset write pointer
189+
if (s_axis_tready && s_axis_tvalid) begin
190+
// transfer in
191+
if (!FRAME_FIFO) begin
192+
// normal FIFO mode
193+
write = 1'b1;
194+
wr_ptr_next = wr_ptr_reg + 1;
195+
end else if (full_cur || full_wr || drop_frame_reg) begin
196+
// full, packet overflow, or currently dropping frame
197+
// drop frame
198+
drop_frame_next = 1'b1;
199+
if (s_axis_tlast) begin
200+
// end of frame, reset write pointer
201+
wr_ptr_cur_next = wr_ptr_reg;
202+
drop_frame_next = 1'b0;
203+
overflow_next = 1'b1;
204+
end
205+
end else begin
206+
write = 1'b1;
207+
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
208+
if (s_axis_tlast) begin
209+
// end of frame
210+
if (DROP_BAD_FRAME && (USER_BAD_FRAME_MASK & s_axis_tuser == USER_BAD_FRAME_VALUE)) begin
211+
// bad packet, reset write pointer
201212
wr_ptr_cur_next = wr_ptr_reg;
202-
drop_frame_next = 1'b0;
203-
overflow_next = 1'b1;
204-
end
205-
end else begin
206-
write = 1'b1;
207-
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
208-
if (s_axis_tlast) begin
209-
// end of frame
210-
if (DROP_BAD_FRAME && (USER_BAD_FRAME_MASK & s_axis_tuser == USER_BAD_FRAME_VALUE)) begin
211-
// bad packet, reset write pointer
212-
wr_ptr_cur_next = wr_ptr_reg;
213-
bad_frame_next = 1'b1;
214-
end else begin
215-
// good packet, update write pointer
216-
wr_ptr_next = wr_ptr_cur_reg + 1;
217-
good_frame_next = 1'b1;
218-
end
213+
bad_frame_next = 1'b1;
214+
end else begin
215+
// good packet, update write pointer
216+
wr_ptr_next = wr_ptr_cur_reg + 1;
217+
good_frame_next = 1'b1;
219218
end
220219
end
221220
end

0 commit comments

Comments
 (0)