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