Each of the SI and MI on the AXI Interconnect core can be individually configured to have a data width of 32, 64, 128, 256, 512, or 1024 bits. When the data width of an interface is configured differently than the data width of the internal Crossbar, a width conversion module is automatically instantiated along the pathway.
The width conversion functions differ depending on whether the datapath width gets wider (upsizing) or narrower (downsizing) when moving in the direction from the SI toward the MI. The width conversion functions are the same in either the SI hemisphere (translating from an SI to the Crossbar) or the MI hemisphere (translating from the Crossbar to a MI).
Selecting a sufficiently high-data width for the AXI Crossbar can avoid loss of data bandwidth. For example, you could elect to set the AXI Crossbar to match the width of a speed-critical slave, such as a memory controller, even though all the masters that access that slave have narrower data widths.
With that setting, the AXI Interconnect core can perform data packing (Write transactions) or serialization (Read transactions) concurrently along multiple SI slot pathways in the SI hemisphere while the wide slave device and crossbar periodically maintain a data throughput rate higher than any one master device can sustain.
In contrast, selecting a lower data width for the AXI Crossbar can reduce logic resource utilization for less speed-critical designs. When seeking to minimize resource utilization, set the data width of the AXI Crossbar so that it minimizes the total number of width converters.
Table: AXI Data Width Converter Functional Truth Table lists the transformations performed by the Data Width Converter for various parametric configurations and incident SI transactions. Table: AXI Data Width Converter Transaction Transformation Formulae provides details of the resulting output (MI-side) transactions for each of the transformations. Use the Transformation Formula name in Table: AXI Data Width Converter Functional Truth Table as an index into Table: AXI Data Width Converter Transaction Transformation Formulae.
Table: AXI Data Width Converter Functional Truth Table and Table: AXI Data Width Converter Transaction Transformation Formulae use these following designators when describing properties, signals, and derived equations.
1.si.DW = SI_DATA_WIDTH
2.mi.DW = MI_DATA_WIDTH
3.si.LEN = S_AXI_AWLEN or C_S_AXI_ARLEN, as applicable
4.si.ADDR = S_AXI_AWADDR or C_S_AXI_ARADDR, as applicable
5.si.Bytes = si.DW / 8
6.mi.Bytes = mi.DW / 8
7.mi.ByteMask = mi.Bytes – 1
8.si.SIZE = S_AXI_AWSIZE or S_AXI_ARSIZE, as applicable
9.si.SizeMask = (2**si.SIZE) – 1
10.mi.SizeMask = (2**mi.SIZE) – 1
11.mi.AlignedStart = si.ADDR & ~mi.ByteMask
12.mi.AlignedEnd = ((si.ADDR & ~si.SizeMask) + (si.LEN * 2**si.SIZE)) & ~mi.ByteMask
13.mi.upsize_LEN = (mi.AlignedEnd - mi.AlignedStart) / mi.Bytes
14.si.conv_ratio = ceil((2**si.SIZE) / mi.Bytes)
15.si.downsize_LEN = (si.LEN+1) * si.conv_ratio - 1
16.mi.AlignedAdjustment = (si.ADDR & si.SizeMask & ~mi.ByteMask) / mi.Bytes
17.si.burst_bytes = 2**si.SIZE * (si.LEN+1)
18.si.burst_mask = si.burst_bytes - 1
19.si.wrap_address = si.ADDR & ~si.burst_mask
20.si.wrap1_LEN = (si.burst_bytes - (si.ADDR & si.burst_mask)) / mi.Bytes - 1
21.si.wrap2_LEN = (si.ADDR & si.burst_mask) / mi.Bytes - 1
22.Downsize_ratio = ceil((2**si.SIZE) / (MI_DATA_WIDTH / 8))
23.MI beats = SI beats * Downsize_ratio (less MI beats skipped due to unaligned ADDR)
24.max_beats = 256 if (PROTOCOL == AXI4), 16 if (PROTOCOL == AXI3)
Table 3-1: AXI Data Width Converter
DATA_WIDTH |
s_axi_a*burst |
PROTOCOL |
Input Conditions |
Resulting |
Transformation Formula |
---|---|---|---|---|---|
SI > MI (downsizer)
|
b01 (INCR) |
0 (AXI4) |
downsize_ratio = 1 |
Transaction unchanged |
Pass-through Downsize |
1 (AXI3) |
downsize_ratio = 1 |
Transaction unchanged |
Pass-through Downsize |
||
0 (AXI4) |
MI beats <= 256, downsize_ratio > 1 |
1 burst |
INCR Downsize |
||
0 (AXI4) |
MI beats > 256, downsize_ratio > 1 |
Split into max 256-beat bursts |
Split INCR Downsize |
||
1 (AXI3) |
MI beats <= 16, downsize_ratio > 1 |
1 burst |
INCR Downsize |
||
1 (AXI3) |
MI beats > 16, downsize_ratio > 1 |
Split into max 16-beat bursts |
Split INCR Downsize |
||
b10 (WRAP) |
0 (AXI4) or 1 (AXI3) |
downsize_ratio = 1
|
Transaction unchanged (remains WRAP) |
Pass-through Downsize
|
|
0 (AXI4) or 1 (AXI3) |
MI beats <= 16, downsize_ratio > 1 |
1 burst |
WRAP Downsize |
||
0 (AXI4) |
16 < MI beats <= 256, ADDR is burst-aligned |
1 burst; change to INCR |
WRAP-to-INCR Downsize |
||
0 (AXI4) |
16 < MI beats <= 256, ADDR is not burst-aligned (wrapping required) |
Split into 2 bursts; change to INCR |
WRAP-to-INCR Downsize |
||
0 (AXI4) |
MI beats > 256 |
Split into max 256-beat bursts; change to INCR |
Split WRAP-to-INCR Downsize |
||
1 (AXI3) |
MI beats > 16 |
Split into max 16-beat bursts; change to INCR |
Split WRAP-to-INCR Downsize
|
||
b00 (FIXED) |
0 (AXI4) or 1 (AXI3) |
downsize_ratio = 1 |
Transaction not modified (remains FIXED) |
Pass-through Downsize |
|
0 (AXI4) |
downsize_ratio > 1 |
Split into (s_axi_alen + 1) bursts; change to INCR |
FIXED-to-INCR Downsize |
||
SI > MI (downsizer)
|
b0b00 (FIXED) (continued) |
1 (AXI3) |
1 < downsize_ratio <= 16 |
Split into (s_axi_alen + 1) bursts; change to INCR |
FIXED-to-INCR Downsize |
1 (AXI3) |
downsize_ratio > 16 |
Split into max 16-beat bursts; change to INCR |
Split FIXED-to-INCR Downsize |
||
x |
2 (AXI4-Lite) |
Write && ~s_axi_awaddr[2] && (s_axi_wstrb[7:4] != 0) && (s_axi_wstrb[3:0] != 0) |
Split into 2 transactions |
Lite Split Downsize |
|
Write && ~s_axi_awaddr[2] && (s_axi_wstrb[7:4] == 0) |
Transaction not modified |
Lite Low-order Write Downsize |
|||
Write && (s_axi_awaddr[2] || ((s_axi_wstrb[7:4] != 0) && (s_axi_wstrb[3:0] == 0))) |
One transaction with m_axi_awaddr = s_axi_awaddr | 'b100; m_axi_wdata = s_axi_wdata[63:32] |
Lite Unaligned Downsize |
|||
Read && ~s_axi_araddr[2] |
Split into 2 transactions |
Lite Split Downsize |
|||
Read && s_axi_araddr[2] |
Transaction not modified; s_axi_rdata[63:32] = m_axi_rdata; s_axi_rdata[31:0] undetermined |
Lite Unaligned Downsize |
|||
SI < MI (upsizer)
|
|
0 (AXI4) or 1 (AXI3) |
~S_AXI_A*CACHE[1] |
Transaction not modified |
Pass-through Upsize |
b01 (INCR) |
x |
S_AXI_A*CACHE[1] |
1 burst |
INCR Upsize |
|
b10 (WRAP) |
0 (AXI4) or 1 (AXI3) |
S_AXI_A*CACHE[1] |
1 burst |
WRAP Upsize |
|
b00 (FIXED) |
0 (AXI4) or 1 (AXI3) |
x |
Transaction not modified |
Pass-through Upsize |
|
x |
2 (AXI4-Lite) |
x |
Transaction not modified |
Pass-through Upsize |
Functional Truth Table
Table 3-2: AXI Data Width Converter Transaction Transformation Formulae
Transformation Formula |
Conditions |
Output Transactions |
Output (MI) LEN |
Output (MI) ADDR |
Output (MI) BURST |
Output (MI) LOCK |
---|---|---|---|---|---|---|
Pass-through Downsize(1) |
x |
1 |
No Change |
No Change |
s_axi_a*burst |
s_axi_a*lock |
INCR Downsize(2) |
x |
1 |
si.downsize_LEN - mi.AlignedAdjustment |
No Change
|
INCR |
s_axi_a*lock |
Split INCR Downsize(2) |
x |
ceil ((si.downsize_LEN+1) / max_beats) |
first = max_beats - mi.AlignedAdjustment - 1 ; last = si.downsize_LEN % max_beats; others = max_beats - 1 |
first = si.ADDR; transaction i = (si.ADDR & ~si.SizeMask ) + ((i-1) * max_beats*mi.Bytes) |
INCR |
0 |
WRAP Downsize(2) |
x |
1 |
si.downsize_LEN |
No change |
WRAP |
s_axi_a*lock |
WRAP-to-INCR Downsize(2) |
if ((si.ADDR & si.burst_mask ) == 0) else |
1 |
si.wrap1_LEN |
si.ADDR |
INCR |
s_axi_a*lock |
2 |
first = si.wrap1_LEN ; second = si.wrap2_LEN |
first = si.ADDR; second = si.wrap_address |
INCR |
0 |
||
Split WRAP-to-INCR Downsize(2) |
if ((si.ADDR & si.burst_mask ) == 0)
|
ceil ((si.wrap1_LEN+1) / max_beats)
|
all = max_beats
|
first = si.ADDR; transaction i = (si.ADDR & ~si.SizeMask) + ((i-1) * max_beats*mi.Bytes) |
INCR |
0 |
else
|
ceil ((si.wrap1_LEN+1) / max_beats) + ceil ((si.wrap2_LEN+1) / max_beats)
|
all = max_beats
|
first = si.ADDR; (others TBD, wrap as required)
|
INCR
|
0 |
|
FIXED-to-INCR Downsize(2) |
x |
si.LEN+1 |
all = max(si.conv_ratio - mi.AlignedAdjustment - 1, 0) |
all = si.ADDR |
INCR |
0 |
Split FIXED-to-INCR Downsize(2) |
x |
(si.LEN+1) * int((si.conv_ratio - mi.AlignedAdjustment) / max_beats) |
first = (si.conv_ratio - mi.AlignedAdjustment - 1) % max_beats; others = max_beats - 1 |
first = si.ADDR; (others TBD, repeat si.ADDR or increment as needed) |
INCR |
0 |
Lite Split Downsize |
x |
2 |
N/A (0) |
first = si.ADDR; second = si.ADDR | 'b100 |
N/A (singles) |
N/A |
Lite Low-order Write Downsize |
x |
1 |
N/A (0) |
si.ADDR |
N/A (singles) |
N/A |
Lite Unaligned Downsize |
x |
1 |
N/A (0) |
si.ADDR | 'b100 |
N/A (singles) |
N/A |
Pass-through Upsize(1) |
x |
1 |
No change |
No change |
s_axi_a*burst |
s_axi_a*lock |
INCR Upsize(2) |
x |
1 |
mi.upsize_LEN |
No change |
INCR |
s_axi_a*lock |
WRAP Upsize(2) |
Write |
1 |
ceil((si.LEN+1) * (2**si.SIZE) /mi.Bytes) - 1 |
si.wrap_address + (ceil((si.ADDR & si.burst_mask ) / mi.Bytes) * mi.Bytes) % si.burst_bytes |
If (mi.LEN>0) then WRAP, else INCR |
s_axi_a*lock |
Read |
1 |
ceil((si.LEN+1) * (2**si.SIZE )/mi.Bytes ) - 1 |
si.wrap_address + (int((si.ADDR & si.burst_mask) / mi.Bytes ) * mi.Bytes ) |
(If mi.LEN>0) then WRAP, else INCR |
s_axi_a*lock |
|