Common AXI Design Mistakes and How to Avoid Them

AXI is widely used for communication between IP blocks in modern SoCs, but implementing an AXI interface correctly is more than connecting the right signals.

Many AXI problems come from relatively small RTL design decisions: making VALID depend incorrectly on READY, losing information when backpressure occurs, mishandling burst boundaries, assuming read and write channels always progress together, or failing to account for multiple outstanding transactions.

These issues can be particularly difficult to debug because an AXI interface may work perfectly in a simple simulation and fail when the slave applies backpressure, transactions overlap, or a burst reaches an address boundary.

This guide explains the common AXI design mistakes VLSI engineers encounter in RTL, why they happen, how to avoid them, and what to check during simulation and verification.

The examples focus on AXI4 concepts, but many of the underlying lessons apply to other ready/valid-based interfaces as well.

What Makes AXI Design Different?

AXI is not a simple single-channel bus.

AXI4 separates communication into five independent channels:

  • Write Address — AW
  • Write Data — W
  • Write Response — B
  • Read Address — AR
  • Read Data — R

Each channel has its own VALID and READY handshake.

A transfer occurs when both sides of the handshake are asserted at the active clock edge:

VALID && READY

This means an AXI design has to handle not only the data itself, but also when that data is accepted, when it must remain stable, how transactions are associated, and what happens when the receiving side is not ready. Arm’s AXI documentation defines the channel structure and transaction rules in detail.

That is where many implementation mistakes begin.

 

1. Making VALID Depend on READY

One of the most common mistakes is designing the source so that it waits for READY before asserting VALID.

For example, conceptually:

if (READY)

    VALID = 1;

 

This may appear convenient, but it creates an undesirable dependency between the sender and receiver.

A source should be able to indicate that it has a valid transfer without waiting for the destination to assert READY.

If both sides wait for each other, the interface can stop making progress.

A ready/valid interface is intended to allow the source to assert VALID when data is available while the destination independently controls READY.

How to avoid it

Think of the signals this way:

Source controls:

  • VALID
  • Payload

Destination controls:

  • READY

The source says:

“I have something to transfer.”

The destination says:

“I can accept it.”

The transfer happens when:

VALID = 1 AND READY = 1

This principle should be applied independently to each AXI channel.

 

2. Changing Payload While VALID Is High and READY Is Low

Another common error occurs when the source changes the address, data, or control information while VALID is asserted but READY is low.

Consider:

Cycle 1:

VALID = 1

READY = 0

DATA = A

 

Cycle 2:

VALID = 1

READY = 0

DATA = B

 

The receiver has not accepted the first transfer.

Changing the payload without a valid transfer can therefore violate the intended handshake behavior.

Correct approach

Once the source asserts VALID, it should keep the relevant transfer information stable until the handshake occurs.

Conceptually:

VALID = 1

READY = 0

DATA = A

 

VALID = 1

READY = 0

DATA = A

 

VALID = 1

READY = 1

DATA = A

 

The transfer happens on the final cycle.

This is one of the first waveform checks you should perform when debugging an AXI interface.

 

3. Treating the Five AXI Channels as One Transaction

AXI has independent channels.

A common design mistake is assuming that the write address and write data must always arrive together.

They do not have to behave as a single combined channel.

For writes, AXI separates:

Write Address → AW channel

from

Write Data → W channel

and the completion response uses:

Write Response → B channel

This means an RTL implementation must be able to handle legal differences in timing between these channels.

Why this matters

Suppose the write address arrives first but the data arrives several cycles later.

Your slave must be able to retain the required information and associate the pieces correctly.

A design that assumes:

AWVALID && WVALID

 

must always occur together can work in a simple testbench and fail with a more realistic master.

How to avoid it

Design and verify each channel according to its own handshake rules.

Then explicitly handle the relationships between channels where the protocol requires them.

 

4. Forgetting Backpressure

Backpressure is normal in AXI.

A slave may temporarily deassert READY because:

  • Internal storage is full
  • A pipeline is busy
  • A downstream block is stalled
  • A response queue is full
  • Arbitration is delaying the transaction

A common mistake is testing an interface only when:

READY = 1

 

all the time.

That does not adequately test the handshake logic.

Arm’s current AXI learning material emphasizes understanding how transactions behave in real systems, including data flow, correctness and performance.

Better verification

Randomly or deliberately introduce periods where:

READY = 0

 

Then verify that:

  • VALID remains asserted as required
  • Payload remains stable
  • No transfer is lost
  • No transfer is duplicated
  • The interface eventually resumes

Backpressure testing is one of the simplest ways to expose weak AXI RTL.

 

5. Assuming READY Must Always Be High

The opposite mistake is designing or verifying an AXI interface under the assumption that READY is permanently asserted.

For example:

assign ARREADY = 1’b1;

 

may be valid for a very simple interface if the architecture genuinely supports accepting every request immediately.

But a more realistic slave may need to apply backpressure.

If the RTL cannot tolerate READY going low, it has not been tested against an important part of the protocol behavior.

Better approach

Design the interface so that it works correctly when:

READY = 1

 

and when:

READY = 0

 

for multiple cycles.

Then verify both cases.

 

6. Creating Combinational Loops Between VALID and READY

A subtle but important problem occurs when the source’s VALID depends on the destination’s READY, while the destination’s READY depends on the source’s VALID.

For example:

Master VALID → Slave READY

      ↑              ↓

      └──────────────┘

 

This can create a combinational loop.

Ready/valid interfaces are particularly vulnerable to this type of design problem because both signals control whether a transfer occurs.

A common solution is to derive the control from registered state or otherwise ensure that the interface does not create an unintended combinational path between source and destination.

Practical check

When reviewing an AXI interface, ask:

Can VALID change combinationally because of READY?

and:

Can READY change combinationally because of VALID?

If the answer produces a loop across connected IP blocks, the architecture needs to be reconsidered.

 

7. Mishandling AXI Burst Length

AXI is burst-based, so burst parameters need careful handling.

Important fields include:

  • AxLEN
  • AxSIZE
  • AxBURST
  • AxADDR

The AXI specification defines the burst length and size rules, and AXI4 allows INCR bursts of up to 256 transfers.

A common RTL mistake is interpreting AxLEN directly as the number of transfers.

For AXI4:

Burst length = AxLEN + 1

So:

AxLEN = 0 → 1 transfer

AxLEN = 3 → 4 transfers

AxLEN = 7 → 8 transfers

 

How to avoid it

Create a clearly defined internal representation such as:

beats_remaining = AxLEN + 1

 

and decrement it only when an actual data transfer occurs.

This makes the RTL and verification environment easier to reason about.

 

8. Ignoring the 4 KB Burst Boundary Rule

This is a particularly important AXI design error.

An AXI burst must not cross a 4 KB address boundary. The rule exists in part to prevent a burst from crossing between different slaves and to limit the address range a subordinate needs to handle.

For example, a burst beginning near the end of one 4 KB region may need to be split rather than allowed to continue into the next region.

Why this matters

If an address generator simply calculates:

next_address = current_address + transfer_size;

 

without checking the boundary, it can generate an illegal burst.

How to avoid it

Before issuing a burst, calculate:

  • Start address
  • Number of beats
  • Bytes per beat
  • Final address

Then verify that the burst remains within the same 4 KB region.

This check belongs in the design or transaction-generation logic where appropriate, rather than relying only on the testbench to catch it.

 

9. Getting Burst Address Calculation Wrong

AXI supports different burst types.

The main types are:

  • FIXED
  • INCR
  • WRAP

An INCR burst increments the address according to the transfer size.

A FIXED burst keeps the address constant.

A WRAP burst follows wrapping-address rules.

The AXI specification defines these behaviors explicitly.

Common mistake

Designers sometimes assume every burst behaves like:

address = address + data_width

 

That is not generally correct.

The address increment is determined by the transfer size, not simply by the physical width of the bus.

Better approach

Calculate the number of bytes per beat from AxSIZE.

For example:

bytes_per_beat = 2 ^ AxSIZE

 

Then use the correct address-generation algorithm for the selected burst type.

 

10. Ignoring WSTRB During AXI Writes

WSTRB identifies which byte lanes of write data are valid.

A slave should not simply assume that every byte of WDATA is meaningful on every transfer.

For example, on a 32-bit data bus:

WDATA  = 32 bits

WSTRB  = 4 bits

 

Each strobe bit corresponds to a byte lane.

Conceptually:

WSTRB[0] → byte 0

WSTRB[1] → byte 1

WSTRB[2] → byte 2

WSTRB[3] → byte 3

 

If only some strobes are asserted, the design must preserve the unaffected bytes according to the memory/register semantics.

Common failure

A register or memory implementation writes all 32 bits regardless of WSTRB.

That can silently corrupt existing data during partial writes.

How to avoid it

Make byte-enable behavior explicit in the RTL and include partial-write cases in the testbench.

 

11. Mishandling the Last Beat of a Burst

For AXI write and read data channels, the LAST signal identifies the final data transfer of a burst.

A common mistake is generating LAST based on a cycle counter rather than on actual accepted transfers.

For example, if:

WVALID = 1

WREADY = 0

 

the write data has not transferred.

The burst counter should not advance simply because a clock cycle passed.

Correct principle

Update transaction state when the handshake occurs:

WVALID && WREADY

 

not merely because:

WVALID

 

is high.

This distinction is critical when backpressure is present.

 

12. Advancing State Without a Handshake

This mistake appears in many AXI implementations.

Suppose an RTL block does:

if (VALID)

    counter <= counter + 1;

 

But the actual transfer occurs only when:

VALID && READY

 

The counter can therefore move ahead of the transaction.

Better pattern

For a channel where transfer completion is defined by the handshake:

if (VALID && READY)

    update_transaction_state();

 

This applies to:

  • Counters
  • Burst tracking
  • Address updates
  • FIFO pointers
  • Beat counters
  • Transaction completion flags

The important question is always:

Did the transfer actually happen?

 

13. Incorrect Reset Behavior

AXI interfaces contain many state-holding elements.

Reset may affect:

  • Valid signals
  • Ready logic
  • Transaction counters
  • Burst tracking
  • Outstanding transaction state
  • Response generation
  • Internal FIFOs

A common mistake is resetting only the visible AXI signals while leaving internal transaction state inconsistent.

For example, the interface may come out of reset with:

AWVALID = 0

 

but an internal state machine still believes a write transaction is active.

That can produce difficult-to-debug failures later.

Better approach

For every AXI channel, document:

  1. Reset value
  2. State after reset
  3. Conditions for becoming active
  4. Conditions for completing a transaction

Then verify reset both during initialization and in appropriate reset/recovery scenarios.

 

14. Mishandling Read and Write Responses

A slave should generate responses based on completed transactions, not merely because a request was observed.

For writes, the B channel carries the write response.

For reads, the R channel carries read data and response information.

A common design error is generating a response too early or losing the relationship between the response and the transaction that caused it.

This becomes more complicated when multiple transactions can be outstanding.

What to check

For every transaction, verify:

Request → Processing → Response

and ensure that:

  • The response is generated exactly once
  • The response corresponds to the correct transaction
  • Error conditions are represented correctly
  • Response backpressure is handled

 

15. Ignoring Multiple Outstanding Transactions

AXI can support multiple transactions in flight.

This is useful for performance, but it introduces additional design complexity.

For example, a master may issue several read requests before receiving all the read data.

If the design assumes:

one request → one response → next request

 

it may accidentally create a much more restrictive interface than intended or mishandle legal transaction behavior.

Arm’s AXI material discusses outstanding transactions and the role they play in system performance and traffic management.

How to avoid it

Decide explicitly whether your IP supports:

  • One outstanding transaction
  • Multiple outstanding transactions
  • Multiple IDs
  • Specific ordering behavior

Then make the RTL and verification environment consistent with that architectural decision.

 

16. Ignoring Transaction IDs and Ordering

When multiple transactions are active, transaction IDs become important.

A design that simply stores one request in one register may not be sufficient if the interface allows multiple transactions to remain outstanding.

AXI’s ordering model contains rules around transaction IDs and ordering requirements. Arm has also published updates to the AXI specification addressing ordering and unique-ID behavior.

Practical rule

Do not implement ID handling as an afterthought.

At the architecture stage, determine:

  • Which IDs are accepted?
  • How many transactions can be outstanding?
  • Can responses return independently?
  • What ordering must be preserved?
  • How are transactions tracked internally?

This is especially important for high-performance AXI masters, slaves and interconnect-related logic.

 

17. Designing Only for the “Happy Path”

A basic test might look like:

VALID = 1

READY = 1

 

every cycle.

Everything works.

But real bugs often appear when the interface is stressed.

A useful AXI testbench should introduce conditions such as:

  • Delayed READY
  • Delayed VALID
  • Back-to-back transfers
  • Single-beat transfers
  • Maximum-length bursts
  • Partial writes
  • Different burst sizes
  • Different burst types
  • Reset during appropriate transaction scenarios
  • Response delays
  • Multiple outstanding transactions

The goal is not to create random complexity for its own sake.

The goal is to test the situations in which the RTL’s assumptions are most likely to break.

 

18. Not Using Assertions for Protocol Rules

AXI behavior is often well suited to assertion-based verification.

Instead of discovering every protocol violation manually from waveforms, assertions can continuously check important properties.

Examples include checking that:

  • Payload remains stable while VALID is high and READY is low
  • A burst has the expected number of beats
  • LAST occurs on the appropriate final beat
  • Internal state advances only after a handshake
  • Requests eventually produce the expected response under the assumptions of the design
  • Illegal combinations do not occur

A simple ready/valid stability property can conceptually look like:

property p_data_stable;

  @(posedge clk)

    VALID && !READY |=> VALID && $stable(DATA);

endproperty

 

The exact assertion should be adapted to the channel and protocol property being checked.

The important point is that assertions should express protocol intent, not simply duplicate implementation details.

 

19. Debugging AXI Waveforms Without Looking at the Handshake First

AXI waveforms can contain dozens of signals.

A common debugging mistake is looking immediately at:

  • Address
  • Data
  • Response

without first identifying where the handshakes occurred.

Start with:

VALID

READY

 

for the channel you are debugging.

Then identify the exact clock edges where:

VALID && READY

 

is true.

Only after identifying the accepted transfers should you examine:

  • Address
  • Data
  • Burst count
  • ID
  • Response
  • LAST

This makes waveform debugging considerably easier.

 

AXI Design Mistakes: Quick Reference

Mistake

Possible consequence

Better practice

VALID waits for READY

Deadlock

Generate VALID independently

Payload changes while stalled

Incorrect transfer

Hold payload stable

Treating channels as one

Lost/blocked transactions

Handle channels independently

Ignoring backpressure

Data loss or deadlock

Test READY deassertion

READY assumed always high

Hidden bugs

Stress with stalls

Combinational VALID/READY loop

Timing/functional problems

Break dependency appropriately

Incorrect AxLEN interpretation

Wrong burst count

Use AxLEN + 1

Crossing 4 KB boundary

Protocol violation

Check burst boundary

Wrong address increment

Incorrect burst addressing

Use AxSIZE/AxBURST rules

Ignoring WSTRB

Partial-write corruption

Implement byte enables

Wrong LAST generation

Broken burst termination

Count accepted beats

State advances without handshake

Lost transactions

Update on VALID & READY

Incomplete reset state

Post-reset failures

Reset internal transaction state

Poor ID handling

Ordering errors

Define ID/outstanding policy

Only happy-path testing

Bugs escape simulation

Add backpressure/stress cases



Final Takeaway

Most AXI bugs are not caused by forgetting a signal name. They come from misunderstanding when a transfer actually occurs and what the design must do when the transfer cannot occur immediately.

The most important principles are:

  1. A transfer happens on a valid handshake.
  2. Do not make the source unnecessarily wait for READY before asserting VALID.
  3. Keep transfer information stable while waiting for acceptance.
  4. Treat AXI’s channels as independent interfaces.
  5. Design for backpressure rather than assuming READY is always high.
  6. Handle burst length, size, type and address boundaries explicitly.
  7. Update transaction state based on accepted transfers, not merely clock cycles.
  8. Define outstanding transaction and ID behavior before implementing the RTL.
  9. Verify the interface under stalls, bursts, partial writes and other non-ideal conditions.
  10. Use assertions and waveform analysis to catch protocol errors early.

AXI becomes much easier to design once you stop thinking of it as a collection of signals and start thinking in terms of transactions, handshakes, state, buffering and backpressure.

For VLSI engineers, that shift in thinking is what turns AXI knowledge from interview-level theory into something useful for real RTL and SoC work.

Leave a Reply

Your email address will not be published. Required fields are marked *