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