1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
module gfx_fmul_lane
(
input logic clk,
input gfx::float_special a,
b,
input logic slow_in,
output gfx::float_round q
);
import gfx::*;
/* Queremos calcular q = a * b.
*
* Donde a = (-1)^s * 1.m * 2^f,
* b = (-1)^t * 1.n * 2^g
*
* Entonces q = (-1)^(s + t) (1.m * 1.n) 2^(f + g)
*
* El producto es entre números >= 1.0 y < 2.0. En el peor caso:
* Mejor caso: 1.000... * 1.000... ~ 1.000...
* Peor caso: 1.999... * 1.999... ~ 3.999... = 2^1 * 1.999
*
* Así que, si el producto es >= 2, hay que hacerle >> 1 a la mantisa
* y sumarle 1 al exponente para normalizar.
*/
logic guard, lo_msb, lo_reduce, overflow_0, overflow_1,
round, sign, slow_0, slow_1, zero;
float_exp exp;
float_round out;
float_mant_full hi;
logic[$bits(float_mant_full) - 3:0] lo;
assign lo_msb = lo[$bits(lo) - 1];
assign lo_reduce = |lo[$bits(lo) - 2:0];
always_comb begin
q = out;
q.slow = slow_1 | overflow_1;
end
always_ff @(posedge clk) begin
// Stage 0: producto
sign <= a.val.sign ^ b.val.sign;
zero <= a.exp_min | b.exp_min;
slow_0 <= slow_in;
{overflow_0, exp} <= {1'b0, a.val.exp} + {1'b0, b.val.exp} - {1'b0, FLOAT_EXP_BIAS};
{hi, guard, round, lo} <= full_mant(a.val.mant) * full_mant(b.val.mant);
// Stage 1: normalización
slow_1 <= slow_0 | overflow_0;
overflow_1 <= 0;
out.slow <= 1'bx; // Ver 'q'
out.zero <= zero;
out.normal.sign <= sign;
if (hi[$bits(hi) - 1]) begin
out.guard <= guard;
out.round <= round;
out.sticky <= lo_msb | lo_reduce;
out.normal.mant <= implicit_mant(hi);
{overflow_1, out.normal.exp} <= {1'b0, exp} + 1;
end else begin
/* Bit antes de msb es necesariamente 1, ya que los msb de
* ambos multiplicandos son 1. Ver assert en implicit_mant().
*/
out.guard <= round;
out.round <= lo[$bits(lo) - 1];
out.sticky <= lo_reduce;
out.normal.exp <= exp;
out.normal.mant <= implicit_mant({hi[$bits(hi) - 2:0], guard});
end
end
endmodule
|