суббота, 12 июля 2014 г.

снова CORDIC - заключительная

Возвращаюсь к старой теме. Самый хороший результат, который был получен: относительная погрешность = 4 при количество итераций N = 16, при 16-битных значениях квадратур и 20-битном значении фазы. Можно ли улучшить результат? Да. Будем использовать тот же прием, что и при ДПФ.
Абсолютная погрешность при множестве итераций алгоритма CORDIC накапливалась при операции сдвига, где отбрасывалась дробная часть. Да и проблема со сдвигом отрицательной единицы вносила погрешность в расчеты. Поэтому модифицируем алгоритм CORDIC, добавив округление в целочисленную математику.
Я долгое время игрался с сишной моделью и вот результат: main.cpp. На выходе программы имеем консольный вывод разницы для косинуса и синуса между правильным значением и рассчитанном алгоритмом и дисперсию. Дисперсия равна нулю, что, как мне кажется, хорошо.
Я решил сэкономить места в ПЛИС, поэтому урезал точность по фазе до 16 бит, а по составляющим до 14 бит, а количество итераций оставил равным 14.
Графики относительной погрешности для синфазной составляющей:

Графики относительной погрешности для квадратурной составляющей:

Можно еще заметить, что я играл с сочетанием математики с округлением и без. Я искал оптимальное использование того и того, чтобы минимизировать абсолютную погрешность. При этом еще одним фактором минимизации было добиться как можно меньшей величины суммы модулей погрешностей. Если говорить сухими цифрами:
При использовании округления при всех итерациях максимальная погрешность по обеим составляющим равна 6 и нормированная сумма модулей погрешности к числу точек равна 1,160645.
При целочисленной математики значения равны 8 и 1,362732
При оптимальном сочетании значения равны 5 и 0,971802. Графики приведены именно для этого случая.
Ну и переписываем один к одному на verilog: main.v. Получившаяся волна:

Бонус: FFT 2048 на FreeMat
cos = load('cos_delta.txt')/8191;
nfft=2048
X = fft(cos, nfft);
X = X(1:nfft/2);
f = (0:nfft/2-1)*Fs/nfft;
plot(f,mx);