Перейти к содержанию
    

Вычисление десятичного логарифма на ПЛИС

Добрый день!

 

Неожиданно потребовалось вычислить десятичный логарифм на ПЛИС (ALTERA CycloneIII).

На входе 16-разрядное беззнаковое число.

Подскажите - как реализовать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...Подскажите - как реализовать?

дял затравки можно тут посомтреть

Или вот ещё ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

_Anatoliy выкладывал код преобразования в децибелы. поищите по форуму

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добрый день!

 

Неожиданно потребовалось вычислить десятичный логарифм на ПЛИС (ALTERA CycloneIII).

На входе 16-разрядное беззнаковое число.

Подскажите - как реализовать?

 

Проще всего аппроксимировать отрезками прямых. Так реально в радиолокационной аппаратуре делается, а также при компадировании звука (см., например, реализацию A- или мю-законов). Разбиение области аргумента ведётся, естественно, нелинейно. Кол-во отрезков зависит от допустимой погрешности. После разбиения - само вычисление элементарно реализуется в HDL-коде. По-крайней мере, этот способ вообще не требует какой-либо таблицы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

совсем недавно делал такую штуку - логарифм по основанию 10, точность 16 бит.

Если в кратце объяснить, то считается логарифм по основанию 2 (у нас все таки двоичные числа), причем можно посчитать с какой- угодно точностью.

После того как нашли логарифм по основанию 2 можно найти по какому угодно основанию - нужно умножить на константу. Но тут надо быть оснорожным, чтобы не потерять точность при умножении.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

совсем недавно делал такую штуку - логарифм по основанию 10, точность 16 бит.

Если в кратце объяснить, то считается логарифм по основанию 2 (у нас все таки двоичные числа), причем можно посчитать с какой- угодно точностью.

После того как нашли логарифм по основанию 2 можно найти по какому угодно основанию - нужно умножить на константу. Но тут надо быть оснорожным, чтобы не потерять точность при умножении.

 

Добрый день!

А сможете подсказать как поступать с дробной частью логарифма? Как её считать?

Спасибо!

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А сможете подсказать как поступать с дробной частью логарифма? Как её считать?

 

Ну, например... Для точности до 24 бит и натурального логарифма:

 

N = exponent x

m = mantissa x, 0.5 <= m < 1

if m < sqrt(0.5), znum = m - 0.5, zden = znum * 0.5 + 0.5

if m > sqrt(0.5), znum = m - 1, zden = m * 0.5 + 0.5

z = znum / zden

w = z * z

a = -0.5527074855;

b = w - 6.632718214;

r = z + z * w * (a / b );

 

result = r + N * ln(2)

 

для перехода к логарифму по другому основанию, домножить на LOGx(e)

для более высоких точностей усложняются формулы вычисления a и b

 

(ссцылка на источник - "Software Manual for the Elementary Functions", Cody and Waite, Prentice Hall 1980)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще можно глянуть Meyer-Baese U., Digital Signal Processing with FPGA.

Раздел 2.10.3 Exponential and Logarithmic Function Approximation, стр. 156.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, например... Для точности до 24 бит и натурального логарифма:

 

N = exponent x

m = mantissa x, 0.5 <= m < 1

if m < sqrt(0.5), znum = m - 0.5, zden = znum * 0.5 + 0.5

if m > sqrt(0.5), znum = m - 1, zden = m * 0.5 + 0.5

z = znum / zden

w = z * z

a = -0.5527074855;

b = w - 6.632718214;

r = z + z * w * (a / b );

 

result = r + N * ln(2)

 

для перехода к логарифму по другому основанию, домножить на LOGx(e)

для более высоких точностей усложняются формулы вычисления a и b

 

(ссцылка на источник - "Software Manual for the Elementary Functions", Cody and Waite, Prentice Hall 1980)

 

Понял. Не рассказал про задачу. На вход поступает поток с БПФ 64-разрядные числа. С этого всего дела нужно брать десятичный логарифм и желательно поточнее. Как я понял, нам в ПЛИС на порядок проще брать логарифм по основанию 2 (много грамотных людей так советуют делать) - просто ищем первую единицу и благополучно получаем целую часть. Но есть ещё и дробная (чтобы отличить, к примеру, результат 4.1 от 4.9). Потом я собираюсь умножить на константу, которая (после нормирования) приведёт логарифм от основания 2 к основанию 10. А вот как анализировать эту "оставшуюся" после определения целой части в VHDL, не понимаю.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот как анализировать эту "оставшуюся" после определения целой части в VHDL, не понимаю.

А вот она и называется "мантисса" (m), и что с ней делать, один вариант, я и описал. И она всегда >=0.5, потому, что всегда имеет единицу в своем старшем разряде по причине того, что его положение уже найдено и выделено в экспоненту (которая N). Ну а целая часть, это и есть та самая экспонента. В общем, это терминология чисел с плавающей точкой.

 

 

 

То есть, на VHDL надо описать:

1) Вычислитель экспоненты. Это по сути - приоритетный шифратор, выдающий позицию старшего единичного бита.

2) Баррелевский сдвигатель, который сдвигает число на столько, чтобы эта 1 оказалась в старшем разряде числа.

3) описанную выше арифметику, которая из полученной в 1) экспоненты и в 2) мантиссы вычисляет логарифм.

 

1) + 2) - это, по сути, преобразователь числа из формата с фиксированной точкой в плавающую.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот она и называется "мантисса" (m), и что с ней делать, один вариант, я и описал. И она всегда >=0.5, потому, что всегда имеет единицу в своем старшем разряде по причине того, что его положение уже найдено и выделено в экспоненту (которая N). Ну а целая часть, это и есть та самая экспонента. В общем, это терминология чисел с плавающей точкой.

 

 

 

То есть, на VHDL надо описать:

1) Вычислитель экспоненты. Это по сути - приоритетный шифратор, выдающий позицию старшего единичного бита.

2) Баррелевский сдвигатель, который сдвигает число на столько, чтобы эта 1 оказалась в старшем разряде числа.

3) описанную выше арифметику, которая из полученной в 1) экспоненты и в 2) мантиссы вычисляет логарифм.

 

1) + 2) - это, по сути, преобразователь числа из формата с фиксированной точкой в плавающую.

 

Давайте, попробуем на реальном примере. Думаю, это будет полезно для форума в целом. Ни одного примера в двоичном коде я так и не нашёл.

Допустим, нам нужно получить десятичный логарифм от числа 15 000.

В итоге нам нужно, чтобы мы получили значение 4,176091259.

Сначала найдём его двоичный логарифм. (Вычисленный результат 13,87267488)

Для этого:

15000=11101010011000

Старший бит стоит 13-ым битом по счёту, следовательно, целая часть нашего логарифма равна 13 (правильно).

После этого я сдвигаю оставшуюся часть влево (чтобы биты, следующие за старшим, сами стали старшими)

Получаем: 1101010011000

А дальше что?

Изменено пользователем Art55555

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...