Multisine Generator — System Identification/Excitation
System_Identification/Excitation/Multisine_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.
Multisine Generator
System Identification / Excitation
A periodic multisine: the sum of K sinusoids placed on harmonics of one base period, y(t) = Σk Ak·sin(2π(hk/T)t + φk).
This is the frequency-domain excitation, and the partner of the PRBS Generator. A PRBS spreads its energy flat up to the chip rate whether you want it there or not; a multisine puts energy exactly on the lines you name and nowhere else. Because every line is a harmonic of the base period, each one lands on an exact DFT bin of that period – so there is no spectral leakage, and the unexcited bins between the lines measure the noise floor directly.
Ports
- Output – a [1,1] scalar, the summed excitation. It is a source: there is no input.
Parameters
- Base Period (s) – T, the period the signal repeats with. Every excited frequency is a whole multiple of 1/T, so this one number sets the frequency resolution of the whole measurement. Choose it so at least one full period fits in the run – a multisine measured over a fraction of its period is not periodic data and the leakage it was chosen to avoid comes straight back.
- Harmonic Numbers – h, a vector of whole numbers naming which harmonics to excite; line k sits at hk/T Hz. Give the band you care about, and prefer values with no common factor if you want to detect even-order nonlinearity by the harmonics it produces in the empty bins.
- Line Amplitudes – A, one amplitude per line, the same length as Harmonic Numbers. Shape the excitation here: put more amplitude where the plant attenuates, so the measured response keeps a usable signal-to-noise ratio across the band.
- Phase Rule – how the per-line phases are chosen:
- Schroeder – the low crest-factor rule, and the reason to use a multisine at all. The lines are given a quadratic phase progression so their peaks do not coincide, which keeps the peak excursion near that of a single sine. A plant that tolerates a given peak can therefore be driven with far more total energy.
- Zero – every line aligned at t = 0. All K peaks then coincide and the signal is an impulse-like burst with a crest factor of order √K; useful when an impulsive input is what is wanted, and a clear contrast to Schroeder.
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. Each line's angular frequency, amplitude and phase are folded to constants at export – the phase rule and the 2πh/T conversion run once here, not per sample – so every backend emits the same sum of K terms and there is no tunable parameter behind them.
The three HDL targets are simulation-only, as every time-driven
source in this library is: they take the current time from the testbench's
sim_time signal and evaluate the sines in real
arithmetic. That is a property of being time-driven rather than of the arithmetic
– Sine Wave is simulation-only for the same reason. If a synthesizable
excitation is what you need, the PRBS Generator is counter-driven and is
genuinely synthesizable.
Simulink bridge
None. Simulink's multisine source belongs to the System
Identification Toolbox, which is not installed here, so the mapping could not
be parity-verified even if it were written – and an unverified bridge is
what the catalog exists to prevent. The bridge reports the block rather than
dropping it silently, and it has no parity testbench, which is the
documented consequence of Support::None rather than a gap. Code
export verification still covers it across all ten languages.
Notes
- Algebraic in the state sense but time-driven: the output depends only on the current time, so the block holds no state a solver has to integrate. Each generated core keeps its own local sample counter rather than reading a global clock.
- The signal is exactly periodic in T, so averaging a measurement over whole periods is valid and is the usual way to lift the noise floor.
- The mean is zero whenever no harmonic number is 0, which is the normal case: every line integrates to zero over the base period.
Code facts#
| Fact | Value |
|---|---|
| registered type | System_Identification/Excitation/Multisine_Generator |
| family | System_Identification/Excitation |
| solver environment class | ICoreBlock_0_System_Identification_1_Excitation_2_Multisine_Generator |
| source | src/ICoreSDK/ICoreBlockLibrary/Blocks/System_Identification/Excitation/Multisine_Generator/ICoreBlock_0_System_Identification_1_Excitation_2_Multisine_Generator.cpp |
| header | src/ICoreSDK/ICoreBlockLibrary/Blocks/System_Identification/Excitation/Multisine_Generator/ICoreBlock_0_System_Identification_1_Excitation_2_Multisine_Generator.h |
| default size on canvas | 115 × 80 px |
| ports at insert | 0 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | out | ICoreDouble | — |
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 variable | Default | Simulink parameter |
|---|---|---|
Base Period (s) | 1 | — |
Harmonic Numbers | [1 2 3 5 7] | — |
Line Amplitudes | [1 1 1 1 1] | — |
Phase Rule | Schroeder%~%Zero~~Schroeder | — |
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.
Simulink bridge#
| support | Support::None |
| Simulink path | — |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
Caveat (shown to the user): Simulink's multisine source belongs to the System Identification Toolbox, which is not installed on this machine, so the mapping could not be parity-verified even if it were written. Re-create the excitation on the Simulink side with the same base period, harmonic numbers and amplitudes
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).
Multisine Generator — the frequency-domain excitation y(t) = SUM_k A_k * sin(omega_k * t + phi_k), omega_k = 2*pi * h_k / T
Energy lands exactly on the named harmonics of the base period and nowhere else, which is what makes it the right input for a frequency-response measurement. Schroeder phases keep the crest factor near that of a single sine, so a much larger amplitude fits inside the same peak excursion a plant will tolerate.
See the header for the settled HDL question (simulation-only, and why the row's baked-period suggestion does not survive contact with this tree) and for the Schroeder phase rule.
Sample results#
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/System_Identification__Excitation__Multisine_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).