PLC Structured Text
IEC 61131-3 Structured Text: the model as a function block, one call per PLC scan.
<name>_deployableCore.st<name>_testbench.st
FUNCTION_BLOCK FB_<name> — one call = one scan
matiec (iec2c)
LREAL
306 of 308
The core is a FUNCTION_BLOCK. Call it once per scan from your program
and the model has advanced one sample — the same contract as every other target, expressed the
way a PLC expects it. Numbers are LREAL, the ST equivalent of the
double the software targets use, so this is a full-precision target and not a
fixed-point one.
Structured Text and VHDL are the strictest of the ten about identifiers, and between them
they set the naming rules the export applies to all targets — anything outside
[A-Za-z0-9] collapses to an underscore, and a leading digit gets a prefix.
Verification compiles the generated ST with matiec (iec2c). If that
transpiler is missing, every block fails this column at once — which is the signature to look
for before suspecting the generator.
What the export looks like
Every target page shows the same model, so the ten are directly comparable:
an input, an error junction, a gain of 1.8, a discrete plant
0.4z⁻¹ / (1 − 0.6z⁻¹), an output — and the plant's
output fed back into the junction. Five blocks, in a diagram the
export-verification suite calls DPT_Feedback_Discrete — which is where the names
in the file come from. Below is what Deploy writes for this target, with only the
file's header banner removed.
DPT_Feedback_Discrete_deployableCore.st
FUNCTION_BLOCK FB_DPT_Feedback_Discrete
VAR_INPUT
(* ---- Tunable parameters (set from the testbench: core.<name> := ...) ---- *)
gain_blk2 : ARRAY[0..0, 0..0] OF LREAL := [LREAL#1.8000000000000000]; (* tunable gain *)
in_sig0 : ARRAY[0..0, 0..0] OF LREAL; (* external input: ICore Blocks/Home/DPT_Feedback_Discrete/In1/ICoreDouble-Out-0 *)
END_VAR
VAR_OUTPUT
(* ---- Signals (observable from the testbench: core.<name>) ---- *)
sig0 : ARRAY[0..0, 0..0] OF LREAL; (* ICore Blocks/Home/DPT_Feedback_Discrete/In1/ICoreDouble-Out-0 *)
sig1 : ARRAY[0..0, 0..0] OF LREAL; (* ICore Blocks/Home/DPT_Feedback_Discrete/Error/ICoreDouble-Out-0 *)
sig2 : ARRAY[0..0, 0..0] OF LREAL; (* ICore Blocks/Home/DPT_Feedback_Discrete/Ctrl_Gain/ICoreDouble-Out-0 *)
sig3 : ARRAY[0..0, 0..0] OF LREAL; (* ICore Blocks/Home/DPT_Feedback_Discrete/Plant/ICoreDouble-Out-0 *)
sig4 : ARRAY[0..0, 0..0] OF LREAL; (* ICore Blocks/Home/DPT_Feedback_Discrete/ICoreDouble-Out-0 *)
END_VAR
VAR
(* ---- Persistent block state ---- *)
(* blk3: ICore Blocks/Home/DPT_Feedback_Discrete/Plant *)
uh_blk3 : ARRAY[0..0, 0..0, 0..1] OF LREAL := [LREAL#0.0, LREAL#0.0];
yh_blk3 : ARRAY[0..0, 0..0, 0..0] OF LREAL := [LREAL#0.0];
y_blk3 : LREAL;
END_VAR
(* ===== Ordered execution pass (one scan == executeBlocks) ===== *)
(* blk0: ICore Blocks/Home/DPT_Feedback_Discrete/In1 *)
sig0[0, 0] := in_sig0[0, 0];
(* blk1: ICore Blocks/Home/DPT_Feedback_Discrete/Error *)
sig1[0, 0] := sig0[0, 0] - sig3[0, 0];
(* blk2: ICore Blocks/Home/DPT_Feedback_Discrete/Ctrl_Gain *)
sig2[0, 0] := sig1[0, 0] * gain_blk2[0, 0];
(* blk3: ICore Blocks/Home/DPT_Feedback_Discrete/Plant *)
(* Discrete transfer function (direct-form IIR) applied per [p,m] entry: rotate u, y = sum num*u - sum den*y *)
uh_blk3[0, 0, 1] := uh_blk3[0, 0, 0];
uh_blk3[0, 0, 0] := sig2[0, 0];
y_blk3 := 0.0;
y_blk3 := y_blk3 + LREAL#0.0 * uh_blk3[0, 0, 0];
y_blk3 := y_blk3 + LREAL#0.40000000000000002 * uh_blk3[0, 0, 1];
y_blk3 := y_blk3 - LREAL#-0.59999999999999998 * yh_blk3[0, 0, 0];
yh_blk3[0, 0, 0] := y_blk3;
sig3[0, 0] := y_blk3;
(* blk4: ICore Blocks/Home/DPT_Feedback_Discrete/Out1 *)
sig4[0, 0] := sig3[0, 0];
END_FUNCTION_BLOCK
Tunable parameters and the external input are VAR_INPUT, the signals are
VAR_OUTPUT, and block state is VAR — so calling the function block
once from your program is one scan and one sample, with the state surviving between scans by
definition. Note what the emitter does with a 1×1 model: the loops are gone entirely and
the pass is a handful of scalar assignments, including the plant's history rotation.
How it is checked
Every one of the ten targets is verifiable, and this one is no exception: the export is compiled with the toolchain above, run across the simulation window, and compared against the solver sample by sample. Software targets pass at around 1e-11 % against a 0.1 % tolerance; the HDL targets are bounded by their fixed-point quantum instead. See verification.
See also: Code export · Multi-target, multi-rate deploy
See it run on your own model.
Download the application from the customer portal, or read the documentation first — the manual, every block with its measured response, and the full command reference are public.