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