Source code: link.
AXI Requests & Responses In Flits
Signals in 5 channels are encapsulated in flit data, with following parameters.
1
2
3
4
5
| parameter ADDR_WIDTH = 32;
parameter DATA_WIDTH = 64;
parameter STRB_WIDTH = DATA_WIDTH / 8;
parameter ID_WIDTH = 8;
parameter USER_WIDTH = 8;
|
LSBs of AxID
indicates the sender. LSBs of AxADDR
indicates the target receiver.
connect_parameters.v
is modified according to the given configurations.
1
2
3
4
5
| `define NUM_USER_SEND_PORTS 4
`define NUM_USER_RECV_PORTS 4
`define NUM_VCS 2
`define FLIT_DATA_WIDTH 92
`define FLIT_WIDTH (`FLIT_DATA_WIDTH + 5)
|
AW/AR Channel
1
2
3
4
5
6
7
8
9
10
11
12
13
| channel - [91 : 89] # aw = 3'b001, ar = 3'b010
axuser - [88 : 81]
axid - [80 : 73]
------ padding ------
axlen - [60 : 53]
axsize - [52 : 50]
axburst - [49 : 48]
axlock - [47 : 47]
axcache - [46 : 43]
axprot - [42 : 40]
axqos - [39 : 36]
axregion - [35 : 32]
axaddr - [31 : 0]
|
Updated on 06/10, we need to unify AXI4-Stream and AXI4 id/user field.
1
2
3
4
5
6
7
8
9
10
11
12
13
| channel - [91 : 89] # r = 3'b110
------ padding ------
axlen - [76 : 69]
axsize - [68 : 66]
axburst - [65 : 64]
axlock - [63 : 63]
axcache - [62 : 59]
axprot - [58 : 56]
axqos - [55 : 52]
axregion - [51 : 48]
axaddr - [47 : 16]
axuser - [15 : 8]
axid - [ 7 : 0]
|
W Channel
1
2
3
4
5
6
| channel - [91 : 89] # w = 3'b011
wuser - [88 : 81]
wid - [80 : 73]
wlast - [72 : 72]
wstrb - [71 : 64]
wdata - [63 : 0]
|
Updated on 06/10, we need to unify AXI4-Stream and AXI4 id/user field.
1
2
3
4
5
6
| channel - [91 : 89] # r = 3'b110
wlast - [88 : 88]
wstrb - [87 : 80]
wdata - [79 : 16]
wuser - [15 : 8]
wid - [ 7 : 0]
|
B Channel
1
2
3
4
5
6
| channel - [91 : 89] # b = 3'b101
buser - [88 : 81]
bid - [80 : 73]
------ padding ------
bresp - [65 : 64]
------ padding ------
|
Updated on 06/10, we need to unify AXI4-Stream and AXI4 id/user field.
1
2
3
4
5
6
| channel - [91 : 89] # r = 3'b110
------ padding ------
bresp - [81 : 80]
------ padding ------
buser - [15 : 8]
bid - [ 7 : 0]
|
R Channel
1
2
3
4
5
6
7
| channel - [91 : 89] # r = 3'b110
ruser - [88 : 81]
rid - [80 : 73]
rlast - [72 : 72]
------ padding ------
rresp - [65 : 64]
rdata - [63 : 0]
|
Updated on 06/10, we need to unify AXI4-Stream and AXI4 id/user field.
1
2
3
4
5
6
7
| channel - [91 : 89] # r = 3'b110
rlast - [88 : 88]
------ padding ------
rresp - [81 : 80]
rdata - [79 : 16]
ruser - [15 : 8]
rid - [ 7 : 0]
|
Bridge Design
A bridge is used to convert a pair of send & recv port to a standard AXI protocol interface, either as a master device or a slave device. For example, for a network with 4 endpoints, we can have 2 master devices and 2 slave devices.
Peek flow control is used in current version.
FSM of Master Bridge
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
| always_comb begin
case (state)
IDLE: begin
if (aw_fire)
next_state = WDATA;
else if (ar_fire)
next_state = RDATA1;
else
next_state = state;
end
WDATA: begin
if (w_fire && axi.wlast)
next_state = WRESP1;
else
next_state = state;
end
WRESP1: begin
if (get_flit[`FLIT_WIDTH - 1]) // flit is valid
next_state = WRESP2;
else
next_state = state;
end
WRESP2: begin
if (b_fire)
next_state = IDLE;
else
next_state = state;
end
RDATA1: begin
if (get_flit[`FLIT_WIDTH - 1]) // flit is valid
next_state = RDATA2;
else
next_state = state;
end
RDATA2: begin
if (r_fire) begin
if (axi.rlast)
next_state = IDLE;
else
next_state = RDATA1;
end else
next_state = state;
end
default: next_state = state;
endcase
end
|
FSM of Slave Bridge
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
| always_comb begin
case (state)
IDLE: begin
if (get_flit[`FLIT_WIDTH - 1]) begin // flit is valid
if (get_flit[`FLIT_DATA_WIDTH - 1 : `FLIT_DATA_WIDTH - 3] == CHANNEL_AW)
next_state = WADDR;
else if (get_flit[`FLIT_DATA_WIDTH - 1 : `FLIT_DATA_WIDTH - 3] == CHANNEL_AR)
next_state = RADDR;
else
next_state = state;
end else
next_state = state;
end
WADDR: begin
if (aw_fire)
next_state = WDATA1;
else
next_state = state;
end
WDATA1: begin
if (get_flit[`FLIT_WIDTH - 1]) // flit is valid
next_state = WDATA2;
else
next_state = state;
end
WDATA2: begin
if (w_fire) begin
if (axi.wlast)
next_state = WRESP;
else
next_state = WDATA1;
end else
next_state = state;
end
WRESP: begin
if (b_fire)
next_state = IDLE;
else
next_state = state;
end
RADDR: begin
if (ar_fire)
next_state = RDATA;
else
next_state = state;
end
RDATA: begin
if (r_fire) begin
if (axi.rlast)
next_state = IDLE;
else
next_state = RDATA;
end else
next_state = state;
end
default: next_state = state;
endcase
end
|
Test
We create a master device and a slave device to send or receive data. See AXI4Device.sv
for example device modules and testbench_sample_peek_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
| # ---- 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: [m0- w] data=deadbeefdeadbeef
# 10: [m1-ar] addr=00000003
# 11: Port 0 send flit 1c60000ffdeadbeefdeadbef0
# 11: [m0- w] data=deadbeefdeadbef0
# 12: Port 0 send flit 1c60000ffdeadbeefdeadbef1
# 12: Port 2 recv flit 1c2000000006d000000000002
# 12: [m0- w] data=deadbeefdeadbef1
# 13: Port 0 send flit 1c60000ffdeadbeefdeadbef2
# 13: [m0- w] data=deadbeefdeadbef2
# 14: Port 0 send flit 1c60001ffdeadbeefdeadbef3
# 14: Port 3 recv flit 1e4000200006d000000000003
# 14: [m0- w] data=deadbeefdeadbef3
# 14: [s0-aw] addr=00000002
# 15: Port 2 recv flit 1c60000ffdeadbeefdeadbeef
# 16: [s0- w] data=deadbeefdeadbeef
# 16: [s1-ar] addr=00000003
# 17: Port 3 send flit 1ac000000deadbeefdeadbeef
# 17: Port 2 recv flit 1c60000ffdeadbeefdeadbef0
# 17: [s1- r] data=deadbeefdeadbeef
# 18: Port 3 send flit 1ac000000deadbeefdeadbef0
# 18: [s0- w] data=deadbeefdeadbef0
# 18: [s1- r] data=deadbeefdeadbef0
# 19: Port 3 send flit 1ac000000deadbeefdeadbef1
# 19: Port 2 recv flit 1c60000ffdeadbeefdeadbef1
# 19: [s1- r] data=deadbeefdeadbef1
# 20: Port 3 send flit 1ac000100deadbeefdeadbef2
# 20: Port 1 recv flit 1ac000000deadbeefdeadbeef
# 20: [s0- w] data=deadbeefdeadbef1
# 20: [s1- r] data=deadbeefdeadbef2
# 21: Port 2 recv flit 1c60000ffdeadbeefdeadbef2
# 21: [m1- r] data=deadbeefdeadbeef
# 22: Port 1 recv flit 1ac000000deadbeefdeadbef0
# 22: [s0- w] data=deadbeefdeadbef2
# 23: Port 2 recv flit 1c60001ffdeadbeefdeadbef3
# 23: [m1- r] data=deadbeefdeadbef0
# 24: Port 1 recv flit 1ac000000deadbeefdeadbef1
# 24: [s0- w] data=deadbeefdeadbef3
# 25: Port 2 send flit 18a0000000000000000000000
# 25: [m1- r] data=deadbeefdeadbef1
# 25: [s0- b]
# 26: Port 1 recv flit 1ac000100deadbeefdeadbef2
# 27: [m1- r] data=deadbeefdeadbef2
# 28: Port 0 recv flit 18a0000000000000000000000
# 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
|