Generated reference › PRBS Generator — System Identification/Excitation
kind: generated#block#system-identification-excitation

PRBS Generator — System Identification/Excitation

System_Identification/Excitation/PRBS_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.

PRBS Generator

System Identification / Excitation

A maximum-length pseudo-random binary sequence: a linear feedback shift register of n bits, clocked once every Samples Per Chip samples, whose output bit is mapped to ±Amplitude. The sequence repeats with period 2n−1 chips and its spectrum is flat up to the chip rate.

This is the standard excitation for system identification: unlike random noise it is deterministic and exactly repeatable – the same seed gives the same sequence on every run and in every exported language – and unlike a chirp it excites the whole band at once rather than sweeping it.

Ports

  • Output – a [1,1] scalar, always either +Amplitude or −Amplitude. It is a source: there is no input.

Parameters

  • Register Lengthn, the number of bits, from 2 to 16. The sequence period is 2n−1 chips, so n is the knob that sets how long the excitation runs before it repeats: a run shorter than one period sees a sequence that never comes back round, and a run much longer than one period sees the same data again. The feedback taps for each n are a baked table of primitive polynomials (see Notes).
  • AmplitudeA, the magnitude of both levels; the output is ±A and never zero. Set it to the largest perturbation the plant tolerates: identification quality follows the signal-to-noise ratio, and a PRBS puts all of its energy at the two levels.
  • Samples Per Chip – how many solver samples each chip is held for, a whole number ≥ 1. This is the block's bandwidth control: the chip rate is the solver rate divided by this, and the excitation is flat to roughly that rate. Raise it to concentrate energy at lower frequencies when the plant is slow.
  • Seed – the register's initial contents. Any whole number is accepted; it is folded into [1, 2n−1], so it can never be the all-zero state, which a linear feedback register can never leave. Changing the seed rotates the starting point within the same sequence – it does not give a different sequence.
  • 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. The register length, tap positions, amplitude, chip length and seed are all baked into the generated code as literals; there is no tunable parameter, because changing any of them changes the sequence rather than scaling it.

⚠ The three HDL targets are genuinely synthesizable, which most blocks that carry state in this library are not. The register is an integer and every divisor is a constant power of two, so the emitted datapath is a shift register with a small XOR tree – there is no transcendental, no division by a signal and no real arithmetic anywhere.

Because the register is exact, the emitted bit sequence matches the in-app run sample for sample and the HDL error does not accumulate over a run. What remains is one rounding of Amplitude into Q16.16 at the output: a constant relative error of the same size on every sample, whatever the register length or chip rate. At an amplitude of 0.65 that is 0.649993896484375, i.e. 9.39×10−6 – which is exactly what the three HDL rows report. A residual that grows with the run would mean something quite different and is worth investigating; this one is the format, not the block.

Every backend emits the recursion in integer arithmetic rather than with bitwise operators – a bit is floor(s/2p) − 2·floor(s/2p+1) and an XOR of two bits is a + b − 2ab – because four of the ten targets have no bitwise XOR on a numeric type worth relying on. The ten sequences are therefore bit-identical rather than merely close.

Simulink bridge

None. Simulink's PRBS source belongs to the System Identification Toolbox, which is not installed here, so a mapping could not be parity-verified even if it were written – and an unverified bridge is exactly 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

  • Stateful and inherently discrete: the register advances once per chip, so the block declares setDiscreteOnlyBlock(true) – there is no derivative for a continuous solver to integrate.
  • The taps are verified, not merely cited. Published tap tables are written for a left-shifting register. Transcribed unchanged into a right-shifting one they omit the bit-0 tap, and the register then drains to zero and sticks – a period of 2 instead of 2n−1. Every register length here was checked by walking the whole sequence and confirming it visits exactly 2n−1 states before returning to its seed.
  • The sequence is balanced by construction: over one full period it takes the +A level 2n−1 times and the −A level 2n−1−1 times, so its mean is one chip's worth of A per period and tends to zero as n grows.

Code facts#

FactValue
registered typeSystem_Identification/Excitation/PRBS_Generator
familySystem_Identification/Excitation
solver environment classICoreBlock_0_System_Identification_1_Excitation_2_PRBS_Generator
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/System_Identification/Excitation/PRBS_Generator/ICoreBlock_0_System_Identification_1_Excitation_2_PRBS_Generator.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/System_Identification/Excitation/PRBS_Generator/ICoreBlock_0_System_Identification_1_Excitation_2_PRBS_Generator.h
default size on canvas110 × 80 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
Register Length7
Amplitude1
Samples Per Chip1
Seed1

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 PRBS 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 sequence on the Simulink side with the same register length, seed and chip length

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).

PRBS Generator — maximum-length pseudo-random binary sequence, the identification excitation bit = b[0] the chip leaving the register fb = b[p0] XOR b[p1] XOR ... tapped feedback (positions from tapPositions()) s = floor(s/2) + fb * 2^(n-1) shift right, feedback into the top bit y = Amplitude * (2*bit - 1) bit 1 -> +A, bit 0 -> -A

Held for "Samples Per Chip" samples, so the chip rate — and with it the bandwidth of the excitation — is set independently of the solver rate.

See the header for the two decisions that shape every generator below: the recursion is spelled in INTEGER ARITHMETIC (no target needs a bitwise XOR), and the emitted register is always seedRegister() rather than the live m_reg.

Sample results#

PRBS Generator — No input: the block run alonePRBS 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/System_Identification__Excitation__PRBS_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).