Skip to content

Commit 932aa35

Browse files
committed
Fix AXI stream async frame FIFO write pointer synchronization
1 parent 3920b28 commit 932aa35

File tree

1 file changed

+58
-2
lines changed

1 file changed

+58
-2
lines changed

rtl/axis_async_fifo.v

Lines changed: 58 additions & 2 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_sync_gray_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_sync_gray_next;
127128
reg [ADDR_WIDTH:0] wr_ptr_cur_gray_reg = {ADDR_WIDTH+1{1'b0}}, wr_ptr_cur_gray_next;
128129
reg [ADDR_WIDTH:0] wr_addr_reg = {ADDR_WIDTH+1{1'b0}};
129130
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
@@ -135,6 +136,14 @@ reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
135136
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
136137
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
137138

139+
reg wr_ptr_update_valid_reg = 1'b0, wr_ptr_update_valid_next;
140+
reg wr_ptr_update_reg = 1'b0, wr_ptr_update_next;
141+
reg wr_ptr_update_sync1_reg = 1'b0;
142+
reg wr_ptr_update_sync2_reg = 1'b0;
143+
reg wr_ptr_update_sync3_reg = 1'b0;
144+
reg wr_ptr_update_ack_sync1_reg = 1'b0;
145+
reg wr_ptr_update_ack_sync2_reg = 1'b0;
146+
138147
reg s_rst_sync1_reg = 1'b1;
139148
reg s_rst_sync2_reg = 1'b1;
140149
reg s_rst_sync3_reg = 1'b1;
@@ -160,7 +169,7 @@ wire full_cur = ((wr_ptr_cur_gray_reg[ADDR_WIDTH] != rd_ptr_gray_sync2_reg[ADDR_
160169
(wr_ptr_cur_gray_reg[ADDR_WIDTH-1] != rd_ptr_gray_sync2_reg[ADDR_WIDTH-1]) &&
161170
(wr_ptr_cur_gray_reg[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2_reg[ADDR_WIDTH-2:0]));
162171
// empty when pointers match exactly
163-
wire empty = rd_ptr_gray_reg == wr_ptr_gray_sync2_reg;
172+
wire empty = rd_ptr_gray_reg == (FRAME_FIFO ? wr_ptr_gray_sync1_reg : wr_ptr_gray_sync2_reg);
164173
// overflow within packet
165174
wire full_wr = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
166175
(wr_ptr_reg[ADDR_WIDTH-1:0] == wr_ptr_cur_reg[ADDR_WIDTH-1:0]));
@@ -253,8 +262,22 @@ always @* begin
253262
wr_ptr_next = wr_ptr_reg;
254263
wr_ptr_cur_next = wr_ptr_cur_reg;
255264
wr_ptr_gray_next = wr_ptr_gray_reg;
265+
wr_ptr_sync_gray_next = wr_ptr_sync_gray_reg;
256266
wr_ptr_cur_gray_next = wr_ptr_cur_gray_reg;
257267

268+
wr_ptr_update_valid_next = wr_ptr_update_valid_reg;
269+
wr_ptr_update_next = wr_ptr_update_reg;
270+
271+
if (FRAME_FIFO && wr_ptr_update_valid_reg) begin
272+
// have updated pointer to sync
273+
if (wr_ptr_update_next == wr_ptr_update_ack_sync2_reg) begin
274+
// no sync in progress; sync update
275+
wr_ptr_update_valid_next = 1'b0;
276+
wr_ptr_sync_gray_next = wr_ptr_gray_reg;
277+
wr_ptr_update_next = !wr_ptr_update_ack_sync2_reg;
278+
end
279+
end
280+
258281
if (s_axis_tready && s_axis_tvalid) begin
259282
// transfer in
260283
if (!FRAME_FIFO) begin
@@ -288,6 +311,17 @@ always @* begin
288311
// good packet, update write pointer
289312
wr_ptr_next = wr_ptr_cur_reg + 1;
290313
wr_ptr_gray_next = wr_ptr_next ^ (wr_ptr_next >> 1);
314+
315+
if (wr_ptr_update_next == wr_ptr_update_ack_sync2_reg) begin
316+
// no sync in progress; sync update
317+
wr_ptr_update_valid_next = 1'b0;
318+
wr_ptr_sync_gray_next = wr_ptr_gray_next;
319+
wr_ptr_update_next = !wr_ptr_update_ack_sync2_reg;
320+
end else begin
321+
// sync in progress; flag it for later
322+
wr_ptr_update_valid_next = 1'b1;
323+
end
324+
291325
good_frame_next = 1'b1;
292326
end
293327
end
@@ -300,8 +334,12 @@ always @(posedge s_clk) begin
300334
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
301335
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
302336
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
337+
wr_ptr_sync_gray_reg <= {ADDR_WIDTH+1{1'b0}};
303338
wr_ptr_cur_gray_reg <= {ADDR_WIDTH+1{1'b0}};
304339

340+
wr_ptr_update_valid_reg <= 1'b0;
341+
wr_ptr_update_reg <= 1'b0;
342+
305343
drop_frame_reg <= 1'b0;
306344
overflow_reg <= 1'b0;
307345
bad_frame_reg <= 1'b0;
@@ -310,8 +348,12 @@ always @(posedge s_clk) begin
310348
wr_ptr_reg <= wr_ptr_next;
311349
wr_ptr_cur_reg <= wr_ptr_cur_next;
312350
wr_ptr_gray_reg <= wr_ptr_gray_next;
351+
wr_ptr_sync_gray_reg <= wr_ptr_sync_gray_next;
313352
wr_ptr_cur_gray_reg <= wr_ptr_cur_gray_next;
314353

354+
wr_ptr_update_valid_reg <= wr_ptr_update_valid_next;
355+
wr_ptr_update_reg <= wr_ptr_update_next;
356+
315357
drop_frame_reg <= drop_frame_next;
316358
overflow_reg <= overflow_next;
317359
bad_frame_reg <= bad_frame_next;
@@ -334,19 +376,33 @@ always @(posedge s_clk) begin
334376
if (s_rst_sync3_reg) begin
335377
rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
336378
rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
379+
wr_ptr_update_ack_sync1_reg <= 1'b0;
380+
wr_ptr_update_ack_sync2_reg <= 1'b0;
337381
end else begin
338382
rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg;
339383
rd_ptr_gray_sync2_reg <= rd_ptr_gray_sync1_reg;
384+
wr_ptr_update_ack_sync1_reg <= wr_ptr_update_sync3_reg;
385+
wr_ptr_update_ack_sync2_reg <= wr_ptr_update_ack_sync1_reg;
340386
end
341387
end
342388

343389
always @(posedge m_clk) begin
344390
if (m_rst_sync3_reg) begin
345391
wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
346392
wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
393+
wr_ptr_update_sync1_reg <= 1'b0;
394+
wr_ptr_update_sync2_reg <= 1'b0;
395+
wr_ptr_update_sync3_reg <= 1'b0;
347396
end else begin
348-
wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg;
397+
if (!FRAME_FIFO) begin
398+
wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg;
399+
end else if (wr_ptr_update_sync2_reg ^ wr_ptr_update_sync3_reg) begin
400+
wr_ptr_gray_sync1_reg <= wr_ptr_sync_gray_reg;
401+
end
349402
wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg;
403+
wr_ptr_update_sync1_reg <= wr_ptr_update_reg;
404+
wr_ptr_update_sync2_reg <= wr_ptr_update_sync1_reg;
405+
wr_ptr_update_sync3_reg <= wr_ptr_update_sync2_reg;
350406
end
351407
end
352408

0 commit comments

Comments
 (0)