Видео в конце...
Приветствую! В прошлый раз мы занимались созданием и исследованием возможностей генератора синусоидальных колебаний. С точки зрения техники там не было ничего необычного. Интегратор накапливает полную фазу гармонического колебания, а таблица значений синуса выставляет эти самые значения на выход в строгом соответствии с аргументом функции фазой.
Небольшое исследование качества генерируемой синусоиды, а также использование ресурсов ПЛИС при разном качестве показывает, что способ генерации хоть и простой, но довольно прожорливый. Можно ли как-то улучшить качество выходного сигнала и при этом не задействовать большое количество дефицитных ресурсов? Разумеется, да и поможет нам в этом достижения в области математики. Если легкая научная разминка не пугает, то добро пожаловать.
Сущность алгоритма CORDIC
CORDIC (Coordinate rotation digital computer) это алгоритм вычисления значения функции методом последовательного приближения и путем выполнения простых операций сложения и сдвига.
Вместо хранения значений синуса в таблице математика предлагает вычислять значения функций при появлении аргумента фазы колебания. Накопление фазы в интеграторе остается как незаменимая часть управляемого генератора. В качестве математической модели используется окружность единичного радиуса с парой векторов, исходящих из центра окружности.
Концы векторов расположены на самой окружности. Один из векторов (зеленый) отклонен от горизонтальной оси на угол, являющийся аргументом функции. Второй (синий) вектор будет производить вращения от этой начальной точки относительно начала координат.
Вообще говоря, координаты вектора имеют значения синуса и косинуса угла, на который вектор отклоняется от горизонтальной оси.
Для синего вектора с углом ноль косинус равен единице, синус равен нулю. Для зеленого искомого вектора с известным углом косинус равен х, синус равен y. Разумеется, необходимо найти эти самые координаты.
Для поиска этих координат синий вектор делает несколько вращений на заданные углы. Первым шагом является поворот на угол 45 градусов.
Понятное дело, при этом маловероятно, что угол 45 градусов совпадет с углом аргументом зеленого вектора, но их углы заметно приблизятся друг к другу по величине.
Аналитически поворот вектора записывается в виде умножения начальных координат вектора V0 на матрицу поворота R. Матрица поворота на плоскости это квадратная матрица 2x2 элемента с синусами и косинусами угла поворота.
Работает это умножение очень просто. По правилам умножения матриц происходит поэлементное умножение строка на столбец.
Остаются вполне понятные координаты x, равное косинусу угла и y, равное синусу угла. На этом шаге мы повернули вектор на известный угол 45 градусов, получили координаты нового вектора V1 и поняли, что пока угол синего вектора отличается от угла зеленого вектора. Мы продолжим вращать синий вектор на меньшие углы, постепенно приближаясь к решению.
Тригонометрические преобразования
В матрице поворота присутствуют синусы и косинусы, что вызывает необходимость хранения этих величин в таблице. Путем применения тригонометрических тождеств преобразуем матрицу поворота в другой вид, тем самым сокращая размер таблицы для хранения этих констант.
Матрица поворота примет такой вид.
Некоторая величина выносится за знак матрицы. Координаты вектора на очередном шаге поворотов примут такой вид.
Как видим, они зависят от старых координат вектора на предыдущем шаге и от тангенса угла поворота, причем угол поворота уменьшается с каждым шагом.
Вынесенный за скобку коэффициент пропорциональности при его отбрасывании приведет к увеличению модуля обоих координат вектора на каждом шаге.
Этот пропорциональный коэффициент с уменьшением угла фи стремится к единице, что в пределе приведет к увеличению амплитуды сгенерированной синусоиды примерно в 1,6 раза. Это потом легко скомпенсировать одним умножителем.
Кратко и по шагам...
И так, что мы теперь имеем. Для постепенного приближения угла поворота к аргументу функции пошагово вращается единичный вектор и для вращения необходимо запомнить табличные значения тангенсов убывающего с каждым шагом угла поворота. Благодаря свойствам геометрической прогрессии, таких углов для хорошей точности будет совсем немного.
На первом шаге поворачиваем синий вектор на 45 градусов, получаем координаты вектора V1.
На втором шаге доворачиваем на меньший угол, получаем координаты вектора V2.
И, наконец, на каком-то шаге x накопленный поворотами угол совпадет с аргументом, в то же самое время координаты получившегося вектора будут результатом синуса и косинуса угла.
Чрезвычайно удобно, элегантно и эффективно. Алгоритм хорошо подходит микропроцессорам для пошагового выполнения, а также при конвейерной реализации на ПЛИС или заказных чипах очень хорошо работает абсолютно параллельно, показывая при этом высокую производительность.
Как CORDIC использует ресурсы ПЛИС?
Давайте сравним табличную генерацию из прошлого выпуска с генерацией алгоритмом CORDIC. Таблица 12-битных отсчетов синуса тогда забрала четверть памяти, а на этот раз потребовалось 6 процентов от общего числа логических ячеек. Блочной памяти при этом не нужно нисколько. По мне так результат превосходный.
А что на счет 16-битных отсчетов, под которые необходимо было бы выделить более 65 тысяч ячеек памяти для синуса и косинуса отдельно? Столько памяти уже не найдется в ПЛИС на имеющейся отладочной плате, а вот представленный в этот раз алгоритм разместился на 10 процентах логических ячеек и это более чем великолепно.
Подписывайтесь на канал и до новых встреч!
Поддержите статью лайком если понравилось и подпишитесь чтобы ничего не пропускать.
Также не обойдите вниманием канал на YouTube. Подписки и лайки будут приятным ответом от аудитории.