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