Resolving Step 7 LAD to STL Conversion Failure on S7-300 FCs

David Krause12 min read
S7-300SiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

1. Problem Description

When a STEP 7 V5.x project targeting an S7-300 station is reopened, individual FC (Function) or FB (Function Block) networks that previously rendered in LAD (Ladder Diagram) appear as STL (Statement List). The view switcher is grayed out, the right-mouse "Display as Ladder" command fails, and the editor refuses to round-trip the network back to LAD even though no source code was changed by the user. The block compiles, downloads, and executes correctly on the CPU, but the engineering view is permanently degraded to STL.

Three independent conditions can trigger this behaviour, and they frequently occur together:

  1. Local data (L-stack) address overlap between user-declared TEMP variables and the implicit temporaries inserted by the LAD compiler.
  2. Type-check of address option mismatch between the project that wrote the block and the project that reads it, combined with mixed-width data types (BYTE/INT, WORD/INT, TIME/DINT) inside one network.
  3. Network size and complexity exceeding the practical limit the LAD parser can re-serialize, especially after a STEP 7 version migration.
Scope: This article targets STEP 7 V5.4 / V5.5 / V5.6 (Classic) on S7-300 CPUs (CPU 312 through CPU 319, including F variants). Behaviour in TIA Portal V16+ is similar in principle; the rule set for changing programming language in TIA Portal is documented at Siemens TIA Portal Rules for Changing the Programming Language.

2. Root Cause Analysis

2.1 L-Stack Overlap with LAD Compiler Internals

Every time the LAD compiler generates code for a network, it inserts an internal, anonymous TEMP region beginning at L 0.0 and extending byte-wise for as many bits, bytes, words, and double words the network requires. The insertion is invisible to the user and carries no symbolic name. In parallel, the user-declared TEMP variables of an FC or FB are also placed in the L stack, starting at the address the user typed in the TEMP declaration table.

If the user assigns TEMP addresses in the low range — L 0.0, L 2.0, L 4.0 — and then expands the network so that the compiler needs more implicit temporaries, the new compiler-internal address collides with a user-declared one. The collision is detected on the next "Display as Ladder" attempt, the conversion is aborted, and STEP 7 leaves the network rendered in STL. The most common symptom in the field is addresses like:

  • L 4.0, L 4.1, L 4.2 ... (compiler scratch bits)
  • L 6.0 (enable/ENO handling)
  • L 8.0, L 8.1 (MOVE-box source/destination)
  • L 10.0, L 10.1 (comparator return values)

The block compiles because the CPU does not enforce symbolic checks at runtime; it only allocates the L stack. The conflict is purely an editor-side, re-serialization problem.

2.2 Type Check of Address and Mixed-Width Operands

STEP 7 has a project-level option at Options → Customize → LAD/FBD → "Type check of address" (German: Typprüfung der Operanden). When enabled — the default in fresh installations — the LAD compiler refuses to generate code that mixes operands of the same bit-width but different data types. The forbidden pairings on S7-300 are:

Width Forbidden pairing LAD result
16 bit BYTE ↔ WORD Compiler error E:0221
16 bit INT ↔ WORD Compiler error E:0221
32 bit DINT ↔ DWORD Compiler error E:0221
32 bit TIME ↔ DINT Compiler error E:0221
16 bit BYTE ↔ INT (via GE_I, LE_I, EQ_I, NE_I, etc.) Compiler error E:0221

When the option is disabled, the LAD editor silently accepts the mixed pair. The block saves successfully and the STL is generated with the user's operand widths (the instruction chosen governs the operation: GE_I on BYTE operands is legal in STL because the instruction does not check the operand type — only LAD does). The block is then non-round-trippable: opening the network in any project where "Type check of address" is enabled flips the network to STL and the "Display as Ladder" command refuses to recover it.

2.3 Network Size and Complexity

STEP 7's LAD parser has practical limits. A single network that contains more than roughly 14–16 contact/coil segments, or 6+ parallel branches, or nested boxes with EN/ENO chains, may serialize to STL cleanly but refuse the reverse conversion. The threshold is lower after a STEP 7 version upgrade (e.g. V5.4 → V5.6) because the parser is more conservative about re-deriving the original graphical structure. The symptom is identical: "Display as Ladder" reports "Network cannot be displayed in Ladder" with no specific error code.

2.4 Global Language File Deletion

Deleting the project-level Globale Sprachdatei (global language file, default name language in the project root) is a known cause of code-recovery issues in S7-300 blocks. The file caches per-network compiler metadata; once deleted, the LAD parser falls back to a generic STL model and refuses round-trip even if the underlying network is valid. This cause is silent and frequently blamed on the user before the L-stack or type-check issues are investigated.

3. Diagnostic Workflow

  1. Open the affected FC/FB in STEP 7 V5.x. Note which networks are stuck in STL.
  2. Switch the block view to STL (View → STL). This is the default fallback; no action required if the editor already shows STL.
  3. Inspect the TEMP declaration table of the block. Sort by address. Look for any TEMP variable at LW0, LW2, LW4, LW6, LW8, or LB0LB15. These are the high-risk addresses.
  4. Open Options → Customize → LAD/FBD. Record the state of Type check of address in the current project and in any colleague's project that last edited the block.
  5. Search the affected network for any of: GE_I, LE_I, EQ_I, NE_I, GE_D, LE_D, EQ_D, NE_D, MOVE with mismatched types, or arithmetic on T# literals.
  6. Compare block source with a known-good backup using "Compare Blocks Online/Offline" (path: Options → Compare Blocks). Look for unexpected differences in the compiler-internal region of the STL.

4. Resolution Methods

4.1 Resolve L-Stack Overlap

  1. Open the FC/FB and switch to STL view.
  2. Identify the highest L-address used by the user-declared TEMPs. For example, if TEMPs end at LW20 / LB40, the safe user ceiling is LW100.
  3. In the TEMP declaration table, renumber every L-address below that ceiling to an address above the user ceiling. Standard convention is to add 100 (or any constant) so the renumbering is easy to grep:
    • L 4.0 → L 104.0
    • L 4.1 → L 104.1
    • L 4.2 → L 104.2
    • LW 6 → LW 106
    • LD 10 → LD 110
  4. Update every STL instruction in the block that references the old addresses. A simple Find & Replace with the "whole word" option handles the bulk; manual review is required for symbolic aliases that resolved to those L addresses.
  5. Switch View → Ladder. The networks should now re-serialize cleanly.
  6. Save the block (Ctrl+S) and recompile (Station → Consistency Check).
Capacity check on S7-300: The CPU's local data stack size is fixed per priority class. For CPU 31x, the default OB1 priority class receives 256 bytes. Renumbering TEMPs upward is safe as long as the new highest byte stays below 256 (or whatever value is set under CPU Properties → Diagnostics/Clock → Local Data for the relevant OB). Exceeding the priority class size triggers SF LED + OB121 at runtime, which is a separate failure mode from the editor issue.

4.2 Adjust the Type Check of Address Setting

  1. In STEP 7, navigate to Options → Customize → LAD/FBD.
  2. Uncheck Type check of address temporarily.
  3. Open the affected block, switch View → STL → LAD, save.
  4. Re-check the option to restore strict typing for future work.

This is a recovery path, not a recommended working configuration. Disabling type checking masks future data-type bugs and should be enabled again once the block is in a clean LAD state. If the type check was disabled in another engineer's project, align all team members on the same setting before any further edit, otherwise the cycle repeats.

4.3 Harmonize Data Types Inside the Network

When the network contains a comparator or MOVE whose operands differ only in symbolic type but not in width, the cleanest fix is to insert an explicit conversion. Common cases on S7-300:

Original (illegal in LAD with type check) Conversion Round-trip safe
GE_I on two BYTE operands Move BYTE → INT (Temp) via MOVE box, then GE_I Yes
EQ_I comparing BYTE ↔ INT Cast BYTE → INT in a Temp ITmp variable Yes
Arithmetic on T# literal + DINT Convert TIME → DINT (ms) via ITD / DIT-to-TIME reverse Yes
Math on a WORD declared as INT Split the network or use a separate WORD variable Yes

Code example for the BYTE / GE_I case (compatible with STEP 7 V5.4+ on S7-300, fully round-trippable to LAD):

// Network 1 - declaration in TEMP
//   ByteVal : BYTE
//   ITmp    : INT
L     ByteVal          // load byte operand
T     ITmp             // move to int temp
L     ThresholdInt     // second int operand
>=I                    // GE_I - both INT, type check passes
JC    GreaterBranch
// ...

For TIME arithmetic, declare a DITmp : DINT in TEMP, move the TIME value into it with L T_Variable / L T#5s / ITD / T DITmp (or via a MOVE_B32 box), perform DINT math, then convert back with DTB before assigning to a TIME variable.

4.4 Refactor Oversized or Version-Migrated Networks

  1. Identify the longest network using View → STL line count. Anything beyond roughly 30 STL lines is a candidate.
  2. Split the network at natural boundaries: between branches, after each set/reset coil, or after each comparator.
  3. Use intermediate flags in the block's STAT (for FB) or TEMP (for FC) to carry values between the new networks. Intermediate flags must be declared with unique symbolic names to avoid the L-stack collision from Section 2.1.
  4. Switch the entire block back to LAD, save, and run a consistency check.
Splitting networks also improves scan-time determinism on S7-300 because the CPU processes each network as a discrete segment in OB1. Smaller networks are easier to debug, easier to step through in Monitor/Modify, and survive STEP 7 version upgrades without losing round-trip capability.

5. Prevention During Project Development

  • Reserve the first 20 bytes of the L stack for the LAD compiler. Declare user TEMPs starting at LW20 / LB40 or higher. This is a project-wide convention enforced through a code-review checklist.
  • Keep "Type check of address" enabled on every engineering station. Use source-controlled project files (.s7p) to prevent divergence between team members.
  • One comparator, one MOVE, one coil per network where practical. The cost in network count is small; the gain in round-trip reliability is large.
  • Match STEP 7 versions across the team. The combination of V5.4 + SP4 + HF11 is the most common stable floor; mixed V5.4 / V5.5 / V5.6 stations have produced the bulk of the field reports.
  • Never delete the global language file (language) from the project root. It is regenerated on save but its absence during a session triggers the parser fallback described in Section 2.4.
  • Document data-type choices in the block header comment. A short note like "all loop counters declared INT, never WORD" prevents the BYTE/INT mixing pattern that triggers type-check failures.

6. Verification

  1. Open the block, confirm every network is rendered in LAD with no STL fallback.
  2. Run Station → Consistency Check across the S7-300 station. Resolve any reported errors before continuing.
  3. Compile and download to the CPU (CPU 31x in STOP or via test slot for F-CPUs).
  4. Open Monitor/Modify on the block. Step through each network; verify all expected EN/ENO behaviour, comparator results, and MOVE outputs.
  5. Reopen the project on a second engineering station with a different STEP 7 service-pack level. The block should still open cleanly in LAD. If it falls back to STL on the second station, the type-check setting or STEP 7 version on the second station is misaligned (Section 4.2).
  6. Add a new TEMP variable in a non-conflicting range (e.g. LW120) and confirm the affected networks remain in LAD. If they flip to STL on this change, the L-stack overlap pattern is still present and the renumbering from Section 4.1 is incomplete.

7. Reference: Settings and Error Messages

Item Location / Value Effect
Type check of address Options → Customize → LAD/FBD → Type check of address Enables strict data-type enforcement; disable only temporarily for recovery
Compiler error E:0221 Online Help → "Error E:0221: Operand type incompatible with instruction" Indicates type check rejection at compile time
Local data stack size CPU Properties → Diagnostics/Clock → Local Data (per OB priority class) Defaults: OB1 = 256 B on S7-300, OB10/20/35 etc. = 256 B; total must not exceed CPU local data maximum
Global language file Project root → language (hidden file) Caches per-network compiler metadata; do not delete
STEP 7 V5.x hotfix matrix Siemens Industry Online Support → search "STEP 7 V5 hotfix" Cross-version block compatibility table

Why did an FC open in LAD yesterday but STL today, with no code changes?

The most common cause is a recent edit to the TEMP declaration table — by you, by a colleague, or by a STEP 7 version migration. New compiler-internal temporaries at L 4.0 / L 4.1 / L 4.2 now collide with user-declared TEMPs. Renumber user TEMPs above the compiler scratch region (e.g. start at LW 20 or LW 100) and switch back to LAD.

Can I recover a network that compares BYTE operands with GE_I?

Yes. Move the BYTE operand into a TEMP INT variable first, then perform the GE_I comparison on INTs. The MOVE box and the GE_I comparator are then both type-checked operands and the network is fully round-trippable to LAD with type-check enabled.

Disabling "Type check of address" lets me switch to LAD — should I keep it disabled?

No. The setting should be enabled (the default) and the offending network should be refactored to use matching data types. Disabling the check hides future type bugs and creates a project that cannot be round-tripped on any other engineering station that runs with the strict default.

Is the LAD ↔ STL rule the same in TIA Portal as in STEP 7 V5?

The high-level rule is identical: a network is convertible from STL to LAD only if the LAD parser can re-derive a unique graphical structure with valid type-checked operands. The formal list of rules for TIA Portal V21 is published at Siemens TIA Portal: Rules for Changing the Programming Language. TIA Portal additionally forbids direct copy/paste between STL and LAD/FBD networks.

My S7-300 FCs are stuck in STL after upgrading from STEP 7 V5.4 to V5.6. What changed?

STEP 7 V5.6 tightened the LAD parser's re-serialization rules. Networks that were tolerated as "display in LAD" in V5.4 are now rejected and shown in STL. The fix is to apply the L-stack renumbering from Section 4.1, harmonise operand types per Section 4.3, and split oversized networks per Section 4.4. Once converted, the blocks remain stable across further V5.x service packs.

Back to blog