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