Siemens S7-300/400 TEMP Variable Not Updating Between LAD

David Krause11 min read
HMI ProgrammingSiemensTroubleshooting
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

Siemens S7-300/400 TEMP Variable Not Updating Between LAD Networks in FBs

Symptom: a TEMP variable written in Network 1 of a Function Block (FB) is read as 0 in Network 2 of the same FB even though no other network overwrites it. The same logic works when the variable is declared as STAT, when the FB is split into two FBs, or when the network is split into two networks. The CPU correctly executes Block 1, then Block 2; the issue is intra-block scope, not the OB scan order.

Scope of this article: STEP 7 V5.x and SIMATIC S7-300/S7-400 systems programmed in LAD (Ladder) or FBD. The CPU reproduced in field reports was a CPU 319-3 PN/DP (6ES7 318-3EL00-0AB0) running on the S7-PLCSIM and on a real rack. The behavior described also affects CPU 312 through CPU 319F, CPU 412 through CPU 417, and the WinAC RTX variants when programmed with the same compiler.

1. Problem Description

A typical failing FB looks like the following. Both networks live inside the same FB, the TEMP variable is declared only once in the FB's TEMP area, and no other code writes to it:

FUNCTION_BLOCK FB100
VAR_TEMP
    bSignal : BOOL;   // written in Net 1, read in Net 2
    bAux    : BOOL;
END_VAR

BEGIN
NETWORK 1   // Title: derive bSignal
      U     E 0.0;
      =     bSignal;        // expected: TRUE when input is TRUE
NETWORK 2   // Title: forward bSignal
      U     bSignal;
      =     A 4.0;          // output stays FALSE even when bSignal is TRUE
END_FUNCTION_BLOCK

The same engineer observes:

  • Output A 4.0 does not change even though E 0.0 is TRUE.
  • Adding a normally-open contact of bSignal after the output coil shows the contact state matches the output, not the input.
  • Changing bVAR from TEMP to STAT (in the static area) makes the network work correctly.
  • Splitting Network 2 into two networks restores correct behavior, even with TEMP.
  • The instance DB has been regenerated and a "Check block consistency" pass reports no errors.

2. Root Cause: LAD/FBD Compiler Scratchpad Reuse

Siemens documents this behavior in entry FAQ 13988019 - "In STEP 7 why are TEMP variables sometimes overwritten?". The compiler that emits MC7 code from LAD and FBD sources does not reserve a dedicated bit per declared TEMP. Instead, the compiler assigns each formal parameter or named local symbol to a slot in the local stack (the L stack / TEMP area) on a per-network basis, reusing the same slot when the symbol is no longer needed in the current network.

Two facts follow from this allocation strategy:

  1. The compiler is free to back the variable in Network 1 with a different bit cell than the same variable in Network 2, as long as both networks can be proven self-consistent. The L-stack slot for Network 1 may be reused for an unrelated TEMP in Network 2.
  2. The optimized MC7 for the second network reads the slot that was just allocated to it - which contains the default value (0 for BOOL) because Network 2 has not yet executed the assignment from Network 1.
The behavior is independent of TIA Portal and independent of S7-1500. The S7-1200/S7-1500 languages do not have this specific scratchpad pattern because their compiler models are different. If you migrate the same FB to a S7-1500 and the symptom disappears, that confirms the LAD compiler was the cause on S7-300/400.

3. Affected Products and Versions

Item Catalog / Version Affected?
STEP 7 V5.x (V5.4, V5.5, V5.6) 6ES7 810-5CC0x Yes - LAD/FBD compiler uses scratchpad optimization
STEP 7 Professional (TIA Portal) for S7-300/S7-400 V13 to V18 Same behavior; only LAD/FBD sources are affected
S7-PLCSIM V5.x 6ES7 841-0CC0x Reproduces the issue (it executes the same MC7)
S7-300 CPU 312, 314, 315, 315F, 317, 319-3 PN/DP 6ES7 31x-xxxxx Affected (firmware-independent)
S7-400 CPU 412, 414, 416, 417 6ES7 41x-xxxxx Affected
S7-1200 / S7-1500 with TIA Portal All firmware Different compiler model - symptom not reproduced
WinAC RTX / Slot PLC All Affected when program is LAD/FBD

4. Why "Check Block Consistency" Does Not Catch It

Block consistency verifies that:

  • The interface declaration of every FB matches the instance DB.
  • Multi-instance DBs are regenerated.
  • Calls of updated FBs force re-instantiation.
  • UDT references are in sync.

It does not validate that a TEMP variable declared in the FB interface is actually propagated between networks, because from a type-checking standpoint the variable exists and is read/written consistently. The compiler-level optimization is invisible to the consistency checker. Running "Check block consistency" on a project that exhibits this symptom will return a green status; this is expected.

5. Workarounds and Solutions

Four engineering options, ranked from recommended to situational.

5.1 Use STAT instead of TEMP (recommended)

Move bSignal from the TEMP area to the STAT area:

FUNCTION_BLOCK FB100
VAR
    bSignal : BOOL;   // STAT: retained across networks and OB cycles
    bAux    : BOOL;
END_VAR

BEGIN
NETWORK 1
      U     E 0.0;
      =     bSignal;
NETWORK 2
      U     bSignal;
      =     A 4.0;
END_FUNCTION_BLOCK

STAT symbols get a fixed backing bit in the instance DB, so the compiler cannot reuse the cell. This is the canonical Siemens recommendation for any value that must survive between networks or between FB calls. Reserve TEMP for true scratch values that are assigned and consumed inside one network.

5.2 Split the network

If the variable must remain TEMP (for example, the FB interface is frozen because it is used by third-party tooling that rejects interface changes), split Network 2 so the read of bSignal happens in a fresh network context:

NETWORK 2
      U     E 0.0;
      =     A 4.0;
NETWORK 3
      U     bSignal;     // still TEMP, but in its own network
      S     M 10.0;
END_FUNCTION_BLOCK

Splitting works because the new network creates a new scratchpad window in the compiler's view; the bit cell that bSignal lived in is still live at the top of the new network. Use this only as a stop-gap; the underlying interface is fragile and any future re-compile can break the timing again.

5.3 Switch the affected network to STL

LAD/FBD networks and STL networks can be mixed inside a single FB. Edit Network 2 as STL and explicitly load and transfer the variable to itself at the top of the network:

NETWORK 2   // STL
      L     #bSignal;   // force a load from the L stack slot
      T     #bSignal;   // and write it back, pinning the slot
      U     #bSignal;
      =     A 4.0;
END_FUNCTION_BLOCK

The redundant load/transfer has no functional effect but it forces the compiler to keep the slot reserved for the rest of the network. This is a single-network patch and is the smallest-blast-radius option when only one of many networks is affected.

5.4 Use a bit memory or marker instead

If neither TEMP nor STAT are acceptable, write the value to a global bit memory (M area) or to a designated shared DB:

NETWORK 1
      U     E 0.0;
      =     M 100.0;    // global bit, always reliable
NETWORK 2
      U     M 100.0;
      =     A 4.0;
END_FUNCTION_BLOCK

This is the worst option because M bits are not encapsulated, are not retained on FB re-instantiation, and conflict with the Siemens naming conventions for global memory. Use it only for diagnosis, never as the long-term fix.

6. TEMP vs STAT - When to Use Which

Attribute TEMP STAT
Backed by L stack (per call frame) Instance DB
Persists across OB cycles No - undefined on next call Yes
Persists across networks within one FB call Compiler-dependent Yes - guaranteed
Multi-instance safe N/A - each call has its own L stack Yes
Default value behavior May be reused / zeroed by compiler Initialized from instance DB defaults
Suitable for handshake flags between networks No Yes
Suitable for one-network scratch Yes (preferred) Works, but wastes instance DB memory

7. Verification Procedure

After applying any of the four workarounds, verify the fix in this order:

  1. Open the FB in STEP 7 and select Options > Check Block Consistency. The status must be green before testing logic.
  2. Regenerate the instance DB (right-click > Instance DB > Generate) if you changed any STAT declarations. For multi-instance calls, regenerate the parent FB's instance DB as well.
  3. Download the FB, the instance DB, and all calling blocks to the CPU. Use PLC > Download, not partial download of the FB only, because the instance DB layout may have changed.
  4. In VAT or a watch table, monitor the affected variable. Toggle the input E 0.0 on, then observe the output A 4.0 and the variable itself on the next OB1 scan. The output should follow the input on the same cycle.
  5. Force a re-run of the PLC restart (warm restart) to make sure the instance DB initializes STAT variables to the declared defaults, not to random values.
  6. If a CPU 319-3 PN/DP or CPU 41x is in RUN with breakpoints, use Debug > Monitor with STEP 7 to single-step the FB and confirm the value seen by Network 2 matches the value written by Network 1.

8. Diagnostic Checklist

Use this matrix to map symptoms to root causes. The "Temp not updated between networks" row is the failure mode described in this article; the others are commonly confused with it.

Symptom Most likely cause Confirm with Fix
TEMP value reads 0 in next network of same FB LAD/FBD compiler scratchpad reuse (FAQ 13988019) Switch to STAT or STL - works Use STAT, split, or STL
TEMP value reads 0 in different FB called from same OB TEMP is per-call frame by definition - never share via TEMP Inspect VAR_TEMP of both FBs Use a shared DB or pass as IN_OUT
STAT value reads stale after online edit Instance DB was not regenerated Check instance DB timestamp vs FB timestamp Re-download both, then warm restart
Output follows input only every other cycle Two networks competing for the same bit memory or output in different OBs Cross-reference the output across OBs Use a single assignment point
Variable correct in VAT, wrong in PLC Compile/run mismatch: blocks compiled but not downloaded Compare online/offline block timestamps Download blocks again
Variable correct in S7-PLCSIM, wrong on real CPU Different firmware or different memory layout; or partial download missed an FC call Cross-reference FC/FB calls Full download including all referenced blocks

9. Step 7 V5.x Reference

10. Best-Practice Rules for Siemens S7-300/400 FB Design

  1. Default to STAT. Anything that is set in one network and read in another, or that must survive across calls, belongs in the instance DB.
  2. Use TEMP only for single-network scratch. Examples: a temporary accumulator name, a temporary loop counter, or a derived BOOL consumed by the very next coil.
  3. Never share TEMP across FBs. The L stack is per call, so a TEMP in FB1 is invisible to FB2 by design.
  4. Always pass shared data via IN_OUT or a shared DB. Avoid implicit cross-FB coupling through global M bits.
  5. Regenerate the instance DB after every interface change. A stale instance DB can hide this symptom behind a different symptom (wrong initial values, wrong field offsets).
  6. Run "Check Block Consistency" before download. It will not catch scratchpad issues, but it prevents the much more common "interface drift" bug that looks similar.
  7. For mixed-language FBs, document which networks are STL. Future maintainers who re-compile in LAD lose the manual load/transfer you inserted.

11. Common Mistakes After the Fix

  • Changing TEMP to STAT but forgetting to regenerate the instance DB - the symptom persists with a "STATIC NOT FOUND" SF LED on the CPU.
  • Splitting the network but re-merging it later for "cleanliness" - the symptom returns.
  • Using a marker (M 100.0) as the fix and then forgetting the marker is global - a different FB overwrites it under load conditions.
  • Fixing the symptom on the development CPU but not downloading the regenerated instance DB to the production CPU - the production CPU keeps running with the old layout until the next restart.

12. Frequently Asked Questions

Why does my TEMP variable read 0 in the next LAD network of the same FB on S7-300?

The LAD/FBD compiler in STEP 7 V5.x and TIA Portal (for S7-300/400) reuses L-stack slots per network for symbols in the TEMP area. The slot assigned to the variable in Network 1 may not be the same slot read in Network 2, so the second network sees the default value (0 for BOOL). Siemens documents this in FAQ 13988019.

Does the same bug affect S7-1500 or S7-1200 in TIA Portal?

No. The S7-1200/S7-1500 compiler model does not perform the same scratchpad optimization for TEMP, so a TEMP written in one network is reliably read in the next. The behavior is specific to S7-300/S7-400 with the STEP 7 V5.x or TIA Portal LAD/FBD compiler.

My "Check Block Consistency" passes but the symptom is still there - why?

Block consistency only verifies interface-to-instance-DB matching and call graph integrity. It does not perform data-flow analysis across networks, so it cannot detect that a TEMP variable is being read from a different L-stack slot than the one it was written to. A green consistency status is necessary but not sufficient.

Should I convert the FB to STL to make the symptom go away?

Yes, but only for the specific affected networks. STL exposes the L-stack directly, so the same TEMP variable behaves predictably. Keep the rest of the FB in LAD/FBD if your team prefers; mixing is allowed. Document the STL networks so future maintainers do not re-compile them as LAD.

Is this a CPU 319-3 PN/DP firmware bug?

No. The CPU firmware executes the MC7 code that the compiler produced. The compiler's scratchpad optimization is documented Siemens behavior and is independent of firmware version. CPU 319-3 PN/DP (6ES7 318-3EL00-0AB0), CPU 317, CPU 315, and the S7-400 CPUs all exhibit the same behavior on identical source code.

Back to blog