В этом примере показано, как вычислять синус и косинус с помощью ядра вращения CORDIC в MATLAB ®. Алгоритмы на основе CORDIC имеют решающее значение для многих встроенных приложений, включая управление двигателями, навигацию, обработку сигналов и беспроводную связь.
CORDIC - аббревиатура от COORDinate Rotation DIgital Computer. Алгоритм CORDIC на основе ротации Givens (см. [1,2]) является одним из наиболее аппаратных эффективных алгоритмов, поскольку требует только итеративных операций добавления сдвига. Алгоритм CORDIC исключает необходимость явных умножителей и подходит для вычисления множества функций, таких как синус, косинус, арксинус, арккосинус, арктангенс, векторная величина, деление, квадратный корень, гиперболические и логарифмические функции.
Алгоритм CORDIC с фиксированной точкой требует выполнения следующих операций:
1 поиск в таблице за одну итерацию
2 сдвига на итерацию
3 добавления на одну итерацию
Алгоритм режима вычисления вращения CORDIC можно использовать для одновременного вычисления синуса и косинуса, вычисления полярно-декартовых преобразований и для других операций. В режиме вращения известны величина вектора и угол поворота, и компоненты координат (X-Y) вычисляются после поворота.
Алгоритм режима поворота CORDIC начинается с инициализации углового накопителя с требуемым углом поворота. Затем решение о повороте при каждой итерации CORDIC выполняется таким образом, что уменьшается величина накопителя остаточного угла. Решение о повороте основано на знаке остаточного угла в угловом накопителе после каждой итерации.
В режиме вращения уравнения CORDIC:



где если
, и 
иначе;
и
является общим числом итераций.
Это дает следующий результат в качестве
подходов:



Где:
.
Обычно
выбирается как достаточно большое постоянное значение. Таким образом,
может быть предварительно вычислено.
В режиме вращения алгоритм CORDIC ограничен углами поворота между
и.
Для поддержки углов за пределами этого диапазона часто используется квадрантная коррекция.
Ниже приведен пример реализации кода MATLAB алгоритма CORDIC Rotation Kernel (для случая скаляра x, y, и z). Этот же код может использоваться как для операций с фиксированной запятой, так и для операций с плавающей запятой.
Ядро вращения CORDIC
function [x, y, z] = cordic_rotation_kernel(x, y, z, inpLUT, n) % Perform CORDIC rotation kernel algorithm for N iterations. xtmp = x; ytmp = y; for idx = 1:n if z < 0 z(:) = accumpos(z, inpLUT(idx)); x(:) = accumpos(x, ytmp); y(:) = accumneg(y, xtmp); else z(:) = accumneg(z, inpLUT(idx)); x(:) = accumneg(x, ytmp); y(:) = accumpos(y, xtmp); end xtmp = bitsra(x, idx); % bit-shift-right for multiply by 2^(-idx) ytmp = bitsra(y, idx); % bit-shift-right for multiply by 2^(-idx) end
Вычисление синуса и косинуса с использованием ядра вращения CORDIC
Разумный выбор начальных значений позволяет алгоритму режима вращения ядра CORDIC непосредственно вычислять одновременно как синус, так и косинус.
Сначала выполняются следующие этапы инициализации:
Таблица поиска входного угла inpLUT имеет значение atan(2 .^ -(0:N-1)).
имеет
значение входного аргумента.
имеет значение.
имеет нулевое значение.
После
итераций эти начальные значения приводят к следующим выводам в качестве
подходов:


Другие аппроксимации функций на основе ядра вращения возможны посредством предварительной и последующей обработки и с использованием других исходных условий (см. [1,2]).
Алгоритм CORDIC обычно выполняется через заданное (постоянное) число итераций, так как завершение ранних итераций CORDIC нарушит конвейерный код, и усиление CORDIC
не будет постоянным, потому что
будет изменяться.
Для очень больших значений
алгоритм CORDIC гарантированно сходится, но не всегда монотонно. Обычно можно достичь большей точности, увеличив общее число итераций.
Пример
Предположим, что у вас есть датчик угла поворота (например, в сервоприводе), который использует отформатированные целочисленные значения для представления измеренных углов поворота. Также предположим, что имеется 16-разрядная целочисленная арифметическая единица, которая может выполнять операции сложения, вычитания, сдвига и памяти. С помощью такого устройства можно реализовать ядро вращения CORDIC для эффективного вычисления косинуса и синуса (эквивалентно декартовым координатам X и Y) по значениям угла датчика без использования умножений или больших таблиц поиска.
sumWL = 16; % CORDIC sum word length thNorm = -1.0:(2^-8):1.0; % Normalized [-1.0, 1.0] angle values theta = fi(thNorm, 1, sumWL); % Fixed-point angle values (best precision) z_NT = numerictype(theta); % Data type for Z xyNT = numerictype(1, sumWL, sumWL-2); % Data type for X-Y x_out = fi(zeros(size(theta)), xyNT); % X array pre-allocation y_out = fi(zeros(size(theta)), xyNT); % Y array pre-allocation z_out = fi(zeros(size(theta)), z_NT); % Z array pre-allocation niters = 13; % Number of CORDIC iterations inpLUT = fi(atan(2 .^ (-((0:(niters-1))'))) .* (2/pi), z_NT); % Normalized AnGain = prod(sqrt(1+2.^(-2*(0:(niters-1))))); % CORDIC gain inv_An = 1 / AnGain; % 1/A_n inverse of CORDIC gain for idx = 1:length(theta) % CORDIC rotation kernel iterations [x_out(idx), y_out(idx), z_out(idx)] = ... fidemo.cordic_rotation_kernel(... fi(inv_An, xyNT), fi(0, xyNT), theta(idx), inpLUT, niters); end % Plot the CORDIC-approximated sine and cosine values figure; subplot(411); plot(thNorm, x_out); axis([-1 1 -1 1]); title('Normalized X Values from CORDIC Rotation Kernel Iterations'); subplot(412); thetaRadians = pi/2 .* thNorm; % real-world range [-pi/2 pi/2] angle values plot(thNorm, cos(thetaRadians) - double(x_out)); title('Error between MATLAB COS Reference Values and X Values'); subplot(413); plot(thNorm, y_out); axis([-1 1 -1 1]); title('Normalized Y Values from CORDIC Rotation Kernel Iterations'); subplot(414); plot(thNorm, sin(thetaRadians) - double(y_out)); title('Error between MATLAB SIN Reference Values and Y Values');

Jack E. Volder, The CORDIC Trigonometric Computing Technique, IRE Transactions on Electronic Computers, том EC-8, сентябрь 1959, pp330-334.
Рэй Андрака, обзор алгоритма CORDIC для компьютеров на основе FPGA, Труды ACM/SIGDA 1998 года шестой международный симпозиум по полевым программируемым матрицам затворов, 22-24 февраля 1998 года, pp191-200