Home CONNECT Note (4) - AXI4 Interface on Credit-based Flow Control Network
Post
Cancel

CONNECT Note (4) - AXI4 Interface on Credit-based Flow Control Network

Source code: link.

Flit FIFO

In credit-based flow control network, a FIFO is needed to store multiple requests and responses and a credit counter is used to reflect the availability of buffer in a client. In FlitFIFO.sv, we design a simple FIFO with valid-ready interface, based on chisel3 queue data structure (source).

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
module BasicFIFO #(parameter DEPTH = `FLIT_BUFFER_DEPTH, parameter DATA_WIDTH = `FLIT_WIDTH) (
    input CLK,
    input RST_N,

    // Input
    input  [DATA_WIDTH - 1 : 0] enq_data,
    input                       enq_valid,
    output                      enq_ready,

    // Output
    output [DATA_WIDTH - 1 : 0] deq_data,
    output                      deq_valid,
    input                       deq_ready
  );

  logic [DATA_WIDTH - 1 : 0]    buffer [0 : DEPTH];
  logic [$clog2(DEPTH) - 1 : 0] enq_ptr;
  logic [$clog2(DEPTH) - 1 : 0] deq_ptr;
  logic                         ptr_match, empty, full, maybe_full;
  logic                         enq_fire, deq_fire, do_enq, do_deq;

  assign ptr_match  = (enq_ptr == deq_ptr);
  assign empty      = ptr_match && !maybe_full;
  assign full       = ptr_match && maybe_full;

  always_ff @(posedge CLK) begin
    if (!RST_N) begin
      enq_ptr <= 0;
      deq_ptr <= 0;
      maybe_full <= 0;
    end else begin
      if (do_enq)
        enq_ptr <= enq_ptr + 1;
      if (do_deq)
        deq_ptr <= deq_ptr + 1;
      if (do_enq != do_deq)
        maybe_full <= do_enq;
    end
  end

  always_ff @(posedge CLK) begin
    if (!RST_N) begin
      for (int i = 0; i < DEPTH; i++) begin
        buffer[i] <= 0;
      end
    end else begin
      if (do_enq)
        buffer[enq_ptr] <= enq_data;
    end
  end

  assign enq_fire = enq_valid && enq_ready;
  assign deq_fire = deq_valid && deq_ready;

  logic [DATA_WIDTH - 1 : 0]  deq_data_;
  logic                       deq_valid_;
  assign deq_data   = deq_data_;
  assign deq_valid  = deq_valid_;

  always_comb begin
    do_enq = enq_fire;
    do_deq = deq_fire;
    deq_data_ = buffer[deq_ptr];
    deq_valid_ = !empty;

    // Flow
    if (empty) begin
      if (deq_ready) begin
        do_enq = 0;
      end
      do_deq = 0;
      deq_data_ = enq_data;
    end
    if (enq_valid) begin
      deq_valid_ = 1;
    end
  end

  logic enq_ready_;
  assign enq_ready = enq_ready_;

  always_comb begin
    enq_ready_ = !full;
    
    // Pipe
    if (deq_ready) begin
      enq_ready_ = 1;
    end
  end

endmodule

A wrapper is also created to connect the network with the AXI interface and include the FIFO as follows.

1
2
3
4
5
6
7
+--------+            +------------+             +-------------+            +---------+
| Device | <--AXI4--> | AXI4Bridge | <--flits--> | InPortFIFO  | <--flits-->|         |
+--------+            +------------+             +-------------+            |         |
                            ^                                               | Network |
                            |                    +-------------+            |         |
                            +-----------flits--> | OutPortFIFO | <--flits-->|         |
                                                 +-------------+            +---------+

Test

See testbench_sample_axi4.sv for test bench.

Results

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
# ---- Performing Reset ----
#     9: Port 0 send flit 1c2000000006d000000000002
#     9: [m0-aw] addr=00000002
#    10: Port 0 send flit 1c60000ffdeadbeefdeadbeef
#    10: Port 1 send flit 1e4000200006d000000000003
#    10: Port 0 get a credit
#    10: [m0- w] data=deadbeefdeadbeef
#    10: [m1-ar] addr=00000003
#    11: Port 0 send flit 1c60000ffdeadbeefdeadbef0
#    11: Port 0 get a credit
#    11: [m0- w] data=deadbeefdeadbef0
#    12: Port 0 send flit 1c60000ffdeadbeefdeadbef1
#    12: Port 2 recv flit 1c2000000006d000000000002
#    12: Port 0 get a credit
#    12: Port 1 get a credit
#    12: Port 2 put a credit
#    12: [m0- w] data=deadbeefdeadbef1
#    13: Port 0 send flit 1c60000ffdeadbeefdeadbef2
#    13: Port 0 get a credit
#    13: [m0- w] data=deadbeefdeadbef2
#    14: Port 0 send flit 1c60001ffdeadbeefdeadbef3
#    14: Port 2 recv flit 1c60000ffdeadbeefdeadbeef
#    14: Port 3 recv flit 1e4000200006d000000000003
#    14: Port 0 get a credit
#    14: Port 3 put a credit
#    14: [m0- w] data=deadbeefdeadbef3
#    14: [s0-aw] addr=00000002
#    15: Port 2 recv flit 1c60000ffdeadbeefdeadbef0
#    15: Port 0 get a credit
#    15: Port 2 put a credit
#    16: Port 2 recv flit 1c60000ffdeadbeefdeadbef1
#    16: [s0- w] data=deadbeefdeadbeef
#    16: [s1-ar] addr=00000003
#    17: Port 3 send flit 1ac000000deadbeefdeadbeef
#    17: Port 2 recv flit 1c60000ffdeadbeefdeadbef2
#    17: Port 2 put a credit
#    17: [s1- r] data=deadbeefdeadbeef
#    18: Port 3 send flit 1ac000000deadbeefdeadbef0
#    18: Port 2 recv flit 1c60001ffdeadbeefdeadbef3
#    18: Port 3 get a credit
#    18: [s0- w] data=deadbeefdeadbef0
#    18: [s1- r] data=deadbeefdeadbef0
#    19: Port 3 send flit 1ac000000deadbeefdeadbef1
#    19: Port 3 get a credit
#    19: Port 2 put a credit
#    19: [s1- r] data=deadbeefdeadbef1
#    20: Port 3 send flit 1ac000100deadbeefdeadbef2
#    20: Port 1 recv flit 1ac000000deadbeefdeadbeef
#    20: Port 3 get a credit
#    20: Port 1 put a credit
#    20: [s0- w] data=deadbeefdeadbef1
#    20: [s1- r] data=deadbeefdeadbef2
#    21: Port 1 recv flit 1ac000000deadbeefdeadbef0
#    21: Port 3 get a credit
#    21: Port 2 put a credit
#    21: [m1- r] data=deadbeefdeadbeef
#    22: Port 1 recv flit 1ac000000deadbeefdeadbef1
#    22: Port 1 put a credit
#    22: [s0- w] data=deadbeefdeadbef2
#    23: Port 1 recv flit 1ac000100deadbeefdeadbef2
#    23: Port 2 put a credit
#    23: [m1- r] data=deadbeefdeadbef0
#    24: Port 1 put a credit
#    24: [s0- w] data=deadbeefdeadbef3
#    25: Port 2 send flit 18a0000000000000000000000
#    25: [m1- r] data=deadbeefdeadbef1
#    25: [s0- b]
#    26: Port 2 get a credit
#    26: Port 1 put a credit
#    27: [m1- r] data=deadbeefdeadbef2
#    28: Port 0 recv flit 18a0000000000000000000000
#    28: Port 0 put a credit
#    29: [m0- b]
# actual:deadbeefdeadbeef expected:deadbeefdeadbeef
# 
# actual:deadbeefdeadbef0 expected:deadbeefdeadbef0
# 
# actual:deadbeefdeadbef1 expected:deadbeefdeadbef1
# 
# actual:deadbeefdeadbef2 expected:deadbeefdeadbef2
# 
# Pass
# actual:deadbeefdeadbeef expected:deadbeefdeadbeef
# 
# actual:deadbeefdeadbef0 expected:deadbeefdeadbef0
# 
# actual:deadbeefdeadbef1 expected:deadbeefdeadbef1
# 
# actual:deadbeefdeadbef2 expected:deadbeefdeadbef2
# 
# Pass
This post is licensed under CC BY 4.0 by the author.