Generated reference › IFFT — Control Systems/Transforms
kind: generated#block#control-systems-transforms

IFFT — Control Systems/Transforms

Control_Systems/Transforms/IFFT · 2 input / 2 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.

IFFT

Control Systems / Transforms

The complex inverse discrete Fourier transform of the spectrum on its inputs, which is MATLAB's ifft(X): u[n] = (1/N)·Σₖ X[k]·e+2πi·kn/N for n = 0 … N−1.

A spectrum is complex on both sides, so the block has four vector ports: the real and imaginary parts in, and the real and imaginary parts of the reconstructed window out. Feeding it the two outputs of the FFT block returns the original window on Re, with Im at rounding noise.

Ports

  • Re (input) – the real part of the spectrum X, a vector: an [N,1] column or a [1,N] row, N from 1 to 32. Entry k is Re(X[k]).
  • Im (input) – the imaginary part of the same X, and it must be the same size and orientation as Re. Wire a zero constant here to invert a purely real spectrum.
  • Re (output) – the real part of the reconstructed window, N long, in the input's orientation.
  • Im (output) – its imaginary part, the same size. For a conjugate-symmetric spectrum this is zero to within rounding, and reading it is the cheapest check that the spectrum was symmetric.

Parameters

  • Scaling – what multiplies the sum.
    • 1/N (ifft) – the inverse transform exactly as ifft defines it, so that IFFT after FFT is the identity. The default.
    • None – the same sum left unscaled, N times larger. Use it when the forward transform already carried the 1/N, so that exactly one of the two does.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

N is not a parameter: it is the width of the input ports, which must agree with each other.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text.

The N×N twiddle pairs are structural and are inlined into the generated arithmetic, so every target emits four products per term – two accumulations, each reading both inputs – and computes no sine or cosine at run time.

The three HDL targets are genuine synthesizable Q16.16: only multiplies and adds, accumulated at double width and shifted back once per entry. With the default 1/N scaling every twiddle has magnitude at most 1/N, which keeps the accumulation comfortably inside the format.

Simulink bridge

No equivalent a bridge can write (Support::None), and the reason is about the wire rather than the block. dspxfrm3/IFFT exists and computes the same transform – simulated on an 8-point complex frame, it agreed with ifft exactly – but it takes its whole spectrum on one complex port, while this block reads the real and imaginary parts on two real ports because an ICore signal carries doubles. There is no port-to-port mapping for the bridge to write. In Simulink, feed dspxfrm3/IFFT through simulink/Math Operations/Real-Imag to Complex on the way in and Complex to Real-Imag on the way out. The bridge reports the block rather than dropping it, and code export verification still covers it across all ten languages.

Notes

  • Algebraic, with no state. The whole spectrum arrives on the ports, so one step is one transform and nothing carries over.
  • Measured against R2026a. The coefficients reproduce ifft to 5.6e−17 on a spectrum whose imaginary part is zero and to 1.1e−16 on one whose two halves are independent – the case that reaches the cross terms – and dspxfrm3/IFFT simulated on an 8-point complex frame agreed with ifft exactly.
  • Both inputs must be the same size. A mismatch is reported by name once the port sizes have settled rather than silently padded.
  • Four products per term. Both operands are complex, so the cross terms −Xi·sin and +Xi·cos are part of the answer; a core that drops them is right only while the imaginary input is zero.
  • A direct sum, not a radix-2 algorithm. N need not be a power of two, and the cost is N² products; the 32-entry limit exists because those products are unrolled into the exported core.
  • No state space. A fixed matrix over N presented samples is not an A/B/C/D pair evolving in time, so model reduction correctly declines to merge it.

Code facts#

FactValue
registered typeControl_Systems/Transforms/IFFT
familyControl_Systems/Transforms
solver environment classICoreBlock_0_Control_Systems_1_Transforms_2_IFFT
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Transforms/IFFT/ICoreBlock_0_Control_Systems_1_Transforms_2_IFFT.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Transforms/IFFT/ICoreBlock_0_Control_Systems_1_Transforms_2_IFFT.h
default size on canvas130 × 100 px
ports at insert2 in, 2 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleRe
2inICoreDoubleIm
3outICoreDoubleRe
4outICoreDoubleIm

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
Scaling1/N (ifft)%~%None~~1/N (ifft)—

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): no single-block equivalent, and the reason is the WIRE rather than the block. dspxfrm3/IFFT exists in the DSP System Toolbox and computes the same transform -- simulated on an 8-point complex frame, it agreed with MATLAB's ifft exactly -- but it takes its whole spectrum on ONE COMPLEX port, while this block reads the real and imaginary parts on two real ports because an ICore signal carries doubles. There is no port-to-port mapping to write. In Simulink, put simulink/Math Operations/Real-Imag to Complex in front of dspxfrm3/IFFT and Complex to Real-Imag after it. See the FFT block for the forward half

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

IFFT -- the complex inverse discrete Fourier transform of a spectrum (MATLAB ifft) u[n] = (1/N) * SUM over k of X[k] * exp(+2*pi*i*k*n/N), n = 0 .. N-1

Four vector ports: Re and Im in, Re and Im out. A spectrum is complex on both sides, and an ICore wire carries doubles.

TWO SIGNS AND A SCALE ARE THE WHOLE DIFFERENCE FROM THE FFT BLOCK: the exponent is positive and the sum is divided by N. The modular angle reduction, the unrolled products and the accumulation order are the forward block's, deliberately, so the two files read side by side.

⚠ FOUR PRODUCTS PER TERM, NOT TWO, because both operands are complex: Re += Xr*cos - Xi*sin Im += Xr*sin + Xi*cos Dropping the cross terms gives an answer that is right whenever the imaginary input is zero and wrong the moment it is not -- which a rig driving both inputs from one shared waveform would never reach. The rig here drives them from INDEPENDENT windows for exactly that reason.

⚠ THE ANGLE IS REDUCED MODULO N BEFORE THE TRIG CALL, as in the forward block: k*n reaches (N-1)^2 = 961 at the longest window, and a cosine of ~6000 radians has already lost most of its low bits to argument reduction.

⚠ MEASURED AGAINST R2026a rather than asserted. The coefficients here were run through a stub harness on the same vectors a MATLAB batch was given: over an 8-point spectrum with a ZERO imaginary part they reproduce ifft() to 5.6e-17, and over one with an INDEPENDENT imaginary window -- the case that reaches the cross terms at all -- to 1.1e-16. Separately, dspxfrm3/IFFT was SIMULATED on an 8-point complex frame and agreed with ifft() EXACTLY.

ALGEBRAIC: the whole spectrum is presented on the input ports, so one step completes one transform and nothing is held between samples. No state space -- the map is linear in the inputs, but a fixed matrix over a WINDOW is not an A/B/C/D pair evolving in time.

Sample results#

IFFT — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleIFFT — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-202012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0out ICoreDouble-Out-1
tin ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0out ICoreDouble-Out-1
0-2-2-2-2
0.40.50.50.50.5
0.8-2-2-2-2
1.20.50.50.50.5
1.6-2-2-2-2
20.50.50.50.5
2.4-2-2-2-2
2.80.50.50.50.5
3.2-2-2-2-2
3.60.50.50.50.5
4-2-2-2-2
4.40.50.50.50.5
4.8-2-2-2-2
5.20.50.50.50.5

Every 4th of 60 samples, from the table stimulus.

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)0 … 1
rampRamp: slope 1 from t = 00 … 5.9
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias-1 … 0.9996
stepStep: 0 -> 1 at t = 1 s0 … 1

Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample

Category static · sample time 0.1 · 60 steps · commit 3c100aff6f27235305db4ad4d572f32e342718ad · produced by docsSample --out <folder> --blocks DCT IDCT FFT IFFT --steps 60 · data docs/generated/samples/Control_Systems__Transforms__IFFT.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).