Convolution — Control Systems/Correlation And Convolution
Control_Systems/Correlation_And_Convolution/Convolution · 2 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.
Convolution
Control Systems / Correlation And Convolution
Convolves the last NA samples of one stream with the last NB
samples of another, every sample:
y[n] = Σk a[k]·b[n−k], a vector of
NA + NB − 1 entries. It is the streaming counterpart of MATLAB's
conv applied to the two windows.
Both operands are signals. Nothing in the arithmetic is a constant, so none of the NA×NB products can be folded away at export – which is what separates this block from Discrete FIR Filter, whose second operand comes from configuration.
Ports
- a – the first stream. Scalar; the block keeps its own window of the last NA samples – see Notes.
- b – the second stream. Scalar, with its own window of the last NB samples.
- y – the convolution of the two windows, a column of NA + NB − 1 entries. Its size follows from the two window lengths alone and does not depend on the inputs' values.
Parameters
- Window Length A – NA, how many samples of a take part. A whole number from 1 to 32. The bound is a code-size bound: both windows are unrolled in every target and the emitted work is their product.
- Window Length B – NB, the same for b. The two need not be equal, and the output grows with their sum.
- 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 two window lengths are structural: they decide how many multiplies the exported core contains and how wide its output is, which no runtime parameter can change, so they are baked in at export time rather than offered as tunable parameters. Re-export after changing either.
The three HDL targets are genuine synthesizable Q16.16: two shift registers and a fixed multiply-accumulate tree, with every product accumulated at full width and shifted back once per output entry rather than per term.
Simulink bridge
No equivalent (Support::None). The Signal Processing
Toolbox ships no Simulink library at all. DSP System Toolbox does have a
Convolution block, and it is a different shape: it convolves two
vector-valued inputs and takes both lengths from those inputs' dimensions,
having no length parameter of its own, so this block's two window lengths have
nothing to map onto. The bridge reports this block rather than dropping it
silently, and it therefore has no parity testbench. Code export
verification still covers it across all ten languages.
Notes
- Stateful, and discrete by nature
(
setDiscreteOnlyBlock(true)): both windows advance once per sample. - Oldest-first is the published order. a[0] is the oldest sample
still in the window and a[NA−1] the newest, so the windows read as
segments of the signal in time order and the result is what
convreturns for those segments. - The windows are zero-prefilled, and the zeros count. Before the
windows have filled, their initial zeros take part in the sum, so the first
max(NA, NB)−1 outputs of a run are a startup transient rather than a
convolution of real data. MATLAB's
convis a batch function with both vectors in hand and has no transient; a streaming block cannot avoid one. - Verified against MATLAB. On a = [0.7 −1.3 0.45 2.1 −0.6] against
b = [−0.9 0.25 1.7 −0.35 0.8], this block's arithmetic and R2026a's
convagree to the last unit in the last place on all nine entries. - Scalar inputs. Each input is one channel with its own window; a vector input is refused rather than convolving the first element and dropping the rest.
- No state space. The block is bilinear rather than linear – it multiplies two signals together – so it carries no A/B/C/D pair and model reduction correctly declines to merge it.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Correlation_And_Convolution/Convolution |
| family | Control_Systems/Correlation_And_Convolution |
| solver environment class | ICoreBlock_0_Control_Systems_1_Correlation_And_Convolution_2_Convolution |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Correlation_And_Convolution/Convolution/ICoreBlock_0_Control_Systems_1_Correlation_And_Convolution_2_Convolution.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Correlation_And_Convolution/Convolution/ICoreBlock_0_Control_Systems_1_Correlation_And_Convolution_2_Convolution.h |
| default size on canvas | 132 × 80 px |
| ports at insert | 2 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 | in | ICoreDouble | a |
| 2 | in | ICoreDouble | b |
| 3 | out | ICoreDouble | y |
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 |
|---|---|---|
Window Length A | 8 | — |
Window Length B | 8 | — |
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): no Simulink equivalent: conv() is a MATLAB function and the Signal Processing Toolbox ships no Simulink library at all. DSP System Toolbox's Convolution block is a different shape -- it convolves two VECTOR inputs and takes both lengths from their dimensions, having no length parameter of its own, so this block's two window lengths have nothing to map onto. Reported rather than dropped, and it carries no parity testbench
Catalog contract: src/ICoreBlocks/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).
Convolution -- the linear convolution of two windowed streams, y = conv(a, b) TWO SIGNALS, NOT A SIGNAL AND A COEFFICIENT SET. Both operands are live: the block keeps the last NA samples of one input and the last NB samples of the other, and every sample it recomputes all NA + NB - 1 entries of their convolution. Nothing can be folded away at export time, because there is no constant in the arithmetic -- which is exactly what separates this block from Discrete FIR Filter, whose second operand comes from configuration.
MEASURED AGAINST MATLAB R2026a rather than asserted. On a = [0.7 -1.3 0.45 2.1 -0.6] and b = [-0.9 0.25 1.7 -0.35 0.8], conv(a, b) in R2026a and this block's arithmetic agree to the last unit in the last place on all nine entries. The probe is recorded in the notes of the toolbox-blocks plan, Family B.
⚠ THE WINDOWS ARE ZERO-PREFILLED AND THE ZEROS COUNT -- the convention Detrend and Moving Median carry, the latter measured against Simulink. The first max(NA, NB) - 1 outputs of a run are a startup transient. MATLAB's conv() has both whole vectors in hand and has no transient at all; a streaming block cannot avoid one, so the choice is which one to document.
⚠ OLDEST-FIRST IS THE PUBLISHED ORDER; NEWEST-FIRST IS THE STORAGE ORDER. a[0] is the oldest sample still in the window, so the two windows read as segments of the signal in time order and the answer is MATLAB's. The shift register beneath holds the newest sample at index 0, because that is the cheapest shift in all ten targets. The two orders meet in exactly one expression per backend and nowhere else.
Sample results#
The same rig also ran:
| Stimulus | What it is | Output range |
|---|---|---|
impulse | Impulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair) | 0 … 1 |
ramp | Ramp: slope 1 from t = 0 | 0 … 27.04 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | 0 … 0.9991 |
table | Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample | 0 … 9 |
Plotted: step — Step: 0 -> 1 at t = 1 s
Category dynamic · sample time 0.1 · 60 steps · commit 3c100aff6f27235305db4ad4d572f32e342718ad · produced by docsSample --out <folder> --blocks Convolution Circular_Convolution Convolution_Matrix Deconvolution Cross_Correlation Cross_Covariance --steps 60 · data docs/generated/samples/Control_Systems__Correlation_And_Convolution__Convolution.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).