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

Chirp Z Transform — Control Systems/Transforms

Control_Systems/Transforms/Chirp_Z_Transform · 1 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.

Chirp-Z Transform

Control Systems / Transforms

Evaluates the z-transform of the window on its input along a spiral contour: X[k] = Σₙ u[n]·a−n·wnk for k = 0 … M−1, which is MATLAB's czt(u, M, w, a). a is where the contour starts and w is the ratio between one point on it and the next; each is given as a magnitude and an angle rather than as a complex number.

The contour is the whole point. With |w| = 1 and an angle of −2π/M the contour is the unit circle and the block is the DFT. Make the angle smaller and it walks a short arc of that circle, so M points resolve a narrow band as finely as you like – a zoom the DFT cannot do, whose resolution is fixed at 2π/N. Take |w| ≠ 1 and it leaves the circle for a spiral into or out of the z-plane.

Ports

  • u – the window to transform, a vector: an [N,1] column or a [1,N] row, with N from 1 to 32. Entry n is u[n] in the sum above, oldest first.
  • Re – the real part of X, one entry per contour point, so M long and in the same orientation as the input.
  • Im – the imaginary part of the same X, the same size. Two real ports rather than one complex one, because an ICore signal carries doubles.

Parameters

  • Output Points – M, how many points of the contour to evaluate. A whole number from 1 to 32. It is independent of the window length: M may be smaller than N, equal to it, or larger.
  • Ratio Magnitude – |w|. Exactly 1 keeps the contour on a circle; less than 1 spirals outward from it and more than 1 inward, since the exponent carries a minus sign in the transform's own convention.
  • Ratio Angle (rad) – arg(w), the angle stepped between consecutive points. −2π/M is the DFT; a value of smaller magnitude zooms into a narrower band.
  • Start Magnitude – |a|, the radius the contour starts at. 1 starts on the unit circle.
  • Start Angle (rad) – arg(a), the angle it starts at. 0 starts at z = |a|, i.e. at DC when |a| = 1.
  • 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 M×N complex weights are structural and are inlined into the generated arithmetic: they follow from the parameters and from both lengths, and how many of them there are is what the emitted core is shaped by. Every target emits two real dot products per output entry and computes no power, sine or cosine at run time – those happened at export.

The three HDL targets are genuine synthesizable Q16.16: only multiplies and adds, accumulated at double width and shifted back once per entry. Whether that is useful is decided by the contour, not by the block: the weights carry |w|nk, and nk reaches (N−1)(M−1), so |w| = 0.97 over an 8-point window bottoms out at 0.9728 = 0.43 – far above the format's 1.5×10−5 quantum – while |w| = 0.8 over 32 points reaches 10−97 and that whole corner of the matrix quantizes to zero. Keep |w| near 1 in fixed point, or export to a software target.

Simulink bridge

No equivalent (Support::None). czt is a Signal Processing Toolbox MATLAB function, and the DSP System Toolbox's transform library carries FFT, IFFT, Magnitude FFT, DCT, IDCT, the two cepstra, the wavelet pair, Analytic Signal, the Short-Time FFTs and Zoom FFT – measured on the installed R2026a, and no chirp-z among them. Zoom FFT is the nearest thing and is a different algorithm (decimate-and-FFT rather than a contour). The bridge reports this block rather than dropping it, and it therefore carries no parity testbench; code export verification still covers it across all ten languages.

Notes

  • Algebraic, with no state. The whole window arrives on the port, so one step is one transform and nothing carries over.
  • Measured against R2026a. Over an 8-point window with M = 5, w = 0.97·e−0.7i and a = 1.05·e0.2i the weights reproduce czt to 1.3e−15, and the DFT special case matches fft to 7e−15.
  • N need not be a power of two, and M need not equal N. A sum has no radix.
  • No state space. The map is linear in the window, but a fixed matrix over N past samples is not an A/B/C/D pair evolving in time, so the block carries none and model reduction correctly declines to merge it.

Code facts#

FactValue
registered typeControl_Systems/Transforms/Chirp_Z_Transform
familyControl_Systems/Transforms
solver environment classICoreBlock_0_Control_Systems_1_Transforms_2_Chirp_Z_Transform
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Transforms/Chirp_Z_Transform/ICoreBlock_0_Control_Systems_1_Transforms_2_Chirp_Z_Transform.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Transforms/Chirp_Z_Transform/ICoreBlock_0_Control_Systems_1_Transforms_2_Chirp_Z_Transform.h
default size on canvas140 × 90 px
ports at insert1 in, 2 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleu
2outICoreDoubleRe
3outICoreDoubleIm

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
Output Points8—
Ratio Magnitude1—
Ratio Angle (rad)-0.78539816339744828—
Start Magnitude1—
Start Angle (rad)0—

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 Simulink equivalent. czt is a Signal Processing Toolbox MATLAB function, not a block, and the DSP System Toolbox transform library was searched on the installed R2026a rather than assumed: it carries FFT, IFFT, Magnitude FFT, DCT, IDCT, the two cepstra, DWT/IDWT, Analytic Signal, the Short-Time FFTs and Zoom FFT, and no chirp-z. Zoom FFT is the nearest name and is a different algorithm

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

Chirp-Z Transform -- the z-transform of a window on a spiral contour (MATLAB czt) X[k] = SUM over n of u[n] * a^(-n) * w^(n*k), k = 0 .. M-1

a is where the contour starts and w is the ratio between consecutive points on it. Both are complex; both arrive here as a MAGNITUDE and an ANGLE, so no configuration variable has to carry a complex number and no target has to do complex arithmetic to read one.

ONE MATRIX PRODUCT, TEN TIMES. a^(-n)*w^(n*k) depends on the parameters and the two lengths and never on the signal, so the M*N complex weights are derived once -- when the configuration is read and the input width is known -- and every target inlines them as two real dot products per output element. No emitted core computes a power, a sine or a cosine; it multiplies and adds.

⚠ MEASURED AGAINST R2026a rather than asserted. Over u = [0.9 -0.35 1.25 0.4 -0.8 0.15 0.55 -1.1] with M = 5, w = 0.97*exp(-0.7i) and a = 1.05*exp(0.2i), the weights derived here reproduce czt's five complex answers to 1.3e-15. The DFT special case was measured too: czt(x) with its own defaults and fft(x) agree to 7e-15, which is the identity the description's "reproduces the DFT" sentence rests on.

⚠ THE HDL TARGETS ARE GENUINE Q16.16 AND THE CONTOUR IS WHAT DECIDES WHETHER THAT IS USEFUL. The weights carry |w|^(n*k), and n*k reaches (N-1)*(M-1): at |w| = 0.97 over an 8-point window that is 0.97^28 = 0.43, comfortably above the format's 1.5e-5 quantum, while at |w| = 0.8 and 32 points it is 1e-97 and every weight in the far corner of the matrix quantizes to zero. That is a property of the CONTOUR, not of the block, and the description says so rather than hiding it behind a "simulation only" label the arithmetic does not need.

ALGEBRAIC: the whole window is presented on the input port, so one step completes one transform and nothing is held between samples. No state space -- the map is linear in the input, but it is a fixed matrix over a WINDOW rather than an A/B/C/D pair evolving in time, which is the same reason Savitzky-Golay carries none.

Sample results#

Chirp Z Transform — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleChirp Z Transform — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-202012345t (s)in ICoreDouble-Out-0out ICoreDouble-Out-0 [8x1] entry 0out ICoreDouble-Out-1 [8x1] entry 0
tin ICoreDouble-Out-0out ICoreDouble-Out-0 [8x1] entry 0out ICoreDouble-Out-1 [8x1] entry 0
0-2[-2, -2, -2, -2]…[0, 0, 0, 0]…
0.40.5[0.5, 0.5, 0.5, 0.5]…[0, 0, 0, 0]…
0.8-2[-2, -2, -2, -2]…[0, 0, 0, 0]…
1.20.5[0.5, 0.5, 0.5, 0.5]…[0, 0, 0, 0]…
1.6-2[-2, -2, -2, -2]…[0, 0, 0, 0]…
20.5[0.5, 0.5, 0.5, 0.5]…[0, 0, 0, 0]…
2.4-2[-2, -2, -2, -2]…[0, 0, 0, 0]…
2.80.5[0.5, 0.5, 0.5, 0.5]…[0, 0, 0, 0]…
3.2-2[-2, -2, -2, -2]…[0, 0, 0, 0]…
3.60.5[0.5, 0.5, 0.5, 0.5]…[0, 0, 0, 0]…
4-2[-2, -2, -2, -2]…[0, 0, 0, 0]…
4.40.5[0.5, 0.5, 0.5, 0.5]…[0, 0, 0, 0]…
4.8-2[-2, -2, -2, -2]…[0, 0, 0, 0]…
5.20.5[0.5, 0.5, 0.5, 0.5]…[0, 0, 0, 0]…

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 Chirp_Z_Transform --steps 60 · data docs/generated/samples/Control_Systems__Transforms__Chirp_Z_Transform.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).