@@ -80,7 +80,11 @@ module axis_async_fifo #
80
80
// Drop incoming frames when full
81
81
// When set, s_axis_tready is always asserted
82
82
// 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
84
88
)
85
89
(
86
90
/*
@@ -111,6 +115,14 @@ module axis_async_fifo #
111
115
output wire [DEST_WIDTH- 1 :0 ] m_axis_tdest,
112
116
output wire [USER_WIDTH- 1 :0 ] m_axis_tuser,
113
117
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
+
114
126
/*
115
127
* Status
116
128
*/
@@ -291,6 +303,7 @@ endgenerate
291
303
292
304
wire [WIDTH- 1 :0 ] m_axis = m_axis_pipe_reg[RAM_PIPELINE+ 1 - 1 ];
293
305
306
+ wire m_axis_tready_pipe;
294
307
wire m_axis_tvalid_pipe = m_axis_tvalid_pipe_reg[RAM_PIPELINE+ 1 - 1 ];
295
308
296
309
wire [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
300
313
wire [DEST_WIDTH- 1 :0 ] m_axis_tdest_pipe = DEST_ENABLE ? m_axis[DEST_OFFSET + : DEST_WIDTH] : {DEST_WIDTH{1'b0 }};
301
314
wire [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 }};
302
315
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
+
303
326
wire pipe_ready;
304
327
305
328
assign s_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1 ) ? {s_depth_reg, {$clog2(KEEP_WIDTH){1'b0 }}} : s_depth_reg;
@@ -574,22 +597,22 @@ end
574
597
integer j;
575
598
576
599
always @(posedge m_clk) begin
577
- if (OUTPUT_FIFO_ENABLE || m_axis_tready ) begin
600
+ if (m_axis_tready_pipe ) begin
578
601
// output ready; invalidate stage
579
602
m_axis_tvalid_pipe_reg[RAM_PIPELINE+ 1 - 1 ] <= 1'b0 ;
580
603
m_terminate_frame_reg <= 1'b0 ;
581
604
end
582
605
583
606
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
585
608
// output ready or bubble in pipeline; transfer down pipeline
586
609
m_axis_tvalid_pipe_reg[j] <= m_axis_tvalid_pipe_reg[j- 1 ];
587
610
m_axis_pipe_reg[j] <= m_axis_pipe_reg[j- 1 ];
588
611
m_axis_tvalid_pipe_reg[j- 1 ] <= 1'b0 ;
589
612
end
590
613
end
591
614
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
593
616
// output ready or bubble in pipeline; read new data from FIFO
594
617
m_axis_tvalid_pipe_reg[0 ] <= 1'b0 ;
595
618
m_axis_pipe_reg[0 ] <= mem[rd_ptr_reg[ADDR_WIDTH- 1 :0 ]];
@@ -604,14 +627,14 @@ always @(posedge m_clk) begin
604
627
605
628
if (m_axis_tvalid_pipe && LAST_ENABLE) begin
606
629
// 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
608
631
m_frame_reg <= 1'b0 ;
609
632
end else begin
610
633
m_frame_reg <= 1'b1 ;
611
634
end
612
635
end
613
636
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
615
638
// terminate frame
616
639
// (only for frame transfers interrupted by source reset)
617
640
m_axis_tvalid_pipe_reg[RAM_PIPELINE+ 1 - 1 ] <= 1'b1 ;
@@ -662,16 +685,17 @@ if (!OUTPUT_FIFO_ENABLE) begin
662
685
663
686
assign pipe_ready = 1'b1 ;
664
687
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;
666
690
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;
673
697
674
- end else begin
698
+ end else begin : output_fifo
675
699
676
700
// output datapath logic
677
701
reg [DATA_WIDTH- 1 :0 ] m_axis_tdata_reg = {DATA_WIDTH{1'b0 }};
@@ -704,16 +728,18 @@ end else begin
704
728
705
729
assign pipe_ready = ! out_fifo_half_full_reg;
706
730
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 }};
714
740
715
741
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 ;
717
743
718
744
out_fifo_half_full_reg <= $unsigned (out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2 ** (OUTPUT_FIFO_ADDR_WIDTH- 1 );
719
745
@@ -727,7 +753,7 @@ end else begin
727
753
out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1 ;
728
754
end
729
755
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
731
757
m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH- 1 :0 ]];
732
758
m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH- 1 :0 ]];
733
759
m_axis_tvalid_reg <= 1'b1 ;
@@ -747,6 +773,85 @@ end else begin
747
773
748
774
end
749
775
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
+
750
855
endgenerate
751
856
752
857
endmodule
0 commit comments