File: axi_fifo_flop.v

package info (click to toggle)
uhd 3.9.5-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 107,272 kB
  • ctags: 57,231
  • sloc: cpp: 66,160; ansic: 59,349; python: 13,245; vhdl: 7,651; tcl: 2,668; sh: 1,634; makefile: 1,031; xml: 557; pascal: 230; csh: 94; asm: 20; perl: 11
file content (83 lines) | stat: -rw-r--r-- 2,857 bytes parent folder | download | duplicates (2)
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
//
// Copyright 2015 Ettus Research LLC
//
// Single cycle latency, depth of 2 "Flip flop" with no end to end combinatorial paths on
// AXI control signals (such as i_tready depends on o_tready). Breaking the combinatorial
// paths requires an additional register stage.
//
// Note: Once i_tvalid is asserted, it cannot be deasserted without i_tready having asserted
//       indicating i_tdata has been read. This is an AXI stream requirement.

module axi_fifo_flop #(
  parameter WIDTH = 32)
(
  input clk,
  input reset,
  input clear,
  input [WIDTH-1:0] i_tdata,
  input i_tvalid,
  output i_tready,
  output [WIDTH-1:0] o_tdata,
  output o_tvalid,
  input o_tready,
  output [1:0] space,
  output [1:0] occupied);

  reg [WIDTH-1:0] i_tdata_pipe, i_tdata_reg;
  reg             i_tvalid_pipe, i_tvalid_reg;

  // Steady state data flow is typically: i_tdata -> i_tdata_reg -> o_tdata
  // but can change to: i_tdata -> i_tdata_reg -> i_tdata_pipe -> o_tdata
  // depending on i_tvalid / o_tready combinations
  always @(posedge clk) begin
    if (reset | clear) begin
      i_tvalid_reg  <= 1'b0;
      i_tvalid_pipe <= 1'b0;
      i_tdata_reg   <= {WIDTH{1'b0}};
      i_tdata_pipe  <= {WIDTH{1'b0}};
    end else begin
      // Always accept new data if there is space in the pipeline
      if (i_tready) begin
        i_tdata_reg  <= i_tdata;
        i_tvalid_reg <= i_tvalid;
      end
      if (o_tready) begin
        if (i_tready) begin
          // Only useful when data flow is i_tdata -> i_tdata_reg -> i_tdata_pipe -> o_tdata
          i_tdata_pipe <= i_tdata_reg;
          if (i_tvalid_pipe) begin
            // Switch from: i_tdata -> i_tdata_reg -> i_tdata_pipe -> o_tdata
            // to:          i_tdata -> i_tdata_reg -> o_tdata
            // will occur if i_tvalid_reg = 0
            i_tvalid_pipe <= i_tvalid_reg;
          end
        // Input is throttled
        end else begin
          i_tdata_pipe  <= i_tdata_reg;
          i_tvalid_pipe <= i_tvalid_reg;
          i_tvalid_reg  <= 1'b0; // Since i_tready = 0, we know we will not get new data this cycle
        end
      // Output is throttled
      end else begin
        // Space available in i_tdata_pipe to store i_tdata_reg.
        // This is the case where data flow will change
        // from: i_tdata -> i_tdata_reg -> o_tdata
        // to:   i_tdata -> i_tdata_reg -> i_tdata_pipe -> o_tdata
        // if i_tvalid_reg = 1
        if (~i_tvalid_pipe) begin
          i_tvalid_pipe <= i_tvalid_reg;
          i_tdata_pipe  <= i_tdata_reg;
        end
      end
    end
  end

  assign i_tready = ~(i_tvalid_reg & i_tvalid_pipe);

  assign o_tvalid = i_tvalid_pipe ? 1'b1         : i_tvalid_reg;
  assign o_tdata  = i_tvalid_pipe ? i_tdata_pipe : i_tdata_reg;

  assign occupied = i_tvalid_reg + i_tvalid_pipe;
  assign space = 2'd2 - occupied;

endmodule