11 · FFT: Altera's IP vs our own

Can you use Altera's FFT IP on the DE10-Lite, and what does it cost compared with writing your own? Both run here on the same 256-point signal, and the PC checks both against numpy.

Verified on the board 2026-10-24 Quartus Prime Lite 17.1 No shield needed Skills: use-ip-library, compute-fft
Download fft.qar (full project, with the generated IP)

The repo keeps the full project (.qar, plus the sources here) but no prebuilt bitstream: one build (a few minutes) makes the .sof on your computer.

The FFT IP is a licensed Altera core. Quartus Prime Lite compiles it in OpenCore Plus evaluation mode: the build makes fft_time_limited.sof instead of fft.sof, and the design runs only while the programmer stays connected ("tethered": quartus_pgm keeps running) or for a limited time. Our own FFT has no such limit.

The result

256-point complex FFT, 16-bitAltera FFT II IP
Burst, 1 engine, block floating point
Our fft_r2
radix-2, 1 butterfly, /2 every stage
Accuracy: signal-to-error vs numpy66.9 dB (max error 188)56.3 dB (max error 786)
Strongest bins found10, 37, 85 (the three tones)10, 37, 85
Time for one FFT at 50 MHz1,637 clocks = 33 µs6,145 clocks = 123 µs
Logic cells1,698398
Memory bits (M9K blocks)9,472 (3)12,288 (3)
Multiplier elements (9-bit)88
Licenseevaluation in Lite (time-limited .sof)none

Reading it: the IP is about 4 times bigger in logic, 4 times faster, and 10 dB more accurate (block floating point scales only when the numbers need it; our FFT halves at every stage and loses bits on a signal that never needed it). Our FFT's 56 dB is about 9 good bits on a 16-bit signal: plenty for a spectrum display, not for audio analysis. Both ran on the board; our FFT gives exactly the same numbers in simulation and on the board.

Block diagram

input ROMinput.hex, 256 × 32 fft256 (FFT II IP)Avalon-ST sink / source+ block exponent fft_r2 (ours)1 RAM, twiddle ROM,1 butterfly / 5 clocks result RAM result RAM dumpline_printer, jtag_uart PCnumpy check

Using an IP from the library, without the GUI

Altera's IP cores live in C:\intelFPGA_lite\17.1\ip\altera. Each has a _hw.tcl file whose add_parameter lines are the settings. ip-generate builds a configured copy into your project:

python examples/11_fft/ip/generate_fft_ip.py
→ ip-generate --component-name=altera_fft_ii --output-name=fft256 --file-set=QUARTUS_SYNTH
    --component-parameter=length=256 --component-parameter=data_flow=Burst ... → ip/fft256/fft256.qip

Add the .qip to the project (src/extra.qsf: set_global_assignment -name QIP_FILE ip/fft256/fft256.qip) and instantiate fft256. When a setting is not allowed for the chosen architecture, ip-generate prints an Error line saying why (here: Burst needs Bi-directional and Natural output order).

Talking to the FFT IP

Our FFT in brief

src/fft_r2.sv: the 256 samples are written into one RAM at bit-reversed addresses; then 8 stages × 128 butterflies, each reading two values and a twiddle (cos, sin in Q15 from assets/twiddle.hex), multiplying with 4 multipliers, and writing back (a + W·b)/2 and (a − W·b)/2. Halving every stage makes overflow impossible; the price is precision. Ideas to make it better: halve only when a stage would overflow (block floating point), or two butterflies in parallel with a second RAM.

Bugs met on the way (each now a gotcha)

Run it

python scripts/de10.py build examples/11_fft
python scripts/de10.py program examples/11_fft    (keeps running: tethered; stop it with Ctrl+C)
python scripts/de10.py send R 8 > logs/fft_dump.txt                    (in a second terminal)
python examples/11_fft/sim/fft_data.py check logs/fft_dump.txt

Build it yourself

python examples/11_fft/sim/fft_data.py make          # input.hex, twiddle.hex
python examples/11_fft/ip/generate_fft_ip.py         # the IP
python scripts/new_project.py examples/11_fft fft_top --lib print seg7
python scripts/de10.py build examples/11_fft

Test without the board

python scripts/sim.py examples/11_fft/sim/tb_fft_r2.sv
python examples/11_fft/sim/fft_data.py check examples/11_fft/sim/diy_dump.txt     → DIY 56.3 dB, bins 10 37 85

Files

FileWhat
src/fft_top.svFeeds both FFTs, collects, sends to the PC
src/fft_r2.svOur radix-2 FFT
ip/generate_fft_ip.py, ip/fft256/The IP generation command and its output
sim/fft_data.pyTest signal, twiddles, accuracy check against numpy
sim/tb_fft_r2.svUnit test of our FFT