product in multiply, not tot (was from add)
[ieee754fpu.git] / src / add / fmul.py
1 from nmigen import Module, Signal
2 from nmigen.cli import main, verilog
3
4 from fpbase import FPNum, FPOp, Overflow, FPBase
5
6
7 class FPMUL(FPBase):
8
9 def __init__(self, width):
10 FPBase.__init__(self)
11 self.width = width
12
13 self.in_a = FPOp(width)
14 self.in_b = FPOp(width)
15 self.out_z = FPOp(width)
16
17 def get_fragment(self, platform=None):
18 """ creates the HDL code-fragment for FPMUL
19 """
20 m = Module()
21
22 # Latches
23 a = FPNum(self.width, False)
24 b = FPNum(self.width, False)
25 z = FPNum(self.width, False)
26
27 mw = (self.m_width)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
28 product = Signal(mw)
29
30 of = Overflow()
31
32 with m.FSM() as fsm:
33
34 with m.State("get_a"):
35 m.next += "get_b"
36 m.d.sync += s.in_a.ack.eq(1)
37 with m.If(s.in_a.ack & in_a.stb):
38 m.d.sync += [
39 a.eq(in_a),
40 s.in_a.ack(0)
41 ]
42
43 with m.State("get_b"):
44 m.next += "unpack"
45 m.d.sync += s.in_b.ack.eq(1)
46 with m.If(s.in_b.ack & in_b.stb):
47 m.d.sync += [
48 b.eq(in_b),
49 s.in_b.ack(0)
50 ]
51
52 with m.State("unpack"):
53 m.next += "special_cases"
54 m.d.sync += [
55 a.m.eq(a[0:22]),
56 b.m.eq(b[0:22]),
57 a.e.eq(a[23:31] - 127),
58 b.e.eq(b[23:31] - 127),
59 a.s.eq(a[31]),
60 b.s.eq(b[31])
61 ]
62
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()):
67 m.next += "put_z"
68 m.d.sync += z.nan(1)
69 #if a is inf return inf
70 with m.Elif(a.is_inf()):
71 m.next += "put_z"
72 m.d.sync += z.inf(0)
73 #if b is zero return NaN
74 with m.If(b.is_zero()):
75 m.d.sync += z.nan(1)
76 #if b is inf return inf
77 with m.Elif(b.is_inf()):
78 m.next += "put_z"
79 m.d.sync += z.inf(0)
80 #if a is zero return NaN
81 with m.If(a.is_zero()):
82 m.next += "put_z"
83 m.d.sync += z.nan(1)
84 #if a is zero return zero
85 with m.Elif(a.is_zero()):
86 m.next += "put_z"
87 m.d.sync += z.zero(0)
88 #if b is zero return zero
89 with m.Elif(b.is_zero()):
90 m.next += "put_z"
91 m.d.sync += z.zero(0)
92 # Denormalised Number checks
93 with m.Else():
94 m.next += "normalise_a"
95 self.denormalise(m, a)
96 self.denormalise(m, b)
97
98 # ******
99 # normalise_a
100
101 with m.State("normalise_a"):
102 self.op_normalise(m, a, "normalise_b")
103
104 # ******
105 # normalise_b
106
107 with m.State("normalise_b"):
108 self.op_normalise(m, b, "multiply_0")
109
110 #multiply_0
111 with m.State("multiply_0"):
112 m.next += "multiply_1"
113 m.d.sync += [
114 z.s.eq(a.s ^ b.s),
115 z.e.eq(a.e + b.e + 1),
116 product.eq(a.m * b.m * 4)
117 ]
118
119 #multiply_1
120 with m.State("multiply_1"):
121 m.next += "normalise_1"
122 m.d.sync += [
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)
127 ]
128
129 # ******
130 # First stage of normalisation.
131 with m.State("normalise_1"):
132 self.normalise_1(m, z, of, "normalise_2")
133
134 # ******
135 # Second stage of normalisation.
136
137 with m.State("normalise_2"):
138 self.normalise_2(m, z, of, "round")
139
140 # ******
141 # rounding stage
142
143 with m.State("round"):
144 self.roundz(m, z, of, "corrections")
145
146 # ******
147 # pack stage
148 with m.State("pack"):
149 self.pack(m, z, "put_z")
150
151 # ******
152 # put_z stage
153
154 with m.State("put_z"):
155 self.put_z(m, z, self.out_z, "get_a")
156
157 return m
158
159 """
160 special_cases:
161 begin
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
164 z[31] <= 1;
165 z[30:23] <= 255;
166 z[22] <= 1;
167 z[21:0] <= 0;
168 state <= put_z;
169 //if a is inf return inf
170 end else if (a_e == 128) begin
171 z[31] <= a_s ^ b_s;
172 z[30:23] <= 255;
173 z[22:0] <= 0;
174 //if b is zero return NaN
175 if (($signed(b_e) == -127) && (b_m == 0)) begin
176 z[31] <= 1;
177 z[30:23] <= 255;
178 z[22] <= 1;
179 z[21:0] <= 0;
180 end
181 state <= put_z;
182 //if b is inf return inf
183 end else if (b_e == 128) begin
184 z[31] <= a_s ^ b_s;
185 z[30:23] <= 255;
186 z[22:0] <= 0;
187 //if a is zero return NaN
188 if (($signed(a_e) == -127) && (a_m == 0)) begin
189 z[31] <= 1;
190 z[30:23] <= 255;
191 z[22] <= 1;
192 z[21:0] <= 0;
193 end
194 state <= put_z;
195 //if a is zero return zero
196 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
197 z[31] <= a_s ^ b_s;
198 z[30:23] <= 0;
199 z[22:0] <= 0;
200 state <= put_z;
201 //if b is zero return zero
202 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
203 z[31] <= a_s ^ b_s;
204 z[30:23] <= 0;
205 z[22:0] <= 0;
206 state <= put_z;
207 //^ done up to here
208 end else begin
209 //Denormalised Number
210 if ($signed(a_e) == -127) begin
211 a_e <= -126;
212 end else begin
213 a_m[23] <= 1;
214 end
215 //Denormalised Number
216 if ($signed(b_e) == -127) begin
217 b_e <= -126;
218 end else begin
219 b_m[23] <= 1;
220 end
221 state <= normalise_a;
222 end
223 end
224
225 normalise_a:
226 begin
227 if (a_m[23]) begin
228 state <= normalise_b;
229 end else begin
230 a_m <= a_m << 1;
231 a_e <= a_e - 1;
232 end
233 end
234
235 normalise_b:
236 begin
237 if (b_m[23]) begin
238 state <= multiply_0;
239 end else begin
240 b_m <= b_m << 1;
241 b_e <= b_e - 1;
242 end
243 end
244
245 multiply_0:
246 begin
247 z_s <= a_s ^ b_s;
248 z_e <= a_e + b_e + 1;
249 product <= a_m * b_m * 4;
250 state <= multiply_1;
251 end
252
253 multiply_1:
254 begin
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;
260 end
261
262 normalise_1:
263 begin
264 if (z_m[23] == 0) begin
265 z_e <= z_e - 1;
266 z_m <= z_m << 1;
267 z_m[0] <= guard;
268 guard <= round_bit;
269 round_bit <= 0;
270 end else begin
271 state <= normalise_2;
272 end
273 end
274
275 normalise_2:
276 begin
277 if ($signed(z_e) < -126) begin
278 z_e <= z_e + 1;
279 z_m <= z_m >> 1;
280 guard <= z_m[0];
281 round_bit <= guard;
282 sticky <= sticky | round_bit;
283 end else begin
284 state <= round;
285 end
286 end
287
288 round:
289 begin
290 if (guard && (round_bit | sticky | z_m[0])) begin
291 z_m <= z_m + 1;
292 if (z_m == 24'hffffff) begin
293 z_e <=z_e + 1;
294 end
295 end
296 state <= pack;
297 end
298
299 pack:
300 begin
301 z[22 : 0] <= z_m[22:0];
302 z[30 : 23] <= z_e[7:0] + 127;
303 z[31] <= z_s;
304 if ($signed(z_e) == -126 && z_m[23] == 0) begin
305 z[30 : 23] <= 0;
306 end
307 //if overflow occur
308 s, return inf
309 if ($signed(z_e) > 127) begin
310 z[22 : 0] <= 0;
311 z[30 : 23] <= 255;
312 z[31] <= z_s;
313 end
314 state <= put_z;
315 end
316
317 put_z:
318 begin
319 s_output_z_stb <= 1;
320 s_output_z <= z;
321 if (s_output_z_stb && output_z_ack) begin
322 s_output_z_stb <= 0;
323 state <= get_a;
324 end
325 end
326
327 """
328
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())