Имплементация вычисления БПФ методом Serial Commutator предложенной в данной научной статье.
Данная реализация построена по конвеерному принципу и позволяет синтезировать проект под любое количество отсчетов N_FFT (где N_FFT = power(2, k)).
- fft_sc - компонент верхнего уровня, для встраивания в проект
- reorder - компонент для перестановки данных между вычислительными стадиями
- out_reorder - компонент для приведения порядка следования данных к нормальному виду
- stage - вычислительная стадия FFT
- butterfly - операция "бабочка"
- proc_elem - вычислительный элемент
- rotator - компонент умножения данных на поворачивающие множители
- twid_idx_gen - генератор индексов доступа к массиву поворачивающих множителей
- twiddles_gen - массив поворачивающих множителей, полученный с помощью скрипта create_twiddles.py
Для подключения компонента fft_sc к проекту необходимо в qsf файле проекта добавить следующую строку:
set_global_assignment -name QIP_FILE path/to/fft_sc.qip
.
Компонент добавляется как часть библиотеки fft_sc_lib, поэтому в случае использования языка VHDL, эту библиотеку необходимо объявить, прежде чем подключать компонент fft_sc:
library fft_sc_lib;
...
fft_sc_inst : entity fft_sc_lib.fft_sc
generic map (
FFT_SIZE => FFT_SIZE -- Кол-во отсчетов FFT (FFT_SIZE = 2^k, где k = 4,5,6,...N)
)
port map (
clk => clk, -- Тактовая частота
din_re => din_re, -- Входные данные (вещественная часть)
din_im => din_im, -- Входные данные (мнимая часть)
din_valid => din_valid, -- Сигнал валидности входных данных
dout_re => dout_re, -- Выходные данные (вещественная часть)
dout_im => dout_im, -- Выходные данные (мнимая часть)
dout_valid => dout_valid -- Сигнал валидности выходных данных
);
Прежде чем начинать синтез (или симуляцию) проекта, необходимо, с помощью утилиты create_twiddles.py сгенерировать массив поворотных коэффициентов. При запуске утилиты, необходимо в нее передать следующие аргументы: количество отсчетов FFT (size) и путь где утилита должна создать файл twiddles_gen.sv. Пример для size=1024:
python create_twiddles.py --size=1024 --filepath=rtl
- Запустить Matlab
- Перейти в директорию sim
- Создать массив данных (in.txt) для подачи на вход компонента fft_sc.Для этого необходимо выполнить скрипт setdata.m.
- Запустить Modelsim
- Перейти в директорию sim/modelsim
- Запустить скрипт run_tb.tcl (
source ../run_tb.tcl
), предварительно поменяв в нем переменную QUARTUS_INSTALL_DIR - Дождаться окончания симуляции. По завершению симуляции Modelsim создаст файл out.txt, в котором записаны результаты расчета FFT
- Для просмотра результатов симуляции, выполнить в Matlab скрипт fftsc.m
На скриншоте показан результат симуляции Modelsim (период тактовой частоты 10 нс):
На скриншоте показаны результаты расчета FFT из входных данных (Figure 2) и FFT построенное из результатов симуляции (Figure 3). Видно, что присутствуют некоторые шумы, обусловленные ошибками округления:
На скриншоте показан результат вычисления влияния ошибок округления на результирующий спектр:
Вышеприведенные результаты симуляции получены при следующих параметрах:
- N_FFT = 1024
- Входной сигнал представлял собой две гармоники расположенные рядом друг с другом
- Амплитуда гармоник равна 8192
- Вносимые шумы во входном сигнале отсутствовали
Синтез проводился при N_FFT = 1024
Получающаяся при синтезе (N_FFT = 1024) максимальная тактовая частота равна 55 МГц. Что является далеко не впечатляющим параметром и не соответствует значениям из статьи. Но данного значения вполне достаточно для многих применений. В будущем необходимо заняться оптимизированием исходного кода для получения более высоких значений максимальной тактовой частоты.