aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/axi/axi_fast_fifo.v
blob: 5ff303b116ca4374b07f89428e80ae2e800a2c33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//
// Copyright 2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
//
// Ultra fast critical path FIFO.
// Only 2 entrys but no combinatorial feed through paths
//


module axi_fast_fifo
  #(parameter WIDTH=64)
  (
   input clk,
   input reset,
   input clear,
   //
   input [WIDTH-1:0] i_tdata,
   input i_tvalid,
   output reg i_tready,
   //
   output [WIDTH-1:0] o_tdata,
   output reg o_tvalid,
   input  o_tready
   );

   reg [WIDTH-1:0] data_reg1, data_reg2;

   reg [1:0] 	   state;
   
   localparam EMPTY = 0;
   localparam HALF = 1;
   localparam FULL = 2;
   
   always @(posedge clk) 
     if (reset | clear) begin
	state <= EMPTY;
	data_reg1 <= 0;
	data_reg2 <= 0;
	o_tvalid <= 1'b0;
	i_tready <= 1'b0;
	
     end else begin
	case (state)
	  // Nothing in either register.
	  // Upstream can always push data to us.
	  // Downstream has nothing to take from us.
	  EMPTY: begin
	     if (i_tvalid) begin
		data_reg1 <= i_tdata;
		state <= HALF;
		i_tready <= 1'b1;
		o_tvalid <= 1'b1;
	     end else begin
		state <= EMPTY;
		i_tready <= 1'b1;
		o_tvalid <= 1'b0;
	     end
	  end
	  // First Register Full.
	  // Upstream can always push data to us.
	  // Downstream can always read from us.
	  HALF: begin
	     if (i_tvalid && o_tready) begin
		data_reg1 <= i_tdata;
		state <= HALF;
		i_tready <= 1'b1;
		o_tvalid <= 1'b1;
	     end else if (i_tvalid) begin
		data_reg1 <= i_tdata;
		data_reg2 <= data_reg1;
		state <= FULL;
		i_tready <= 1'b0;
		o_tvalid <= 1'b1;
	     end else if (o_tready) begin
		state <= EMPTY;
		i_tready <= 1'b1;
		o_tvalid <= 1'b0;
	     end else begin
		state <= HALF;
		i_tready <= 1'b1;
		o_tvalid <= 1'b1;
	     end
	  end // case: HALF
	  // Both Registers Full.
	  // Upstream can not push to us in this state.
	  // Downstream can always read from us.
	  FULL: begin
	     if (o_tready) begin
		state <= HALF;
		i_tready <= 1'b1;
		o_tvalid <= 1'b1;
	     end
	     else begin
		state <= FULL;
		i_tready <= 1'b0;
		o_tvalid <= 1'b1;
	     end
	  end
	endcase // case(state)
     end // else: !if(reset | clear)

   assign o_tdata = (state == FULL) ? data_reg2 : data_reg1;
   

endmodule // axi_fast_fifo