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

Округление при сдвиговом делении

Итак, есть число, знаковое. Его надо разделить

Вариант 1: на степень двойки. Сдвигаем вправо и все. Округление, на сколько я знаю, до ближайшего целого в сторону минус бесконечности.

Вариант 2: не на степень двойки, а, скажем, на 1.6. Деление на 1.6 выполняем следующим образом:

1/1.6 = 0.625 = (1/2+1/8). Т.е. сдвигаем на один бит и прибавляем результат сдвига на 3 бита. Какое округление происходит в данном случае я даже не знаю.

 

А теперь вопрос: как выполнить деление по первому и второму варианту, но гарантировать округление до ближайшего целого (и для положительных, и для отрицательных)? Причем, в проекте это одно из самых узких мест, не хотелось бы накручивать сложную логику и плодить задержки.

Заранее спасибо

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


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

А теперь вопрос: как выполнить деление по первому и второму варианту, но гарантировать округление до ближайшего целого (и для положительных, и для отрицательных)? Причем, в проекте это одно из самых узких мест, не хотелось бы накручивать сложную логику и плодить задержки.

В самом простом случае добавляете к числу +0.5 и для положительных и для отрицательных чисел, и откидываете дробную часть.

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


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

Вы дробную арифметику самостоятельно в целочисленную приводите?!? Матлабом пользоваться не пробовали? Советую попробовать связку программ: AccelDSP + Matlab (HDL-код напишется автоматически)

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


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

В самом простом случае добавляете к числу +0.5 и для положительных и для отрицательных чисел, и откидываете дробную часть.

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

 

Вы дробную арифметику самостоятельно в целочисленную приводите?!? Матлабом пользоваться не пробовали? Советую попробовать связку программ: AccelDSP + Matlab (HDL-код напишется автоматически)

А что мне предлагается делать на матлабе? Мне нужно выполнить квантование на набор заранее рассчитанных коефициентов, округляя результат к ближайшему целому. Что мне тут сделать на матлабе и чем он мне поможет? Я сегодня проверю, но, на сколько помню, функции округления в матлабе - не hdl синтезируемые.

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


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

Похоже, Вы масштабируете на заранее известные коэффициенты: попробуйте заменить деление умножением. Или условия другие?

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


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

Похоже, Вы масштабируете на заранее известные коэффициенты: попробуйте заменить деление умножением. Или условия другие?

Ну да, есть входной поток 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. Округление - путем суммирования в единицей произведения в старшем отбрасываемом разряде.

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


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

Тут правельно сказано что надо добавлять 0,5. Реализация подобного может быть сделана примерно так:

число 010101000 надо круглить отбросив 3 младших бита. Для этого надо к 010101000 добавить 000000100.

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


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

Если у Вас есть свободный умножитель в ПЛИС, .... тогда лучше объяснить все на примерах:

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

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

 

Всем большое спасибо за помощь!

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


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

Методы существуют разные. Скажите - а какую ПЛИС Вы используете и с какой частотой Вам надо делить данные?

Для начала надо определиться с ресурсами, а уж потом - развивать метод деления.

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


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

Итак, есть число, знаковое. Его надо разделить

Вариант 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 разраядов.

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


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

Кстати в матлаб+ system generator очень хорошо продумано округление и переполнение - для всех блоков можно задать как округлять - просто обрезать или к ближайшему целому, и как себя вести при переполнении - обрезать или насыщаться. В код переводит нормально.

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


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

Тут правельно сказано что надо добавлять 0,5. Реализация подобного может быть сделана примерно так:

число 010101000 надо круглить отбросив 3 младших бита. Для этого надо к 010101000 добавить 000000100.

 

Абсолютно с Вами согласен, а что если 011111111 надо округлить отбросив 3 младших бита?При добавлении 000000100 не произойдет ли переполнение?

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


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

Тут правельно сказано что надо добавлять 0,5. Реализация подобного может быть сделана примерно так:

число 010101000 надо круглить отбросив 3 младших бита. Для этого надо к 010101000 добавить 000000100.

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

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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