11/*
22
3- Copyright (c) 2014-2018 Alex Forencich
3+ Copyright (c) 2014-2021 Alex Forencich
44
55Permission is hereby granted, free of charge, to any person obtaining a copy
66of this software and associated documentation files (the "Software"), to deal
@@ -66,12 +66,15 @@ module axis_async_fifo #
6666 parameter USER_BAD_FRAME_VALUE = 1'b1 ,
6767 // tuser mask for bad frame marker
6868 parameter USER_BAD_FRAME_MASK = 1'b1 ,
69- // Drop frames marked bad
69+ // Drop frames larger than FIFO
7070 // Requires FRAME_FIFO set
71+ parameter DROP_OVERSIZE_FRAME = FRAME_FIFO,
72+ // Drop frames marked bad
73+ // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set
7174 parameter DROP_BAD_FRAME = 0 ,
7275 // Drop incoming frames when full
7376 // When set, s_axis_tready is always asserted
74- // Requires FRAME_FIFO set
77+ // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set
7578 parameter DROP_WHEN_FULL = 0
7679)
7780(
@@ -131,13 +134,18 @@ initial begin
131134 $finish ;
132135 end
133136
134- if (DROP_BAD_FRAME && ! FRAME_FIFO) begin
135- $error("Error: DROP_BAD_FRAME set requires FRAME_FIFO set (instance %m)" );
137+ if (DROP_OVERSIZE_FRAME && ! FRAME_FIFO) begin
138+ $error("Error: DROP_OVERSIZE_FRAME set requires FRAME_FIFO set (instance %m)" );
136139 $finish ;
137140 end
138141
139- if (DROP_WHEN_FULL && ! FRAME_FIFO) begin
140- $error("Error: DROP_WHEN_FULL set requires FRAME_FIFO set (instance %m)" );
142+ if (DROP_BAD_FRAME && ! (FRAME_FIFO && DROP_OVERSIZE_FRAME)) begin
143+ $error("Error: DROP_BAD_FRAME set requires FRAME_FIFO and DROP_OVERSIZE_FRAME set (instance %m)" );
144+ $finish ;
145+ end
146+
147+ if (DROP_WHEN_FULL && ! (FRAME_FIFO && DROP_OVERSIZE_FRAME)) begin
148+ $error("Error: DROP_WHEN_FULL set requires FRAME_FIFO and DROP_OVERSIZE_FRAME set (instance %m)" );
141149 $finish ;
142150 end
143151
@@ -226,6 +234,7 @@ reg read;
226234reg store_output;
227235
228236reg drop_frame_reg = 1'b0 ;
237+ reg send_frame_reg = 1'b0 ;
229238reg overflow_reg = 1'b0 ;
230239reg bad_frame_reg = 1'b0 ;
231240reg good_frame_reg = 1'b0 ;
@@ -243,7 +252,7 @@ reg good_frame_sync2_reg = 1'b0;
243252reg good_frame_sync3_reg = 1'b0 ;
244253reg good_frame_sync4_reg = 1'b0 ;
245254
246- assign s_axis_tready = (FRAME_FIFO ? (! full_cur || full_wr || DROP_WHEN_FULL) : ! full) && ! s_rst_sync3_reg;
255+ assign s_axis_tready = (FRAME_FIFO ? (! full_cur || ( full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : ! full) && ! s_rst_sync3_reg;
247256
248257generate
249258 assign s_axis[DATA_WIDTH- 1 :0 ] = s_axis_tdata;
@@ -320,7 +329,7 @@ always @(posedge s_clk) begin
320329 wr_ptr_temp = wr_ptr_reg + 1 ;
321330 wr_ptr_reg <= wr_ptr_temp;
322331 wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1 );
323- end else if (full_cur || full_wr || drop_frame_reg) begin
332+ end else if (( full_cur && DROP_WHEN_FULL) || ( full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin
324333 // full, packet overflow, or currently dropping frame
325334 // drop frame
326335 drop_frame_reg <= 1'b1 ;
@@ -337,16 +346,17 @@ always @(posedge s_clk) begin
337346 wr_ptr_temp = wr_ptr_cur_reg + 1 ;
338347 wr_ptr_cur_reg <= wr_ptr_temp;
339348 wr_ptr_cur_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1 );
340- if (s_axis_tlast) begin
341- // end of frame
342- if (DROP_BAD_FRAME && USER_BAD_FRAME_MASK & ~ (s_axis_tuser ^ USER_BAD_FRAME_VALUE)) begin
349+ if (s_axis_tlast || (! DROP_OVERSIZE_FRAME && (full_wr || send_frame_reg))) begin
350+ // end of frame or send frame
351+ send_frame_reg <= ! s_axis_tlast;
352+ if (s_axis_tlast && DROP_BAD_FRAME && USER_BAD_FRAME_MASK & ~ (s_axis_tuser ^ USER_BAD_FRAME_VALUE)) begin
343353 // bad packet, reset write pointer
344354 wr_ptr_temp = wr_ptr_reg;
345355 wr_ptr_cur_reg <= wr_ptr_temp;
346356 wr_ptr_cur_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1 );
347357 bad_frame_reg <= 1'b1 ;
348358 end else begin
349- // good packet, update write pointer
359+ // good packet or packet overflow , update write pointer
350360 wr_ptr_temp = wr_ptr_cur_reg + 1 ;
351361 wr_ptr_reg <= wr_ptr_temp;
352362 wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1 );
@@ -361,10 +371,27 @@ always @(posedge s_clk) begin
361371 wr_ptr_update_valid_reg <= 1'b1 ;
362372 end
363373
364- good_frame_reg <= 1'b1 ;
374+ good_frame_reg <= s_axis_tlast ;
365375 end
366376 end
367377 end
378+ end else if (s_axis_tvalid && full_wr && FRAME_FIFO && ! DROP_OVERSIZE_FRAME) begin
379+ // data valid with packet overflow
380+ // update write pointer
381+ send_frame_reg <= 1'b1 ;
382+ wr_ptr_temp = wr_ptr_cur_reg;
383+ wr_ptr_reg <= wr_ptr_temp;
384+ wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1 );
385+
386+ if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin
387+ // no sync in progress; sync update
388+ wr_ptr_update_valid_reg <= 1'b0 ;
389+ wr_ptr_sync_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1 );
390+ wr_ptr_update_reg <= ! wr_ptr_update_ack_sync2_reg;
391+ end else begin
392+ // sync in progress; flag it for later
393+ wr_ptr_update_valid_reg <= 1'b1 ;
394+ end
368395 end
369396
370397 if (s_rst_sync3_reg) begin
@@ -378,6 +405,7 @@ always @(posedge s_clk) begin
378405 wr_ptr_update_reg <= 1'b0 ;
379406
380407 drop_frame_reg <= 1'b0 ;
408+ send_frame_reg <= 1'b0 ;
381409 overflow_reg <= 1'b0 ;
382410 bad_frame_reg <= 1'b0 ;
383411 good_frame_reg <= 1'b0 ;
0 commit comments