Generated reference › Waveform Generator — Control Systems/Sources
kind: generated#block#control-systems-sources

Waveform Generator — Control Systems/Sources

Control_Systems/Sources/Waveform_Generator · 0 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Waveform Generator

Control Systems / Sources

A source producing one of six parameterized waveforms. Everything except constant starts at Delay; before that the output is Bias. With τ = t − Delay and φ = frac(f·τ):

  • sinusoidy = A·sin(ω·τ + φ0) + bias
  • square+A + bias while φ < duty, −A + bias after (bipolar)
  • sawtoothy = A·(2φ − 1) + bias, a ramp rising from −A to +A
  • pulse+A + bias while φ < duty, bias after (unipolar)
  • stepy = A + bias once the delay has passed
  • constanty = A + bias for all t

Ports

  • Output – the generated signal, always a scalar. It has no inputs.

Parameters

  • Waveform – which of the six to generate. This selects the implementation rather than retuning one, so each is a separate code path, and several of the parameters below apply only to some of them.
  • Amplitude – the peak A. Applies to every waveform; for step and constant it is the level itself.
  • Frequency (Hz) – cycles per second, used by sinusoid, square, sawtooth and pulse. Ignored by step and constant. Must be greater than zero.
  • Phase (rad) – the phase offset of the sinusoid, in radians. Ignored by the other five.
  • Bias – a constant offset added to every waveform, and the value produced before Delay.
  • Duty Cycle (%) – the percentage of each cycle spent high, used by square and pulse. Between 0 and 100; 50 gives an even square.
  • Delay (s) – when the waveform starts. Before it the output is Bias. It is a genuine start time rather than a phase shift, so the first cycle always begins at its own beginning. constant ignores it.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period. It also sets how finely the waveform is resolved, so a coarse rate visibly aliases a fast one.

The sawtooth rises here, and falls on Signal Generator

Deliberately. The Signal Generator block mirrors simulink/Sources/Signal Generator, whose sawtooth was measured falling from +A to −A; this block follows the conventional rising ramp of a waveform-notation generator. Reach for whichever matches the model you are reproducing.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. Each uses a per-block local sample clock rather than a global one. The chosen Waveform and all of its timing – frequency, phase, duty cycle and delay – are structural and are baked into the exported body, so the generated core carries the one waveform rather than a run-time switch; Amplitude and Bias stay tunable, being a pure scale and offset that appear as a multiplier and an addend in every branch.

The three HDL targets are simulation-only: they read the testbench's simulation time and carry the phase in real arithmetic, quantizing only on the way out to the fixed-point signal ports. The timing is inlined there as exact real literals rather than quantized into Q16.16 parameter ports, because a rate carrying the 1.5×10−5 Q-format step would accumulate a phase error that grows with the length of the run.

Simulink bridge

Neither direction. Simulink's Waveform Generator defines its output through a WaveformDefinition of signal-notation strings, and that definition is not reachable through set_param – the block's dialog parameters are only OutMin, OutMax, OutDataTypeStr, LockScale, RndMeth, SaturateOnIntegerOverflow, SelectedSignal and SampleTime, with no waveform parameter among them. The bridge writes .m scripts driven by set_param, so there is nothing it could emit that would carry the waveform, and nothing it could read back. Rather than assert a mapping that could never be checked, the bridge reports this block and skips it.

The waveform names above are Simulink's own, so a model can be moved by hand: place the Simulink block, and write the matching notation into its dialog.

Notes

  • Stateless and time-driven: the output is a function of the current time alone, so there is nothing to reset and a re-run reproduces it exactly.
  • square, sawtooth, pulse and step are discontinuous. A continuous solver does not step onto their jumps, so a transition lands on whichever sample follows it; at a coarse rate that is visible as jitter in the edge position.
  • Scalar only. Use several blocks, or a Mux, for a vector of waveforms.

Code facts#

FactValue
registered typeControl_Systems/Sources/Waveform_Generator
familyControl_Systems/Sources
solver environment classICoreBlock_0_Control_Systems_1_Sources_2_Waveform_Generator
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Sources/Waveform_Generator/ICoreBlock_0_Control_Systems_1_Sources_2_Waveform_Generator.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Sources/Waveform_Generator/ICoreBlock_0_Control_Systems_1_Sources_2_Waveform_Generator.h
default size on canvas80 × 70 px
ports at insert0 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1outICoreDouble

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Waveformsinusoid%~%square%~%sawtooth%~%pulse%~%step%~%constant~~s…
Amplitude1
Frequency (Hz)1
Phase (rad)0
Bias0
Duty Cycle (%)50
Delay (s)0

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::None
Simulink path
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): Simulink's Waveform Generator defines its output through a WaveformDefinition of signal-notation strings, which is not reachable through set_param: the block's dialog exposes only OutMin, OutMax, OutDataTypeStr, LockScale, RndMeth, SaturateOnIntegerOverflow, SelectedSignal and SampleTime, with no waveform parameter among them. The bridge writes .m scripts driven by set_param, so there is nothing it could emit to carry the waveform and nothing it could read back. The waveform names here are Simulink's own, so a model can be moved by hand by writing the matching notation into the Simulink block's dialog

Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Waveform Generator block — six parameterized waveforms from one block Everything but constant starts at Delay; before it the output is Bias. With tau = t - Delay and phi = frac(f*tau):

sinusoid y = A*sin(w*tau + phase) + bias square y = +A + bias while phi < duty, -A + bias after (bipolar) sawtooth y = A*(2*phi - 1) + bias (RISING) pulse y = +A + bias while phi < duty, bias after (unipolar) step y = A + bias constant y = A + bias, for all t (the one waveform Delay does not apply to)

WHY EVERY PERIODIC WAVEFORM IS GATED ON t >= Delay, and not merely phase-shifted. It makes the argument of frac() non-negative everywhere it is evaluated, which is what lets all ten backends spell it the same way. Structured Text has no floor: it has TRUNC, which rounds toward ZERO, and the two agree only for non-negative arguments. Phase-shifting instead would put negative times into frac() before the waveform starts, and the ST core alone would disagree with the other nine -- a one-backend failure with no obvious cause.

NOTE THE SAWTOOTH RISES, and Signal Generator's FALLS. That is not an oversight: Signal Generator mirrors simulink/Sources/Signal Generator, whose sawtooth was measured falling from +A to -A, while this block follows the conventional rising ramp of a waveform-notation generator. Both are documented on their own block; they are different blocks, not one behaviour written twice.

ONE RULE, FORMATTED TEN TIMES. buildBranches() produces the waveform as a language-neutral ordered list of (condition, value) pairs, and each backend only chooses punctuation. Six waveforms across ten targets is sixty chances to get a comparison backwards; this reduces it to one. The two places languages genuinely differ -- Rust's postfix x.sin() and ST's wrapped truncation -- are passed in as MathSyntax rather than switched on.

WHY THERE IS NO SIMULINK BRIDGE. Simulink's Waveform Generator defines its output through a WaveformDefinition of signal-notation strings, and that definition is not reachable through set_param at all. Verified against R2026a: the block's DialogParameters are only OutMin, OutMax, OutDataTypeStr, LockScale, RndMeth, SaturateOnIntegerOverflow, SelectedSignal and SampleTime -- no waveform parameter among them -- and set_param on 'WaveformDefinition', 'SignalDefinition' and 'Waveforms' each fail with "block (mask) does not have a parameter named ...", while 'IOSignalStrings' rejects the value. The bridge writes .m scripts driven by set_param, so there is nothing it could emit that would carry the waveform. It registers Support::None with that reason rather than asserting a mapping that nothing could check.

Sample results#

Waveform Generator — No input: the block run aloneWaveform Generator — No input: the block run alone-1-0.500.51012345t (s)

Plotted: free — No input: the block run alone

Category source · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/Control_Systems__Sources__Waveform_Generator.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).