Какой алгоритм деления следует использовать для аппаратного деления небольших целых чисел?

Мне нужно умножить целое число в диапазоне от 0 до 1023 на 1023 и разделить результат на число в диапазоне от 1 до 1023 в аппаратном обеспечении (реализация Verilog/fpga). Умножение выполняется прямолинейно, поскольку я, вероятно, могу обойтись простым сдвигом на 10 бит (и, если необходимо, я вычту дополнительные 1023). Хотя разделение немного интересное. Площадь/мощность для меня не критичны (у меня ПЛИС, так что ресурсы уже есть). Задержка (в пределах разумного) не имеет большого значения, пока я могу конвейеризировать дизайн. Очевидно, есть несколько вариантов с разными компромиссами, но мне интересно, есть ли «очевидный» или «легкий» алгоритм для такой ситуации. Учитывая ограниченный диапазон операндов и изобилие ресурсов, которые у меня есть (bram и т. д.), мне интересно, нет ли чего-то очевидного, что нужно сделать.


person Doov    schedule 07.08.2013    source источник
comment
Двоичное длинное деление может быть вашим лучшим выбором   -  person Drew McGowen    schedule 07.08.2013
comment
Если у вас достаточно ресурсов, возможно, создайте для него LUT (таблицу поиска).   -  person saeedn    schedule 07.08.2013


Ответы (2)


Если вы можете работать с точностью с фиксированной точкой, а не с целыми числами, возможно, вы сможете изменить:

разделить результат на число в диапазоне от 1 до 1023

для умножения на число в диапазоне от 1 до 1/1023, т.е. предварительно вычислите деление и сохраните его как коэффициент для умножения.

person Morgan    schedule 07.08.2013
comment
Думаю, я мог бы сделать что-то подобное. Общая операция (целое число от 0 до 1023) * 1023 / (целое число от 0 до 1023). Учитывая вторую половину, я мог бы просто уменьшить это до умножения с фиксированной точкой (целое число от 0 до 1023) * (число с фиксированной точкой 1-1023). Вторую половину уравнения можно предварительно вычислить, полностью избавившись от деления. Мысли? - person Doov; 08.08.2013
comment
@Doov, вот как я бы к этому подошел. - person Morgan; 08.08.2013

Если вы можете предварительно вычислить все, и у вас есть запасной множитель 20x20 и какой-то способ сохранить предварительно вычисленное число, тогда воспользуйтесь предложением Моргана. Вам нужно предварительно вычислить 20-битное множимое (частное 10b, остаток 10b), умножить на первое число 10b и взять нижние 30b результата 40b.

В противном случае легкая задача — это невосстанавливающее деление, поскольку вы говорите, что задержка не важна (в сети много чего, большая часть непонятна). у вас есть 20-битный числитель (результат вашего (1023 x) умножения) и 10-битный знаменатель. Это дает частное 20b и остаток 10b (т.е. 20 бит для целой части ответа и 10 бит для дробной части, что дает ответ 30b).

Фактическое аппаратное обеспечение довольно тривиально: сумматор/вычитатель 11 бит, регистр сдвига 31 бит и регистр 10 бит или 11 бит для хранения делителя. Вам также понадобится небольшой FSM, чтобы управлять им (2b). Вы должны выполнять сравнение, складывать или вычитать и сдвигать каждый такт, и вы получите ответ за 21 такт. Я думаю. :)

person EML    schedule 08.08.2013
comment
Спасибо за ответ @EML. Я думаю, что буду придерживаться подхода Моргана (и, конечно, с вашей детализацией). Я действительно могу предварительно вычислить все - написал сценарий Matlab, чтобы получить коэффициенты/составить LUT. Кстати, num2fixpt — хорошая функция, о существовании которой я не знал, пока не написал свою собственную версию. На самом деле я использую спартанский 3a-dsp, в который встроено несколько множителей. При этом я думаю, что задержка умножения лучше, чем у деления. Я бы проголосовал за ответ, но Морган был первым :) - person Doov; 09.08.2013