Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Округление при сдвиговом делении
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
RHnd
Итак, есть число, знаковое. Его надо разделить
Вариант 1: на степень двойки. Сдвигаем вправо и все. Округление, на сколько я знаю, до ближайшего целого в сторону минус бесконечности.
Вариант 2: не на степень двойки, а, скажем, на 1.6. Деление на 1.6 выполняем следующим образом:
1/1.6 = 0.625 = (1/2+1/8). Т.е. сдвигаем на один бит и прибавляем результат сдвига на 3 бита. Какое округление происходит в данном случае я даже не знаю.

А теперь вопрос: как выполнить деление по первому и второму варианту, но гарантировать округление до ближайшего целого (и для положительных, и для отрицательных)? Причем, в проекте это одно из самых узких мест, не хотелось бы накручивать сложную логику и плодить задержки.
Заранее спасибо
rloc
Цитата(RHnd @ Nov 20 2007, 19:26) *
А теперь вопрос: как выполнить деление по первому и второму варианту, но гарантировать округление до ближайшего целого (и для положительных, и для отрицательных)? Причем, в проекте это одно из самых узких мест, не хотелось бы накручивать сложную логику и плодить задержки.

В самом простом случае добавляете к числу +0.5 и для положительных и для отрицательных чисел, и откидываете дробную часть.
Гвоздик
Вы дробную арифметику самостоятельно в целочисленную приводите?!? Матлабом пользоваться не пробовали? Советую попробовать связку программ: AccelDSP + Matlab (HDL-код напишется автоматически)
RHnd
Цитата(rloc @ Nov 20 2007, 19:36) *
В самом простом случае добавляете к числу +0.5 и для положительных и для отрицательных чисел, и откидываете дробную часть.

Хм. Осталось только придумать, как это реализовать.

Цитата(Гвоздик @ Nov 21 2007, 00:47) *
Вы дробную арифметику самостоятельно в целочисленную приводите?!? Матлабом пользоваться не пробовали? Советую попробовать связку программ: AccelDSP + Matlab (HDL-код напишется автоматически)

А что мне предлагается делать на матлабе? Мне нужно выполнить квантование на набор заранее рассчитанных коефициентов, округляя результат к ближайшему целому. Что мне тут сделать на матлабе и чем он мне поможет? Я сегодня проверю, но, на сколько помню, функции округления в матлабе - не hdl синтезируемые.
Волощенко
Похоже, Вы масштабируете на заранее известные коэффициенты: попробуйте заменить деление умножением. Или условия другие?
RHnd
Цитата(Волощенко @ Nov 21 2007, 09:45) *
Похоже, Вы масштабируете на заранее известные коэффициенты: попробуйте заменить деление умножением. Или условия другие?

Ну да, есть входной поток d0, d1, d2,..., d63. Есть набор значений, заранее известных и доступных небольшому варьированию q0, q1, q2,..., q63. На выходе нужно d0/q0, d1/q1, d2/q2, ..., d63/q34 с округлением к ближайшему целому.
Можно пример замены деления умножением?
Волощенко
Если у Вас есть свободный умножитель в ПЛИС, .... тогда лучше объяснить все на примерах:
1. Укажите значения для коэффициентов, например, q0, q1, чтобы вычислить обратные значения.
2. Затем укажите пределы изменения d0, d1.
3. Выбираем разрядную сетку и фиксируем запятые для сомножителей.
4. Определяем положение запятой в произведении на выходе умножителя.
5. Округление - путем суммирования в единицей произведения в старшем отбрасываемом разряде.
AsJohnAs
Тут правельно сказано что надо добавлять 0,5. Реализация подобного может быть сделана примерно так:
число 010101000 надо круглить отбросив 3 младших бита. Для этого надо к 010101000 добавить 000000100.
RHnd
Цитата(Волощенко @ Nov 21 2007, 11:48) *
Если у Вас есть свободный умножитель в ПЛИС, .... тогда лучше объяснить все на примерах:

Об этом и подумал, но решил уточнить. Спасибо. Если не удастся придумать другой вариант, то так и буду делать, но изначально хотелось все сделать на сдвигах.
Хотя, пока писал - в уме прикинул, на умножителе получится удобнее в плане написания самого кода. Пожалуй, так и сделаю, а уж если по ТТХ не пройдет, тогда буду изворачиваться.

Всем большое спасибо за помощь!
EvgenyNik
Методы существуют разные. Скажите - а какую ПЛИС Вы используете и с какой частотой Вам надо делить данные?
Для начала надо определиться с ресурсами, а уж потом - развивать метод деления.
alex5991
Цитата(RHnd @ Nov 20 2007, 20:26) *
Итак, есть число, знаковое. Его надо разделить
Вариант 1: на степень двойки. Сдвигаем вправо и все. Округление, на сколько я знаю, до ближайшего целого в сторону минус бесконечности.
Вариант 2: не на степень двойки, а, скажем, на 1.6. Деление на 1.6 выполняем следующим образом:
1/1.6 = 0.625 = (1/2+1/8). Т.е. сдвигаем на один бит и прибавляем результат сдвига на 3 бита. Какое округление происходит в данном случае я даже не знаю.


Думаю, все будет гораздо наглядней и понятней, если изменить последовательность операций.

Вариант 1.

(А >> n) + 0.5 == (A+2**(n-1)) >> n

Вариант 2.

A/2 + A/8 + 0.5 == (A >> 1) + (A >> 3) + 0.5 == ((A << 2) + A + (0.5 << 3)) >> 3 ==
((A << 2) + A + (1 << 2)) >> 3

Иными словами: вначале прибавить 2**(n-1), а затем смело отбросить n разраядов.
syoma
Кстати в матлаб+ system generator очень хорошо продумано округление и переполнение - для всех блоков можно задать как округлять - просто обрезать или к ближайшему целому, и как себя вести при переполнении - обрезать или насыщаться. В код переводит нормально.
YuP
Цитата(AsJohnAs @ Nov 21 2007, 16:00) *
Тут правельно сказано что надо добавлять 0,5. Реализация подобного может быть сделана примерно так:
число 010101000 надо круглить отбросив 3 младших бита. Для этого надо к 010101000 добавить 000000100.


Абсолютно с Вами согласен, а что если 011111111 надо округлить отбросив 3 младших бита?При добавлении 000000100 не произойдет ли переполнение?
Singer
Цитата(AsJohnAs @ Nov 21 2007, 15:00) *
Тут правельно сказано что надо добавлять 0,5. Реализация подобного может быть сделана примерно так:
число 010101000 надо круглить отбросив 3 младших бита. Для этого надо к 010101000 добавить 000000100.

Петрушка какая то получается, пример вы приводите некорректный. Вы округляете 010101000 до целого числа, представляя младшие 3 бита как дробную часть. Округляют обычно так - если дробная часть >= 0.5 к целой части добавляют 1, иначе берут просто целую часть. В Вашем примере дробная часть (первые три бита) уже и так равна нулю, так что прибавлять единицу не надо. Прибавляют обычно росто бинарный разряд, стоящий на одну позицию меньше чем остающиеся разряды. В таком случае прибавление 1 происходит автоматически если дробная не меньше 0.5
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.