В этом примере показано, как вычислить квадратный корень с помощью алгоритма ядра CORDIC в MATLAB ®. Алгоритмы на основе CORDIC имеют решающее значение для многих встроенных приложений, включая управление двигателями, навигацию, обработку сигналов и беспроводную связь.
CORDIC - аббревиатура от COORDinate Rotation DIgital Computer. Алгоритм CORDIC на основе ротации Givens (см. [1,2]) является одним из наиболее аппаратных эффективных алгоритмов, поскольку требует только итеративных операций добавления сдвига. Алгоритм CORDIC исключает необходимость явных умножителей и подходит для вычисления множества функций, таких как синус, косинус, арксинус, арккосинус, арктангенс, векторная величина, деление, квадратный корень, гиперболические и логарифмические функции.
Алгоритм CORDIC с фиксированной точкой требует выполнения следующих операций:
1 поиск в таблице за одну итерацию
2 сдвига на итерацию
3 добавления на одну итерацию
Заметим, что для гиперболических алгоритмов на основе CORDIC, таких как квадратный корень, некоторые итерации (i = 4, 13, 40, 121,..., k, 3k + 1,...) повторяются для достижения сходимости результата.
Можно использовать алгоритм режима вычислений CORDIC для вычисления гиперболических функций, таких как гиперболический тригонометрический, квадратный корень, log, exp и т. д.
КОРДИЧЕСКИЕ УРАВНЕНИЯ В РЕЖИМЕ ГИПЕРБОЛИЧЕСКОГО ВЕКТОРИРОВАНИЯ.
Гиперболический режим векторизации используется для вычисления квадратного корня.
Для режима векторизации уравнения CORDIC следующие:



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



где
.
Обычно
выбирается как достаточно большое постоянное значение. Таким образом,
может быть предварительно вычислено.
Обратите внимание, что для квадратного корня мы будем использовать только
результат.
Ниже приведен пример реализации кода MATLAB алгоритма CORDIC Hyperbolic Vectoring Kernel (для случая скаляра x, y, и z). Этот же код может использоваться как для данных с фиксированной запятой, так и для данных с плавающей запятой.
Ядро гиперболической векторизации CORDIC
k = 4; % Used for the repeated (3*k + 1) iteration steps for idx = 1:n xtmp = bitsra(x, idx); % multiply by 2^(-idx) ytmp = bitsra(y, idx); % multiply by 2^(-idx) if y < 0 x(:) = x + ytmp; y(:) = y + xtmp; z(:) = z - atanhLookupTable(idx); else x(:) = x - ytmp; y(:) = y - xtmp; z(:) = z + atanhLookupTable(idx); end if idx==k xtmp = bitsra(x, idx); % multiply by 2^(-idx) ytmp = bitsra(y, idx); % multiply by 2^(-idx) if y < 0 x(:) = x + ytmp; y(:) = y + xtmp; z(:) = z - atanhLookupTable(idx); else x(:) = x - ytmp; y(:) = y - xtmp; z(:) = z + atanhLookupTable(idx); end k = 3*k + 1; end end % idx loop
Вычисление квадратного корня с использованием ядра гиперболического векторизации CORDIC
Разумный выбор начальных значений позволяет алгоритму гиперболического режима векторизации ядра CORDIC вычислять квадратный корень.
Сначала выполняются следующие этапы инициализации:
имеет значение.
имеет значение.
После
итераций эти начальные значения приводят к следующим выводам по мере
приближения:

Это может быть дополнительно упрощено следующим образом:

где
- коэффициент усиления CORDIC, определенный выше.
Примечание: для квадратного корня и
atanhLookupTable не оказывают никакого влияния на результат. Следовательно,
и atanhLookupTable не используются.
Ниже приведен пример реализации кода MATLAB алгоритма CORDIC Square Root Kernel (для случая скаляра x и y). Этот же код может использоваться как для данных с фиксированной запятой, так и для данных с плавающей запятой.
Корневая корневая корня CORDIC
k = 4; % Used for the repeated (3*k + 1) iteration steps
for idx = 1:n xtmp = bitsra(x, idx); % multiply by 2^(-idx) ytmp = bitsra(y, idx); % multiply by 2^(-idx) if y < 0 x(:) = x + ytmp; y(:) = y + xtmp; else x(:) = x - ytmp; y(:) = y - xtmp; end
if idx==k
xtmp = bitsra(x, idx); % multiply by 2^(-idx)
ytmp = bitsra(y, idx); % multiply by 2^(-idx)
if y < 0
x(:) = x + ytmp;
y(:) = y + xtmp;
else
x(:) = x - ytmp;
y(:) = y - xtmp;
end
k = 3*k + 1;
end
end % idx loopЭтот код идентичен реализации ядра гиперболического векторинга CORDIC выше, за исключением того, что z и atanhLookupTable не используются. Это снижение затрат на 1 поиск в таблице и 1 добавление на итерацию.
Пример
Используйте функцию CORDICSQRT для вычисления приблизительного квадратного корня v_fix используя десять итераций ядра CORDIC:
step = 2^-7; v_fix = fi(0.5:step:(2-step), 1, 20); % fixed-point inputs in range [.5, 2) niter = 10; % number of CORDIC iterations x_sqr = cordicsqrt(v_fix, niter); % Get the Real World Value (RWV) of the CORDIC outputs for comparison % and plot the error between the MATLAB reference and CORDIC sqrt values x_cdc = double(x_sqr); % CORDIC results (scaled by An_hp) v_ref = double(v_fix); % Reference floating-point input values x_ref = sqrt(v_ref); % MATLAB reference floating-point results figure; subplot(211); plot(v_ref, x_cdc, 'r.', v_ref, x_ref, 'b-'); legend('CORDIC', 'Reference', 'Location', 'SouthEast'); title('CORDIC Square Root (In-Range) and MATLAB Reference Results'); subplot(212); absErr = abs(x_ref - x_cdc); plot(v_ref, absErr); title('Absolute Error (vs. MATLAB SQRT Reference Results)');

Преодоление ограничений входного диапазона алгоритма
Многие алгоритмы квадратного корня нормализуют входное значение,,
в пределах диапазона [0,5, 2). Эта предварительная обработка обычно выполняется с использованием нормализации фиксированной длины слова и может использоваться для поддержки малых и больших диапазонов входных значений.
Реализация алгоритма квадратного корня на основе CORDIC особенно чувствительна к входам вне этого диапазона. Функция CORDICSQRT преодолевает это ограничение диапазона алгоритма посредством подхода нормализации, основанного на следующих математических соотношениях:
, для некоторых
и некоторые даже целое число.
Таким образом:

В функции CORDICSQRT значения
и,
описанные выше, обнаруживаются во время нормализации входного сигнала.
-
количество первых нулевых старших битов (MSB) в двоичном представлении входного сигнала.
Эти значения обнаруживаются посредством последовательности побитовой логики и сдвигов. Примечание: потому что должно
быть четным, если число ведущих нулевых MSB нечетное, производится один дополнительный битовый сдвиг, чтобы сделать четным.
Результирующим значением после этих сдвигов является значение.
становится входом в ядро квадратного корня на основе CORDIC, где
вычисляется приближение к. Затем результат масштабируется
таким образом, что он возвращается в правильный выходной диапазон. Это достигается простым сдвигом битов на
биты. Направление сдвига (влево или вправо) зависит от знака.
Пример
Вычислите квадратный корень 10-разрядных входных данных с фиксированной точкой с небольшим неотрицательным диапазоном с помощью CORDIC. Сравните результаты алгоритма на основе CORDIC с исходными результатами MATLAB с плавающей запятой в одном и том же диапазоне ввода.
step = 2^-8; u_ref = 0:step:(0.5-step); % Input array (small range of values) u_in_arb = fi(u_ref,0,10); % 10-bit unsigned fixed-point input data values u_len = numel(u_ref); sqrt_ref = sqrt(double(u_in_arb)); % MATLAB sqrt reference results niter = 10; results = zeros(u_len, 2); results(:,2) = sqrt_ref(:); % Compute the equivalent Real World Value result for plotting. % Plot the Real World Value (RWV) of CORDIC and MATLAB reference results. x_out = cordicsqrt(u_in_arb, niter); results(:,1) = double(x_out); figure; subplot(211); plot(u_ref, results(:,1), 'r.', u_ref, results(:,2), 'b-'); legend('CORDIC', 'Reference', 'Location', 'SouthEast'); title('CORDIC Square Root (Small Input Range) and MATLAB Reference Results'); axis([0 0.5 0 0.75]); subplot(212); absErr = abs(results(:,2) - results(:,1)); plot(u_ref, absErr); title('Absolute Error (vs. MATLAB SQRT Reference Results)');

Пример
Вычислите квадратный корень 16-разрядных входных данных с фиксированной точкой с большим положительным диапазоном с помощью CORDIC. Сравните результаты алгоритма на основе CORDIC с исходными результатами MATLAB с плавающей запятой в одном и том же диапазоне ввода.
u_ref = 0:5:2500; % Input array (larger range of values) u_in_arb = fi(u_ref,0,16); % 16-bit unsigned fixed-point input data values u_len = numel(u_ref); sqrt_ref = sqrt(double(u_in_arb)); % MATLAB sqrt reference results niter = 16; results = zeros(u_len, 2); results(:,2) = sqrt_ref(:); % Compute the equivalent Real World Value result for plotting. % Plot the Real World Value (RWV) of CORDIC and MATLAB reference results. x_out = cordicsqrt(u_in_arb, niter); results(:,1) = double(x_out); figure; subplot(211); plot(u_ref, results(:,1), 'r.', u_ref, results(:,2), 'b-'); legend('CORDIC', 'Reference', 'Location', 'SouthEast'); title('CORDIC Square Root (Large Input Range) and MATLAB Reference Results'); axis([0 2500 0 55]); subplot(212); absErr = abs(results(:,2) - results(:,1)); plot(u_ref, absErr); title('Absolute Error (vs. MATLAB SQRT Reference Results)');

Джек Э. Волдер, «Техника тригонометрических вычислений CORDIC», IRE Transactions on Electronic Computers, том EC-8, сентябрь 1959, стр. 330-334.
J.S. Walther, «Единый алгоритм элементарных функций», Материалы конференции, Весенняя совместная компьютерная конференция, май 1971, стр. 379-385.