В этом примере показано, как вычислить синус и косинус с помощью ядра вращения CORDIC в MATLAB®. Основанные на CORDIC алгоритмы очень важны для многих встраиваемых приложений, включая блоки управления приводом, навигацию, обработку сигналов и радиосвязи.
CORDIC является акронимом для Координатного Компьютера Вращения. Основанный на вращении алгоритм CORDIC Givens (см. [1,2]) является одним из большей части оборудования эффективные алгоритмы, потому что это только требует итеративных операций shift-add. Алгоритм CORDIC избавляет от необходимости явные множители и подходит для вычисления множества функций, таков как синус, косинус, arcsine, arccosine, арктангенс, векторная величина, разделитесь, квадратный корень, гиперболические и логарифмические функции.
Фиксированная точка алгоритм CORDIC требует следующих операций:
1 поиск по таблице на итерацию
2 сдвига на итерацию
3 сложения на итерацию
Можно использовать вращение CORDIC вычислительный алгоритм режима, чтобы вычислить синус и косинус одновременно, вычислить полярные-к-декартову преобразования, и для других операций. В режиме вращения векторная величина и угол вращения известны и координата (X-Y), компоненты вычисляются после вращения.
Алгоритм режима вращения CORDIC начинается путем инициализации углового аккумулятора желаемым углом поворота. Затем решение вращения в каждой итерации CORDIC сделано способом, который уменьшает величину остаточного углового аккумулятора. Решение вращения основано на знаке остаточного угла в угловом аккумуляторе после каждой итерации.
В режиме вращения уравнения CORDIC:
где, если, и в противном случае;
, и общее количество итераций.
Это обеспечивает следующий результат как подходы:
Где:
.
Обычно выбирается, чтобы быть достаточно большим постоянным значением. Таким образом, может быть предварительно вычислен.
В режиме вращения алгоритм CORDIC ограничивается углами поворота между и. Чтобы поддержать углы за пределами той области значений, квадрантная коррекция часто используется.
Пример реализации кода MATLAB алгоритма Ядра Вращения CORDIC следует (для случая скалярного 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, как гарантируют, будет сходиться, но не всегда монотонно. Можно обычно достигать большей точности путем увеличения общего числа итераций.
Пример
Предположим, что у вас есть датчик угла поворота (e.g. в сервоприводе), который использует отформатированные целочисленные значения, чтобы представлять измеренные углы вращения. Также предположите, что у вас есть 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');
Джек Э. Волдер, Тригонометрический Вычислительный Метод CORDIC, Транзакции IRE на Электронно-вычислительных машинах, Volume EC 8, сентябрь 1959, pp330-334.
Рэй Андрэка, обзор алгоритма CORDIC для основанных на FPGA компьютеров, Продолжений 1998 шестых международных симпозиумов ACM/SIGDA по Программируемым пользователем вентильным матрицам, 22-24 февраля 1998, pp191-200