Direct Instance DB Bit Access in Siemens FBs: DIX vs DBX

David Krause12 min read
HMI ProgrammingSiemensTutorial / How-to
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

Overview

When programming a Siemens Function Block (FB) in STEP 7 classic or TIA Portal, the FB's working variables, parameters, and static data are stored in an associated Instance Data Block (Instance DB / DI). A long-standing question from STEP 7 STL programmers is how to access individual bits inside that instance DB without hard-coding the DB number, especially when the same FB is reused as a multi-instance with several different instance DBs assigned at runtime.

The answer in STEP 7 STL is the DIX operand area. DIX<byte>.<bit> always resolves to the instance DB of the FB in which the instruction is being executed. It is the direct, fully-resolved counterpart to DBX<byte>.<bit>, which is only valid after a OPN DB or OPN DI instruction has opened a specific data block.

This article consolidates the rule set, contrasts DIX with DBX and OPN, demonstrates the STL, LAD, and FBD variants, and covers multi-instance, single-instance, and external-DB cases for the S7-300, S7-400, S7-1200, and S7-1500 controller families.

Prerequisites

  • STEP 7 V5.5 / V5.6 (classic) or TIA Portal V15.1 or later (V16, V17, V18 supported on S7-1200/1500).
  • An S7-300 (CPU 31x), S7-400 (CPU 41x), S7-1200 (CPU 12xx firmware V4.0+), or S7-1500 (CPU 15xx firmware V1.5+). The DIX operand is documented in the SIMATIC S7-300/400 STL reference manual and the S7-1500 System Manual.
  • A Function Block (FB) with at least one STAT or TEMP variable of type WORD, BYTE, or DWORD that holds individual boolean flags.
  • Access to the FB's instance DB (single-instance) or the parent FB's instance DB (multi-instance).
  • Knowledge of symbolic vs. absolute addressing. The DIX operand is always absolute in the sense that the byte/bit offset is fixed at FB compile time; symbolic access uses the instance DB name (e.g. "iDB_FB1".MyBit).

Address Type Reference: DBX, DIX, DBW, DIW, DBB, DIB

The Siemens STL operand areas for data blocks are split into two roots: the global data block area (DB) opened with OPN DB, and the instance data block area (DI) opened with OPN DI. The DIX family is the bit-addressed short form that always references the currently-open instance DB regardless of how that DB is identified at runtime.

Operand Width Resolves to Typical Use
DBX<b>.<x> 1 bit Bit in the global DB opened by the last OPN DB External/global DB bit access
DBB<b> 8 bits Byte in the global DB External byte access
DBW<b> 16 bits Word in the global DB External word access
DBD<b> 32 bits Double word in the global DB External DWord access
DIX<b>.<x> 1 bit Bit in the instance DB of the calling FB Direct instance bit access from inside FB
DIB<b> 8 bits Byte in the instance DB Direct instance byte access
DIW<b> 16 bits Word in the instance DB Direct instance word access
DID<b> 32 bits DWord in the instance DB Direct instance DWord access

The DI root is reserved for the instance DB currently associated with the executing FB. The compiler resolves DIX at compile time to an offset within the instance DB; the CPU resolves the instance DB number at call time via the DB register (DI register) loaded when the FB is entered.

Critical: DIX only works inside an FB. Inside an OB, FC, or global program section, DIX has no meaning because there is no implicit instance DB. Use DBX with an explicit OPN DB in those contexts.

Direct Instance Data Access with DIX

Inside an FB, write the bit address using the DI operand area. The bit is read from or written to the FB's instance DB. No OPN DI is required because the CPU automatically opens the FB's instance DB on entry.

STL example: read a bit, combine with logic, write back.

// FB "ShiftControl" with STAT "StatusWord" of type WORD (offset 0.0)
// Bit 0.0 is the run bit, bit 0.1 is the fault bit
A    DIX0.0           // Load StatusWord bit 0 (run flag)
AN   DIX0.1           // AND-NOT StatusWord bit 1 (fault flag)
=    DIX2.0           // Output to OutputBit STAT at offset 2.0

// Shift the word left by 1, keep result in the same STAT word
L    DIW0             // Load StatusWord (WORD = 16 bits, offsets 0-1)
SLW  1                // Shift left word by 1 bit
T    DIW0             // Store back into instance DB at offset 0

This solves the source question directly: a programmer can keep all sixteen flags packed inside one WORD in the instance DB and still manipulate individual bits through DIX without ever typing a DB number. The PLC always resolves DIX to whatever instance DB is currently bound to the FB execution.

Absolute Instance Access via Explicit DB Number

Some legacy code prefers fully-qualified addresses such as DB1.DBX5.1. This still works inside an FB, but it requires that the named DB really is the instance DB for this FB. In multi-instance use this becomes brittle: if FB1 is invoked as instance "Motor1" in DB50 and as instance "Motor2" in DB51, hard-coding DB50.DBX5.1 would always hit DB50 regardless of which copy is currently running.

STEP 7 supports two solutions for this scenario:

  1. Use DIX (recommended) as described above.
  2. Open the instance DB explicitly with OPN DI, then use DBX with no further DB prefix. The two roots are then read/write to the same DI area, but using OPN DI is rarely necessary inside an FB.
// Equivalent forms inside an FB whose instance DB is "iDB_FB1" (DB100 in this example)
A    DB100.DBX5.1     // Fully qualified absolute
A    DIX5.1           // Implicit, always the running instance DB
OPN  DI              // Optional; reopens the same instance DB
A    DBX5.1           // Resolves to the same bit through DB register

Accessing External DBs with OPN DB

When the data lives in a non-instance, project-wide DB (a "global" DB), the FB cannot use DIX. The instance DB area is reserved. Instead, open the external DB explicitly, then use the DBX family.

// Inside FB "ShiftControl" — reading/writing project-wide DB "RecipeData" (DB50)
OPN  DB    50         // Open DB50 as the global DB
A    DBX0.0           // Read bit 0.0 of DB50
=    DBX2.0           // Write bit 2.0 of DB50
L    DBW10            // Load word at offset 10 of DB50
T    DIW20            // Store into instance DB at offset 20 (STAT "ExtWord")

The OPN DB only changes the DB register; the DI register (instance DB) is untouched, so subsequent DIX / DIW accesses still address the FB's own instance DB.

Warning: OPN DB and OPN DI in the same FB can be confusing. The compiler's cross-reference may show a single bit access as either DBX or DIX depending on which register is open at the access point. Use the cross-reference table ("Go to > Location") to verify the target.

Multi-Instance Scenario

Multi-instance capability is the principal reason DIX exists. A parent FB (FB10 "Station") declares three child FB instances: "Motor1" of type FB1, "Motor2" of type FB1, and "Valve1" of type FB2. Each instance gets a slice of FB10's instance DB. Inside FB1 (the motor FB) every DIX resolves to the correct slice automatically because the CPU loads the appropriate base offset when entering the FB through the multi-instance call.

// FB1 "Motor" definition (parameter / STAT layout)
//   IN  : StartCmd (BOOL), StopCmd (BOOL)
//   OUT : Running  (BOOL), Fault (BOOL)
//   STAT: StatusWord (WORD) — packed flags at instance DB offset 0.0
//   STAT: TmrTicks   (TIME) — at instance DB offset 4.0

A    DIX0.0           // StatusWord bit 0 = "StartedLatched"
S    DIX0.1           // Set bit 1 = "RunningOutput"

// FB10 "Station" call
CALL FB1, DB-Motor1   // First instance — DIX hits DB-Motor1
CALL FB1, DB-Motor2   // Second instance — DIX hits DB-Motor2

If you instead wrote DB-Motor1.DBX0.1, you would break the second instance: every motor's running flag would always land in DB-Motor1.

LAD / FBD Implementation (S7-300/400/1200/1500)

Ladder and Function Block Diagram editors do not surface the DIX mnemonic directly. Instead, select the FB's instance DB as the address source from the drop-down selector and address bits inside that DB. The compiler generates equivalent OPN DI + DBX sequences in STL.

Goal LAD / FBD Generated STL equivalent
Read instance bit MyStat.BoolFlag on a NO contact ---| |--- with operand "iDB".MyStat.BoolFlag A "iDB".MyStat.BoolFlag
Address a STAT WORD as a bit slice Use slice operator "iDB".MyStat.Word[5] in LAD/FBD A DIX5.5
Move external DB word to instance WORD MOVE block: IN="RecipeData".Field10, OUT="iDB".MyStat.ExtWord L "RecipeData".Field10
T "iDB".MyStat.ExtWord

On S7-1200 / S7-1500 with TIA Portal V16 and later, slice addressing "iDB".MyStat.Word.%X5 directly selects bit 5 of a STAT word. Slice access is a TIA Portal compiler feature; it lowers to the same DIX machine code at runtime.

Bit Packing and Shift Logic in a STAT WORD

The original question concerned packing multiple boolean flags into a single WORD for shift operations while still needing single-bit access. The recommended pattern:

// STAT layout in FB "FlagPack"
//   Offset 0.0 .. 1.7 : Flags : WORD    ; packed boolean bank
//   Offset 2.0 .. 3.7 : ShiftBuf : WORD ; buffer for shift result

// Read individual bits for control logic
A    DIX0.0           // Flag bit 0
JC   HANDLE_BIT0

A    DIX0.7           // Flag bit 7
JC   HANDLE_BIT7

// Shift the entire bank by 1
L    DIW0             // Load packed flags (WORD)
SLW  1                // Shift left word by 1
T    DIW2             // Store into ShiftBuf

// OR result back to the original bank
L    DIW0
L    DIW2
OW                    // Word OR
T    DIW0

This pattern compiles cleanly in STEP 7 V5.x and TIA Portal. Avoid using UC / CC with absolute jumps into the FB code outside the FB; that violates the block boundary enforced by the S7 operating system.

TIA Portal vs STEP 7 Classic Differences

Feature STEP 7 V5.5 (classic) TIA Portal V15.1+
STL editor available Yes (separate package) Yes (optional since V13, default in V16+)
Direct DIX operand typing Yes Yes in STL; LAD/FBD use slice syntax instead
Slice syntax Var.%X0 No Yes for S7-1200/1500
Multi-instance support Yes Yes (single-instance and multi-instance DB configurable in FB properties)
Optimized vs non-optimized block access Non-optimized only User-selectable; optimized disables absolute DIX
Critical for S7-1500: "Optimized block access" (the default in TIA Portal) removes the fixed offsets that DIX relies on. To use DIX on S7-1500 with absolute byte/bit offsets, uncheck "Optimized block access" in the FB properties. Symbolic access through the instance DB name still works either way.

Common Errors and Diagnostics

Symptom Likely Cause Correction
Compiler error "Unknown operand DIX..." STL line written outside an FB (OB/FC context) Move the bit logic into the FB or qualify it with a specific DB number
Bits update on the wrong instance DB Programmer used DBX after a stray OPN DB inside the FB Remove the OPN DB or change the operand back to DIX
Symbol shows 'invalid operand' in cross-reference on S7-1500 Block is optimized; offsets are stripped from the compile output Disable optimized block access for that FB or switch to fully symbolic addressing
Runtime: bit stays stuck at last value after FB exit Static TEMP variable was used by mistake — TEMP is re-initialized each call Declare the bit storage as STAT so it persists in the instance DB
CPU stops with SF (system fault) on FB call FB called without an instance DB, or DB number/type mismatch Verify call: CALL FB1, DB10 with DB10 generated as instance of FB1

Verification Procedure

  1. Open the FB in STEP 7 / TIA Portal and confirm each DIX<offset> operand resolves to a STAT declared in the FB interface. The offset must match the layout.
  2. Compile and download. In online mode, open the FB and force a break on the first DIX instruction.
  3. Use the watch table or the instance DB monitor to confirm that the byte/bit written by DIX is exactly the byte/bit declared in the instance DB layout.
  4. Instantiate the FB in two separate calls (single-instance with two DBs, or as multi-instances inside a parent FB). Force bit 0.0 on each instance and verify in the online DB view that only the targeted instance changes.
  5. If on S7-1500, go to FB Properties > Attributes > confirm "Optimized block access" is unchecked if absolute offsets are required.
  6. Trigger a PLC restart (warm restart) to ensure the instance DBs are re-initialized to their default values; confirm bit positions match the FB initial values.
  7. Document the address map in the project's tag list so future maintenance engineers can map DIX offsets back to the symbolic STAT names.

Best Practices

  • Use DIX exclusively for instance-bit access inside an FB; never hard-code the instance DB number.
  • Declare a comment on every STAT WORD that documents which bit offset holds which flag.
  • Reserve a STAT area for the input image of external flags and a separate STAT area for outputs. This keeps the shift logic isolated from signals read directly from I/O.
  • For boolean-heavy FB interfaces, prefer S7-1500 slice syntax over packing into WORDs — modern CPUs handle slice access at full scan time.
  • When porting classic STEP 7 FBs to TIA Portal, audit every DIX for offset collisions with the new compiler's STAT layout; TIA may reorder STATs in optimized blocks.

FAQ

Can I access instance DB bits from inside an FB without writing a DB number?

Yes. Use the DIX<byte>.<bit> operand area inside the FB. It always resolves to the FB's currently-bound instance DB, including in multi-instance scenarios. The companion areas DIB, DIW, and DID address byte, word, and double-word widths in the same instance DB.

What is the difference between DBX and DIX in STEP 7?

DBX addresses the global data block opened by the last OPN DB. DIX addresses the instance data block (instance DB) opened automatically on entry into an FB. The two are mutually exclusive roots: OPN DB does not change the DI register, so DIX keeps pointing at the FB's own instance DB even after an OPN DB.

Why does DIX not compile in an OB or FC?

The DI operand area only has meaning inside an FB. In an OB or FC there is no implicit instance DB, so the compiler rejects DIX. Use DBX with an explicit OPN DB in those contexts, or move the bit logic into an FB.

Can I still use DIX on an S7-1500 with optimized block access?

Not directly. Optimized block access on S7-1200/1500 strips fixed byte offsets from the compile output, so absolute DIX<b>.<x> addressing is disabled. Either uncheck "Optimized block access" in the FB properties, or switch to fully symbolic addressing through the instance DB name combined with the slice operator (Var.%X0).

How do I keep packed boolean flags while still accessing individual bits?

Declare a single STAT WORD in the FB and use DIX<b>.<x> for each individual flag. Shift the whole WORD with the SLW / SRW instructions using DIW<b>, and store the result back into the same or another STAT location. This avoids re-coding each flag as a separate BOOL variable and gives the bit-packing efficiency originally requested.

Back to blog