@@ -78,15 +78,11 @@ module axis_async_fifo #
7878 parameter DROP_WHEN_FULL = 0
7979)
8080(
81- /*
82- * Common asynchronous reset
83- */
84- input wire async_rst,
85-
8681 /*
8782 * AXI input
8883 */
8984 input wire s_clk,
85+ input wire s_rst,
9086 input wire [DATA_WIDTH- 1 :0 ] s_axis_tdata,
9187 input wire [KEEP_WIDTH- 1 :0 ] s_axis_tkeep,
9288 input wire s_axis_tvalid,
@@ -100,6 +96,7 @@ module axis_async_fifo #
10096 * AXI output
10197 */
10298 input wire m_clk,
99+ input wire m_rst,
103100 output wire [DATA_WIDTH- 1 :0 ] m_axis_tdata,
104101 output wire [KEEP_WIDTH- 1 :0 ] m_axis_tkeep,
105102 output wire m_axis_tvalid,
@@ -214,9 +211,7 @@ reg mem_read_data_valid_reg = 1'b0;
214211
215212wire [WIDTH- 1 :0 ] s_axis;
216213
217- (* SHREG_EXTRACT = "NO" * )
218214reg [WIDTH- 1 :0 ] m_axis_pipe_reg[PIPELINE_OUTPUT- 1 :0 ];
219- (* SHREG_EXTRACT = "NO" * )
220215reg [PIPELINE_OUTPUT- 1 :0 ] m_axis_tvalid_pipe_reg = 1'b0 ;
221216
222217// full when first TWO MSBs do NOT match, but rest matches
@@ -233,12 +228,18 @@ reg write;
233228reg read;
234229reg store_output;
235230
231+ reg s_frame_reg = 1'b0 ;
232+ reg m_frame_reg = 1'b0 ;
233+
236234reg drop_frame_reg = 1'b0 ;
237235reg send_frame_reg = 1'b0 ;
238236reg overflow_reg = 1'b0 ;
239237reg bad_frame_reg = 1'b0 ;
240238reg good_frame_reg = 1'b0 ;
241239
240+ reg m_drop_frame_reg = 1'b0 ;
241+ reg m_terminate_frame_reg = 1'b0 ;
242+
242243reg overflow_sync1_reg = 1'b0 ;
243244reg overflow_sync2_reg = 1'b0 ;
244245reg overflow_sync3_reg = 1'b0 ;
@@ -263,14 +264,23 @@ generate
263264 if (USER_ENABLE) assign s_axis[USER_OFFSET + : USER_WIDTH] = s_axis_tuser;
264265endgenerate
265266
266- assign m_axis_tvalid = m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT- 1 ];
267+ wire m_axis_tvalid_pipe = m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT- 1 ];
267268
268- assign m_axis_tdata = m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][DATA_WIDTH- 1 :0 ];
269- assign m_axis_tkeep = KEEP_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][KEEP_OFFSET + : KEEP_WIDTH] : {KEEP_WIDTH{1'b1 }};
270- assign m_axis_tlast = LAST_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][LAST_OFFSET] : 1'b1 ;
271- assign m_axis_tid = ID_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][ID_OFFSET + : ID_WIDTH] : {ID_WIDTH{1'b0 }};
272- assign m_axis_tdest = DEST_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][DEST_OFFSET + : DEST_WIDTH] : {DEST_WIDTH{1'b0 }};
273- assign m_axis_tuser = USER_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][USER_OFFSET + : USER_WIDTH] : {USER_WIDTH{1'b0 }};
269+ wire [DATA_WIDTH- 1 :0 ] m_axis_tdata_pipe = m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][DATA_WIDTH- 1 :0 ];
270+ wire [KEEP_WIDTH- 1 :0 ] m_axis_tkeep_pipe = KEEP_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][KEEP_OFFSET + : KEEP_WIDTH] : {KEEP_WIDTH{1'b1 }};
271+ wire m_axis_tlast_pipe = LAST_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][LAST_OFFSET] : 1'b1 ;
272+ wire [ID_WIDTH- 1 :0 ] m_axis_tid_pipe = ID_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][ID_OFFSET + : ID_WIDTH] : {ID_WIDTH{1'b0 }};
273+ wire [DEST_WIDTH- 1 :0 ] m_axis_tdest_pipe = DEST_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][DEST_OFFSET + : DEST_WIDTH] : {DEST_WIDTH{1'b0 }};
274+ wire [USER_WIDTH- 1 :0 ] m_axis_tuser_pipe = USER_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT- 1 ][USER_OFFSET + : USER_WIDTH] : {USER_WIDTH{1'b0 }};
275+
276+ assign m_axis_tvalid = m_axis_tvalid_pipe;
277+
278+ assign m_axis_tdata = m_axis_tdata_pipe;
279+ assign m_axis_tkeep = m_axis_tkeep_pipe;
280+ assign m_axis_tlast = (m_terminate_frame_reg ? 1'b1 : m_axis_tlast_pipe);
281+ assign m_axis_tid = m_axis_tid_pipe;
282+ assign m_axis_tdest = m_axis_tdest_pipe;
283+ assign m_axis_tuser = (m_terminate_frame_reg ? USER_BAD_FRAME_VALUE : m_axis_tuser_pipe);
274284
275285assign s_status_overflow = overflow_reg;
276286assign s_status_bad_frame = bad_frame_reg;
@@ -281,30 +291,32 @@ assign m_status_bad_frame = bad_frame_sync3_reg ^ bad_frame_sync4_reg;
281291assign m_status_good_frame = good_frame_sync3_reg ^ good_frame_sync4_reg;
282292
283293// reset synchronization
284- always @(posedge s_clk or posedge async_rst ) begin
285- if (async_rst ) begin
294+ always @(posedge m_clk or posedge m_rst ) begin
295+ if (m_rst ) begin
286296 s_rst_sync1_reg <= 1'b1 ;
287- s_rst_sync2_reg <= 1'b1 ;
288- s_rst_sync3_reg <= 1'b1 ;
289297 end else begin
290298 s_rst_sync1_reg <= 1'b0 ;
291- s_rst_sync2_reg <= s_rst_sync1_reg || m_rst_sync1_reg;
292- s_rst_sync3_reg <= s_rst_sync2_reg;
293299 end
294300end
295301
296- always @(posedge m_clk or posedge async_rst) begin
297- if (async_rst) begin
302+ always @(posedge s_clk) begin
303+ s_rst_sync2_reg <= s_rst_sync1_reg;
304+ s_rst_sync3_reg <= s_rst_sync2_reg;
305+ end
306+
307+ always @(posedge s_clk or posedge s_rst) begin
308+ if (s_rst) begin
298309 m_rst_sync1_reg <= 1'b1 ;
299- m_rst_sync2_reg <= 1'b1 ;
300- m_rst_sync3_reg <= 1'b1 ;
301310 end else begin
302311 m_rst_sync1_reg <= 1'b0 ;
303- m_rst_sync2_reg <= s_rst_sync1_reg || m_rst_sync1_reg;
304- m_rst_sync3_reg <= m_rst_sync2_reg;
305312 end
306313end
307314
315+ always @(posedge m_clk) begin
316+ m_rst_sync2_reg <= m_rst_sync1_reg;
317+ m_rst_sync3_reg <= m_rst_sync2_reg;
318+ end
319+
308320// Write logic
309321always @(posedge s_clk) begin
310322 overflow_reg <= 1'b0 ;
@@ -321,14 +333,39 @@ always @(posedge s_clk) begin
321333 end
322334 end
323335
336+ if (s_axis_tready && s_axis_tvalid && LAST_ENABLE) begin
337+ // track input frame status
338+ s_frame_reg <= ! s_axis_tlast;
339+ end
340+
341+ if (s_rst_sync3_reg && LAST_ENABLE) begin
342+ // if sink side is reset during transfer, drop partial frame
343+ if (s_frame_reg && ! (s_axis_tready && s_axis_tvalid && s_axis_tlast)) begin
344+ drop_frame_reg <= 1'b1 ;
345+ end
346+ if (s_axis_tready && s_axis_tvalid && ! s_axis_tlast) begin
347+ drop_frame_reg <= 1'b1 ;
348+ end
349+ end
350+
324351 if (s_axis_tready && s_axis_tvalid) begin
325352 // transfer in
326353 if (! FRAME_FIFO) begin
327354 // normal FIFO mode
328355 mem[wr_ptr_reg[ADDR_WIDTH- 1 :0 ]] <= s_axis;
329- wr_ptr_temp = wr_ptr_reg + 1 ;
330- wr_ptr_reg <= wr_ptr_temp;
331- wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1 );
356+ if (drop_frame_reg && LAST_ENABLE) begin
357+ // currently dropping frame
358+ // (only for frame transfers interrupted by sink reset)
359+ if (s_axis_tlast) begin
360+ // end of frame, clear drop flag
361+ drop_frame_reg <= 1'b0 ;
362+ end
363+ end else begin
364+ // update pointers
365+ wr_ptr_temp = wr_ptr_reg + 1 ;
366+ wr_ptr_reg <= wr_ptr_temp;
367+ wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1 );
368+ end
332369 end else if ((full_cur && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin
333370 // full, packet overflow, or currently dropping frame
334371 // drop frame
@@ -403,6 +440,19 @@ always @(posedge s_clk) begin
403440
404441 wr_ptr_update_valid_reg <= 1'b0 ;
405442 wr_ptr_update_reg <= 1'b0 ;
443+ end
444+
445+ if (s_rst) begin
446+ wr_ptr_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
447+ wr_ptr_cur_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
448+ wr_ptr_gray_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
449+ wr_ptr_sync_gray_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
450+ wr_ptr_cur_gray_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
451+
452+ wr_ptr_update_valid_reg <= 1'b0 ;
453+ wr_ptr_update_reg <= 1'b0 ;
454+
455+ s_frame_reg <= 1'b0 ;
406456
407457 drop_frame_reg <= 1'b0 ;
408458 send_frame_reg <= 1'b0 ;
@@ -419,7 +469,7 @@ always @(posedge s_clk) begin
419469 wr_ptr_update_ack_sync1_reg <= wr_ptr_update_sync3_reg;
420470 wr_ptr_update_ack_sync2_reg <= wr_ptr_update_ack_sync1_reg;
421471
422- if (s_rst_sync3_reg ) begin
472+ if (s_rst ) begin
423473 rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
424474 rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
425475 wr_ptr_update_ack_sync1_reg <= 1'b0 ;
@@ -438,7 +488,7 @@ always @(posedge m_clk) begin
438488 wr_ptr_update_sync2_reg <= wr_ptr_update_sync1_reg;
439489 wr_ptr_update_sync3_reg <= wr_ptr_update_sync2_reg;
440490
441- if (m_rst_sync3_reg ) begin
491+ if (m_rst ) begin
442492 wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
443493 wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
444494 wr_ptr_update_sync1_reg <= 1'b0 ;
@@ -453,7 +503,7 @@ always @(posedge s_clk) begin
453503 bad_frame_sync1_reg <= bad_frame_sync1_reg ^ bad_frame_reg;
454504 good_frame_sync1_reg <= good_frame_sync1_reg ^ good_frame_reg;
455505
456- if (s_rst_sync3_reg ) begin
506+ if (s_rst ) begin
457507 overflow_sync1_reg <= 1'b0 ;
458508 bad_frame_sync1_reg <= 1'b0 ;
459509 good_frame_sync1_reg <= 1'b0 ;
@@ -471,7 +521,7 @@ always @(posedge m_clk) begin
471521 good_frame_sync3_reg <= good_frame_sync2_reg;
472522 good_frame_sync4_reg <= good_frame_sync3_reg;
473523
474- if (m_rst_sync3_reg ) begin
524+ if (m_rst ) begin
475525 overflow_sync2_reg <= 1'b0 ;
476526 overflow_sync3_reg <= 1'b0 ;
477527 overflow_sync4_reg <= 1'b0 ;
@@ -491,6 +541,7 @@ always @(posedge m_clk) begin
491541 if (m_axis_tready) begin
492542 // output ready; invalidate stage
493543 m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT- 1 ] <= 1'b0 ;
544+ m_terminate_frame_reg <= 1'b0 ;
494545 end
495546
496547 for (j = PIPELINE_OUTPUT- 1 ; j > 0 ; j = j - 1 ) begin
@@ -506,7 +557,7 @@ always @(posedge m_clk) begin
506557 // output ready or bubble in pipeline; read new data from FIFO
507558 m_axis_tvalid_pipe_reg[0 ] <= 1'b0 ;
508559 m_axis_pipe_reg[0 ] <= mem[rd_ptr_reg[ADDR_WIDTH- 1 :0 ]];
509- if (! empty) begin
560+ if (! empty && ! m_rst_sync3_reg && ! m_drop_frame_reg ) begin
510561 // not empty, increment pointer
511562 m_axis_tvalid_pipe_reg[0 ] <= 1'b1 ;
512563 rd_ptr_temp = rd_ptr_reg + 1 ;
@@ -515,10 +566,50 @@ always @(posedge m_clk) begin
515566 end
516567 end
517568
569+ if (m_axis_tvalid && LAST_ENABLE) begin
570+ // track output frame status
571+ if (m_axis_tlast && m_axis_tready) begin
572+ m_frame_reg <= 1'b0 ;
573+ end else begin
574+ m_frame_reg <= 1'b1 ;
575+ end
576+ end
577+
578+ if (m_drop_frame_reg && (m_axis_tready || ! m_axis_tvalid_pipe) && LAST_ENABLE) begin
579+ // terminate frame
580+ // (only for frame transfers interrupted by source reset)
581+ m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT- 1 ] <= 1'b1 ;
582+ m_terminate_frame_reg <= 1'b1 ;
583+ m_drop_frame_reg <= 1'b0 ;
584+ end
585+
586+ if (m_rst_sync3_reg && LAST_ENABLE) begin
587+ // if source side is reset during transfer, drop partial frame
588+
589+ // empty output pipeline, except for last stage
590+ if (PIPELINE_OUTPUT > 1 ) begin
591+ m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT- 2 :0 ] <= 0 ;
592+ end
593+
594+ if (m_frame_reg && (! m_axis_tvalid || (m_axis_tvalid && ! m_axis_tlast)) &&
595+ ! (m_drop_frame_reg || m_terminate_frame_reg)) begin
596+ // terminate frame
597+ m_drop_frame_reg <= 1'b1 ;
598+ end
599+ end
600+
518601 if (m_rst_sync3_reg) begin
519602 rd_ptr_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
520603 rd_ptr_gray_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
604+ end
605+
606+ if (m_rst) begin
607+ rd_ptr_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
608+ rd_ptr_gray_reg <= {ADDR_WIDTH+ 1 {1'b0 }};
521609 m_axis_tvalid_pipe_reg <= {PIPELINE_OUTPUT{1'b0 }};
610+ m_frame_reg <= 1'b0 ;
611+ m_drop_frame_reg <= 1'b0 ;
612+ m_terminate_frame_reg <= 1'b0 ;
522613 end
523614end
524615
0 commit comments