ad57a9ef63d27a2eaa55a5488d0897c46ea9a183
[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
88
89
90 """
91 special_cases:
92 begin
93 //if a is NaN or b is NaN return NaN
94 if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
95 z[31] <= 1;
96 z[30:23] <= 255;
97 z[22] <= 1;
98 z[21:0] <= 0;
99 state <= put_z;
100 //if a is inf return inf
101 end else if (a_e == 128) begin
102 z[31] <= a_s ^ b_s;
103 z[30:23] <= 255;
104 z[22:0] <= 0;
105 //if b is zero return NaN
106 if (($signed(b_e) == -127) && (b_m == 0)) begin
107 z[31] <= 1;
108 z[30:23] <= 255;
109 z[22] <= 1;
110 z[21:0] <= 0;
111 end
112 state <= put_z;
113 //if b is inf return inf
114 end else if (b_e == 128) begin
115 z[31] <= a_s ^ b_s;
116 z[30:23] <= 255;
117 z[22:0] <= 0;
118 //if a is zero return NaN
119 if (($signed(a_e) == -127) && (a_m == 0)) begin
120 z[31] <= 1;
121 z[30:23] <= 255;
122 z[22] <= 1;
123 z[21:0] <= 0;
124 end
125 state <= put_z;
126 //if a is zero return zero
127 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
128 z[31] <= a_s ^ b_s;
129 z[30:23] <= 0;
130 z[22:0] <= 0;
131 state <= put_z;
132 //if b is zero return zero
133 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
134 z[31] <= a_s ^ b_s;
135 z[30:23] <= 0;
136 z[22:0] <= 0;
137 state <= put_z;
138 end else begin
139 //Denormalised Number
140 if ($signed(a_e) == -127) begin
141 a_e <= -126;
142 end else begin
143 a_m[23] <= 1;
144 end
145 //Denormalised Number
146 if ($signed(b_e) == -127) begin
147 b_e <= -126;
148 end else begin
149 b_m[23] <= 1;
150 end
151 state <= normalise_a;
152 end
153 end
154
155 normalise_a:
156 begin
157 if (a_m[23]) begin
158 state <= normalise_b;
159 end else begin
160 a_m <= a_m << 1;
161 a_e <= a_e - 1;
162 end
163 end
164
165 normalise_b:
166 begin
167 if (b_m[23]) begin
168 state <= multiply_0;
169 end else begin
170 b_m <= b_m << 1;
171 b_e <= b_e - 1;
172 end
173 end
174
175 multiply_0:
176 begin
177 z_s <= a_s ^ b_s;
178 z_e <= a_e + b_e + 1;
179 product <= a_m * b_m * 4;
180 state <= multiply_1;
181 end
182
183 multiply_1:
184 begin
185 z_m <= product[49:26];
186 guard <= product[25];
187 round_bit <= product[24];
188 sticky <= (product[23:0] != 0);
189 state <= normalise_1;
190 end
191
192 normalise_1:
193 begin
194 if (z_m[23] == 0) begin
195 z_e <= z_e - 1;
196 z_m <= z_m << 1;
197 z_m[0] <= guard;
198 guard <= round_bit;
199 round_bit <= 0;
200 end else begin
201 state <= normalise_2;
202 end
203 end
204
205 normalise_2:
206 begin
207 if ($signed(z_e) < -126) begin
208 z_e <= z_e + 1;
209 z_m <= z_m >> 1;
210 guard <= z_m[0];
211 round_bit <= guard;
212 sticky <= sticky | round_bit;
213 end else begin
214 state <= round;
215 end
216 end
217
218 round:
219 begin
220 if (guard && (round_bit | sticky | z_m[0])) begin
221 z_m <= z_m + 1;
222 if (z_m == 24'hffffff) begin
223 z_e <=z_e + 1;
224 end
225 end
226 state <= pack;
227 end
228
229 pack:
230 begin
231 z[22 : 0] <= z_m[22:0];
232 z[30 : 23] <= z_e[7:0] + 127;
233 z[31] <= z_s;
234 if ($signed(z_e) == -126 && z_m[23] == 0) begin
235 z[30 : 23] <= 0;
236 end
237 //if overflow occurs, return inf
238 if ($signed(z_e) > 127) begin
239 z[22 : 0] <= 0;
240 z[30 : 23] <= 255;
241 z[31] <= z_s;
242 end
243 state <= put_z;
244 end
245
246 put_z:
247 begin
248 s_output_z_stb <= 1;
249 s_output_z <= z;
250 if (s_output_z_stb && output_z_ack) begin
251 s_output_z_stb <= 0;
252 state <= get_a;
253 end
254 end
255
256 """