OpenCores
URL https://opencores.org/ocsvn/ft816float/ft816float/trunk

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [verilog2/] [fpNormalize32combo.sv] - Blame information for rev 84

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 74 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2006-2022  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch@finitron.ca
6
//       ||
7
//
8
//      fpNormalize32combo.sv
9
//    - floating point normalization unit
10
//    - combinational logic only
11
//    - IEEE 754 representation
12
//
13
//
14
// BSD 3-Clause License
15
// Redistribution and use in source and binary forms, with or without
16
// modification, are permitted provided that the following conditions are met:
17
//
18
// 1. Redistributions of source code must retain the above copyright notice, this
19
//    list of conditions and the following disclaimer.
20
//
21
// 2. Redistributions in binary form must reproduce the above copyright notice,
22
//    this list of conditions and the following disclaimer in the documentation
23
//    and/or other materials provided with the distribution.
24
//
25
// 3. Neither the name of the copyright holder nor the names of its
26
//    contributors may be used to endorse or promote products derived from
27
//    this software without specific prior written permission.
28
//
29
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
33
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
37
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
//
40
//      This unit takes a floating point number in an intermediate
41
// format and normalizes it. No normalization occurs
42
// for NaN's or infinities. The unit has a two cycle latency.
43
//
44
// The mantissa is assumed to start with two whole bits on
45
// the left. The remaining bits are fractional.
46
//
47
// The width of the incoming format is reduced via a generation
48
// of sticky bit in place of the low order fractional bits.
49
//
50
// On an underflowed input, the incoming exponent is assumed
51
// to be negative. A right shift is needed.
52
// ============================================================================
53
 
54
import fp32Pkg::*;
55
 
56
module fpNormalize32combo(i, o, under_i, under_o, inexact_o);
57
input FP32X i;          // expanded format input
58
output FP32N o;         // normalized output + guard, sticky and round bits, + 1 whole digit
59
input under_i;
60
output reg under_o;
61
output reg inexact_o;
62
 
63
integer n;
64
// ----------------------------------------------------------------------------
65
// No Clock required
66
// ----------------------------------------------------------------------------
67
reg [fp32Pkg::EMSB+1:0] xo0;
68
reg so0;
69
 
70
always_comb
71
        xo0 <= {under_i,i.exp};
72
always_comb
73
        so0 <= i.sign;          // sign doesn't change
74
 
75
// ----------------------------------------------------------------------------
76
// Clock #1
77
// - Capture exponent information
78
// ----------------------------------------------------------------------------
79
reg xInf1a, xInf1b, xInf1c;
80
FP32X i1;
81
 
82
always_comb
83
        i1 <= i;
84
always_comb
85
        xInf1a <= &xo0 & !under_i;
86
always_comb
87
        xInf1b <= &xo0[fp32Pkg::EMSB:1] & !under_i;
88
always_comb
89
        xInf1c <= &xo0[fp32Pkg::EMSB:0] & !under_i;
90
 
91
// ----------------------------------------------------------------------------
92
// Clock #2
93
// - determine exponent increment
94
// Since the there are *three* whole digits in the incoming format
95
// the number of whole digits needs to be reduced. If the MSB is
96
// set, then increment the exponent and no shift is needed.
97
// ----------------------------------------------------------------------------
98
reg xInf2c, xInf2b;
99
reg [fp32Pkg::EMSB:0] xo2;
100
reg incExpByOne2, incExpByTwo2;
101
reg under2;
102
always_comb
103
        xInf2c <= xInf1c;
104
always_comb
105
        xInf2b <= xInf1b;
106
always_comb
107
        xo2 <= xo0;
108
always_comb
109
        under2 <= under_i;
110
always_comb
111
        incExpByTwo2 <= !xInf1b & i1[fp32Pkg::FX];
112
always_comb
113
        incExpByOne2 <= !xInf1a & i1[fp32Pkg::FX-1];
114
 
115
// ----------------------------------------------------------------------------
116
// Clock #3
117
// - increment exponent
118
// - detect a zero mantissa
119
// ----------------------------------------------------------------------------
120
 
121
reg incExpByTwo3;
122
reg incExpByOne3;
123
FP32X i3;
124
reg [fp32Pkg::EMSB+1:0] xo3;
125
reg zeroMan3;
126
always_comb
127
        incExpByTwo3 <= incExpByTwo2;
128
always_comb
129
        incExpByOne3 <= incExpByOne2;
130
always_comb
131
        i3 <= i;
132
wire [fp32Pkg::EMSB+1:0] xv3a = xo2 + {incExpByTwo2,1'b0};
133
wire [fp32Pkg::EMSB+1:0] xv3b = xo2 + incExpByOne2;
134
 
135
always_comb
136
        xo3 <= xo2 + (incExpByTwo2 ? 2'd2 : incExpByOne2 ? 2'd1 : 2'd0);
137
 
138
always_comb
139
        zeroMan3 <= ((xv3b[fp32Pkg::EMSB+1]|| &xv3b[fp32Pkg::EMSB:0])||(xv3a[fp32Pkg::EMSB+1]| &xv3a[fp32Pkg::EMSB:0]))
140
                                                                                         && !under2 && !xInf2c;
141
 
142
// ----------------------------------------------------------------------------
143
// Clock #4
144
// - Shift mantissa left
145
// - If infinity is reached then set the mantissa to zero
146
//   shift mantissa left to reduce to a single whole digit
147
// - create sticky bit
148
// ----------------------------------------------------------------------------
149
 
150
reg [fp32Pkg::FMSB+5:0] mo4;
151
reg inexact4;
152
 
153
always_comb
154
casez({zeroMan3,incExpByTwo3,incExpByOne3})
155
3'b1??: mo4 <= 1'd0;
156
3'b01?: mo4 <= {i3[fp32Pkg::FX:fp32Pkg::FMSB],|i3[fp32Pkg::FMSB-1:0]};
157
3'b001: mo4 <= {i3[fp32Pkg::FX-1:fp32Pkg::FMSB-1],|i3[fp32Pkg::FMSB-2:0]};
158
default:        mo4 <= {i3[fp32Pkg::FX-2:fp32Pkg::FMSB-2],|i3[fp32Pkg::FMSB-3:0]};
159
endcase
160
 
161
always_comb
162
casez({zeroMan3,incExpByTwo3,incExpByOne3})
163
3'b1??: inexact4 <= 1'd0;
164
3'b01?: inexact4 <= |i3[fp32Pkg::FMSB+1:0];
165
3'b001: inexact4 <= |i3[fp32Pkg::FMSB:0];
166
default:        inexact4 <= |i3[fp32Pkg::FMSB-1:0];
167
endcase
168
 
169
// ----------------------------------------------------------------------------
170
// Clock edge #5
171
// - count leading zeros
172
// ----------------------------------------------------------------------------
173
reg [7:0] leadingZeros5;
174
reg [fp32Pkg::EMSB+1:0] xo5;
175
reg xInf5;
176
always_comb
177
        xo5 <= xo3;
178
always_comb
179
        xInf5 <= xInf2c;
180
 
181
/* Lookup table based leading zero count modules give slightly better
182
   performance but cases must be coded.
183
generate
184
begin
185
if (FPWID <= 32) begin
186
cntlz32Reg clz0 (.clk(clk), .ce(ce), .i({mo4,4'b0}), .o(leadingZeros5) );
187
assign leadingZeros5[7:6] = 2'b00;
188
end
189
else if (FPWID<=32) begin
190
assign leadingZeros5[7] = 1'b0;
191
cntlz32Reg clz0 (.clk(clk), .ce(ce), .i({mo4,7'h0}), .o(leadingZeros5) );
192
end
193
else if (FPWID<=80) begin
194
assign leadingZeros5[7] = 1'b0;
195
cntlz80Reg clz0 (.clk(clk), .ce(ce), .i({mo4,11'b0}), .o(leadingZeros5) );
196
end
197
else if (FPWID<=84) begin
198
assign leadingZeros5[7] = 1'b0;
199
cntlz96Reg clz0 (.clk(clk), .ce(ce), .i({mo4,23'b0}), .o(leadingZeros5) );
200
end
201
else if (FPWID<=96) begin
202
assign leadingZeros5[7] = 1'b0;
203
cntlz96Reg clz0 (.clk(clk), .ce(ce), .i({mo4,11'b0}), .o(leadingZeros5) );
204
end
205
else if (FPWID<=128)
206
cntlz128Reg clz0 (.clk(clk), .ce(ce), .i({mo4,11'b0}), .o(leadingZeros5) );
207
end
208
endgenerate
209
*/
210
 
211
// Sideways add.
212
// Normally there would be only one to two leading zeros. It is tempting then
213
// to check for only one or two. But, denormalized numbers might have more
214
// leading zeros. If denormals were not supported this could be made smaller
215
// and faster.
216
`ifdef SUPPORT_DENORMALS
217
reg [7:0] lzc;
218
reg got_one;
219
always_comb
220
begin
221
  got_one = 1'b0;
222
  lzc = 8'h00;
223
  for (n = fp32Pkg::FMSB+5; n >= 0; n = n - 1) begin
224
    if (!got_one) begin
225
      if (mo4[n])
226
        got_one = 1'b1;
227
      else
228
        lzc = lzc + 1'b1;
229
    end
230
  end
231
end
232
always_comb
233
  leadingZeros5 <= lzc;
234
`else
235
always_comb
236
casez(mo4[fp32Pkg::FMSB+5:fp32Pkg::FMSB+4])
237
2'b1?:  leadingZeros5 <= 8'd0;
238
2'b01:  leadingZeros5 <= 8'd1;
239
2'b00:  leadingZeros5 <= 8'd2;
240
endcase
241
`endif
242
 
243
 
244
// ----------------------------------------------------------------------------
245
// Clock edge #6
246
// - Compute how much we want to decrement exponent by
247
// - compute amount to shift left and right
248
// - at infinity the exponent can't be incremented, so we can't shift right
249
//   otherwise it was an underflow situation so the exponent was negative
250
//   shift amount needs to be negated for shift register
251
// If the exponent underflowed, then the shift direction must be to the
252
// right regardless of mantissa bits; the number is denormalized.
253
// Otherwise the shift direction must be to the left.
254
// ----------------------------------------------------------------------------
255
reg [7:0] lshiftAmt6;
256
reg [7:0] rshiftAmt6;
257
reg rightOrLeft6;       // 0=left,1=right
258
reg xInf6;
259
reg [fp32Pkg::EMSB+1:0] xo6;
260
reg [fp32Pkg::FMSB+5:0] mo6;
261
reg zeroMan6;
262
always_comb
263
        rightOrLeft6 <= under_i;
264
always_comb
265
        xo6 <= xo5;
266
always_comb
267
        mo6 <= mo4;
268
always_comb
269
        xInf6 <= xInf5;
270
always_comb
271
        zeroMan6 <= zeroMan3;
272
 
273
always_comb
274
        lshiftAmt6 <= leadingZeros5 > xo5 ? xo5 : leadingZeros5;
275
 
276
always_comb
277
        rshiftAmt6 <= xInf5 ? 1'd0 : $signed(xo5) > 1'd0 ? 1'd0 : ~xo5+2'd1;    // xo2 is negative !
278
 
279
// ----------------------------------------------------------------------------
280
// Clock edge #7
281
// - figure exponent
282
// - shift mantissa
283
// - figure sticky bit
284
// ----------------------------------------------------------------------------
285
 
286
reg [fp32Pkg::EMSB:0] xo7;
287
reg rightOrLeft7;
288
reg [fp32Pkg::FMSB+5:0] mo7l, mo7r;
289
reg St6,St7;
290
always_comb
291
        rightOrLeft7 <= rightOrLeft6;
292
 
293
always_comb
294
        xo7 <= zeroMan6 ? xo6 :
295
                xInf6 ? xo6 :                                   // an infinite exponent is either a NaN or infinity; no need to change
296
                rightOrLeft6 ? 1'd0 :   // on a right shift, the exponent was negative, it's being made to zero
297
                xo6 - lshiftAmt6;                       // on a left shift, the exponent can't be decremented below zero
298
 
299
always_comb
300
        mo7r <= mo6 >> rshiftAmt6;
301
always_comb
302
        mo7l <= mo6 << lshiftAmt6;
303
 
304
// The sticky bit is set if the bits shifted out on a right shift are set.
305
always_comb
306
begin
307
  St6 = 1'b0;
308
  for (n = 0; n < FMSB+5; n = n + 1)
309
    if (n <= rshiftAmt6 + 1) St6 = St6|mo6[n];
310
end
311
always_comb
312
  St7 <= St6;
313
 
314
// ----------------------------------------------------------------------------
315
// Clock edge #8
316
// - select mantissa
317
// ----------------------------------------------------------------------------
318
 
319
reg so;
320
reg [fp32Pkg::EMSB:0] xo;
321
reg [fp32Pkg::FMSB+5:0] mo;
322
always_comb
323
        so <= so0;
324
always_comb
325
        xo <= xo7;
326
always_comb
327
        inexact_o <= inexact4;
328
always_comb
329
        under_o <= rightOrLeft7;
330
 
331
always_comb
332
        mo <= rightOrLeft7 ? mo7r|{St7,2'b0} : mo7l;
333
 
334
assign o.sign = so;
335
assign o.exp = xo;
336
assign o.sig = mo[FMSB+5:2];
337
 
338
endmodule
339
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.