Skip to content

Verified: Function Block Diagram

Each claim the Function Block Diagram page makes, with the tests that prove it in the last green CI run: 29 of 30 verified. The claims live in docs/claims/function-block.yaml.

Last green CI run 16 Oct 2026, 14:48 UTC on c7618d3 · all runtime claims

FBD-001 verified

An .fbd body is a netlist of named wires, coils, and function-block instances inside an ordinary ST POU; everything before FBD and after END_FBD is plain ST.

where the docs say so · TestArithmeticAndFanout added: neither of the other two tests has a named wire, and it runs one (s = ADD(A, B)) feeding three coils.

  • pass TestTranspileMultipleBlocks in lang/fbd
  • pass TestFunctionBlockInstance in lang/fbd
  • pass TestArithmeticAndFanout in lang/fbd

FBD-002 verified

A coil writes a variable; the target may be an array element or struct member (TempHist[1] := TempC), and array/struct accessors work as inputs.

where the docs say so · Array elements as coil targets and inputs are run (TestArrayElementFeedback) and a struct member as a coil target is run, leaving its sibling alone (TestStructMemberCoil); a struct member as an input is run (TestSharedTypes).

FBD-003 verified

An FB instance is declared and called in one statement (lic : PID(...)); lic : PID alone declares it and lic(PV := ...) calls it later; lic.CV reads an output pin.

where the docs say so · The one-statement form declares the instance even when another block in the same file has a local of that name (#332).

  • pass TestFunctionBlockInstance in lang/fbd
  • pass TestTranspileMultipleBlocks in lang/fbd
  • pass TestConformance/fb-ton in lang/conformance (7 of 7 passed)
  • pass TestSplitDeclareThenCall in lang/fbd
  • pass TestInlineInstanceNotHiddenByLibraryBlockVar in lang/fbd (4 of 4 passed)

FBD-004 verified

The => output binding (ET => Elapsed) captures a non-BOOL pin into a variable.

where the docs say so · TestOutputBinding runs the program: ET lands in Elapsed (2000 ms, then 5000 ms at PT).

FBD-005 verified

Inline NOT negates a pin; constants (5.0, T#10S, TRUE, 'ok') are literal inputs.

where the docs say so

  • pass TestSealInLatch in lang/fbd
  • pass TestArithmeticAndFanout in lang/fbd
  • pass TestFunctionBlockInstance in lang/fbd
  • pass TestBoolAndStringLiteralInputs in lang/fbd

FBD-006 verified

Statements may end with ; or just a newline, and full-line // comments are allowed in the body.

where the docs say so

  • pass TestCommentsInModel in lang/fbd
  • pass TestSemicolonTerminatedStatements in lang/fbd

FBD-007 verified

A standard function's inputs are positional (LIMIT(0.0, x, 9.0)) or all named by their standard names (LIMIT(MN := 0.0, IN := x, MX := 9.0)).

where the docs say so

  • pass TestArithmeticAndFanout in lang/fbd
  • pass TestConformance/fbd-en-eno/EN TRUE runs the call and ENO is TRUE in lang/conformance
  • pass TestENOErrors in lang/fbd
  • pass TestAllNamedStandardCallWithoutEN in lang/fbd

FBD-008 verified

Compilation transpiles the netlist to ST and runs it through the ST front end, so errors map back to the exact .fbd line.

where the docs say so

  • pass TestTranspileLineMap in lang/fbd
  • pass TestCheckReportsIdentifierColumn in cmd/naut
  • pass TestAnalyzeFBDMapsDiagnosticsToSource in internal/lsp

FBD-009 verified

A wire is a pure combinational expression inlined at every read, so fan-out duplicates an expression rather than creating shared state.

where the docs say so

  • pass TestArithmeticAndFanout in lang/fbd
  • pass TestWireInlinedAtEveryRead in lang/fbd

FBD-010 verified

Wires must be acyclic: a wire that reads itself, directly or through another wire, is a compile error ("combinational loop through wire").

where the docs say so · The indirect loop (a reads b, b reads a) and a wire reading itself directly both fail with "combinational loop".

  • pass TestCombinationalLoopRejected in lang/fbd
  • pass TestWireReadingItselfRejected in lang/fbd
  • pass TestCheckRejects/FBD self-feeding wire in cmd/naut

FBD-011 verified

A variable read early in the body carries the value its coil wrote on the previous scan, so HighLevelAlm := AND(OR(above, HighLevelAlm), NOT below) is a seal-in latch.

where the docs say so · TestSealInLatch runs one program and tag store across scans with nothing re-seeded, so Run stays on only through the carried value; the lift-station test does the same for level.fbd's own HighLevelAlm line, holding the alarm at 87 (inside the band).

FBD-012 verified

Statements evaluate in source order, except that a function-block call is emitted ahead of any statement that reads its output pins, so lic.CV reads this scan's result wherever lic sits in the file.

where the docs say so · TestFunctionBlockInstance runs a reader written above its TON call and sees Q on the scan PT elapses (this scan's value); in TestArrayElementFeedback a[2] := a[1] reads the value a[1] was given earlier in the same scan (source order).

  • pass TestFunctionBlockInstance in lang/fbd
  • pass TestNetworksRunInOrder in lang/fbd
  • pass TestArrayElementFeedback in lang/fbd

FBD-013 verified

A body can be divided into NETWORKs; network 1 runs to completion, then network 2, and the FB-before-reader rule holds within a network only, so a read of a later network's FB output sees the previous scan's value.

where the docs say so

  • pass TestNetworksRunInOrder in lang/fbd
  • pass TestNetworksParseModelAndOrder in lang/fbd

FBD-014 verified

Statements before the first NETWORK line are an untitled first network, and a body with no NETWORK line is one network.

where the docs say so

  • pass TestNetworksParseModelAndOrder in lang/fbd
  • pass TestNetworksRunInOrder in lang/fbd

FBD-015 verified

Any block takes EN (BOOL, TRUE when unbound) and gives ENO; while EN is FALSE a function's result is not written (its variable keeps its value) and a function block's outputs and internal state hold.

where the docs say so

FBD-016 verified

ENO is EN AND no error; DIV and MOD report a zero divisor through ENO.

where the docs say so

  • pass TestConformance/fbd-en-eno/DIV's ENO is FALSE on a zero divisor, TRUE otherwise in lang/conformance
  • pass TestConformance/fbd-en-eno/DIV with EN FALSE holds its result and reports ENO FALSE in lang/conformance
  • pass TestENOModByZero in lang/fbd

FBD-017 verified

A block with EN/ENO must drive a variable (a coil, directly or through its named wire), and its ENO reads like a pin (t1.ENO, sp.ENO).

where the docs say so

FBD-018 verified

While EN is FALSE a function block does not run: its outputs and internal state hold.

where the docs say so

  • pass TestConformance/fbd-en-eno/an FB with EN FALSE does not run — edges it misses are not counted in lang/conformance
  • pass TestConformance/fbd-en-eno/the FB's edge memory is stale while disabled — a rise across it counts on return in lang/conformance

FBD-019 verified

AND, OR, XOR, ADD and MUL take two or more inputs; SUB, DIV, MOD and the comparisons take exactly two; MOVE is a one-input pass-through.

where the docs say so

FBD-020 verified

An FB input left out of the call keeps its value (its declared initial value until something writes it).

where the docs say so

  • pass TestOmittedFBInputKeepsInitial in lang/fbd
  • pass TestOmittedFBInputKeepsLastWrittenValue in lang/fbd

FBD-021 verified

User-defined TYPE structs work as inputs and coil targets.

where the docs say so · A struct member as an input (TestSharedTypes) and as a coil target (TestStructMemberCoil) are run.

FBD-022 verified

A user FUNCTION_BLOCK instantiates in FBD the way a TON does, whether authored in an ST, FBD or ladder library file; a .fbd/.ld/.st file with no PROGRAM is a project library.

where the docs say so

  • pass TestLibrariesUserFBFromFBD in runtime
  • pass TestFBDInstantiatesBlocksFromSTFBDAndLadderLibraries in runtime

FBD-023 verified

A controller running an FBD program serves and accepts the .fbd text; a warm swap migrates retained state by name and type, so a PID's integral or a running TON keeps its value.

where the docs say so

  • pass TestSwapWarmFBDCarriesRetainedState in runtime
  • pass TestSwapWarmFBDKeepsPIDIntegralAndRunningTON in runtime
  • pass TestSwapWarmFBDTypeChangeResets in runtime
  • pass TestProgramFBDServedAndRoutedByPOU in server

FBD-024 verified

An .fbd download behaves as a .st one does: a failed compile leaves the running program untouched.

where the docs say so · Reworded: this page does not state the failed-compile rule itself; it says download works as it does for .st and links to online edits, whose opening paragraph makes the promise.

  • pass TestSwapWarmFBDCompileErrorLeavesRunning in runtime

FBD-025 verified

An edit routes to a task by PROGRAM name, so a task's own .fbd downloads without disturbing another task's program.

where the docs say so

  • pass TestProgramFBDServedAndRoutedByPOU in server

FBD-026 verified

Authoring a FUNCTION in FBD is not supported; functions are ST.

where the docs say so

  • pass TestCheckRejects/FBD_FUNCTION in cmd/naut

FBD-027 partly verified

There are no execution-order overrides and no control flow (IF, CASE, loops) in the netlist.

where the docs say so · IF, CASE, FOR and WHILE in an FBD body are refused by naut check. No test tries an execution-order override.

  • pass TestCheckRejects/FBD IF in cmd/naut
  • pass TestCheckRejects/FBD CASE in cmd/naut
  • pass TestCheckRejects/FBD FOR in cmd/naut
  • pass TestCheckRejects/FBD WHILE in cmd/naut

FBD-028 verified

Inline arithmetic in an array index is not supported; the index is computed on a named wire first.

where the docs say so

  • pass TestCheckRejects/FBD index arithmetic in cmd/naut

FBD-029 verified

Defining the same wire twice is a compile error.

where the docs say so

  • pass TestCheckRejects/FBD duplicate wire in cmd/naut

FBD-030 verified

A wire that feeds itself is a compile error.

where the docs say so · A two-wire loop (TestCombinationalLoopRejected) and a wire that reads itself directly (TestWireReadingItselfRejected, and naut check) are refused.

  • pass TestCombinationalLoopRejected in lang/fbd
  • pass TestWireReadingItselfRejected in lang/fbd
  • pass TestCheckRejects/FBD self-feeding wire in cmd/naut