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