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

Деление двоичных чисел с плавающей точкой

Всем добрый день. Пытаюсь реализовать деление двоичных чисел с плавающей точкой в формате IEEE754. Если с определением знака и экспоненты проблем не возникает, то в определении мантиссы частного возникли сложности. Пытаюсь реализовать ниже представленный алгоритм:

Спойлер

Деление с неподвижным делителем и сдвигаемым влево делимым. Деление начинается со сдвига влево делимого. Далее на вход сумматора подаётся сдвинутое влево делимое, образуется частичный остаток путём подсуммирования дополнительного кода отрицательного делителя, и очередная цифра частного заносится в освободившийся при сдвиге X разряд.

1) берутся модули делимого и делителя, 2) исходное значение частичного остатка полагается равным старшим разрядам делимого, и 3) частичный остаток удваивается путём сдвига на один разряд влево, при этом в освобождающийся при сдвиге младший разряд частичного остатка заносится очередная цифра делимого 4) если сдвинутый частичный остаток >0, то из него вычитается делитель; в противном случае прибавляется делитель. 5) Очередная цифра частного равна 1, если результат четвёртого пункта положителен, и 0, если отрицателен. Выполнение повторяется с третьего пункта до получения всех цифр модуля частного. В конце деления, если остаток отрицателен, то он восстанавливается путём подсуммирования делителя.

Ниже представлен код. В модуль параллельно поступают 2 16 разрядных числа с плавающей точкой, у которых [9:0] биты - мантиссы, которые и необходимо разделить. На выходе нужно получить частное и параллельно передать его. Счетчик начинает работать, когда числа поступят. Подозреваю, что проблема получения некорректного результата может быть связана с проверкой знака остатка. Буду благодарен за любые идеи! 

Спойлер
module div_fraction(clk, res, divisible, divider, out);

input                           clk, res;
input               [15:0]      divisible, divider;

output   reg        [9:0]       out;

reg                 [9:0]       reg_quotient;
reg       signed    [10:0]      remains;
reg       signed    [9:0]       divider_copy;
reg                 [3:0]       cnt;

always@(posedge clk) begin
    if(!res)
        reg_quotient <= 0;
    else if((divisible !== 16'bX) && (divider !== 16'bX)) begin
            cnt          <= 4'b1010;
            divider_copy <= divider[9:0];
            remains      <= divisible[9:0];
            reg_quotient <= 0;
            if (cnt >= 0)begin
                cnt <= cnt - 1'b1;
                remains      <= {1'b0, remains[8:0], 1'b0};
                    if(!remains[10]) begin
                        remains <= remains + (~divider_copy + 1'b1);
                        reg_quotient <= {reg_quotient[8:0], 1'b1}; end
                    else begin
                        remains <= remains + divider_copy;
                        reg_quotient <= {reg_quotient[8:0], 1'b0}; end end 
end
end
endmodule

 

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


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

Для начала отделите инициализацию cnt, divider_copy, remains и reg_quotient от их дальнейшего вычисления. Сейчас у вас на каждом такте вычисляется одно и тоже

 

9 hours ago, SarBon88 said:

Счетчик начинает работать, когда числа поступят.

Для определения что числа поступили используется отдельный сигнал, а не проверка данных на X - эта конструкция синтезируется не так, как вы ожидаете 🙂

 

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


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

Понял, то есть необходимо начинать счет по сигналу load(который приходит из предыдущего модуля), сигнализирующий о полной передачи чисел. 

Можете, пожалуйста, еще подсказать на счет самой операции деления? Смущает проверка знака частичного остатка.

Спойлер
1 час назад, xvr сказал:

Для начала отделите инициализацию cnt, divider_copy, remains и reg_quotient от их дальнейшего вычисления. Сейчас у вас на каждом такте вычисляется одно и тоже

Для определения что числа поступили используется отдельный сигнал, а не проверка данных на X - эта конструкция синтезируется не так, как вы ожидаете 🙂

 

 

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


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

посмотрите алгоритм и его реализуйте пошагово. Там пример есть - добейтесь соответствия в симуляторе для начала для данного примера...

Определитесь с архитектурой FSM или pipeline реализации.

 

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


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

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

Спойлер
13 минут назад, Maverick_ сказал:

посмотрите алгоритм и его реализуйте пошагово. Там пример есть - добейтесь соответствия в симуляторе для начала для данного примера...

Определитесь с архитектурой FSM или pipeline реализации.

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


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

2 hours ago, SarBon88 said:

Смущает проверка знака частичного остатка.

Знак проверяется правильно, а вот сдвиг частичного остатка (п3 в вашем алгоритме) делается не правильно.

Ну и собственно реализация в целом неправильная - у вас описан алгоритм, а не схема. HDL язык - это не язык програмирования! Это язык описания аппаратуры.

Посмотрите какие нибудь примеры, как на нём пишут.

 

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


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

В 08.06.2023 в 15:54, xvr сказал:

Знак проверяется правильно, а вот сдвиг частичного остатка (п3 в вашем алгоритме) делается не правильно.

Ну и собственно реализация в целом неправильная - у вас описан алгоритм, а не схема. HDL язык - это не язык програмирования! Это язык описания аппаратуры.

Посмотрите какие нибудь примеры, как на нём пишут.

А ещё лучше -- разобраться, как это делается в реальном железе, на логических элементах, триггерах и прочая. Если подходить к HDL как к языку программирования, хорошего результата не будет (даже если что-то и будет работать).

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


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

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...