Xilinx
HLS
Block Preview

Introduction

The Goertzel Multi (tone bank) block monitors several frequencies at once, each as an independent DFT bin, but reuses one time-shared multiplier across all of them rather than instantiating a separate resonator per tone. It emits one POWER_b output pin per monitored frequency plus a shared VALID_OUT.

Each bin runs the same second-order Goertzel resonator as the single-tone block:

      s[n] = x[n] + 2*cos(w_b)*s[n-1] - s[n-2]        (w_b = 2*pi*k_b/N)
  

but the per-sample recurrence is iterated one bin per system clock: between two input samples the core steps through all NUM_FREQS bins in turn. Because of this the block needs at least NUM_FREQS system clocks per input sample, controlled by the SysClk / DataClk ratio (ClockRatio >= number of frequencies). Resource cost is a small fixed number of multipliers regardless of how many tones are monitored, versus one (real) or two (complex) multipliers per tone for a parallel bank.

Goertzel Designer

Every frequency is snapped to its nearest DFT bin k_b = round(N*f_b/Fs); all bins share the same block length N, so they share the same resolution Fs/N and update together every N samples.

For a single tone use Component_Goertzel; for a per-sample sliding output use Component_GoertzelSliding.

Pin Description

IN Input InputSize bit BIT VECTOR
Real input sample. Present only when SignalType = Real. Signed, InputSize bits.
SAMPLE_IN Input 1 bit BIT
New-sample strobe. Pulse high for one clock per input sample. There must be at least NUM_FREQS system clocks between pulses (ClockRatio >= number of tones) so the time-shared core can step every bin.
CLK Input 1 bit BIT
System clock input. Default: Acquisition clock. Runs ClockRatio times faster than the data rate.
Default: Default Board Clock
RESET Input 1 bit BIT
HLS synchronous reset (ap_rst). Clears every bin’s states and the block counter. Default: Global reset.
Default: Default Board Reset
VALID_OUT Output 1 bit BIT
Pulses high for one clock when a block completes; all POWER_b outputs are refreshed together on that pulse (every N-th SAMPLE_IN).
IN_I InputSize bit
In-phase (I) input sample. Present only when SignalType = Complex. Signed, InputSize bits.
IN_Q InputSize bit
Quadrature (Q) input sample. Present only when SignalType = Complex. Signed, InputSize bits.
POWER_b 2*(InputSize + ceil(log2 N) + 2) + 4 bit
One output per monitored tone (POWER_0, POWER_1, …), in the order the frequencies were added in the designer. Carries that bin’s power |X(k_b)|^2, updated every N samples and held between updates. Each is 2(InputSize + ceil(log2 N) + 2) + 4* bits.

Properties

Property window

Signal Type SignalType

Real: one input channel. Complex: I/Q input.

Real: single input channel IN. Complex: I/Q input IN_I / IN_Q (true one-sided bins; two recurrences per tone). Default Real.

Default: Real

Options: Real Complex

Input Bit Width InputSize

Bit width of the input sample(s).

Bit width of each signed input sample. Range 4..32, default 16.

Default: 16

Options: 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

Coefficient Bit Width CoefSize

Bit width of the cos/sin coefficients.

Bit width of the signed cos/sin coefficients (scale 2^(CoefSize-2)). One of 12, 14, 16, 18, 20, 24. Default 18.

Default: 18

Options: 12 14 16 18 20 24

Block Length N BlockN

DFT size: resolution Fs/N, latency N samples.

Block length = DFT size N, shared by all tones. Resolution Fs/N, measurement latency N samples. One of 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192. Default 256.

Default: 256

Options: 16 32 64 128 256 512 1024 2048 4096 8192

Data Rate Fs (Hz) Fs

Sample rate of the data feeding this block.

Sample rate (Hz) of the data feeding this block. Used to map each target frequency to its DFT bin k = round(N*f/Fs). Default 1000000.

Default: 1000000

SysClk / DataClk ClockRatio

System clocks per input sample. Must be >= number of frequencies.

System clocks per input sample (SysClk / DataClk). Must be >= the number of monitored frequencies, because the time-shared core steps one bin per system clock. One of 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024. Default 16.

Default: 16

Options: 2 4 8 16 32 64 128 256 512 1024

Frequencies (JSON, use editor) GoertzelProject

The monitored frequencies + coefficients, produced by the Goertzel Designer.

Hidden JSON blob produced by the Goertzel Designer holding the monitored-frequency list, coefficients and hardware config. Managed by the visual designer, not edited by hand. If empty (no tones added) the block fails to compile.

Usage

Time-shared resonator bank

The Goertzel algorithm computes a DFT bin as a second-order IIR resonator (see the single-tone block). This variant keeps a small state array s1[b], s2[b] (plus s1q/s2q in complex mode) for every monitored bin b and, instead of updating them all in parallel, walks the array one entry per system clock:

  • On each SAMPLE_IN pulse the new input sample is latched and the bin index is reset to 0.
  • On each following system clock one bin b is advanced with its own coefficient 2*cos(w_b) (and sin(w_b) for complex).
  • After all NUM_FREQS bins have been stepped the core waits for the next sample.

So one input sample is fully processed in NUM_FREQS system clocks; the rest of the ClockRatio window is idle. This is why the design constraint is ClockRatio >= NUM_FREQS (enforced at compile time — otherwise the plugin raises an error telling you to raise SysClk/DataClk or drop tones).

Per-bin math

Identical to the single-tone Goertzel, per bin. Real (SignalType = Real): one recurrence, power from the last two states

      power_b = s1_b^2 + s2_b^2 - 2*cos(w_b)*s1_b*s2_b
  

Complex (SignalType = Complex): two recurrences per bin sharing the bin’s cos/sin, giving the one-sided complex bin

      Xr = s1i - cos(w_b)*s2i - sin(w_b)*s2q
    Xi = s1q - cos(w_b)*s2q + sin(w_b)*s2i
    power_b = Xr^2 + Xi^2
  

DFT-bin snapping and resolution

Each requested frequency is mapped to an integer bin:

      k_b = round(N * f_b / Fs)
    df  = Fs / N                     (shared resolution / bin spacing)
  

All tones use the same N, so they share the same selectivity (a ~Fs/N-wide main lobe per bin) and complete together. Choose distinct bins spaced by at least one Fs/N step for clean separation.

Coefficients

For each bin the plugin quantises cos(w_b) and sin(w_b) to signed CoefSize bits (scale 2^(CoefSize-2)) and writes them into the generated goertzel_cos.inc / goertzel_sin.inc coefficient ROMs; the recurrence uses 2*cos(w_b).

Generated top and pins

The HLS worker goertzel_multi_core() is fixed; the plugin generates the top goertzel_multi() with one explicit power_b output port per frequency so the diagram symbol grows one POWER_b pin per monitored tone. Adding or removing tones in the designer changes the pin count and triggers a redesign.

Bit widths

Data is signed two’s complement.

  • IN / IN_I / IN_Q : signed InputSize bits.
  • Each POWER_b : POW_SIZE = 2*STATE_SIZE + 4 bits, where STATE_SIZE = InputSize + ceil(log2 N) + 2.

Timing and handshake

  • #pragma HLS PIPELINE II=1, ap_ctrl_none : free-running.
  • SAMPLE_IN pulses once per input sample; there must be at least NUM_FREQS system clocks between pulses (ClockRatio >= NUM_FREQS).
  • VALID_OUT pulses one clock when a fresh block completes; at that point every POWER_b is simultaneously updated. Between updates each POWER_b holds its last value.
  • Measurement latency is N samples (all tones update together).

Reset

RESET (ap_rst) clears every bin’s states and the sample counter; the states are also cleared at the end of each block.

Visual designer

This block is configured through the Goertzel Designer (a WebView2 graphical tool), not the property grid. Double-click the block to open it. In multi mode you set the hardware target (signal type, input/ coefficient bits, block length N, Fs and the SysClk / DataClk ratio), then add each frequency to monitor with the “Add tone” control. The tool snaps every tone to its nearest DFT bin k = round(N*f/Fs), overlays all tones on the frequency-selectivity plot (each bin’s Goertzel main lobe, ~Fs/N wide, showing what it integrates) and shows a live resource / result estimate: resolution Fs/N, -3 dB width, integration time, output bits, tones-vs-max (the ClockRatio budget) and multiplier count. Save & Close writes the tone list and quantised coefficients into the block, creating one POWER_b pin per tone.

Typical applications

  • DTMF / multi-tone signalling decode (all keypad tones at once).
  • Multi-pilot monitoring in a modulated carrier.
  • Sparse spectral analysis: a handful of lines instead of a full FFT.
  • Cheap tone bank where DSPs are scarce and the data rate leaves spare system-clock cycles.

Resources & Timing

  • Latency: 1 clock per bin step; a new POWER set every N samples (block latency = N samples)

  • Throughput: 1 input sample every ClockRatio system clocks; ClockRatio >= number of tones

Implemented with Vitis HLS. A single time-shared multiplier services all tones (a small fixed multiplier count independent of the number of frequencies), trading latency (NUM_FREQS system clocks per sample) for area versus a parallel resonator bank. Coefficient ROMs (goertzel_cos.inc / goertzel_sin.inc) hold one quantised cos (and sin, complex) per bin. Best when DSPs are scarce and the data rate leaves spare system-clock cycles; if you need one tone per clock with no ratio constraint, instantiate several single-tone Goertzel blocks instead.