Welcome back to the Transaction Layer series! In Lecture 3, we decoded the generic TLP header format. Now, we are moving beyond the header to explore the actual data being transferred. In this lecture, we will look at the strict rules governing TLP data payloads and learn how “Byte Enables” allow PCIe to manage partial and non-aligned data transfers with pinpoint accuracy.
Part 1: Rules for Data Payloads
When a Transaction Layer Packet (TLP) includes data—such as in a Memory Write Request—the payload is appended immediately after the header. PCIe enforces several strict rules to manage this payload safely:
- Size Limits: The data payload is optional and can range from 1 to 1024 Double Words (DW). A transfer of 1024 DW equates to exactly 4KB of data.
- Integral DW Transfers: The Length field in the TLP header strictly refers to the data payload and always represents an integral number of DWs transferred.
- The 4KB Boundary Rule: Requests must not mix a start address and transfer length that would cause a memory access to cross a 4KB boundary. If a receiver checks for this and spots a violation, it treats it as a Malformed TLP.
- Max Payload Size Limitation: The TLP data payload cannot exceed the current value set in the device’s
Max_Payload_Sizeregister. Because only write transactions contain data payloads, this restriction does not apply to read requests. - Address Ordering: The very first byte of data in the payload (sitting right after the header) is always associated with the lowest, or start, address.
Part 2: The Magic of Byte Enables
PCI Express addresses are generally Double Word (DW) aligned. However, software occasionally needs to transfer sizes that are not perfectly DW-aligned, or needs to start/end an access at an unaligned byte address.
To reconcile DW-aligned addresses with non-aligned data requirements, PCIe uses Byte Enables. The generic TLP header includes two specific 4-bit fields for this: the First DW Byte Enable and the Last DW Byte Enable.
These bits are “high true,” meaning a value of 1 tells the Completer that the corresponding byte in the payload is valid and should be used, while a 0 indicates the byte should be ignored.
Part 3: Byte Enable Rules
To prevent confusion across the Link, the First and Last DW Byte Enables must follow strict usage rules depending on the size of the transfer:
- Single DW Transfers: If all the valid data fits within a single Double Word, the Last DW Byte Enable field must be set to
0000b. For these 1-DW transfers, discontinuous byte enable patterns (e.g.,1010b) in the First DW are perfectly legal. - Two DW Transfers: Discontinuous byte enable bit patterns across both the First and Last DW Byte Enable fields are permitted if the transfer is between one and two DWs.
- Transfers of 3 DW or More: If the transfer length is 3 DW or greater, the First DW Byte Enable and the Last DW Byte Enable fields must have contiguous bits set. In these longer transfers, the byte enables are solely used to indicate the effective starting and ending byte offsets from the DW-aligned address. Furthermore, the First DW Byte Enable must have at least one bit enabled.
- Zero-Length Transfers (The Flush Mechanism): The PCIe Length field does not allow you to specify a length of zero. However, you can approximate a zero-length read by requesting a 1 DW transfer but setting all First DW Byte Enables to zero (
0000b). The completer will return a 1 DW payload of undefined data, but this action is incredibly useful—it serves as a “Flush” mechanism that uses transaction ordering rules to force all previously posted writes out to memory.
