1. Problem Overview
When integrating a PROFINET device into a SIMATIC S7-1200 or S7-1500 project, engineers frequently declare an input UDT and an output UDT that mirror the device's slot layout, then paste those UDTs into a custom Tag Table for direct I/O access. Under TIA Portal V16 through V19, this design pattern can produce an unexpected byte shift: a Word member declared to start at byte 6 of the process image is silently relocated to byte 7, breaking the adjacency contract between sub-modules of the PROFINET station.
Typical symptom observed in the project tree:
- User-defined UDT contains: Bool A5.7 (occupies byte 5, bit 7), Word User_Data_Length (should occupy bytes 6-7).
- Generated address in the Tag Table: A5.7 → AW6 is shown, but the absolute offset calculation in HW Config shows User_Data_Length at %QW7 instead of %QW6.
- Online monitoring reveals a one-byte gap between the last Bool slot and the first Word slot, even though the device description (GSD) shows contiguous bytes.
This drift is not a compiler bug. It is the documented alignment behavior of TIA Portal when a UDT member larger than one byte (Word, DWord, LWord, Real, LReal) follows a member that does not fill an even-byte boundary. The tool inserts an implicit padding byte so that the larger element sits on its natural alignment. The padding is invisible in the UDT declaration but visible in the address column of the Tag Table.
2. Root Cause: Byte vs. Word Alignment Inside UDTs
Every member of a UDT (or DB of a derived type) carries an implicit alignment attribute. The alignment equals the size of the member in bytes, rounded up to the next power of two:
| Elementary Data Type | Size (bytes) | Natural Alignment |
|---|---|---|
| Bool, Byte, SInt, USInt, Char | 1 | 1 byte |
| Int, UInt, Word | 2 | 2 bytes (even offset) |
| DInt, UDInt, DWord, Real | 4 | 4 bytes |
| LInt, ULInt, LWord, LReal | 8 | 8 bytes |
When TIA Portal lays out a UDT it walks the members in declaration order and, before placing each member, advances the offset to the next multiple of that member's alignment. A single Bool at offset 5 does not consume a full second byte, so the next Word must start at offset 6 to satisfy its 2-byte alignment — which is exactly what the engineer requested. However, when the UDT is loaded as the data type of a tag inside a Tag Table that points directly at a process image address, the portal evaluates alignment relative to the process image start, not the UDT start, and may re-align the Word to byte 7 to keep it on a word boundary with respect to the input/output image origin. This double-evaluation is the source of the drift.
The behavior is documented in the TIA Portal help under "Alignment of data types in structures" and is enforced even when the underlying GSD slot itself is one byte. PROFINET does not require word alignment for sub-slots; TIA Portal imposes it as an editor convenience.
3. Affected Configurations
| Component | Versions / Models Affected |
|---|---|
| TIA Portal | V15.1, V16, V17, V18, V19 (all current maintenance releases) |
| STEP 7 | Basic, Professional; both Win32 and TIA Portal Cloud connector flows |
| PLC families | SIMATIC S7-1200 (CPU 1211C through CPU 1217C with firmware ≥ V4.2), S7-1500 (CPU 1510SP through CPU 1518, ET 200SP, ET 200pro) |
| Block access mode | Optimized block access (default for S7-1500) and non-optimized (legacy S7-1200 / classic) |
| PROFINET devices | Any PROFINET IO Device whose sub-slots end on an odd byte, especially vision systems (Cognex In-Sight, Keyence CV-X, Sick InspectorP), RFID readers (Balluff BIS M, Siemens RF180C), and I/O couplers with mixed digital/analog sub-modules |
| Typical GSDs | Modular GSDML-V2.3x and GSDML-V2.4x files where slot/sub-slot widths are declared in bits |
The issue is independent of the PROFINET conformance class (CC-A, CC-B, CC-C) and is unaffected by IRT vs. RT communication class.
4. Detailed Symptom Recognition
Before applying any workaround, confirm the drift with the following checks:
- Open Devices & Networks, select the PROFINET device, switch to Device view, and read the slot addresses from the I/O addresses column. Note the byte offset of every sub-slot.
- Cross-reference those offsets with the addresses shown in the custom Tag Table. A drift of exactly one byte on a Word member, or four bytes on a DWord member, is diagnostic.
- Place the UDT instance into a Watch Table and trigger an online monitor. Compare the absolute address column against the slot offset from step 1.
- Export the tag list via Tools → Export Tag Table as a CSV. The exported addresses show the post-alignment offsets and can be diffed against the GSD.
- Repeat the test on a brand-new project with no user code. If the drift still occurs, the cause is the alignment rule, not application code.
5. Workaround Catalog
Five field-proven workarounds exist. Each preserves PROFINET adjacency; the right choice depends on project conventions and customer standards.
5.1 Workaround A — Split the UDT at the Alignment Boundary
Declare one UDT for all single-byte members up to and including the last odd byte, and a second UDT starting with the Word/DWord member. Two consecutive UDTs in the Tag Table place each on its own alignment origin.
Example:
// UDT_In_Bytes
TYPE UDT_In_Bytes
STRUCT
bStatus : Bool; // IB0 bit area
bReady : Bool;
bError : Bool;
b5_7 : Bool; // IB5 bit 7 (last odd byte)
bReserve: Byte; // IB6 - explicit pad to keep next UDT aligned
END_STRUCT
END_TYPE
// UDT_In_Words
TYPE UDT_In_Words
STRUCT
wLen : Word; // IW7 - aligned to even byte 7
wCmd : Word; // IW9
END_STRUCT
END_TYPE
Paste UDT_In_Bytes at %IB0 and UDT_In_Words at %IB7 in the Tag Table. The explicit bReserve byte is the engineer's acknowledgment of TIA Portal's rule; it eliminates ambiguity.
5.2 Workaround B — Use a Buffer Data Block Instead of a Tag Table
When the customer standard forbids a Tag Table, route all PROFINET I/O through a non-optimized Data Block. The DB internal layout honors the UDT declaration order without re-aligning to the process image start.
DATA_BLOCK "DB_IODevice"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : AutoGen
FAMILY : IO
VERSION : 1.0
STRUCT
InRaw : UDT_In_Bytes; // mapped to PIB 0..6 via AT
OutRaw : UDT_Out_Bytes; // mapped to PQB 0..6 via AT
END_STRUCT
END_DATA_BLOCK
Overlay the UDT members with an AT view that points at the process image:
FUNCTION_BLOCK "FB_IOBuffer"
VAR
ibBuffer AT %IB0 : ARRAY[0..31] OF Byte;
qbBuffer AT %QB0 : ARRAY[0..31] OF Byte;
stInput : UDT_In_Full; // single combined UDT
END_VAR
BEGIN
// Capture PROFINET inputs once per cycle
stInput.b5_7 := ibBuffer[5].%X7;
stInput.wLen := WORD_TO_INT(ibBuffer[6]) + ibBuffer[7]*256;
// ... application logic on stInput ...
// Push outputs back at end of cycle
ibBuffer[6] := INT_TO_BYTE(stInput.wLen AND 16#00FF);
ibBuffer[7] := INT_TO_BYTE((stInput.wLen SHR 8) AND 16#00FF);
END_FUNCTION_BLOCK
This pattern is the canonical Siemens recommendation for any direct I/O access that must respect odd byte boundaries.
5.3 Workaround C — Adjust the Slot Offset in HW Config
If the GSD exposes more sub-slots than the device physically uses, insert a one-byte "reserved" sub-module in the empty slot. The reserved slot occupies the byte the editor wants to pad, and the next real sub-slot starts on its desired offset.
- Open Devices & Networks → Device view.
- Select the empty slot immediately before the misaligned sub-module.
- Drag a 1-byte "Reserved" module (or any unused 1-byte input module from the catalog) into that slot.
- Re-compile the project. The Word member now lands at the expected offset because the pad byte is provided by the hardware slot, not by the editor.
5.4 Workaround D — Force Non-Optimized Block Access on the Containing Block
If the custom Tag Table is actually a wrapper around a global DB (common in TIA Portal V17+ when "Tags from the PLC" view is used), switch the DB to non-optimized access. In non-optimized mode, TIA Portal preserves the byte offsets exactly as declared in the UDT, ignoring alignment rules.
Steps:
- Right-click the DB → Properties → Attributes.
- Uncheck Optimized block access.
- Confirm and recompile. The Tag Table will now show the UDT members at their declared offsets.
This workaround is incompatible with S7-1500 motion, certain security features, and any block that uses the multi-instance DB concept. Confirm before applying.
5.5 Workaround E — Declare Alignment Explicitly with a Dummy Member
Inside the UDT, declare a Byte filler named PadToEven at every odd-to-even transition. The filler is recognized by the alignment algorithm and the next Word starts on the correct offset, eliminating the editor's implicit padding.
TYPE UDT_In_Aligned
STRUCT
b5_0 : Bool; // IB5 bit 0
b5_7 : Bool; // IB5 bit 7 (last odd byte)
rsv : Byte; // IB6 explicit pad (same byte TIA would have inserted)
wLen : Word; // IB7 - editor honors the explicit pad and no longer shifts
wCmd : Word; // IB9
END_STRUCT
END_TYPE
This approach keeps a single UDT (satisfying internal coding standards) while making the alignment requirement visible in the source.
6. Recommended Solution Matrix
| Constraint | Recommended Workaround |
|---|---|
| Customer standard mandates a single UDT | Workaround E (explicit pad) |
| Customer standard forbids a Tag Table | Workaround B (buffer DB) |
| GSD allows extra slot modules | Workaround C (HW Config pad) |
| Multiple misaligned boundaries in one device | Workaround A (split UDTs) |
| Tag Table is required and UDT integrity is required | Workaround D (non-optimized DB wrapper) |
| Application code already uses AT views | Workaround B (buffer DB + AT) |
7. Step-by-Step Implementation: Workaround A (Most Common)
The following procedure is the lowest-risk fix for a running project. Estimated time: 15 minutes.
7.1 Prerequisites
- TIA Portal V16 or later, STEP 7 Professional license.
- PLC project offline with the affected device downloaded and the custom Tag Table present.
- Read/write access to the UDT source folder and the Tag Table.
- GSD file for the PROFINET device installed in Options → Manage General Station Description (GSD) files.
7.2 Procedure
- In the project tree, expand PLC data types and duplicate the existing
UDT_In. Rename one toUDT_In_Bytes(all members up to and including the last odd byte) and the other toUDT_In_Words(members from the first even-aligned Word onward). - Open
UDT_In_Bytes. Remove every member larger than 1 byte. Save. - Open
UDT_In_Words. Remove every single-byte member. Insert an explicitByte Padfiller only if the new UDT must start on the same byte as the pad in the original UDT. - Open the custom Tag Table. Locate every line that uses the original
UDT_In. Replace the data type with the appropriate split UDT, and set the address to the next free byte after the previous UDT instance. - Repeat for
UDT_Outif outputs are also affected. - Compile (Project tree → right-click PLC → Compile → Software (rebuild all blocks)).
- Resolve any compiler errors referencing the old UDT. Most will be "Data type UDT_In unknown"; replace each with the correct split UDT.
- Download to the PLC. Use "Download to device → Stop and download" only if production allows; otherwise use "Download to device → Continue" with care for transient output states.
8. Verification
- Open the Tag Table and confirm every Word member now shows the expected even address.
- Open a Watch Table that contains both the original UDT-equivalent members and the raw process image bytes. Force each Word to a known value (e.g., 16#1234) and verify that the bytes at the offset appear correctly.
- Use Online & Diagnostics → PROFINET topology to confirm the device reports no slot errors.
- Run a forced I/O test from the device side (e.g., set the vision system's output length field to a known value) and confirm the PLC reads it without offset drift.
- Trigger a download to a second engineering station and recompile. The drift must not reappear — if it does, an old reference to the original UDT is still in use.
9. PROFINET Adjacency Rules — Why the Drift Matters
PROFINET IO follows strict slot/sub-slot rules defined in IEC 61784-2 and the PROFINET Design Guideline (PNO order No. 8.062):
- Every sub-slot occupies a contiguous range of bytes within its slot.
- The IO Controller assigns sub-slot offsets based on the GSD's ModuleInfo block; these offsets are immutable at runtime.
- If the PLC's view of the offsets disagrees with the device's view, the controller raises PROFINET diagnostics error 0x001E ("Slot mismatch") on slot 0 and disables the affected AR (Application Relationship).
- Word alignment is not required by PROFINET. Only the byte offsets in the GSD are authoritative.
The TIA Portal alignment rule is therefore a display-side feature, not a bus-side requirement. A correct PROFINET application tolerates odd offsets; the misalignment only matters inside the PLC's editor and Tag Table display.
10. Long-Term Best Practices
- Mirror the GSD exactly. When generating the UDT, write down the byte offset of every sub-slot from the GSD and lay out the UDT in that order. The editor's alignment algorithm can then be predicted.
- Document alignment pragmas. Add a comment at the top of every UDT describing the expected offsets. Future engineers will not have to rediscover the rule.
- Prefer DB + AT over Tag Tables for non-standard layouts. The buffer DB pattern is the most defensive and survives TIA Portal upgrades intact.
- Use the GSD-specific module names in the UDT. If the vendor publishes a TIA Portal HSP or a device library, prefer it over the generic GSD import — the vendor UDTs are pre-aligned.
-
Add a project-wide convention: every PROFINET UDT must end with an explicit
Byte Reservedif its last member is a single byte. This eliminates the drift on future edits. - Validate after every TIA Portal upgrade. The alignment rule has been stable from V15.1 onward, but upgrade-induced changes in OPC UA export or HMI tag generation can re-expose the drift.
11. Quick Diagnostic Reference
| Symptom | Cause | Fix |
|---|---|---|
| Word shifted +1 byte | Previous member ends on odd byte; TIA inserts pad | Add Byte filler or split UDT |
| DWord shifted +1..3 bytes | Previous member ends between byte and 4-byte boundary | Add Word filler or restructure |
| LReal shifted +1..7 bytes | Previous member ends between byte and 8-byte boundary | Add LWord filler or restructure |
| Drift only inside Tag Table, not DB | Tag Table re-aligns against process image start | Use buffer DB pattern (Workaround B) |
| Drift disappears after switching DB to non-optimized | Non-optimized access skips alignment | Keep non-optimized if application allows |
| Drift reappears after TIA Portal upgrade | Editor rule change in new version | Recompile and re-verify offsets |
12. Frequently Asked Questions
Why does TIA Portal shift a Word by one byte when the previous Bool sits on an odd byte?
TIA Portal enforces natural alignment for every UDT member larger than one byte. A Word requires a 2-byte (even) offset. When the previous member ends on an odd byte, the editor inserts an implicit pad so the Word starts on the next even byte. This pad is added both inside the UDT and again at the Tag Table level when the UDT is anchored at the process image origin.
Is the drift a PROFINET bus error or an editor display issue?
It is an editor display and address-mapping issue. PROFINET itself only cares about the byte offsets defined in the GSD. The drift only causes a real bus problem if the PLC writes to or reads from a wrong byte, which happens when application code uses the drifted addresses instead of the GSD-authoritative ones.
Does the rule change between TIA Portal V16 and V19?
No. The alignment rule has been stable since V15.1 and is preserved across all current versions. Firmware updates on S7-1500 CPUs (V2.9 through V3.1) also do not change the rule. Upgrades to OPC UA export, however, may surface the drift indirectly through HMI tag generation.
Can I disable the alignment rule with a pragma or compiler switch?
No. STEP 7 does not expose a pragma to disable UDT alignment. The only way to bypass the rule is to switch the containing block to non-optimized access, use an explicit pad member, or split the UDT.
What is the safest workaround for a machine already in production?
Workaround E (explicit Byte filler inside the UDT) is the lowest-risk online change. It does not require a new block, does not change I/O addresses, and only adds a documented pad byte. After recompile, perform a single online download and verify with a Watch Table before resuming production.