S5 STL to S7 Ladder Conversion: Migration Reference Guide

David Krause17 min read
SiemensTechnical ReferenceTIA Portal
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

S5 STL to S7 Ladder Conversion: Migration Reference Guide

Siemens SIMATIC S5 controllers have been discontinued since 2003 for the S5-90U/95U/100U/115U/135U/155U families, and spare-part/support windows have progressively narrowed. The dominant migration path is to SIMATIC S7-300/400 with STEP 7 V5.x, or to S7-1500 with TIA Portal. Customers that require the converted logic in LAD (Ladder Diagram) rather than the original STL (Statement List) face an additional conversion layer that is not always lossless. This reference documents the technical constraints, the operation-by-operation mapping, and a worked translation of a representative S5 STL program into S7 ladder.

Field note: Not every S5 STL construct can be expressed in LAD. Bit-conditional jumps, multi-assignment sequences, and accumulator-dependent flow must be restructured before LAD can be generated. Treat any STL→LAD conversion as a re-implementation, not a translation.

1. Why S5 STL Cannot Be Converted 1:1 to Ladder

LAD is a graphical, network-bounded language. Each network has a fixed left power rail and a single right rail. The fundamental execution model is: evaluate Boolean combinations → drive a single coil or box. STL is a textual, accumulator-based language with arbitrary jumps, multiple parallel transfers, and direct access to status bits. The mismatch is structural, not cosmetic:

STL Feature LAD Equivalent Status
Direct bit logic (A, O, AN, ON, X, XN) Series/parallel contacts Convertible
Set/Reset (S, R) on a bit S/R coil or SR/RS box Convertible
Load/Transfer (L/T) of a word MOVE box Convertible (one box per T)
Compare (==I, <>I, >I, etc.) Comparator box (CMP ==, CMP <>, …) Convertible
Math (ADD, SUB, MUL, DIV) ADD/SUB/MUL/DIV box Convertible
Conditional jump (JC, JCN, JCB) Not native — requires re-structure Restructure required
Unconditional jump (JU) Not native Replace with logic rewrite
Label (Mxxx) targets Not native Replace with state flag or subroutine
Multiple sequential T instructions Several parallel MOVE boxes in one network Convertible but visually noisy
INC/DEC accumulator (INC, DEC) ADD box (+1, -1) Convertible
DO loop (DO, LOOP) Not native Use FOR/WHILE in SCL
Direct accumulator operations (TAK, PUSH, POP, ENT, LEAVE) Not native Use temporary variables / SCL

The hard rule is: any STL construct that uses a jump label as a control-flow target must be rewritten as straight-line Boolean logic or a function block call. JC, JCN, JCB, JBI, JB, JZ, JP, JM, JU, JL, JP, and the loop instructions all fall into this category. The STEP 7 / TIA Portal "Source > Generate Ladder from STL" routine refuses these statements and leaves a network comment such as // Cannot be converted automatically.

2. S5 STL Operation Set vs. S7 STL/LAD Operation Set

The S5-115U STL instruction set is a strict subset of the S7-300/400 STL instruction set. The following table shows the direct mapping that you can use as a lookup during manual re-implementation:

S5 STL S7 STL (STEP 7 V5.x / TIA Portal) LAD Representation
OPN DB n OPN DB [n] or OPN "DataBlock" Implicit; DB is bound by MOVE / contact address
L DBW n L "DB_name".DBW n Input of MOVE / comparator / arithmetic box
T DBW n T "DB_name".DBW n Output (ENO) of MOVE box
L 0 L 0 Constant input of comparator
<>I <>I CMP <> (INT) box
==I ==I CMP == (INT) box
JC Mxxx JC Mxxx (or restructured) Not native — re-implement
JU Mxxx JU Mxxx (or restructured) Not native — re-implement
AN "Bit" AN "Bit" / A "Bit" with NC contact NC contact |—|/—|
INC 1 + 1 (in STL) or ADD 1 box ADD box with IN2 = 1
DEC 1 - 1 (in STL) or SUB 1 box SUB box with IN2 = 1
NOP 0 NOP 0 Empty network (placeholder)
Important syntax change: In S5 the data block reference is implicit (the last OPN DB or OPN DX defines the active DB). In S7 the DB is bound per operand: L DB190.DBW 420 or, by symbolic name, L "RecipeDB".RecipeCount. When generating S7 STL, every absolute DB access must be expanded with the DB number prefix; when generating LAD, the symbol must be used because the active-DB concept does not exist in ladder.

3. Reading the Source S5 STL

The snippet supplied by the user is reproduced here with the same line numbering style as STEP 7:

OPN   DB   190              // Open DB190 as the active data block
L     DBW  420              // Load word 420 from active DB into ACCU1
L     0                     // Load constant 0 into ACCU1 (old value moves to ACCU2)
<>I                        // ACCU2 <> ACCU1 ? sets RLO from status flags
JC    M001                  // If RLO=1 (DBW420 <> 0) jump to M001
T     DBW  122              // ELSE: transfer ACCU1 (the 0) to DBW122
T     DBW  124              //          transfer ACCU1 to DBW124
T     DBW  126              //          transfer ACCU1 to DBW126
T     DBW  128              //          transfer ACCU1 to DBW128
INC   1                     // ACCU1 = ACCU1 + 1  (0 + 1 = 1)
AN    #H_ZY                 // NC contact on flag H_ZY
JC    M002                  // If H_ZY = 0 jump to M002 (skip next T)
T     DBW  122              // H_ZY = 1: transfer current ACCU1 to DBW122
M002: AN  #H_ZW             // NC contact on flag H_ZW
JC    M003                  // If H_ZW = 0 jump to M003
T     DBW  128              // H_ZW = 1: transfer to DBW128
M003: AN  #H_WE             // NC contact on flag H_WE
JC    M004                  // If H_WE = 0 jump to M004
T     DBW  120              // H_WE = 1: transfer to DBW120
M004: AN  #H_WA             // NC contact on flag H_WA
JC    M005                  // If H_WA = 0 jump to M005
T     DBW  126              // H_WA = 1: transfer to DBW126
M005: AN  #H_SP             // NC contact on flag H_SP
JC    M006                  // If H_SP = 0 jump to M006
T     DBW  124              // H_SP = 1: transfer to DBW124
JU    M006                  // Unconditional jump to M006
M001: T   DBW  420          // DBW420 <> 0 branch: transfer to DBW420
M006: NOP 0                 // End label / fall-through

Functional summary, written in English for the documentation:

  • Read DB190.DBW420.
  • If the value is non-zero, write that value into DBW420 (a no-op except for the status-word effect) and exit.
  • If the value is zero, clear words 122, 124, 126, 128 by writing 0, then increment to 1 in the accumulator.
  • For each of the five flags H_ZY, H_ZW, H_WE, H_WA, H_SP, if the flag is set (1), overwrite the corresponding target word with the current accumulator value (1).

This is a classic “initialize-from-defaults-then-overlay-from-flags” pattern. It is a prime candidate for re-implementation in ladder because the control flow is a flat cascade of conditionals — exactly the shape ladder is good at.

4. S7 STL Equivalent (Lossless)

Before generating ladder, generate the S7 STL first. This is the lossless target and is the reference against which the ladder must be validated. The following is a hand-written S7-300/400 STL version of the S5 source:

// Network 1 -- DBW420 <> 0 ?
A "Process_DB".DBX421.0     // optional: avoid; use the comparator
L     "Process_DB".DBW420
L     0
<>I
JC    LAB1
// Network 2 -- clear and set 1
T     "Process_DB".DBW122
T     "Process_DB".DBW124
T     "Process_DB".DBW126
T     "Process_DB".DBW128
+     1                      // ACCU1 = 1
// Network 3..7 -- overlay
A     "H_ZY"                 // = AN #H_ZY inverted
JCN   LAB2
T     "Process_DB".DBW122
LAB2: A   "H_ZW"
JCN   LAB3
T     "Process_DB".DBW128
LAB3: A   "H_WE"
JCN   LAB4
T     "Process_DB".DBW120
LAB4: A   "H_WA"
JCN   LAB5
T     "Process_DB".DBW126
LAB5: A   "H_SP"
JCN   LAB6
T     "Process_DB".DBW124
JU    LAB6
LAB1: T "Process_DB".DBW420
LAB6: NOP 0

Note the inversion of the S5 AN #flag + JC pair: in S5 the AN sets the RLO based on the negated bit, and JC jumps when RLO=1, so the meaning is “if flag = 0, jump past the next T.” In S7 the equivalent is “if flag = 0, skip the next T” which is A "flag" followed by JCN label. The polarity is preserved.

5. Step-by-Step Translation to Ladder

The ladder translation requires eliminating every JC/JU by converting the cascade into a series of enable-gated MOVE boxes. The accumulator value of 1 is replaced by a constant 1 on the MOVE input, since “clear-to-zero-then-add-one” is equivalent to “load 1 directly”.

5.1 Prerequisites for the LAD

  • STEP 7 V5.5 SP2 (or later) with the S7-300/400 programming package, or TIA Portal V16 or later for S7-1500 targets. The conversion tool is the same STL source — only the editor and the target firmware differ.
  • Symbolic name "Process_DB" bound to DB190. Symbols may be defined in the symbol table (STEP 7) or in the PLC tag table (TIA Portal).
  • Flags H_ZY, H_ZW, H_WE, H_WA, H_SP as BOOL in the local interface (FB temporary) or in a global DB / M area.
  • Data block 190 must contain at least the following symbols, all typed as INT:
Symbol Address Type Comment
InputValue DBW420 INT Source from field
Out_ZY DBW122 INT Output for H_ZY branch
Out_SP DBW124 INT Output for H_SP branch
Out_WA DBW126 INT Output for H_WA branch
Out_ZW DBW128 INT Output for H_ZW branch
Out_WE DBW120 INT Output for H_WE branch

5.2 Network 1 — Branch on InputValue <> 0

The S5 JC M001 after a non-zero check is implemented as a single-coil SPLIT. Branch A writes the input back to DBW420 and jumps to the end; Branch B is the default path (zero, then overlay). In ladder this becomes a CMP <> box whose result drives two parallel branches.

// Network 1
|    CMP <> (INT)         EN    ENO        |
|     IN1: "Process_DB".InputValue         |
|     IN2: 0                                 |
|                                            |
|--+ |<>|--[MOVE]----------------------( )--+    // "non-zero" branch
|  |        IN : "Process_DB".InputValue     |
|  |        OUT: "Process_DB".DBW420         |
|  |                                          |
|--+ |<>|--( JMP to end via JMP_LABEL )------+  // "zero" branch continues below
|                                            |
No JMP coils in LAD. STEP 7 LAD has no native jump coil. The usual substitution is a label declared via the network title bar and a JMP_LABEL referenced only by SCL or by structural re-arrangement. In practice, the cleanest path is to not model the early-exit; instead, build the zero path as the natural flow and only overwrite DBW420 inside a “non-zero” branch that is placed last in the network sequence. This is the approach shown below.

5.3 Network 2 — Clear-to-zero (the four T DBW in the S5 source)

The S5 cascade “T DBW122 / T DBW124 / T DBW126 / T DBW128” is the “default-zero” write. After the addition, the accumulator holds 1, but in the S5 source the four T instructions occur before the INC. So the four writes transfer 0. In ladder we encode this literally:

// Network 2 -- clear to zero
|    MOVE         EN    ENO        |
|     IN : 0                       |
|     OUT: "Process_DB".Out_ZY     |
|                                  |
|    MOVE         EN    ENO        |
|     IN : 0                       |
|     OUT: "Process_DB".Out_SP     |
|                                  |
|    MOVE         EN    ENO        |
|     IN : 0                       |
|     OUT: "Process_DB".Out_WA     |
|                                  |
|    MOVE         EN    ENO        |
|     IN : 0                       |
|     OUT: "Process_DB".Out_ZW     |

5.4 Networks 3-7 — Conditional Overwrites with the Value 1

Each S5 AN #flag / JC label pair becomes a single NC contact driving a MOVE box:

// Network 3
|--| |H_ZY|--+--[MOVE]--------------------( )--|
|            |   IN : 1                        |
|            |   OUT: "Process_DB".Out_ZY      |

// Network 4
|--| |H_ZW|--+--[MOVE]--------------------( )--|
|            |   IN : 1                        |
|            |   OUT: "Process_DB".Out_ZW      |

// Network 5
|--| |H_WE|--+--[MOVE]--------------------( )--|
|            |   IN : 1                        |
|            |   OUT: "Process_DB".Out_WE      |

// Network 6
|--| |H_WA|--+--[MOVE]--------------------( )--|
|            |   IN : 1                        |
|            |   OUT: "Process_DB".Out_WA      |

// Network 7
|--| |H_SP|--+--[MOVE]--------------------( )--|
|            |   IN : 1                        |
|            |   OUT: "Process_DB".Out_SP      |

5.5 Network 8 — The Non-Zero-Input Override (the M001 branch)

The original S5 M001: T DBW 420 is the fallback that copies the input value into DBW420 when the input is non-zero. In the ladder re-implementation, this is moved to the bottom of the program and gated by the inverse of the comparator from Network 1:

// Network 8 -- non-zero input: write back to DBW420 (preserves original semantics)
|--| |<>|--[MOVE]-----------------------------|
|     |   IN : "Process_DB".InputValue         |
|     |   OUT: "Process_DB".DBW420             |
Semantic caveat: The original S5 logic, when input <> 0, performs only the T DBW420 and skips every T DBW12x and the flag-overlay cascade. The ladder re-implementation above writes the overlay first and then the DBW420 on the non-zero path. The outputs of the overlay (DBW120..128) are therefore left at zero when input <> 0, which matches the S5 behaviour. If your S5 project depended on the overlay writes happening before the DBW420 write, the ordering must be changed.

6. Using the STL-to-LAD Converter Tool

For large programs where the manual cascade rewrite is impractical, the Siemens-STL-to-ladder-converter project on GitHub automates the structural rewrite. It targets the S5-115U family STL that was the most common in production plants. Important characteristics:

  • Parses S5 STL line by line and emits S7 LAD networks with one network per logical block.
  • Maps A, O, AN, ON, X, XN to contacts in series / parallel.
  • Converts =, S, R to standard coils and SR/RS boxes.
  • Converts L/T pairs to MOVE boxes.
  • Performs structured loop unrolling for SPB/SPBN jumps and emits a warning for any JC/JU it cannot resolve.
Tooling caveat: This converter is an open-source project, not a Siemens product. It is licensed under the project's repository terms and is not supported by Siemens AG. Always validate the generated ladder against a hand-written S7 STL reference and run an online test on a PLCSIM instance before downloading to a real CPU. For safety-related logic, do not rely on automated conversion at all — re-implement from the printed I/O list.

7. TIA Portal-Specific Notes

If the migration target is an S7-1500 with TIA Portal V16 or later, additional adjustments apply:

S7-300/400 / STEP 7 V5.x Construct S7-1500 / TIA Portal Equivalent
OPN DB n Not used; addresses are "DB".Tag
DB with absolute-only access Must add symbolic names; S7-1500 discourages absolute
ANY pointer in STL VARIANT or DB_ANY in TIA Portal
SF / SPB / SPBN jumps Replace with structured control flow in SCL or with label/JMP in FBD/ST
Bit memory M area Avoid; use global DB or instance DB
16-bit MOVE (MOVE_BLK) Use MOVE_BLK_VARIANT for S7-1500 ≥ firmware V2.0

For S7-1500 targets, the cleanest migration is often to use SCL as the intermediate language. SCL accepts IF, CASE, FOR, WHILE, and CONTINUE/EXIT in a syntax that mirrors the S5 STL jump cascade. Once the SCL source compiles, TIA Portal can call the SCL block from a LAD network via a CAL box, which keeps the top-level program visible as ladder while the heavy logic is in SCL.

8. Verification

After the ladder is built, run the following verification sequence before any field deployment:

  1. Compile check. In TIA Portal, "Compile > Software (rebuild all blocks)" must complete with zero errors. Treat warnings about unreachable code as errors and investigate.
  2. Cross-reference. Open the cross-reference (right-click block > Cross-references) and verify that every DBW referenced in the original S5 program is read or written by exactly the same network in the new ladder.
  3. PLCSIM simulation. Create a watch table with the five flags H_ZY, H_ZW, H_WE, H_WA, H_SP and force each combination 0..31 (5 bits = 32 cases). For each case set InputValue to 0 and to a non-zero value, run OB1 once, and confirm that DBW120, DBW122, DBW124, DBW126, DBW128 match the STL reference's output.
  4. Online / step. In Online & Diagnostics > Monitor & Force, single-step the S7 STL reference and the LAD block side by side and confirm RLO / ACCU1 transitions match for every input combination.
  5. Watch the BR / ENO bit. MOVE boxes in ladder signal ENO = 0 if the input is a denormalized float or the DB is not loaded. The S5 source does not check ENO, so a non-zero ENO in the new ladder is a benign — but a stuck ENO across cycles indicates a missing OPN or a typed-mismatch.
Safety integrity: If the program is part of a safety function (S5-95F / S5-115F / safety-related S7-300F), the ladder conversion must be re-validated by the safety engineer. Automatic conversion tools are not approved for SIL 1-3 paths. The S5 safety-related modules are end-of-life; migration to S7-1500F with TIA Portal Safety is mandatory and is governed by the safety plan, not by the conversion tool.

9. Common Conversion Faults and Fixes

Symptom Likely Cause Fix
Comment in compiled block: "Cannot be converted" JC / JU / JL encountered Restructure as a cascade of enabled MOVE boxes; see §5
Compile error: DB not loaded S5 OPN DB pattern not preserved Add the DB number to every absolute operand; or fully symbolic
Outputs lag by one scan Mid-network jump removed but a contact wasn't re-evaluated Verify the contacts upstream of every MOVE box; the S5 RLO is freshly computed per network in ladder
MOVE box never executes NC contact wired backwards (AN vs. A) In LAD, the contact <bit> is an NO, /<bit> is an NC; the AN semantics in S5 are an NC contact on RLO, which is /<bit> in ladder
ACCU1 not what STL showed INC 1 done before T, or T done before INC Re-read the S5 lines; the order of T and INC matters and the S5 sequence must be preserved
Compiler warns about DBW area overlap DB layout was hand-patched during migration Recreate the DB from the original S5 DB190 declaration block

10. Re-Implementation Heuristics for Large S5 Programs

For multi-thousand-line S5 STL programs, the manual ladder conversion is not tractable in one pass. Use the following heuristics:

  1. Convert STL → S7 STL first, mechanically. Add the DB number to each absolute operand, replace OPN with explicit "DB_name", replace INC with + 1, and recompile. The S7 STL is lossless.
  2. Identify jump clusters. Use the S7 STL editor's "Go to label" navigation (or a static analyser) to list every label and every jump target. The dense clusters are the candidates for SCL rewrite.
  3. Replace each cluster with a state machine in SCL. The typical S5 jump cluster is a state machine: encode the state in a INT tag, and use a CASE state OF block. The CASE block compiles to ladder-equivalent FBD on the S7-1500.
  4. Re-export from SCL to ladder if required. TIA Portal does not natively re-render SCL as ladder, but you can call the SCL FB from a LAD network and the top-level remains ladder.
  5. Document the conversion with a deltasheet. For every STL construct, list the LAD replacement, the test case, and the cross-reference address. This is the audit trail required by most end-customer QA processes.

11. Standards and References

The following Siemens official documents cover the STL, LAD, and migration topics relevant to this guide:

FAQ

Can every S5 STL construct be auto-converted to S7 ladder?

No. JC, JU, JL, LOOP, and any other conditional/unconditional jump cannot be expressed directly in ladder. They must be restructured as a cascade of gated MOVE boxes or rewritten in SCL. The STEP 7 "Generate Ladder from STL" command inserts a comment in place of every construct it cannot convert and refuses to compile a partial ladder.

Why do the S5 OPN DB / L DBW instructions need rewriting for S7?

The S5 CPU keeps a single "active data block" register; all subsequent DBx.DBy accesses use it. The S7 CPU does not have an active-DB concept in ladder — the DB is bound per operand, either as DB190.DBW420 (absolute) or as "Process_DB".InputValue (symbolic). The STEP 7 compiler requires the DB prefix on every absolute access inside the block.

What is the LAD equivalent of the S5 AN (AND-NOT) instruction?

An NC contact on the flag, i.e. the |—|/—| symbol. If the S5 source is AN #flag / JC label, the ladder equivalent is a single NC contact |/flag| driving the next MOVE box; the JC label disappears because ladder has no jump coil. The polarity must be checked: AN sets RLO from the negated bit, so a true branch corresponds to the flag being 0.

What replaces the S5 INC 1 in ladder?

An ADD box with IN2 = 1, or, more often, simply remove the INC and write the literal 1 into the MOVE boxes downstream. The S5 pattern of “load 0, T to clear, INC to 1, T to overlay” collapses to “MOVE 0 then MOVE 1” in ladder and produces the same DBW values.

Is the STL-to-LAD converter tool supported by Siemens?

No. The JoeRecursionJoe/Siemens-STL-to-ladder-converter project on GitHub is community-maintained, not a Siemens product. It is useful for first-pass conversion but every output must be cross-checked against a hand-written S7 STL reference and validated with PLCSIM before it is downloaded to a real CPU. Safety-related logic should never rely on automated conversion.

Back to blog