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.
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) |
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_SPasBOOLin 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
| |
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 |
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,XNto contacts in series / parallel. - Converts
=,S,Rto standard coils and SR/RS boxes. - Converts
L/Tpairs to MOVE boxes. - Performs structured loop unrolling for
SPB/SPBNjumps and emits a warning for anyJC/JUit cannot resolve.
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:
- Compile check. In TIA Portal, "Compile > Software (rebuild all blocks)" must complete with zero errors. Treat warnings about unreachable code as errors and investigate.
- 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.
-
PLCSIM simulation. Create a watch table with the five flags
H_ZY,H_ZW,H_WE,H_WA,H_SPand force each combination 0..31 (5 bits = 32 cases). For each case setInputValueto 0 and to a non-zero value, run OB1 once, and confirm thatDBW120,DBW122,DBW124,DBW126,DBW128match the STL reference's output. - 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.
-
Watch the BR / ENO bit. MOVE boxes in ladder signal
ENO = 0if 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 missingOPNor a typed-mismatch.
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:
-
Convert STL → S7 STL first, mechanically. Add the DB number to each absolute operand, replace
OPNwith explicit"DB_name", replaceINCwith+ 1, and recompile. The S7 STL is lossless. - 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.
-
Replace each cluster with a state machine in SCL. The typical S5 jump cluster is a state machine: encode the state in a
INTtag, and use aCASE state OFblock. The CASE block compiles to ladder-equivalent FBD on the S7-1500. - 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.
- 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:
- Siemens Support entry 109751595 — S5 to S7 migration overview and recommended CPU families.
- STEP 7 V5.5 Programming and Operating Manual — LAD/FBD/STL reference.
- S7-300 Module Data Manual — data block layout and address assignments used in the target S7-300 program.
- SIMATIC S7-1500 / ET 200MP System Manual — firmware- and version-specific notes for S7-1500 targets.
- SCL for S7-300/400 Programming and Operating Manual — structured control as an alternative to ladder for jump-heavy STL.
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.