§ Общие принципы
Взглянем правде в глаза: я так и не смог сделать модуль умножения для чисел float. Не смог. Но надо хотя бы попытаться, что ли!Для того, чтобы перемножить два числа, которые представлены в float форме, надо для начала, узнать, как они записываются:
Где S-это знак, P-порядок, M-мантисса.
Чтобы умножить 2 числа, нужно перемножить мантиссы между собой, сложить степени, и применить XOR к знаку. Если же мантисса превысила число 2, то сдвинуть итоговый порядок, прибавив +1.
§ Число в верилоге
Давайте теперь представим это число в верилоге:1input [31:0] value; 2... 3wire sign = value[31]; 4wire [7:0] exponent = value[30:23]; 5wire [23:0] mantissa = {exponent != 0, value[22:0]};Обращу внимание на скрытую единицу! Если экспонента не будет равна 0, то тогда туда записывается 1, иначе будет 0 — такое число называется денормализованным.
Я расскажу только про умножение нормализованных чисел.
При умножении двух чисел, может получится число, которое больше по количеству значащих знаков в 2 раза больше. Это надо учесть и потому взять итоговый результат только из более старших знаков.
§ Модуль вычисления
1 2module fp32mul 3( 4 input [31:0] a, 5 input [31:0] b, 6 output [31:0] c 7); 8 9wire sign = a[31] ^ b[31]; 10 11// Значение порядков и мантиссы 12wire [ 7:0] pa = a[30:23], pb = b[30:23]; 13wire [22:0] ma = a[22:0], mb = b[22:0]; 14 15// Умножение нормализованных чисел 16wire [47:0] t = {|pa, ma} * {|pb, mb}; 17wire [22:0] m = t[47] ? t[46:24] : t[45:23]; // Результирующая мантисса 18wire [ 8:0] p0 = pa + pb + t[47], // Переполнение вверх 19 p1 = p0 - 8'h7F; // Переполнение вниз 20 21// Если порядок более 255, то +inf, если менее 0, то это будет 0 22assign c = {sign, p0[8] ? {31{1'b1}} : p1[8] ? {31{1'b0}} : {p1, m}}; 23 24endmoduleНа вход подаются нормализованные float a и b, на выход получается c.