1 from nmigen
import Module
, Signal
2 from nmigen
.cli
import main
, verilog
4 from fpbase
import FPNum
, FPOp
, Overflow
, FPBase
9 def __init__(self
, width
):
13 self
.in_a
= FPOp(width
)
14 self
.in_b
= FPOp(width
)
15 self
.out_z
= FPOp(width
)
17 def get_fragment(self
, platform
=None):
18 """ creates the HDL code-fragment for FPMUL
23 a
= FPNum(self
.width
, False)
24 b
= FPNum(self
.width
, False)
25 z
= FPNum(self
.width
, False)
27 mw
= (self
.width
)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
37 with m
.State("get_a"):
38 self
.get_op(m
, self
.in_a
, a
, "get_b")
43 with m
.State("get_b"):
44 self
.get_op(m
, self
.in_b
, b
, "special_cases")
49 with m
.State("special_cases"):
50 #if a or b is NaN return NaN
51 with m
.If(a
.is_nan() | b
.is_nan()):
54 #if a is inf return inf
55 with m
.Elif(a
.is_inf()):
57 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
58 #if b is zero return NaN
59 with m
.If(b
.is_zero()):
61 #if b is inf return inf
62 with m
.Elif(b
.is_inf()):
64 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
65 #if a is zero return NaN
66 with m
.If(a
.is_zero()):
69 #if a is zero return zero
70 with m
.Elif(a
.is_zero()):
72 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
73 #if b is zero return zero
74 with m
.Elif(b
.is_zero()):
76 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
77 # Denormalised Number checks
79 m
.next
= "normalise_a"
80 self
.denormalise(m
, a
)
81 self
.denormalise(m
, b
)
86 with m
.State("normalise_a"):
87 self
.op_normalise(m
, a
, "normalise_b")
92 with m
.State("normalise_b"):
93 self
.op_normalise(m
, b
, "multiply_0")
96 with m
.State("multiply_0"):
100 z
.e
.eq(a
.e
+ b
.e
+ 1),
101 product
.eq(a
.m
* b
.m
* 4)
105 with m
.State("multiply_1"):
106 m
.next
= "normalise_1"
108 z
.m
.eq(product
[26:50]),
109 of
.guard
.eq(product
[25]),
110 of
.round_bit
.eq(product
[24]),
111 of
.sticky
.eq(product
[0:23] != 0)
115 # First stage of normalisation.
116 with m
.State("normalise_1"):
117 self
.normalise_1(m
, z
, of
, "normalise_2")
120 # Second stage of normalisation.
122 with m
.State("normalise_2"):
123 self
.normalise_2(m
, z
, of
, "round")
128 with m
.State("round"):
129 self
.roundz(m
, z
, of
, "corrections")
134 with m
.State("corrections"):
135 self
.corrections(m
, z
, "pack")
139 with m
.State("pack"):
140 self
.pack(m
, z
, "put_z")
145 with m
.State("put_z"):
146 self
.put_z(m
, z
, self
.out_z
, "get_a")
153 //if a is NaN or b is NaN return NaN
154 if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
160 //if a is inf return inf
161 end else if (a_e == 128) begin
165 //if b is zero return NaN
166 if (($signed(b_e) == -127) && (b_m == 0)) begin
173 //if b is inf return inf
174 end else if (b_e == 128) begin
178 //if a is zero return NaN
179 if (($signed(a_e) == -127) && (a_m == 0)) begin
186 //if a is zero return zero
187 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
192 //if b is zero return zero
193 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
200 //Denormalised Number
201 if ($signed(a_e) == -127) begin
206 //Denormalised Number
207 if ($signed(b_e) == -127) begin
212 state <= normalise_a;
219 state <= normalise_b;
239 z_e <= a_e + b_e + 1;
240 product <= a_m * b_m * 4;
246 z_m <= product[49:26];
247 guard <= product[25];
248 round_bit <= product[24];
249 sticky <= (product[23:0] != 0);
250 state <= normalise_1;
255 if (z_m[23] == 0) begin
262 state <= normalise_2;
268 if ($signed(z_e) < -126) begin
273 sticky <= sticky | round_bit;
281 if (guard && (round_bit | sticky | z_m[0])) begin
283 if (z_m == 24'hffffff) begin
292 z[22 : 0] <= z_m[22:0];
293 z[30 : 23] <= z_e[7:0] + 127;
295 if ($signed(z_e) == -126 && z_m[23] == 0) begin
300 if ($signed(z_e) > 127) begin
312 if (s_output_z_stb && output_z_ack) begin
320 if __name__
== "__main__":
321 alu
= FPMUL(width
=32)
322 main(alu
, ports
=alu
.in_a
.ports() + alu
.in_b
.ports() + alu
.out_z
.ports())