1 |
2 |
rudi |
/////////////////////////////////////////////////////////////////////
|
2 |
|
|
//// ////
|
3 |
|
|
//// Post Norm ////
|
4 |
|
|
//// Floating Point Post Normalisation Unit ////
|
5 |
|
|
//// ////
|
6 |
|
|
//// Author: Rudolf Usselmann ////
|
7 |
|
|
//// rudi@asics.ws ////
|
8 |
|
|
//// ////
|
9 |
|
|
/////////////////////////////////////////////////////////////////////
|
10 |
|
|
//// ////
|
11 |
|
|
//// Copyright (C) 2000 Rudolf Usselmann ////
|
12 |
|
|
//// rudi@asics.ws ////
|
13 |
|
|
//// ////
|
14 |
|
|
//// This source file may be used and distributed without ////
|
15 |
|
|
//// restriction provided that this copyright statement is not ////
|
16 |
|
|
//// removed from the file and that any derivative work contains ////
|
17 |
|
|
//// the original copyright notice and the associated disclaimer.////
|
18 |
|
|
//// ////
|
19 |
|
|
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
20 |
|
|
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
21 |
|
|
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
22 |
|
|
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
23 |
|
|
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
24 |
|
|
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
25 |
|
|
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
26 |
|
|
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
27 |
|
|
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
28 |
|
|
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
29 |
|
|
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
30 |
|
|
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
31 |
|
|
//// POSSIBILITY OF SUCH DAMAGE. ////
|
32 |
|
|
//// ////
|
33 |
|
|
/////////////////////////////////////////////////////////////////////
|
34 |
|
|
|
35 |
|
|
|
36 |
|
|
`timescale 1ns / 100ps
|
37 |
|
|
|
38 |
5 |
rudi |
module post_norm( clk, fpu_op, opas, sign, rmode, fract_in, exp_in, exp_ovf,
|
39 |
2 |
rudi |
opa_dn, opb_dn, rem_00, div_opa_ldz, output_zero, out,
|
40 |
5 |
rudi |
ine, overflow, underflow, f2i_out_sign);
|
41 |
2 |
rudi |
input clk;
|
42 |
|
|
input [2:0] fpu_op;
|
43 |
5 |
rudi |
input opas;
|
44 |
2 |
rudi |
input sign;
|
45 |
|
|
input [1:0] rmode;
|
46 |
|
|
input [47:0] fract_in;
|
47 |
|
|
input [1:0] exp_ovf;
|
48 |
|
|
input [7:0] exp_in;
|
49 |
|
|
input opa_dn, opb_dn;
|
50 |
|
|
input rem_00;
|
51 |
|
|
input [4:0] div_opa_ldz;
|
52 |
|
|
input output_zero;
|
53 |
|
|
output [30:0] out;
|
54 |
|
|
output ine;
|
55 |
|
|
output overflow, underflow;
|
56 |
5 |
rudi |
output f2i_out_sign;
|
57 |
2 |
rudi |
|
58 |
|
|
////////////////////////////////////////////////////////////////////////
|
59 |
|
|
//
|
60 |
|
|
// Local Wires and registers
|
61 |
|
|
//
|
62 |
|
|
|
63 |
|
|
wire [22:0] fract_out;
|
64 |
|
|
wire [7:0] exp_out;
|
65 |
|
|
wire [30:0] out;
|
66 |
|
|
wire exp_out1_co, overflow, underflow;
|
67 |
|
|
wire [22:0] fract_out_final;
|
68 |
|
|
reg [22:0] fract_out_rnd;
|
69 |
|
|
wire [8:0] exp_next_mi;
|
70 |
|
|
wire dn;
|
71 |
|
|
wire exp_rnd_adj;
|
72 |
|
|
wire [7:0] exp_out_final;
|
73 |
|
|
reg [7:0] exp_out_rnd;
|
74 |
|
|
wire op_dn = opa_dn | opb_dn;
|
75 |
|
|
wire op_mul = fpu_op[2:0]==3'b010;
|
76 |
|
|
wire op_div = fpu_op[2:0]==3'b011;
|
77 |
5 |
rudi |
wire op_i2f = fpu_op[2:0]==3'b100;
|
78 |
|
|
wire op_f2i = fpu_op[2:0]==3'b101;
|
79 |
2 |
rudi |
reg [5:0] fi_ldz;
|
80 |
|
|
|
81 |
|
|
wire g, r, s;
|
82 |
|
|
wire round, round2, round2a, round2_fasu, round2_fmul;
|
83 |
|
|
wire [7:0] exp_out_rnd0, exp_out_rnd1, exp_out_rnd2, exp_out_rnd2a;
|
84 |
|
|
wire [22:0] fract_out_rnd0, fract_out_rnd1, fract_out_rnd2, fract_out_rnd2a;
|
85 |
|
|
wire exp_rnd_adj0, exp_rnd_adj2a;
|
86 |
|
|
wire r_sign;
|
87 |
|
|
wire ovf0, ovf1;
|
88 |
|
|
wire [23:0] fract_out_pl1;
|
89 |
|
|
wire [7:0] exp_out_pl1, exp_out_mi1;
|
90 |
|
|
wire exp_out_00, exp_out_fe, exp_out_ff, exp_in_00, exp_in_ff;
|
91 |
|
|
wire exp_out_final_ff, fract_out_7fffff;
|
92 |
|
|
wire [24:0] fract_trunc;
|
93 |
|
|
wire [7:0] exp_out1;
|
94 |
|
|
wire grs_sel;
|
95 |
|
|
wire fract_out_00, fract_in_00;
|
96 |
|
|
wire shft_co;
|
97 |
|
|
wire [8:0] exp_in_pl1, exp_in_mi1;
|
98 |
|
|
wire [47:0] fract_in_shftr;
|
99 |
|
|
wire [47:0] fract_in_shftl;
|
100 |
|
|
|
101 |
|
|
wire [7:0] exp_div;
|
102 |
|
|
wire [7:0] shft2;
|
103 |
|
|
wire [7:0] exp_out1_mi1;
|
104 |
|
|
wire div_dn;
|
105 |
|
|
wire div_nr;
|
106 |
|
|
wire grs_sel_div;
|
107 |
|
|
|
108 |
|
|
wire div_inf;
|
109 |
|
|
wire [6:0] fi_ldz_2a;
|
110 |
|
|
wire [7:0] fi_ldz_2;
|
111 |
|
|
wire [7:0] div_shft1, div_shft2, div_shft3, div_shft4;
|
112 |
|
|
wire div_shft1_co;
|
113 |
|
|
wire [8:0] div_exp1;
|
114 |
|
|
wire [7:0] div_exp2, div_exp3;
|
115 |
|
|
wire left_right, lr_mul, lr_div;
|
116 |
|
|
wire [7:0] shift_right, shftr_mul, shftr_div;
|
117 |
|
|
wire [7:0] shift_left, shftl_mul, shftl_div;
|
118 |
|
|
wire [7:0] fasu_shift;
|
119 |
|
|
wire [7:0] exp_fix_div;
|
120 |
|
|
|
121 |
|
|
wire [7:0] exp_fix_diva, exp_fix_divb;
|
122 |
|
|
wire [5:0] fi_ldz_mi1;
|
123 |
|
|
wire [5:0] fi_ldz_mi22;
|
124 |
|
|
wire exp_zero;
|
125 |
|
|
wire [6:0] ldz_all;
|
126 |
|
|
wire [7:0] ldz_dif;
|
127 |
|
|
|
128 |
5 |
rudi |
wire [8:0] div_scht1a;
|
129 |
|
|
wire [7:0] f2i_shft;
|
130 |
|
|
wire [55:0] exp_f2i_1;
|
131 |
|
|
wire f2i_zero, f2i_max;
|
132 |
|
|
wire [7:0] f2i_emin;
|
133 |
|
|
wire [7:0] conv_shft;
|
134 |
|
|
wire [7:0] exp_i2f, exp_f2i, conv_exp;
|
135 |
|
|
wire round2_f2i;
|
136 |
|
|
|
137 |
2 |
rudi |
////////////////////////////////////////////////////////////////////////
|
138 |
|
|
//
|
139 |
|
|
// Normalize and Round Logic
|
140 |
|
|
//
|
141 |
|
|
|
142 |
|
|
// ---------------------------------------------------------------------
|
143 |
|
|
// Count Leading zeros in fraction
|
144 |
|
|
|
145 |
|
|
always @(fract_in)
|
146 |
|
|
casex(fract_in) // synopsys full_case parallel_case
|
147 |
|
|
48'b1???????????????????????????????????????????????: fi_ldz = 1;
|
148 |
|
|
48'b01??????????????????????????????????????????????: fi_ldz = 2;
|
149 |
|
|
48'b001?????????????????????????????????????????????: fi_ldz = 3;
|
150 |
|
|
48'b0001????????????????????????????????????????????: fi_ldz = 4;
|
151 |
|
|
48'b00001???????????????????????????????????????????: fi_ldz = 5;
|
152 |
|
|
48'b000001??????????????????????????????????????????: fi_ldz = 6;
|
153 |
|
|
48'b0000001?????????????????????????????????????????: fi_ldz = 7;
|
154 |
|
|
48'b00000001????????????????????????????????????????: fi_ldz = 8;
|
155 |
|
|
48'b000000001???????????????????????????????????????: fi_ldz = 9;
|
156 |
|
|
48'b0000000001??????????????????????????????????????: fi_ldz = 10;
|
157 |
|
|
48'b00000000001?????????????????????????????????????: fi_ldz = 11;
|
158 |
|
|
48'b000000000001????????????????????????????????????: fi_ldz = 12;
|
159 |
|
|
48'b0000000000001???????????????????????????????????: fi_ldz = 13;
|
160 |
|
|
48'b00000000000001??????????????????????????????????: fi_ldz = 14;
|
161 |
|
|
48'b000000000000001?????????????????????????????????: fi_ldz = 15;
|
162 |
|
|
48'b0000000000000001????????????????????????????????: fi_ldz = 16;
|
163 |
|
|
48'b00000000000000001???????????????????????????????: fi_ldz = 17;
|
164 |
|
|
48'b000000000000000001??????????????????????????????: fi_ldz = 18;
|
165 |
|
|
48'b0000000000000000001?????????????????????????????: fi_ldz = 19;
|
166 |
|
|
48'b00000000000000000001????????????????????????????: fi_ldz = 20;
|
167 |
|
|
48'b000000000000000000001???????????????????????????: fi_ldz = 21;
|
168 |
|
|
48'b0000000000000000000001??????????????????????????: fi_ldz = 22;
|
169 |
|
|
48'b00000000000000000000001?????????????????????????: fi_ldz = 23;
|
170 |
|
|
48'b000000000000000000000001????????????????????????: fi_ldz = 24;
|
171 |
|
|
48'b0000000000000000000000001???????????????????????: fi_ldz = 25;
|
172 |
|
|
48'b00000000000000000000000001??????????????????????: fi_ldz = 26;
|
173 |
|
|
48'b000000000000000000000000001?????????????????????: fi_ldz = 27;
|
174 |
|
|
48'b0000000000000000000000000001????????????????????: fi_ldz = 28;
|
175 |
|
|
48'b00000000000000000000000000001???????????????????: fi_ldz = 29;
|
176 |
|
|
48'b000000000000000000000000000001??????????????????: fi_ldz = 30;
|
177 |
|
|
48'b0000000000000000000000000000001?????????????????: fi_ldz = 31;
|
178 |
|
|
48'b00000000000000000000000000000001????????????????: fi_ldz = 32;
|
179 |
|
|
48'b000000000000000000000000000000001???????????????: fi_ldz = 33;
|
180 |
|
|
48'b0000000000000000000000000000000001??????????????: fi_ldz = 34;
|
181 |
|
|
48'b00000000000000000000000000000000001?????????????: fi_ldz = 35;
|
182 |
|
|
48'b000000000000000000000000000000000001????????????: fi_ldz = 36;
|
183 |
|
|
48'b0000000000000000000000000000000000001???????????: fi_ldz = 37;
|
184 |
|
|
48'b00000000000000000000000000000000000001??????????: fi_ldz = 38;
|
185 |
|
|
48'b000000000000000000000000000000000000001?????????: fi_ldz = 39;
|
186 |
|
|
48'b0000000000000000000000000000000000000001????????: fi_ldz = 40;
|
187 |
|
|
48'b00000000000000000000000000000000000000001???????: fi_ldz = 41;
|
188 |
|
|
48'b000000000000000000000000000000000000000001??????: fi_ldz = 42;
|
189 |
|
|
48'b0000000000000000000000000000000000000000001?????: fi_ldz = 43;
|
190 |
|
|
48'b00000000000000000000000000000000000000000001????: fi_ldz = 44;
|
191 |
|
|
48'b000000000000000000000000000000000000000000001???: fi_ldz = 45;
|
192 |
|
|
48'b0000000000000000000000000000000000000000000001??: fi_ldz = 46;
|
193 |
|
|
48'b00000000000000000000000000000000000000000000001?: fi_ldz = 47;
|
194 |
|
|
48'b00000000000000000000000000000000000000000000000?: fi_ldz = 48;
|
195 |
|
|
endcase
|
196 |
|
|
|
197 |
|
|
|
198 |
|
|
// ---------------------------------------------------------------------
|
199 |
|
|
// Normalize
|
200 |
|
|
|
201 |
|
|
wire exp_in_80;
|
202 |
|
|
wire rmode_00, rmode_01, rmode_10, rmode_11;
|
203 |
|
|
|
204 |
|
|
// Misc common signals
|
205 |
|
|
assign exp_in_ff = &exp_in;
|
206 |
|
|
assign exp_in_00 = !(|exp_in);
|
207 |
|
|
assign exp_in_80 = exp_in[7] & !(|exp_in[6:0]);
|
208 |
|
|
assign exp_out_ff = &exp_out;
|
209 |
|
|
assign exp_out_00 = !(|exp_out);
|
210 |
|
|
assign exp_out_fe = &exp_out[7:1] & !exp_out[0];
|
211 |
|
|
assign exp_out_final_ff = &exp_out_final;
|
212 |
|
|
|
213 |
|
|
assign fract_out_7fffff = &fract_out;
|
214 |
|
|
assign fract_out_00 = !(|fract_out);
|
215 |
|
|
assign fract_in_00 = !(|fract_in);
|
216 |
|
|
|
217 |
|
|
assign rmode_00 = (rmode==2'b00);
|
218 |
|
|
assign rmode_01 = (rmode==2'b01);
|
219 |
|
|
assign rmode_10 = (rmode==2'b10);
|
220 |
|
|
assign rmode_11 = (rmode==2'b11);
|
221 |
|
|
|
222 |
|
|
// Fasu Output will be denormalized ...
|
223 |
|
|
assign dn = !op_mul & !op_div & (exp_in_00 | (exp_next_mi[8] & !fract_in[47]) );
|
224 |
|
|
|
225 |
|
|
// ---------------------------------------------------------------------
|
226 |
|
|
// Fraction Normalization
|
227 |
5 |
rudi |
parameter f2i_emax = 8'h9d;
|
228 |
2 |
rudi |
|
229 |
5 |
rudi |
// Incremented fraction for rounding
|
230 |
2 |
rudi |
assign fract_out_pl1 = fract_out + 1;
|
231 |
|
|
|
232 |
5 |
rudi |
// Special Signals for f2i
|
233 |
|
|
assign f2i_emin = rmode_00 ? 8'h7e : 8'h7f;
|
234 |
|
|
assign f2i_zero = (!opas & (exp_in<f2i_emin)) | (opas & (exp_in>f2i_emax)) | (opas & (exp_in<f2i_emin) & (fract_in_00 | !rmode_11));
|
235 |
|
|
assign f2i_max = (!opas & (exp_in>f2i_emax)) | (opas & (exp_in<f2i_emin) & !fract_in_00 & rmode_11);
|
236 |
|
|
|
237 |
2 |
rudi |
// Claculate various shifting options
|
238 |
|
|
|
239 |
|
|
assign {shft_co,shftr_mul} = (!exp_ovf[1] & exp_in_00) ? {1'b0, exp_out} : exp_in_mi1 ;
|
240 |
|
|
assign {div_shft1_co, div_shft1} = exp_in_00 ? {1'b0, div_opa_ldz} : div_scht1a;
|
241 |
|
|
|
242 |
|
|
assign div_scht1a = exp_in-div_opa_ldz; // 9 bits - includes carry out
|
243 |
|
|
assign div_shft2 = exp_in+2;
|
244 |
|
|
assign div_shft3 = div_opa_ldz+exp_in;
|
245 |
|
|
assign div_shft4 = div_opa_ldz-exp_in;
|
246 |
|
|
|
247 |
|
|
assign div_dn = op_dn & div_shft1_co;
|
248 |
|
|
assign div_nr = op_dn & exp_ovf[1] & !(|fract_in[46:23]) & (div_shft3>8'h16);
|
249 |
|
|
|
250 |
5 |
rudi |
assign f2i_shft = exp_in-8'h7d;
|
251 |
2 |
rudi |
|
252 |
|
|
// Select shifting direction
|
253 |
|
|
assign left_right = op_div ? lr_div : op_mul ? lr_mul : 1;
|
254 |
|
|
|
255 |
|
|
assign lr_div = (op_dn & !exp_ovf[1] & exp_ovf[0]) ? 1 :
|
256 |
|
|
(op_dn & exp_ovf[1]) ? 0 :
|
257 |
|
|
(op_dn & div_shft1_co) ? 0 :
|
258 |
|
|
(op_dn & exp_out_00) ? 1 :
|
259 |
|
|
(!op_dn & exp_out_00 & !exp_ovf[1]) ? 1 :
|
260 |
|
|
exp_ovf[1] ? 0 :
|
261 |
|
|
1;
|
262 |
|
|
assign lr_mul = (shft_co | (!exp_ovf[1] & exp_in_00) |
|
263 |
|
|
(!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00) )) ? 1 :
|
264 |
|
|
( exp_ovf[1] | exp_in_00 ) ? 0 :
|
265 |
|
|
1;
|
266 |
|
|
|
267 |
|
|
// Select Left and Right shift value
|
268 |
|
|
assign fasu_shift = (dn | exp_out_00) ? (exp_in_00 ? 8'h2 : exp_in_pl1[7:0]) : {2'h0, fi_ldz};
|
269 |
|
|
assign shift_right = op_div ? shftr_div : shftr_mul;
|
270 |
|
|
|
271 |
5 |
rudi |
assign conv_shft = op_f2i ? f2i_shft : {2'h0, fi_ldz};
|
272 |
|
|
|
273 |
|
|
assign shift_left = op_div ? shftl_div : op_mul ? shftl_mul : (op_f2i | op_i2f) ? conv_shft : fasu_shift;
|
274 |
|
|
|
275 |
2 |
rudi |
assign shftl_mul = (shft_co |
|
276 |
|
|
(!exp_ovf[1] & exp_in_00) |
|
277 |
|
|
(!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00))) ? exp_in_pl1[7:0] : {2'h0, fi_ldz};
|
278 |
|
|
|
279 |
|
|
assign shftl_div = ( op_dn & exp_out_00 & !(!exp_ovf[1] & exp_ovf[0])) ? div_shft1[7:0] :
|
280 |
|
|
(!op_dn & exp_out_00 & !exp_ovf[1]) ? exp_in[7:0] :
|
281 |
|
|
{2'h0, fi_ldz};
|
282 |
|
|
assign shftr_div = (op_dn & exp_ovf[1]) ? div_shft3 :
|
283 |
|
|
(op_dn & div_shft1_co) ? div_shft4 :
|
284 |
|
|
div_shft2;
|
285 |
|
|
// Do the actual shifting
|
286 |
5 |
rudi |
assign fract_in_shftr = (|shift_right[7:6]) ? 0 : fract_in>>shift_right[5:0];
|
287 |
|
|
assign fract_in_shftl = (|shift_left[7:6] | (f2i_zero & op_f2i)) ? 0 : fract_in<<shift_left[5:0];
|
288 |
2 |
rudi |
|
289 |
|
|
// Chose final fraction output
|
290 |
|
|
assign {fract_out,fract_trunc} = left_right ? fract_in_shftl : fract_in_shftr;
|
291 |
|
|
|
292 |
|
|
// ---------------------------------------------------------------------
|
293 |
|
|
// Exponent Normalization
|
294 |
|
|
|
295 |
|
|
assign fi_ldz_mi1 = fi_ldz - 1;
|
296 |
|
|
assign fi_ldz_mi22 = fi_ldz - 22;
|
297 |
|
|
assign exp_out_pl1 = exp_out + 1;
|
298 |
|
|
assign exp_out_mi1 = exp_out - 1;
|
299 |
|
|
assign exp_in_pl1 = exp_in + 1; // 9 bits - includes carry out
|
300 |
|
|
assign exp_in_mi1 = exp_in - 1; // 9 bits - includes carry out
|
301 |
|
|
assign exp_out1_mi1 = exp_out1 - 1;
|
302 |
|
|
|
303 |
|
|
assign exp_next_mi = exp_in_pl1 - fi_ldz_mi1; // 9 bits - includes carry out
|
304 |
5 |
rudi |
|
305 |
2 |
rudi |
assign exp_fix_diva = exp_in - fi_ldz_mi22;
|
306 |
|
|
assign exp_fix_divb = exp_in - fi_ldz_mi1;
|
307 |
|
|
|
308 |
|
|
assign exp_zero = (exp_ovf[1] & !exp_ovf[0] & op_mul & (!exp_rnd_adj2a | !rmode[1])) | (op_mul & exp_out1_co);
|
309 |
|
|
assign {exp_out1_co, exp_out1} = fract_in[47] ? exp_in_pl1 : exp_next_mi;
|
310 |
|
|
|
311 |
5 |
rudi |
assign f2i_out_sign = !opas ? ((exp_in<f2i_emin) ? 0 : (exp_in>f2i_emax) ? 0 : opas) :
|
312 |
|
|
((exp_in<f2i_emin) ? 0 : (exp_in>f2i_emax) ? 1 : opas);
|
313 |
|
|
|
314 |
|
|
assign exp_i2f = fract_in_00 ? (opas ? 8'h9e : 0) : (8'h9e-fi_ldz);
|
315 |
|
|
assign exp_f2i_1 = {{8{fract_in[47]}}, fract_in }<<f2i_shft;
|
316 |
|
|
assign exp_f2i = f2i_zero ? 0 : f2i_max ? 8'hff : exp_f2i_1[55:48];
|
317 |
|
|
assign conv_exp = op_f2i ? exp_f2i : exp_i2f;
|
318 |
|
|
|
319 |
|
|
assign exp_out = op_div ? exp_div : (op_f2i | op_i2f) ? conv_exp : exp_zero ? 8'h0 : dn ? {6'h0, fract_in[47:46]} : exp_out1;
|
320 |
|
|
|
321 |
2 |
rudi |
assign ldz_all = div_opa_ldz + fi_ldz;
|
322 |
|
|
assign ldz_dif = fi_ldz_2 - div_opa_ldz;
|
323 |
|
|
assign fi_ldz_2a = 6'd23 - fi_ldz;
|
324 |
|
|
assign fi_ldz_2 = {fi_ldz_2a[6], fi_ldz_2a[6:0]};
|
325 |
5 |
rudi |
|
326 |
2 |
rudi |
assign div_exp1 = exp_in_mi1 + fi_ldz_2; // 9 bits - includes carry out
|
327 |
5 |
rudi |
|
328 |
2 |
rudi |
assign div_exp2 = exp_in_pl1 - ldz_all;
|
329 |
|
|
assign div_exp3 = exp_in + ldz_dif;
|
330 |
|
|
|
331 |
|
|
assign exp_div =(opa_dn & opb_dn) ? div_exp3 :
|
332 |
|
|
opb_dn ? div_exp1[7:0] :
|
333 |
|
|
(opa_dn & !( (exp_in<div_opa_ldz) | (div_exp2>9'hfe) )) ? div_exp2 :
|
334 |
|
|
(opa_dn | (exp_in_00 & !exp_ovf[1]) ) ? 0 :
|
335 |
5 |
rudi |
exp_out1_mi1;
|
336 |
2 |
rudi |
|
337 |
|
|
assign div_inf = opb_dn & !opa_dn & (div_exp1[7:0] < 8'h7f);
|
338 |
|
|
|
339 |
|
|
// ---------------------------------------------------------------------
|
340 |
|
|
// Round
|
341 |
|
|
|
342 |
|
|
// Extract rounding (GRS) bits
|
343 |
|
|
assign grs_sel_div = op_div & (exp_ovf[1] | div_dn | exp_out1_co | exp_out_00);
|
344 |
|
|
|
345 |
|
|
assign g = grs_sel_div ? fract_out[0] : fract_out[0];
|
346 |
|
|
assign r = grs_sel_div ? (fract_trunc[24] & !div_nr) : fract_trunc[24];
|
347 |
|
|
assign s = grs_sel_div ? |fract_trunc[24:0] : (|fract_trunc[23:0] | (fract_trunc[24] & op_div));
|
348 |
|
|
|
349 |
|
|
// Round to nearest even
|
350 |
|
|
assign round = (g & r) | (r & s) ;
|
351 |
|
|
assign {exp_rnd_adj0, fract_out_rnd0} = round ? fract_out_pl1 : {1'b0, fract_out};
|
352 |
|
|
assign exp_out_rnd0 = exp_rnd_adj0 ? exp_out_pl1 : exp_out;
|
353 |
5 |
rudi |
assign ovf0 = exp_out_final_ff & !rmode_01 & !op_f2i;
|
354 |
2 |
rudi |
|
355 |
|
|
// round to zero
|
356 |
5 |
rudi |
assign fract_out_rnd1 = (exp_out_ff & !op_div & !dn & !op_f2i) ? 23'h7fffff : fract_out;
|
357 |
|
|
assign exp_fix_div = (fi_ldz>22) ? exp_fix_diva : exp_fix_divb;
|
358 |
2 |
rudi |
assign exp_out_rnd1 = (g & r & s & exp_in_ff) ? (op_div ? exp_fix_div : exp_next_mi[7:0]) :
|
359 |
5 |
rudi |
(exp_out_ff & !op_f2i) ? exp_in : exp_out;
|
360 |
2 |
rudi |
assign ovf1 = exp_out_ff & !dn;
|
361 |
|
|
|
362 |
|
|
// round to +inf (UP) and -inf (DOWN)
|
363 |
|
|
assign r_sign = sign;
|
364 |
|
|
|
365 |
|
|
assign round2a = !exp_out_fe | !fract_out_7fffff | (exp_out_fe & fract_out_7fffff);
|
366 |
|
|
assign round2_fasu = ((r | s) & !r_sign) & (!exp_out[7] | (exp_out[7] & round2a));
|
367 |
|
|
|
368 |
|
|
assign round2_fmul = !r_sign &
|
369 |
|
|
(
|
370 |
|
|
(exp_ovf[1] & !fract_in_00 &
|
371 |
|
|
( ((!exp_out1_co | op_dn) & (r | s | (!rem_00 & op_div) )) | fract_out_00 | (!op_dn & !op_div))
|
372 |
|
|
) |
|
373 |
|
|
(
|
374 |
|
|
(r | s | (!rem_00 & op_div)) & (
|
375 |
|
|
(!exp_ovf[1] & (exp_in_80 | !exp_ovf[0])) | op_div |
|
376 |
|
|
( exp_ovf[1] & !exp_ovf[0] & exp_out1_co)
|
377 |
|
|
)
|
378 |
|
|
)
|
379 |
|
|
);
|
380 |
|
|
|
381 |
5 |
rudi |
assign round2_f2i = rmode_10 & (( |fract_in[23:0] & !opas & (exp_in<8'h80 )) | (|fract_trunc));
|
382 |
|
|
assign round2 = (op_mul | op_div) ? round2_fmul : op_f2i ? round2_f2i : round2_fasu;
|
383 |
2 |
rudi |
|
384 |
|
|
assign {exp_rnd_adj2a, fract_out_rnd2a} = round2 ? fract_out_pl1 : {1'b0, fract_out};
|
385 |
5 |
rudi |
assign exp_out_rnd2a = exp_rnd_adj2a ? ((exp_ovf[1] & op_mul) ? exp_out_mi1 : exp_out_pl1) : exp_out;
|
386 |
2 |
rudi |
|
387 |
5 |
rudi |
assign fract_out_rnd2 = (r_sign & exp_out_ff & !op_div & !dn & !op_f2i) ? 23'h7fffff : fract_out_rnd2a;
|
388 |
|
|
assign exp_out_rnd2 = (r_sign & exp_out_ff & !op_f2i) ? 8'hfe : exp_out_rnd2a;
|
389 |
2 |
rudi |
|
390 |
|
|
|
391 |
|
|
// Choose rounding mode
|
392 |
|
|
always @(rmode or exp_out_rnd0 or exp_out_rnd1 or exp_out_rnd2)
|
393 |
|
|
case(rmode) // synopsys full_case parallel_case
|
394 |
|
|
0: exp_out_rnd = exp_out_rnd0;
|
395 |
|
|
1: exp_out_rnd = exp_out_rnd1;
|
396 |
|
|
2,3: exp_out_rnd = exp_out_rnd2;
|
397 |
|
|
endcase
|
398 |
|
|
|
399 |
|
|
always @(rmode or fract_out_rnd0 or fract_out_rnd1 or fract_out_rnd2)
|
400 |
|
|
case(rmode) // synopsys full_case parallel_case
|
401 |
|
|
0: fract_out_rnd = fract_out_rnd0;
|
402 |
|
|
1: fract_out_rnd = fract_out_rnd1;
|
403 |
|
|
2,3: fract_out_rnd = fract_out_rnd2;
|
404 |
|
|
endcase
|
405 |
|
|
|
406 |
|
|
// ---------------------------------------------------------------------
|
407 |
|
|
// Final Output Mux
|
408 |
|
|
// Fix Output for denormalized and special numbers
|
409 |
|
|
wire max_num, inf_out;
|
410 |
|
|
|
411 |
|
|
assign max_num = ( !rmode_00 & (op_mul | op_div ) & (
|
412 |
|
|
( exp_ovf[1] & exp_ovf[0]) |
|
413 |
|
|
(!exp_ovf[1] & !exp_ovf[0] & exp_in_ff & (fi_ldz_2<24) & (exp_out!=8'hfe) )
|
414 |
|
|
)
|
415 |
|
|
) |
|
416 |
|
|
|
417 |
|
|
( op_div & (
|
418 |
|
|
( rmode_01 & ( div_inf |
|
419 |
|
|
(exp_out_ff & !exp_ovf[1] ) |
|
420 |
|
|
(exp_ovf[1] & exp_ovf[0] )
|
421 |
|
|
)
|
422 |
|
|
) |
|
423 |
|
|
|
424 |
|
|
( rmode[1] & !exp_ovf[1] & (
|
425 |
|
|
( exp_ovf[0] & exp_in_ff & r_sign & fract_in[47]
|
426 |
|
|
) |
|
427 |
|
|
|
428 |
|
|
( r_sign & (
|
429 |
|
|
(fract_in[47] & div_inf) |
|
430 |
|
|
(exp_in[7] & !exp_out_rnd[7] & !exp_in_80 & exp_out!=8'h7f ) |
|
431 |
|
|
(exp_in[7] & exp_out_rnd[7] & r_sign & exp_out_ff & op_dn &
|
432 |
|
|
div_exp1>9'h0fe )
|
433 |
|
|
)
|
434 |
|
|
) |
|
435 |
|
|
|
436 |
|
|
( exp_in_00 & r_sign & (
|
437 |
|
|
div_inf |
|
438 |
|
|
(r_sign & exp_out_ff & fi_ldz_2<24)
|
439 |
|
|
)
|
440 |
|
|
)
|
441 |
|
|
)
|
442 |
|
|
)
|
443 |
|
|
)
|
444 |
|
|
);
|
445 |
|
|
|
446 |
|
|
|
447 |
|
|
assign inf_out = (rmode[1] & (op_mul | op_div) & !r_sign & ( (exp_in_ff & !op_div) |
|
448 |
|
|
(exp_ovf[1] & exp_ovf[0] & (exp_in_00 | exp_in[7]) )
|
449 |
|
|
)
|
450 |
|
|
) | (div_inf & op_div & (
|
451 |
|
|
rmode_00 |
|
452 |
|
|
(rmode[1] & !exp_in_ff & !exp_ovf[1] & !exp_ovf[0] & !r_sign ) |
|
453 |
|
|
(rmode[1] & !exp_ovf[1] & exp_ovf[0] & exp_in_00 & !r_sign)
|
454 |
|
|
)
|
455 |
|
|
) | (op_div & rmode[1] & exp_in_ff & op_dn & !r_sign & (fi_ldz_2 < 24) & (exp_out_rnd!=8'hfe) );
|
456 |
|
|
|
457 |
5 |
rudi |
assign fract_out_final = (inf_out | ovf0 | output_zero ) ? 23'h0 :
|
458 |
|
|
(max_num | (f2i_max & op_f2i) ) ? 23'h7fffff :
|
459 |
2 |
rudi |
fract_out_rnd;
|
460 |
|
|
|
461 |
5 |
rudi |
assign exp_out_final = ((op_div & exp_ovf[1] & !exp_ovf[0]) | output_zero ) ? 8'h00 :
|
462 |
|
|
((op_div & exp_ovf[1] & exp_ovf[0] & rmode_00) | inf_out | (f2i_max & op_f2i) ) ? 8'hff :
|
463 |
2 |
rudi |
max_num ? 8'hfe :
|
464 |
|
|
exp_out_rnd;
|
465 |
|
|
|
466 |
|
|
|
467 |
|
|
// ---------------------------------------------------------------------
|
468 |
|
|
// Pack Result
|
469 |
|
|
|
470 |
|
|
assign out = {exp_out_final, fract_out_final};
|
471 |
|
|
|
472 |
|
|
// ---------------------------------------------------------------------
|
473 |
|
|
// Exceptions
|
474 |
|
|
wire underflow_fmul;
|
475 |
|
|
wire overflow_fdiv;
|
476 |
|
|
wire undeflow_div;
|
477 |
|
|
|
478 |
|
|
wire z = shft_co | ( exp_ovf[1] | exp_in_00) |
|
479 |
|
|
(!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00));
|
480 |
|
|
|
481 |
|
|
assign underflow_fmul = ( (|fract_trunc) & z & !exp_in_ff ) |
|
482 |
|
|
(fract_out_00 & !fract_in_00 & exp_ovf[1]);
|
483 |
|
|
|
484 |
|
|
assign undeflow_div = !(exp_ovf[1] & exp_ovf[0] & rmode_00) & !inf_out & !max_num & exp_out_final!=8'hff & (
|
485 |
|
|
|
486 |
|
|
((|fract_trunc) & !opb_dn & (
|
487 |
|
|
( op_dn & !exp_ovf[1] & exp_ovf[0]) |
|
488 |
|
|
( op_dn & exp_ovf[1]) |
|
489 |
|
|
( op_dn & div_shft1_co) |
|
490 |
|
|
exp_out_00 |
|
491 |
|
|
exp_ovf[1]
|
492 |
|
|
)
|
493 |
|
|
|
494 |
|
|
) |
|
495 |
|
|
|
496 |
|
|
( exp_ovf[1] & !exp_ovf[0] & (
|
497 |
|
|
( op_dn & exp_in>8'h16 & fi_ldz<23) |
|
498 |
|
|
( op_dn & exp_in<23 & fi_ldz<23 & !rem_00) |
|
499 |
|
|
( !op_dn & (exp_in[7]==exp_div[7]) & !rem_00) |
|
500 |
|
|
( !op_dn & exp_in_00 & (exp_div[7:1]==7'h7f) ) |
|
501 |
|
|
( !op_dn & exp_in<8'h7f & exp_in>8'h20 )
|
502 |
|
|
)
|
503 |
|
|
) |
|
504 |
|
|
|
505 |
|
|
(!exp_ovf[1] & !exp_ovf[0] & (
|
506 |
|
|
( op_dn & fi_ldz<23 & exp_out_00) |
|
507 |
|
|
( exp_in_00 & !rem_00) |
|
508 |
|
|
( !op_dn & ldz_all<23 & exp_in==1 & exp_out_00 & !rem_00)
|
509 |
|
|
)
|
510 |
|
|
)
|
511 |
|
|
|
512 |
|
|
);
|
513 |
|
|
|
514 |
|
|
assign underflow = op_div ? undeflow_div : op_mul ? underflow_fmul : (!fract_in[47] & exp_out1_co) & !dn;
|
515 |
|
|
|
516 |
|
|
assign overflow_fdiv = inf_out |
|
517 |
|
|
(!rmode_00 & max_num) |
|
518 |
|
|
(exp_in[7] & op_dn & exp_out_ff) |
|
519 |
|
|
(exp_ovf[0] & (exp_ovf[1] | exp_out_ff) );
|
520 |
|
|
|
521 |
|
|
assign overflow = op_div ? overflow_fdiv : (ovf0 | ovf1);
|
522 |
|
|
|
523 |
5 |
rudi |
wire f2i_ine;
|
524 |
|
|
|
525 |
|
|
assign f2i_ine = (f2i_zero & !fract_in_00 & !opas) |
|
526 |
|
|
(|fract_trunc) |
|
527 |
|
|
(f2i_zero & (exp_in<8'h80) & opas & !fract_in_00) |
|
528 |
|
|
(f2i_max & rmode_11 & (exp_in<8'h80));
|
529 |
|
|
|
530 |
|
|
|
531 |
|
|
|
532 |
|
|
assign ine = op_f2i ? f2i_ine :
|
533 |
|
|
op_i2f ? (|fract_trunc) :
|
534 |
|
|
((r & !dn) | (s & !dn) | max_num | (op_div & !rem_00));
|
535 |
|
|
|
536 |
2 |
rudi |
// ---------------------------------------------------------------------
|
537 |
|
|
// Debugging Stuff
|
538 |
|
|
|
539 |
|
|
// synopsys translate_off
|
540 |
|
|
|
541 |
|
|
wire [26:0] fracta_del, fractb_del;
|
542 |
|
|
wire [2:0] grs_del;
|
543 |
|
|
wire dn_del;
|
544 |
|
|
wire [7:0] exp_in_del;
|
545 |
|
|
wire [7:0] exp_out_del;
|
546 |
|
|
wire [22:0] fract_out_del;
|
547 |
|
|
wire [47:0] fract_in_del;
|
548 |
|
|
wire overflow_del;
|
549 |
|
|
wire [1:0] exp_ovf_del;
|
550 |
5 |
rudi |
wire [22:0] fract_out_x_del, fract_out_rnd2a_del;
|
551 |
2 |
rudi |
wire [24:0] trunc_xx_del;
|
552 |
|
|
wire exp_rnd_adj2a_del;
|
553 |
|
|
wire [22:0] fract_dn_del;
|
554 |
|
|
wire [4:0] div_opa_ldz_del;
|
555 |
|
|
wire [23:0] fracta_div_del;
|
556 |
|
|
wire [23:0] fractb_div_del;
|
557 |
|
|
wire div_inf_del;
|
558 |
|
|
wire [7:0] fi_ldz_2_del;
|
559 |
|
|
wire inf_out_del, max_out_del;
|
560 |
|
|
wire [5:0] fi_ldz_del;
|
561 |
|
|
wire rx_del;
|
562 |
|
|
wire ez_del;
|
563 |
5 |
rudi |
wire lr;
|
564 |
|
|
wire [7:0] shr, shl, exp_div_del;
|
565 |
2 |
rudi |
|
566 |
|
|
delay2 #26 ud000(clk, test.u0.fracta, fracta_del);
|
567 |
|
|
delay2 #26 ud001(clk, test.u0.fractb, fractb_del);
|
568 |
|
|
delay1 #2 ud002(clk, {g,r,s}, grs_del);
|
569 |
|
|
delay1 #0 ud004(clk, dn, dn_del);
|
570 |
|
|
delay1 #7 ud005(clk, exp_in, exp_in_del);
|
571 |
|
|
delay1 #7 ud007(clk, exp_out_rnd, exp_out_del);
|
572 |
|
|
delay1 #47 ud009(clk, fract_in, fract_in_del);
|
573 |
|
|
delay1 #0 ud010(clk, overflow, overflow_del);
|
574 |
|
|
delay1 #1 ud011(clk, exp_ovf, exp_ovf_del);
|
575 |
|
|
delay1 #22 ud014(clk, fract_out, fract_out_x_del);
|
576 |
|
|
delay1 #24 ud015(clk, fract_trunc, trunc_xx_del);
|
577 |
|
|
delay1 #0 ud017(clk, exp_rnd_adj2a, exp_rnd_adj2a_del);
|
578 |
|
|
delay1 #4 ud019(clk, div_opa_ldz, div_opa_ldz_del);
|
579 |
|
|
delay3 #23 ud020(clk, test.u0.fdiv_opa[49:26], fracta_div_del);
|
580 |
|
|
delay3 #23 ud021(clk, test.u0.fractb_mul, fractb_div_del);
|
581 |
|
|
delay1 #0 ud023(clk, div_inf, div_inf_del);
|
582 |
|
|
delay1 #7 ud024(clk, fi_ldz_2, fi_ldz_2_del);
|
583 |
|
|
delay1 #0 ud025(clk, inf_out, inf_out_del);
|
584 |
|
|
delay1 #0 ud026(clk, max_num, max_num_del);
|
585 |
|
|
delay1 #5 ud027(clk, fi_ldz, fi_ldz_del);
|
586 |
|
|
delay1 #0 ud028(clk, rem_00, rx_del);
|
587 |
|
|
|
588 |
5 |
rudi |
delay1 #0 ud029(clk, left_right, lr);
|
589 |
|
|
delay1 #7 ud030(clk, shift_right, shr);
|
590 |
|
|
delay1 #7 ud031(clk, shift_left, shl);
|
591 |
|
|
delay1 #22 ud032(clk, fract_out_rnd2a, fract_out_rnd2a_del);
|
592 |
|
|
|
593 |
|
|
delay1 #7 ud033(clk, exp_div, exp_div_del);
|
594 |
|
|
|
595 |
2 |
rudi |
always @(test.error_event)
|
596 |
|
|
begin
|
597 |
|
|
|
598 |
|
|
$display("\n----------------------------------------------");
|
599 |
|
|
|
600 |
|
|
$display("ERROR: GRS: %b exp_ovf: %b dn: %h exp_in: %h exp_out: %h, exp_rnd_adj2a: %b",
|
601 |
|
|
grs_del, exp_ovf_del, dn_del, exp_in_del, exp_out_del, exp_rnd_adj2a_del);
|
602 |
|
|
|
603 |
5 |
rudi |
$display(" div_opa: %b, div_opb: %b, rem_00: %b, exp_div: %h",
|
604 |
|
|
fracta_div_del, fractb_div_del, rx_del, exp_div_del);
|
605 |
2 |
rudi |
|
606 |
5 |
rudi |
$display(" lr: %b, shl: %h, shr: %h",
|
607 |
|
|
lr, shl, shr);
|
608 |
|
|
|
609 |
|
|
|
610 |
2 |
rudi |
$display(" overflow: %b, fract_in=%b fa:%h fb:%h",
|
611 |
|
|
overflow_del, fract_in_del, fracta_del, fractb_del);
|
612 |
|
|
|
613 |
|
|
$display(" div_opa_ldz: %h, div_inf: %b, inf_out: %b, max_num: %b, fi_ldz: %h, fi_ldz_2: %h",
|
614 |
|
|
div_opa_ldz_del, div_inf_del, inf_out_del, max_num_del, fi_ldz_del, fi_ldz_2_del);
|
615 |
|
|
|
616 |
5 |
rudi |
$display(" fract_out_x: %b, fract_out_rnd2a_del: %h, fract_trunc: %b\n",
|
617 |
|
|
fract_out_x_del, fract_out_rnd2a_del, trunc_xx_del);
|
618 |
2 |
rudi |
end
|
619 |
|
|
|
620 |
|
|
|
621 |
|
|
// synopsys translate_on
|
622 |
|
|
|
623 |
|
|
endmodule
|
624 |
|
|
|
625 |
|
|
// synopsys translate_off
|
626 |
|
|
|
627 |
|
|
module delay1(clk, in, out);
|
628 |
|
|
parameter N = 1;
|
629 |
|
|
input [N:0] in;
|
630 |
|
|
output [N:0] out;
|
631 |
|
|
input clk;
|
632 |
|
|
|
633 |
|
|
reg [N:0] out;
|
634 |
|
|
|
635 |
|
|
always @(posedge clk)
|
636 |
|
|
out <= #1 in;
|
637 |
|
|
|
638 |
|
|
endmodule
|
639 |
|
|
|
640 |
|
|
|
641 |
|
|
module delay2(clk, in, out);
|
642 |
|
|
parameter N = 1;
|
643 |
|
|
input [N:0] in;
|
644 |
|
|
output [N:0] out;
|
645 |
|
|
input clk;
|
646 |
|
|
|
647 |
|
|
reg [N:0] out, r1;
|
648 |
|
|
|
649 |
|
|
always @(posedge clk)
|
650 |
|
|
r1 <= #1 in;
|
651 |
|
|
|
652 |
|
|
always @(posedge clk)
|
653 |
|
|
out <= #1 r1;
|
654 |
|
|
|
655 |
|
|
endmodule
|
656 |
|
|
|
657 |
|
|
module delay3(clk, in, out);
|
658 |
|
|
parameter N = 1;
|
659 |
|
|
input [N:0] in;
|
660 |
|
|
output [N:0] out;
|
661 |
|
|
input clk;
|
662 |
|
|
|
663 |
|
|
reg [N:0] out, r1, r2;
|
664 |
|
|
|
665 |
|
|
always @(posedge clk)
|
666 |
|
|
r1 <= #1 in;
|
667 |
|
|
|
668 |
|
|
always @(posedge clk)
|
669 |
|
|
r2 <= #1 r1;
|
670 |
|
|
|
671 |
|
|
always @(posedge clk)
|
672 |
|
|
out <= #1 r2;
|
673 |
|
|
|
674 |
|
|
endmodule
|
675 |
|
|
|
676 |
|
|
// synopsys translate_on
|