@@ -80,7 +80,11 @@ module axis_async_fifo #
8080 // Drop incoming frames when full
8181 // When set, s_axis_tready is always asserted
8282 // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set
83- parameter DROP_WHEN_FULL = 0
83+ parameter DROP_WHEN_FULL = 0 ,
84+ // Enable pause request input
85+ parameter PAUSE_ENABLE = 0 ,
86+ // Pause between frames
87+ parameter FRAME_PAUSE = FRAME_FIFO
8488)
8589(
8690 /*
@@ -111,6 +115,14 @@ module axis_async_fifo #
111115 output wire [DEST_WIDTH- 1 :0 ] m_axis_tdest,
112116 output wire [USER_WIDTH- 1 :0 ] m_axis_tuser,
113117
118+ /*
119+ * Pause
120+ */
121+ input wire s_pause_req,
122+ output wire s_pause_ack,
123+ input wire m_pause_req,
124+ output wire m_pause_ack,
125+
114126 /*
115127 * Status
116128 */
@@ -291,6 +303,7 @@ endgenerate
291303
292304wire [WIDTH- 1 :0 ] m_axis = m_axis_pipe_reg[RAM_PIPELINE+ 1 - 1 ];
293305
306+ wire m_axis_tready_pipe;
294307wire m_axis_tvalid_pipe = m_axis_tvalid_pipe_reg[RAM_PIPELINE+ 1 - 1 ];
295308
296309wire [DATA_WIDTH- 1 :0 ] m_axis_tdata_pipe = m_axis[DATA_WIDTH- 1 :0 ];
@@ -300,6 +313,16 @@ wire [ID_WIDTH-1:0] m_axis_tid_pipe = ID_ENABLE ? m_axis[ID_OFFSET +: ID
300313wire [DEST_WIDTH- 1 :0 ] m_axis_tdest_pipe = DEST_ENABLE ? m_axis[DEST_OFFSET + : DEST_WIDTH] : {DEST_WIDTH{1'b0 }};
301314wire [USER_WIDTH- 1 :0 ] m_axis_tuser_pipe = USER_ENABLE ? (m_terminate_frame_reg ? USER_BAD_FRAME_VALUE : m_axis[USER_OFFSET + : USER_WIDTH]) : {USER_WIDTH{1'b0 }};
302315
316+ wire m_axis_tready_out;
317+ wire m_axis_tvalid_out;
318+
319+ wire [DATA_WIDTH- 1 :0 ] m_axis_tdata_out;
320+ wire [KEEP_WIDTH- 1 :0 ] m_axis_tkeep_out;
321+ wire m_axis_tlast_out;
322+ wire [ID_WIDTH- 1 :0 ] m_axis_tid_out;
323+ wire [DEST_WIDTH- 1 :0 ] m_axis_tdest_out;
324+ wire [USER_WIDTH- 1 :0 ] m_axis_tuser_out;
325+
303326wire pipe_ready;
304327
305328assign s_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1 ) ? {s_depth_reg, {$clog2(KEEP_WIDTH){1'b0 }}} : s_depth_reg;
@@ -574,22 +597,22 @@ end
574597integer j;
575598
576599always @(posedge m_clk) begin
577- if (OUTPUT_FIFO_ENABLE || m_axis_tready ) begin
600+ if (m_axis_tready_pipe ) begin
578601 // output ready; invalidate stage
579602 m_axis_tvalid_pipe_reg[RAM_PIPELINE+ 1 - 1 ] <= 1'b0 ;
580603 m_terminate_frame_reg <= 1'b0 ;
581604 end
582605
583606 for (j = RAM_PIPELINE+ 1 - 1 ; j > 0 ; j = j - 1 ) begin
584- if (OUTPUT_FIFO_ENABLE || m_axis_tready || ((~ m_axis_tvalid_pipe_reg) >> j)) begin
607+ if (m_axis_tready_pipe || ((~ m_axis_tvalid_pipe_reg) >> j)) begin
585608 // output ready or bubble in pipeline; transfer down pipeline
586609 m_axis_tvalid_pipe_reg[j] <= m_axis_tvalid_pipe_reg[j- 1 ];
587610 m_axis_pipe_reg[j] <= m_axis_pipe_reg[j- 1 ];
588611 m_axis_tvalid_pipe_reg[j- 1 ] <= 1'b0 ;
589612 end
590613 end
591614
592- if (OUTPUT_FIFO_ENABLE || m_axis_tready || ~ m_axis_tvalid_pipe_reg) begin
615+ if (m_axis_tready_pipe || ~ m_axis_tvalid_pipe_reg) begin
593616 // output ready or bubble in pipeline; read new data from FIFO
594617 m_axis_tvalid_pipe_reg[0 ] <= 1'b0 ;
595618 m_axis_pipe_reg[0 ] <= mem[rd_ptr_reg[ADDR_WIDTH- 1 :0 ]];
@@ -604,14 +627,14 @@ always @(posedge m_clk) begin
604627
605628 if (m_axis_tvalid_pipe && LAST_ENABLE) begin
606629 // track output frame status
607- if (m_axis_tlast_pipe && (OUTPUT_FIFO_ENABLE || m_axis_tready) ) begin
630+ if (m_axis_tlast_pipe && m_axis_tready_pipe ) begin
608631 m_frame_reg <= 1'b0 ;
609632 end else begin
610633 m_frame_reg <= 1'b1 ;
611634 end
612635 end
613636
614- if (m_drop_frame_reg && (OUTPUT_FIFO_ENABLE ? pipe_ready : m_axis_tready || ! m_axis_tvalid_pipe) && LAST_ENABLE) begin
637+ if (m_drop_frame_reg && (OUTPUT_FIFO_ENABLE ? pipe_ready : m_axis_tready_pipe || ! m_axis_tvalid_pipe) && LAST_ENABLE) begin
615638 // terminate frame
616639 // (only for frame transfers interrupted by source reset)
617640 m_axis_tvalid_pipe_reg[RAM_PIPELINE+ 1 - 1 ] <= 1'b1 ;
@@ -662,16 +685,17 @@ if (!OUTPUT_FIFO_ENABLE) begin
662685
663686 assign pipe_ready = 1'b1 ;
664687
665- assign m_axis_tvalid = m_axis_tvalid_pipe;
688+ assign m_axis_tready_pipe = m_axis_tready_out;
689+ assign m_axis_tvalid_out = m_axis_tvalid_pipe;
666690
667- assign m_axis_tdata = m_axis_tdata_pipe;
668- assign m_axis_tkeep = m_axis_tkeep_pipe;
669- assign m_axis_tlast = m_axis_tlast_pipe;
670- assign m_axis_tid = m_axis_tid_pipe;
671- assign m_axis_tdest = m_axis_tdest_pipe;
672- assign m_axis_tuser = m_axis_tuser_pipe;
691+ assign m_axis_tdata_out = m_axis_tdata_pipe;
692+ assign m_axis_tkeep_out = m_axis_tkeep_pipe;
693+ assign m_axis_tlast_out = m_axis_tlast_pipe;
694+ assign m_axis_tid_out = m_axis_tid_pipe;
695+ assign m_axis_tdest_out = m_axis_tdest_pipe;
696+ assign m_axis_tuser_out = m_axis_tuser_pipe;
673697
674- end else begin
698+ end else begin : output_fifo
675699
676700 // output datapath logic
677701 reg [DATA_WIDTH- 1 :0 ] m_axis_tdata_reg = {DATA_WIDTH{1'b0 }};
@@ -704,16 +728,18 @@ end else begin
704728
705729 assign pipe_ready = ! out_fifo_half_full_reg;
706730
707- assign m_axis_tdata = m_axis_tdata_reg;
708- assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1 }};
709- assign m_axis_tvalid = m_axis_tvalid_reg;
710- assign m_axis_tlast = LAST_ENABLE ? m_axis_tlast_reg : 1'b1 ;
711- assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0 }};
712- assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0 }};
713- assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0 }};
731+ assign m_axis_tready_pipe = 1'b1 ;
732+
733+ assign m_axis_tdata_out = m_axis_tdata_reg;
734+ assign m_axis_tkeep_out = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1 }};
735+ assign m_axis_tvalid_out = m_axis_tvalid_reg;
736+ assign m_axis_tlast_out = LAST_ENABLE ? m_axis_tlast_reg : 1'b1 ;
737+ assign m_axis_tid_out = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0 }};
738+ assign m_axis_tdest_out = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0 }};
739+ assign m_axis_tuser_out = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0 }};
714740
715741 always @(posedge m_clk) begin
716- m_axis_tvalid_reg <= m_axis_tvalid_reg && ! m_axis_tready ;
742+ m_axis_tvalid_reg <= m_axis_tvalid_reg && ! m_axis_tready_out ;
717743
718744 out_fifo_half_full_reg <= $unsigned (out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2 ** (OUTPUT_FIFO_ADDR_WIDTH- 1 );
719745
@@ -727,7 +753,7 @@ end else begin
727753 out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1 ;
728754 end
729755
730- if (! out_fifo_empty && (! m_axis_tvalid_reg || m_axis_tready )) begin
756+ if (! out_fifo_empty && (! m_axis_tvalid_reg || m_axis_tready_out )) begin
731757 m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH- 1 :0 ]];
732758 m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH- 1 :0 ]];
733759 m_axis_tvalid_reg <= 1'b1 ;
@@ -747,6 +773,85 @@ end else begin
747773
748774end
749775
776+ if (PAUSE_ENABLE) begin : pause
777+
778+ // Pause logic
779+ reg pause_reg = 1'b0 ;
780+ reg pause_frame_reg = 1'b0 ;
781+
782+ reg s_pause_req_sync1_reg;
783+ reg s_pause_req_sync2_reg;
784+ reg s_pause_req_sync3_reg;
785+ reg s_pause_ack_sync1_reg;
786+ reg s_pause_ack_sync2_reg;
787+ reg s_pause_ack_sync3_reg;
788+
789+ always @(posedge s_clk) begin
790+ s_pause_req_sync1_reg <= s_pause_req;
791+ s_pause_ack_sync2_reg <= s_pause_ack_sync1_reg;
792+ s_pause_ack_sync3_reg <= s_pause_ack_sync2_reg;
793+ end
794+
795+ always @(posedge m_clk) begin
796+ s_pause_req_sync2_reg <= s_pause_req_sync1_reg;
797+ s_pause_req_sync3_reg <= s_pause_req_sync2_reg;
798+ s_pause_ack_sync1_reg <= pause_reg;
799+ end
800+
801+ assign m_axis_tready_out = m_axis_tready && ! pause_reg;
802+ assign m_axis_tvalid = m_axis_tvalid_out && ! pause_reg;
803+
804+ assign m_axis_tdata = m_axis_tdata_out;
805+ assign m_axis_tkeep = m_axis_tkeep_out;
806+ assign m_axis_tlast = m_axis_tlast_out;
807+ assign m_axis_tid = m_axis_tid_out;
808+ assign m_axis_tdest = m_axis_tdest_out;
809+ assign m_axis_tuser = m_axis_tuser_out;
810+
811+ assign s_pause_ack = s_pause_ack_sync3_reg;
812+ assign m_pause_ack = pause_reg;
813+
814+ always @(posedge m_clk) begin
815+ if (FRAME_PAUSE) begin
816+ if (m_axis_tvalid && m_axis_tready) begin
817+ if (m_axis_tlast) begin
818+ pause_frame_reg <= 1'b0 ;
819+ pause_reg <= m_pause_req || s_pause_req_sync3_reg;
820+ end else begin
821+ pause_frame_reg <= 1'b1 ;
822+ end
823+ end else begin
824+ if (! pause_frame_reg) begin
825+ pause_reg <= m_pause_req || s_pause_req_sync3_reg;
826+ end
827+ end
828+ end else begin
829+ pause_reg <= m_pause_req || s_pause_req_sync3_reg;
830+ end
831+
832+ if (m_rst) begin
833+ pause_frame_reg <= 1'b0 ;
834+ pause_reg <= 1'b0 ;
835+ end
836+ end
837+
838+ end else begin
839+
840+ assign m_axis_tready_out = m_axis_tready;
841+ assign m_axis_tvalid = m_axis_tvalid_out;
842+
843+ assign m_axis_tdata = m_axis_tdata_out;
844+ assign m_axis_tkeep = m_axis_tkeep_out;
845+ assign m_axis_tlast = m_axis_tlast_out;
846+ assign m_axis_tid = m_axis_tid_out;
847+ assign m_axis_tdest = m_axis_tdest_out;
848+ assign m_axis_tuser = m_axis_tuser_out;
849+
850+ assign s_pause_ack = 1'b0 ;
851+ assign m_pause_ack = 1'b0 ;
852+
853+ end
854+
750855endgenerate
751856
752857endmodule
0 commit comments