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
.m_width
)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
34 with m
.State("get_a"):
36 m
.d
.sync
+= s
.in_a
.ack
.eq(1)
37 with m
.If(s
.in_a
.ack
& in_a
.stb
):
43 with m
.State("get_b"):
45 m
.d
.sync
+= s
.in_b
.ack
.eq(1)
46 with m
.If(s
.in_b
.ack
& in_b
.stb
):
52 with m
.State("unpack"):
53 m
.next
+= "special_cases"
57 a
.e
.eq(a
[23:31] - 127),
58 b
.e
.eq(b
[23:31] - 127),
63 with m
.State("special_cases"):
64 m
.next
= "normalise_a"
65 #if a or b is NaN return NaN
66 with m
.If(a
.is_nan() | b
.is_nan()):
69 #if a is inf return inf
70 with m
.Elif(a
.is_inf()):
73 #if b is zero return NaN
74 with m
.If(b
.is_zero()):
76 #if b is inf return inf
77 with m
.Elif(b
.is_inf()):
80 #if a is zero return NaN
81 with m
.If(a
.is_zero()):
84 #if a is zero return zero
85 with m
.Elif(a
.is_zero()):
88 #if b is zero return zero
89 with m
.Elif(b
.is_zero()):
92 # Denormalised Number checks
94 m
.next
+= "normalise_a"
95 self
.denormalise(m
, a
)
96 self
.denormalise(m
, b
)
101 with m
.State("normalise_a"):
102 self
.op_normalise(m
, a
, "normalise_b")
107 with m
.State("normalise_b"):
108 self
.op_normalise(m
, b
, "multiply_0")
111 with m
.State("multiply_0"):
112 m
.next
+= "multiply_1"
115 z
.e
.eq(a
.e
+ b
.e
+ 1),
116 product
.eq(a
.m
* b
.m
* 4)
120 with m
.State("multiply_1"):
121 m
.next
+= "normalise_1"
123 z
.m
.eq(product
[26:50]),
124 guard
.eq(product
[25]),
125 round_bit
.eq(product
[24]),
126 sticky
.eq(product
[0:23] != 0)
130 # First stage of normalisation.
131 with m
.State("normalise_1"):
132 self
.normalise_1(m
, z
, of
, "normalise_2")
135 # Second stage of normalisation.
137 with m
.State("normalise_2"):
138 self
.normalise_2(m
, z
, of
, "round")
143 with m
.State("round"):
144 self
.roundz(m
, z
, of
, "corrections")
148 with m
.State("pack"):
149 self
.pack(m
, z
, "put_z")
154 with m
.State("put_z"):
155 self
.put_z(m
, z
, self
.out_z
, "get_a")
162 //if a is NaN or b is NaN return NaN
163 if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
169 //if a is inf return inf
170 end else if (a_e == 128) begin
174 //if b is zero return NaN
175 if (($signed(b_e) == -127) && (b_m == 0)) begin
182 //if b is inf return inf
183 end else if (b_e == 128) begin
187 //if a is zero return NaN
188 if (($signed(a_e) == -127) && (a_m == 0)) begin
195 //if a is zero return zero
196 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
201 //if b is zero return zero
202 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
209 //Denormalised Number
210 if ($signed(a_e) == -127) begin
215 //Denormalised Number
216 if ($signed(b_e) == -127) begin
221 state <= normalise_a;
228 state <= normalise_b;
248 z_e <= a_e + b_e + 1;
249 product <= a_m * b_m * 4;
255 z_m <= product[49:26];
256 guard <= product[25];
257 round_bit <= product[24];
258 sticky <= (product[23:0] != 0);
259 state <= normalise_1;
264 if (z_m[23] == 0) begin
271 state <= normalise_2;
277 if ($signed(z_e) < -126) begin
282 sticky <= sticky | round_bit;
290 if (guard && (round_bit | sticky | z_m[0])) begin
292 if (z_m == 24'hffffff) begin
301 z[22 : 0] <= z_m[22:0];
302 z[30 : 23] <= z_e[7:0] + 127;
304 if ($signed(z_e) == -126 && z_m[23] == 0) begin
309 if ($signed(z_e) > 127) begin
321 if (s_output_z_stb && output_z_ack) begin
329 if __name__
== "__main__":
330 alu
= FPMUL(width
=32)
331 main(alu
, ports
=alu
.in_a
.ports() + alu
.in_b
.ports() + alu
.out_z
.ports())