Я продолжаю работать над проектом SDR-Radio на FPGA плате Марсоход3GW2. Напомню, что здесь на плате у нас стоит микросхема ПЛИС от компании Gowin. Это значит, что если придется использовать IP Core, то это будут коры от говин.
В проекте SDR-Radio мне нужны следующие базовые компоненты:
- NCO - Numerically Controlled Oscilator, перестраиваемый генератор синусоидальных колебаний:
- модуль приема команд от ПК и данных к ПК, например, можно использовать последовательный порт;
- умножители для переноса спектра сигнала;
- цифровые фильтры нижних частот CIC и FIR.
Первые два пункта у меня практически уже есть реализованные в предыдущем проекте. Теперь мне нужно сделать цифровые фильтры.
Сказать по правде, я не большой специалист в цифровых фильтрах, хотя общее представление, как это всё работает у меня конечно есть. Я считаю, что самый правильный способ разобраться с работой какого либо устройства или модуля - это либо заглянуть внутрь и рассмотреть его детали, либо попытаться измерить его внешние характеристики. В случае с цифровым фильтром его основная характеристика это АЧХ - амплитудно частотная характеристика. Она показывает сигналы каких частот пропускает или подавляет фильтр. Попробуем провести эксперименты по измерению частотных характеристик цифровых фильтров.
В среде Gowin FPGA Designer я запускаю IP Core Generator и выбираю создание CIC фильтра. Появляется вот такое диалоговое окно:
Почему я в первую очередь обращаю внимание на CIC фильтр?
У меня по плану для SDR-Radio нужно оцифровать с помощью АЦП входной сигнал с антенны и получить эти данные внутри FPGA. Частота оцифровки будет 50МГц. Последовательность выборок затем будет перемножена на выборки синусоидального и косинусоидального сигнала от NCO. Это действие переносит спектр в область нижних частот. Теперь нужно понизить частоту сэмплирования скажем в 500 раз, чтобы она стала не 50МГц, а 100КГц. А понизить частоту оцифровки как раз помогает CIC фильтр. Точнее даже не просто CIC-Фильтр, а Дециматор.
На снимке диалогового окна выбора параметров CIC фильтра как раз я и вижу нужный мне тип фильтра Decimator и Down Sampling Rate 500. Это те параметры которые я сразу выбрал потому, что это понятные параметры. Из понятных параметров тут так же есть разрядность входных данных. Я ставлю 16 бит. Это потому, что АЦП на плате ADC1117-50 и оно восьми разрядное. Если я возьму с NCO синусоидальный сигнал так же 8ми битный, то при перемножении получатся 16-ти разрядные выборки. Остаются непонятными еще два параметра: Differencial Delay и Stages.
Чтобы разобраться с этими параметрами нужно прочитать теоретические материалы. Самые понятные статьи для меня оказались статьи на dsplib: http://www.dsplib.ru/content/cicid/cicid.html и цикл лекций на гитхабе https://github.com/hukenovs/dsp-theory.
Из этих лекций я понял для себя, что внутреннее устройство CIC фильтра вот такое:
В начале идет цепочка интеграторов, потом модуль понижения частоты R и затем цепочка гребёнчатых фильтров. Количество интеграторов равно количеству гребенчатых фильтров и это и есть параметр Stages.
Компоненты с надписью Z-1 или Z-m это линии задержки. Причем индекс "-1" значит задержку выборок сигнала на один такт, а индекс "-m" обозначает задержку на "m" тактов. Вот эта задержка "m" это и есть параметр Differential Delay в визарде Gowin.
Из статей по теории которые я упоминал выше следует, что чем больше Stages, тем более крутая частотная характеристика получится, но и больше логики она займет в ПЛИС. От Differential Delay зависит на какой частоте получится первый минимум АЧХ.
Из разумных компромисов между крутостью АЧХ и количеством занимаемой логики можно выбирать например 1-4, 2-4, 1-5, 2-5, где первое число это Diff Delay, а второе число это количество звеньев Stages.
Сразу нужно обратить внимание, что за лучшую фильтрацию нужно больше платить ресурсами внутри FPGA ну и разрядность сиграла на выходе фильтра так же завист от параметров. Например, как на рисунке выше, фильтр 2-4 и разрядность выходных выборок 56 бит. А если поставить фильтр 2-5, то разрядность на выходе будет уже 66 бит.
Итак, в диалоговом окне визарда Gowin я нажимаю OK и среда создаем мне нужный мне компонент CIC дециматора. Можно попробовать заглянуть внутрь сгенерированных модулей, но они зашифрованы. Это же IP Core. Вроде бы как интеллектуальная собственность. Ну вот остаётся либо поверить им на слово, либо всё таки поизучать, что получился у них за фильтр там. Изучать его можно как черный ящик. Собственно этому исследованию и посвещена эта статья.
Я делаю вот этот проект в котором выход NCO подается на фильтр CIC и затем специальная логика измеряет амплитуду выходного сигнала на выходе фильтра. Измеренное значение амплитуды отображается на семисегментном индикаторе. Сделаем много измерений и получим реальную, а не теоретическую АЧХ нашего фильтра. Как-то примерно вот так:
У меня есть же программа на питоне, которая берет параметр "желаемая частота" из командной строки и посылает специальную команду в плату Марсоход3GW чере последовательный порт. В FPGA принятая команда транслируется в "инкремент угла" для модуля NCO, таким образом, перестраивая частоту NCO. Меняю частоту на выходе NCO, подаем этот сигнал на CIC фильтр, на выходе измеряем амплитуду и записываем.
Я сделал измерения для трёх вариантов фильтра CIC-Decimator: 1-4, 2-4, 2-5. Вот эти измерения:
Это то, что у меня получилось.
На самом деле довольно похоже на графики, которые я видел на dsplib и других интернет ресурсах. Получается, что фильтр созданный Gowin FPGA Designer Wisard вполне работоспособный.
Я думаю, что для моего SDR-Radio я буду использовать CIC фильтр с параметрами 2-4. Он и ресурсов не так много берёт и характеристики у него вполне приличные.
Далее возникает вопрос о дальнейшей фильтрации. Обычно после CIC фильтра рекомендуют ставить FIR фильтр, чтобы компенсировать довольно пологий спад АЧХ.
Я ведь когда-то уже делал SDR-Radio на плате Марсоход2 с ПЛИС Cyclone III. Но это бло уже давно. Когда-то среда проектирования Quartus II при создании CIC фильтра сразу генерировала специальный скрипт для матлаба. Этот скрипт позволял рассчитать коэффициенты компенсирующего FIR фильтра. Интересно, что современный Quartus Prime больше не генерирует такой скрипт.
Чтобы понять, как рассчитывать эти коэффициенты я могу посоветовать вот эту статью https://habr.com/ru/articles/324986/.
Я же просто немного поленился и взял скрипт из моего старого проекта и использовал его, но предварительно отредактировал, чтобы количество звеньев было 4 и дифференциальная задержка стала 2.
И использовал для запуска скрипта GNU Octave и задавал следующие параметры:
Рассчетные коеффициенты были записаны в текстовый файл и кроме того скрипт выдал мне графики АЧХ CIC фильтра, корректирующего фильтра и итоговую теоретическую АЧХ:
Теперь, когда у меня есть список коеффициентов FIR фильтра я могу запустить Gowin диалог для создания компенсирующего FIR фильтра:
Число коеффициентов фильтра Taps Number должно совпадать с числом коэффициентов в файле mcic_fir_comp_coeff.txt.
У меня это число 23. Чем оно больше, тем более прямоугольная получится итоговая АЧХ связки CIC->FIR фильтра.
И теперь, когда у меня есть FIR фильтр я могу так же измерить его АЧХ. Я изменяю свой исследовательский проект для ПЛИС таким образом, чтобы у меня получилась цепочка: NCO -> CIC -> FIR -> Измеритель амплитуды.
Теперь пожно измерить АЧХ и посмотреть, что получилось в итоге:
Вот такая итоговая АЧХ у меня нарисовалась.
И это не теоретические изыскания, а практически измеренный результат. В принципе, я считаю, что результат не плохой.
Выборки с выхода FIR фильтра далее будут передаваться в ПК и там программа SDR радио будет их анализировать и воспроизводить звук, если удастся, что-то поймать в эфире.
Весь этот проект, исходники для FPGA для платы Марсоход3GW2 можно взять на github: https://github.com/marsohod4you/Marsohod3GW/tree/Marsohod3GW2_GW1NR-LV9QN88PC6I5/_cordic_nco_filters
А первая часть, где создавался NCO, вот здесь:
https://github.com/marsohod4you/Marsohod3GW/tree/Marsohod3GW2_GW1NR-LV9QN88PC6I5/_cordic_nco
В следующей статье я думаю наше радио должно уже заиграть.
Подробнее...