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 Length – n, 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).
- Amplitude – A, 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#
| Fact | Value |
|---|---|
| registered type | System_Identification/Excitation/PRBS_Generator |
| family | System_Identification/Excitation |
| solver environment class | ICoreBlock_0_System_Identification_1_Excitation_2_PRBS_Generator |
| source | src/ICoreSDK/ICoreBlockLibrary/Blocks/System_Identification/Excitation/PRBS_Generator/ICoreBlock_0_System_Identification_1_Excitation_2_PRBS_Generator.cpp |
| header | src/ICoreSDK/ICoreBlockLibrary/Blocks/System_Identification/Excitation/PRBS_Generator/ICoreBlock_0_System_Identification_1_Excitation_2_PRBS_Generator.h |
| default size on canvas | 110 × 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 |
|---|---|---|
Register Length | 7 | — |
Amplitude | 1 | — |
Samples Per Chip | 1 | — |
Seed | 1 | — |
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 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#
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).