методи обчислення фіксованої точки atan2 на FPGA


12

Мені потрібні обчислення atan2(x,y)на FPGA з безперервним потоком введення / виводу даних. Мені вдалося реалізувати це за допомогою розкручених, конвеєрних ядер CORDIC, але щоб отримати потрібну точність, мені довелося виконати 32 ітерації. Це призвело до того, що цій задачі було присвячено досить велику кількість LUT. Я спробував змінити потік, щоб використовувати частково розкручені ядра CORDIC, але тоді мені потрібна була помножена тактова частота для виконання повторних циклів, зберігаючи постійний потік вводу / виводу. З цим я не міг зустріти терміни.

Тому зараз я прагну до альтернативних способів обчислення atan2(x,y).

Я думав про використання таблиць пошуку блок-оперативної пам’яті з інтерполяцією, але оскільки є 2 змінні, мені знадобляться 2 виміри таблиць пошуку, і це дуже ресурсомістке з точки зору використання блокової оперативної пам’яті.

Потім я думав про те, щоб скористатися тим фактом, який atan2(x,y)пов'язаний atan(x/y)з регулюванням квадранта. Проблема в цьому полягає в тому, що x/yпотрібна справжня розбіжність, оскільки yвона не є постійною, і підрозділи на FPGA дуже трудомісткі.

Чи є нові способи впровадження atan2(x,y)на FPGA, які б призвели до зменшення використання LUT, але все ж забезпечують хорошу точність?


2
Яка тактова частота обробки та швидкість введення даних?
Джим Клей

Яка точність вам потрібна? Я припускаю, що ви також використовуєте обчислення з фіксованою точкою. Яку глибину біта ви використовуєте? Поліноміальне наближення (або LUT) з регулюванням квадранта є загальним методом реалізації atan2. Не впевнений, чи можна обійтись без поділу.
Jason R

Тактова частота вводу - 150 МГц, швидкість вхідних даних - 150 МСамп / сек. В основному я отримую новий вхід кожного тактового циклу. Затримка - це нормально, але я повинен також отримати вихід зі швидкістю 150 МСамп / с.
користувач2913869

Мої симуляції показують, що я можу жити приблизно з 1 * 10 ^ -9. Не впевнений, абсолютний мінімальний біт фіксованої точки, але я моделював формат з фіксованою точкою
Q10.32

У цій статті пояснюється реалізація системи з фіксованою точкою atan2. Вам все одно знадобиться підрозділ.
Метт Л.

Відповіді:


20

Для позбавлення від поділу можна використовувати логарифми. Для у першому квадранті:(x,y)

z=log2(y)log2(x)atan2(y,x)=atan(y/x)=atan(2z)

атан (2 ^ z)

Рисунок 1. Ділянкаatan(2z)

Вам потрібно буде наблизити до діапазону щоб отримати необхідну точність 1E-9. Ви можете скористатися симетрією або альтернативно переконатися, що знаходиться у відомому октанті. Щоб наблизити :atan(2z)30<z<30atan(2z)=π2atan(2z)(x,y)log2(a)

b=floor(log2(a))c=a2blog2(a)=b+log2(c)

bc log 2 ( c ) 1 c < 2 можна обчислити, знайшовши розташування найбільш значущого нульового біта. можна обчислити за допомогою трохи зрушення. Вам потрібно буде наблизити в діапазоні .clog2(c)1c<2

log2 (c)

Малюнок 2. Діаграма log2(c)

Для ваших вимог точності, лінійної інтерполяції та рівномірного відбору проб, достатньо 214+1=16385 зразків log2(c) та 30×212+1=122881 зразків atan(2z) для 0<z<30 . Остання таблиця досить велика. З ним похибка внаслідок інтерполяції сильно залежить від z :

Помилка наближення атана (2 ^ z)

Малюнок 3. atan(2z) наближення найбільшої абсолютної похибки для різних діапазонів z (горизонтальна вісь) для різної кількості зразків (32-8192) на одиничний інтервал z . Найбільша абсолютна похибка для 0z<1 (опущена) трохи менше, ніж для floor(log2(z))=0 .

atan(2z) таблиця може бути розбита на кілька підтаблиць , які відповідають 0z<1 і іншому floor(log2(z)) з z1 , який легко обчислити. Довжини таблиці можна вибрати, керуючись рис. 3. Індекс, що підлягає заміні, може бути обчислений за допомогою простої маніпуляції з бітними рядками. Для ваших вимог до точності atan(2z) матимуть загальну кількість 29217 зразків, якщо ви розширите діапазон z до 0z<32 для простоти.

Для подальшого ознайомлення, ось незграбний сценарій Python, який я використовував для обчислення помилок наближення:

from numpy import *
from math import *
N = 10
M = 20
x = array(range(N + 1))/double(N) + 1
y = empty(N + 1, double)
for i in range(N + 1):
    y[i] = log(x[i], 2)

maxErr = 0
for i in range(N):
    for j in range(M):
        a = y[i] + (y[i + 1] - y[i])*j/M
        if N*M < 1000: 
            print str((i*M + j)/double(N*M) + 1) + ' ' + str(a)
        b = log((i*M + j)/double(N*M) + 1, 2)
        err = abs(a - b)
        if err > maxErr:
            maxErr = err

print maxErr

y2 = empty(N + 1, double)
for i in range(1, N):
    y2[i] = -1.0/16.0*y[i-1] + 9.0/8.0*y[i] - 1.0/16.0*y[i+1]


y2[0] = -1.0/16.0*log(-1.0/N + 1, 2) + 9.0/8.0*y[0] - 1.0/16.0*y[1]
y2[N] = -1.0/16.0*y[N-1] + 9.0/8.0*y[N] - 1.0/16.0*log((N+1.0)/N + 1, 2)

maxErr = 0
for i in range(N):
    for j in range(M):
        a = y2[i] + (y2[i + 1] - y2[i])*j/M
        b = log((i*M + j)/double(N*M) + 1, 2)
        if N*M < 1000: 
            print a
        err = abs(a - b)
        if err > maxErr:
            maxErr = err

print maxErr

y2[0] = 15.0/16.0*y[0] + 1.0/8.0*y[1] - 1.0/16.0*y[2]
y2[N] = -1.0/16.0*y[N - 2] + 1.0/8.0*y[N - 1] + 15.0/16.0*y[N]

maxErr = 0
for i in range(N):
    for j in range(M):
        a = y2[i] + (y2[i + 1] - y2[i])*j/M
        b = log((i*M + j)/double(N*M) + 1, 2)
        if N*M < 1000: 
            print str(a) + ' ' + str(b)
        err = abs(a - b)
        if err > maxErr:
            maxErr = err

print maxErr

P = 32
NN = 13
M = 8
for k in range(NN):
    N = 2**k
    x = array(range(N*P + 1))/double(N)
    y = empty((N*P + 1, NN), double)
    maxErr = zeros(P)
    for i in range(N*P + 1):
        y[i] = atan(2**x[i])

    for i in range(N*P):
        for j in range(M):
            a = y[i] + (y[i + 1] - y[i])*j/M
            b = atan(2**((i*M + j)/double(N*M)))
            err = abs(a - b)
            if (i*M + j > 0 and err > maxErr[int(i/N)]):
                maxErr[int(i/N)] = err

    print N
    for i in range(P):
        print str(i) + " " + str(maxErr[i])    

Локальна помилка максимум з апроксимуючої функції f(x) шляхом лінійної інтерполяції п ( х ) з зразків F ( х ) , взятий з рівномірною дискретизації вибірки інтервалу Δ х , може бути апроксимована аналітично:f^(x)f(x)Δx

f^(x)f(x)(Δx)2limΔx0f(x)+f(x+Δx)2f(x+Δx2)(Δx)2=(Δx)2f(x)8,

де є другою похідною і знаходиться на локальному максимумі абсолютної похибки. З урахуванням сказаного ми отримуємо наближення:f(x)f(x)x

atan^(2z)atan(2z)(Δz)22z(14z)ln(2)28(4z+1)2,log2^(a)log2(a)(Δa)28a2ln(2).

Оскільки функції увігнуті і зразки відповідають функції, помилка завжди в одному напрямку. Локальна максимальна абсолютна помилка може бути зменшена вдвічі, якби знак помилки був змінений вперед і назад один раз на кожному інтервалі вибірки. При лінійній інтерполяції близькі до оптимальних результатів можна досягти, попередньо фільтруючи кожну таблицю:

y[k]={b0x[k]+b1x[k+1]+b2x[k+2]if k=0,c1x[k1]+c0x[k]+c1x[k+1]if 0<k<N,b2x[k2]+b1x[k1]+b0x[k]if k=N,

де і - оригінал і відфільтрована таблиця, що охоплює а ваги . Кінцеве кондиціонування (перший і останній рядок у наведеному вище рівнянні) зменшує помилку на кінцях таблиці порівняно з використанням зразків функції поза таблицею, тому що перший і останній зразок не потрібно коригувати для зменшення помилки від інтерполяції між нею та зразком безпосередньо за столом. Підрозділи з різними інтервалами вибірки попередньо фільтруються. Значення ваг були знайдені мінімізацією послідовно для збільшення показникаxy0kNc0=98,c1=116,b0=1516,b1=18,b2=116c0,c1N максимальне абсолютне значення приблизної помилки:

(Δx)NlimΔx0(c1f(xΔx)+c0f(x)+c1f(x+Δx))(1a)+(c1f(x)+c0f(x+Δx)+c1f(x+2Δx))af(x+aΔx)(Δx)N={(c0+2c11)f(x)if N=0,|c1=1c020if N=1,1+aa2c02(Δx)2f(x)if N=2,|c0=98

для міжпробних інтерполяційних позицій , з увігнутою або опуклою функцією (наприклад, ). При вирішенні цих ваг значення кінцевих вагових умов були знайдені шляхом мінімізації аналогічно максимального абсолютного значення:0a<1f(x)f(x)=exb0,b1,b2

(Δx)NlimΔx0(b0f(x)+b1f(x+Δx)+b2f(x+2Δx))(1a)+(c1f(x)+c0f(x+Δx)+c1f(x+2Δx))af(x+aΔx)(Δx)N={(b0+b1+b21+a(1b0b1b2))f(x)if N=0,|b2=1b0b1(a1)(2b0+b12)Δxf(x)if N=1,|b1=22b0(12a2+(2316b0)a+b01)(Δx)2f(x)if N=2,|b0=1516

при . Використання попереднього фільтра про половину помилки наближення і зробити це простіше, ніж повна оптимізація таблиць.0a<1

Помилка наближення з та без попереднього фільтру та закінчення кондиціонування

Малюнок 4. Похибка апроксимації з 11 зразків, з попереднім та без і з кінцевим кондиціонуванням. Без завершення кондиціонування попередній фільтр має доступ до значень функції безпосередньо за межами таблиці.log2(a)

У цій статті, мабуть, представлений дуже схожий алгоритм: Р. Гутьєррес, В. Торрес та Дж. Валлс, “ FPGA-реалізація атана (Y / X) на основі логарифмічної трансформації та методів на основі LUT ”, Journal of System Architecture , vol . 56, 2010. У рефераті сказано, що їх реалізація перемагає попередні алгоритми на основі CORDIC у швидкості та алгоритми на основі LUT у розмірі сліду.


3
Ми з Меттью Гамбреллом створили звуковий мікросхему Yamaha YM3812 1985 р. За допомогою мікроскопії та знайшли в ній аналогічні таблиці журналу / досвіду читання лише в пам'яті (ROM). Yamaha використав додатковий трюк, щоб замінити кожен другий запис у кожній таблиці різницею до попереднього. Для плавних функцій різниця займає менше бітів та області чіпа, ніж функція. Вони вже мали додаток до мікросхеми, який вони змогли використати, щоб додати різницю до попереднього запису.
Оллі Ніемітало

3
Дуже дякую! Я люблю такі види подвигів математичних властивостей. Я обов'язково розробимо декілька сим-файлів MATLAB, і якщо все буде добре, перейдіть на HDL. Я звітну про свої заощадження LUT, коли все буде зроблено.
користувач2913869

Я використовував ваш опис як керівництво, і я радий залишатися, що мене скоротили на LUT майже на 60%. У мене була потреба зменшити BRAM, тому я зрозумів, що я можу отримати послідовну максимальну помилку на своїй таблиці ATAN, роблячи нерівномірну вибірку: у мене було декілька LUT BRAM (все та ж кількість бітів адреси), тим ближче до нуль, тим швидше вибірка. Я вибрав діапазони таблиць, щоб бути потужністю 2, щоб я міг легко визначити, в якому діапазоні я був, і зробити автоматичну індексацію таблиці за допомогою маніпуляцій бітом. Я застосував атанову симетрію, тому я зберігав лише половину форми хвилі.
користувач2913869

Також, можливо, я пропустив деякі ваші зміни, але мені вдалося реалізувати 2 ^ z, розділивши його на 2 ^ {якщо} = 2 ^ i * 2 ^ {0.f}, де i - ціла частина, а f - дробова частина. 2 ^ i - це проста, просто бітова маніпуляція, і 2 ^ {0.f} мали обмежений діапазон, тому вона добре піддавалася LUT з інтерполяцією. Я також розглядав негативний випадок: 2 ^ {- якщо} = 2 ^ {- i} * 1 / (2 ^ {0.f}. Отже, ще одна таблиця для 1/2 ^ {0.f}. Наступний мій крок можливо, застосувати потужність 2 діапазону / нерівномірного відбору проб на log2 (y) LUT, як це здається, це було б ідеальною формою хвилі кандидата для подібних речей.
Привіт

1
Lol yup я повністю пропустив цей крок. Я зараз спробую це спробувати. Потрібно врятувати мене ще більше LUT та ще більше БРАМ
користувач2913869
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.