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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [verilog/] [fpNormalize.v] - Blame information for rev 27

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 robfinch
`timescale 1ns / 1ps
2 6 robfinch
// ============================================================================
3
//        __
4 26 robfinch
//   \\__/ o\    (C) 2006-2019  Robert Finch, Waterloo
5 6 robfinch
//    \  __ /    All rights reserved.
6
//     \/_//     robfinch<remove>@finitron.ca
7
//       ||
8
//
9 8 robfinch
//      fpNormalize.v
10
//    - floating point normalization unit
11 27 robfinch
//    - eight cycle latency
12 8 robfinch
//    - parameterized width
13
//    - IEEE 754 representation
14
//
15
//
16 6 robfinch
// This source file is free software: you can redistribute it and/or modify 
17
// it under the terms of the GNU Lesser General Public License as published 
18
// by the Free Software Foundation, either version 3 of the License, or     
19
// (at your option) any later version.                                      
20
//                                                                          
21
// This source file is distributed in the hope that it will be useful,      
22
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
23
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
24
// GNU General Public License for more details.                             
25
//                                                                          
26
// You should have received a copy of the GNU General Public License        
27
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
28 8 robfinch
//                                                                          
29 6 robfinch
//      This unit takes a floating point number in an intermediate
30
// format and normalizes it. No normalization occurs
31
// for NaN's or infinities. The unit has a two cycle latency.
32
//
33 8 robfinch
// The mantissa is assumed to start with two whole bits on
34
// the left. The remaining bits are fractional.
35 6 robfinch
//
36
// The width of the incoming format is reduced via a generation
37
// of sticky bit in place of the low order fractional bits.
38
//
39
// On an underflowed input, the incoming exponent is assumed
40
// to be negative. A right shift is needed.
41
// ============================================================================
42 8 robfinch
 
43 27 robfinch
module fpNormalize(clk, ce, i, o, under_i, under_o, inexact_o);
44
parameter WID = 84;
45 26 robfinch
`include "fpSize.sv"
46 6 robfinch
 
47
input clk;
48
input ce;
49 8 robfinch
input [EX:0] i;          // expanded format input
50
output [WID+2:0] o;              // normalized output + guard, sticky and round bits, + 1 whole digit
51 27 robfinch
input under_i;
52
output under_o;
53
output inexact_o;
54 6 robfinch
 
55
 
56 27 robfinch
// ----------------------------------------------------------------------------
57
// No Clock required
58
// ----------------------------------------------------------------------------
59
reg [EMSB:0] xo0;
60
reg so0;
61 6 robfinch
 
62 27 robfinch
always @*
63
        xo0 <= i[EX-1:FX+1];
64
always @*
65
        so0 <= i[EX];           // sign doesn't change
66
 
67
// ----------------------------------------------------------------------------
68
// Clock #1
69
// - Capture exponent information
70
// ----------------------------------------------------------------------------
71
reg xInf1a, xInf1b, xInf1c;
72
wire [FX:0] i1;
73
delay1 #(FX+1) u11 (.clk(clk), .ce(ce), .i(i), .o(i1));
74
 
75
always @(posedge clk)
76
        if (ce) xInf1a <= &xo0 & !under_i;
77
always @(posedge clk)
78
        if (ce) xInf1b <= &xo0[EMSB:1] & !under_i;
79
always @(posedge clk)
80
        if (ce) xInf1c = &xo0;
81
 
82
// ----------------------------------------------------------------------------
83
// Clock #2
84
// - determine exponent increment
85 26 robfinch
// Since the there are *three* whole digits in the incoming format
86 6 robfinch
// the number of whole digits needs to be reduced. If the MSB is
87 8 robfinch
// set, then increment the exponent and no shift is needed.
88 27 robfinch
// ----------------------------------------------------------------------------
89
wire xInf2c, xInf2b;
90 6 robfinch
wire [EMSB:0] xo2;
91 27 robfinch
reg incExpByOne2, incExpByTwo2;
92
delay1 u21 (.clk(clk), .ce(ce), .i(xInf1c), .o(xInf2c));
93
delay1 u22 (.clk(clk), .ce(ce), .i(xInf1b), .o(xInf2b));
94
delay2 #(EMSB+1) u23 (.clk(clk), .ce(ce), .i(xo0), .o(xo2));
95
delay2 u24 (.clk(clk), .ce(ce), .i(under_i), .o(under2));
96 6 robfinch
 
97 27 robfinch
always @(posedge clk)
98
        if (ce) incExpByTwo2 <= !xInf1b & i1[FX];
99
always @(posedge clk)
100
        if (ce) incExpByOne2 <= !xInf1a & i1[FX-1];
101 6 robfinch
 
102 27 robfinch
// ----------------------------------------------------------------------------
103
// Clock #3
104
// - increment exponent
105
// - detect a zero mantissa
106
// ----------------------------------------------------------------------------
107
 
108
wire incExpByTwo3;
109
wire incExpByOne3;
110
wire [FX:0] i3;
111
reg [EMSB:0] xo3;
112
reg zeroMan3;
113
delay1 u31 (.clk(clk), .ce(ce), .i(incExpByTwo2), .o(incExpByTwo3));
114
delay1 u32 (.clk(clk), .ce(ce), .i(incExpByOne2), .o(incExpByOne3));
115
delay3 #(FX+1) u33 (.clk(clk), .ce(ce), .i(i[FX:0]), .o(i3));
116
wire [EMSB+1:0] xv3a = xo2 + {incExpByTwo2,1'b0};
117
wire [EMSB+1:0] xv3b = xo2 + incExpByOne2;
118
 
119
always @(posedge clk)
120
        if (ce) xo3 <= xo2 + (incExpByTwo2 ? 2'd2 : incExpByOne2 ? 2'd1 : 2'd0);
121
 
122
always @(posedge clk)
123
        if(ce) zeroMan3 <= ((xv3b[EMSB+1]|| &xv3b[EMSB:0])||(xv3a[EMSB+1]| &xv3a[EMSB:0]))
124
                                                                                         && !under2 && !xInf2c;
125
 
126
// ----------------------------------------------------------------------------
127
// Clock #4
128
// - Shift mantissa left
129
// - If infinity is reached then set the mantissa to zero
130
//   shift mantissa left to reduce to a single whole digit
131
// - create sticky bit
132
// ----------------------------------------------------------------------------
133
 
134
reg [FMSB+4:0] mo4;
135
reg inexact4;
136
 
137
always @(posedge clk)
138
if(ce)
139
casez({zeroMan3,incExpByTwo3,incExpByOne3})
140
3'b1??: mo4 <= 1'd0;
141
3'b01?: mo4 <= {i3[FX:FMSB+1],|i3[FMSB:0]};
142
3'b001: mo4 <= {i3[FX-1:FMSB],|i3[FMSB-1:0]};
143
default:        mo4 <= {i3[FX-2:FMSB-1],|i3[FMSB-2:0]};
144
endcase
145
 
146
always @(posedge clk)
147
if(ce)
148
casez({zeroMan3,incExpByTwo3,incExpByOne3})
149
3'b1??: inexact4 <= 1'd0;
150
3'b01?: inexact4 <= |i3[FMSB:0];
151
3'b001: inexact4 <= |i3[FMSB-1:0];
152
default:        inexact4 <= |i3[FMSB-2:0];
153
endcase
154
 
155
// ----------------------------------------------------------------------------
156
// Clock edge #5
157
// - count leading zeros
158
// ----------------------------------------------------------------------------
159
wire [7:0] leadingZeros5;
160
wire [EMSB:0] xo5;
161
wire xInf5;
162
delay2 #(EMSB+1) u51 (.clk(clk), .ce(ce), .i(xo3), .o(xo5));
163
delay3 #(1)      u52 (.clk(clk), .ce(ce), .i(xInf2c), .o(xInf5) );
164
 
165 6 robfinch
generate
166
begin
167 12 robfinch
if (WID <= 32) begin
168 27 robfinch
cntlz32Reg clz0 (.clk(clk), .ce(ce), .i({mo4,5'b0}), .o(leadingZeros5) );
169
assign leadingZeros5[7:6] = 2'b00;
170 10 robfinch
end
171 13 robfinch
else if (WID<=64) begin
172 27 robfinch
assign leadingZeros5[7] = 1'b0;
173
cntlz64Reg clz0 (.clk(clk), .ce(ce), .i({mo4,8'h0}), .o(leadingZeros5) );
174 11 robfinch
end
175 13 robfinch
else if (WID<=80) begin
176 27 robfinch
assign leadingZeros5[7] = 1'b0;
177
cntlz80Reg clz0 (.clk(clk), .ce(ce), .i({mo4,12'b0}), .o(leadingZeros5) );
178 11 robfinch
end
179 26 robfinch
else if (WID<=84) begin
180 27 robfinch
assign leadingZeros5[7] = 1'b0;
181
cntlz96Reg clz0 (.clk(clk), .ce(ce), .i({mo4,24'b0}), .o(leadingZeros5) );
182 26 robfinch
end
183 13 robfinch
else if (WID<=96) begin
184 27 robfinch
assign leadingZeros5[7] = 1'b0;
185
cntlz96Reg clz0 (.clk(clk), .ce(ce), .i({mo4,12'b0}), .o(leadingZeros5) );
186 6 robfinch
end
187 13 robfinch
else if (WID<=128)
188 27 robfinch
cntlz128Reg clz0 (.clk(clk), .ce(ce), .i({mo4,12'b0}), .o(leadingZeros5) );
189 11 robfinch
end
190 6 robfinch
endgenerate
191
 
192
 
193 27 robfinch
// ----------------------------------------------------------------------------
194
// Clock edge #6
195
// - Compute how much we want to decrement exponent by
196
// - compute amount to shift left and right
197
// - at infinity the exponent can't be incremented, so we can't shift right
198
//   otherwise it was an underflow situation so the exponent was negative
199
//   shift amount needs to be negated for shift register
200 6 robfinch
// If the exponent underflowed, then the shift direction must be to the
201
// right regardless of mantissa bits; the number is denormalized.
202
// Otherwise the shift direction must be to the left.
203 27 robfinch
// ----------------------------------------------------------------------------
204
reg [7:0] lshiftAmt6;
205
reg [7:0] rshiftAmt6;
206
wire rightOrLeft6;      // 0=left,1=right
207
wire xInf6;
208
wire [EMSB:0] xo6;
209
wire [FMSB+4:0] mo6;
210
wire zeroMan6;
211
vtdl #(1) u61 (.clk(clk), .ce(ce), .a(4'd5), .d(under_i), .q(rightOrLeft6) );
212
delay1 #(EMSB+1) u62 (.clk(clk), .ce(ce), .i(xo5), .o(xo6));
213
delay2 #(FMSB+5) u63 (.clk(clk), .ce(ce), .i(mo4), .o(mo6) );
214
delay1 #(1)      u64 (.clk(clk), .ce(ce), .i(xInf5), .o(xInf6) );
215
delay3 u65 (.clk(clk), .ce(ce),  .i(zeroMan3), .o(zeroMan6));
216 6 robfinch
 
217 27 robfinch
always @(posedge clk)
218
        if (ce) lshiftAmt6 <= leadingZeros5 > xo5 ? xo5 : leadingZeros5;
219 6 robfinch
 
220 27 robfinch
always @(posedge clk)
221
        if (ce) rshiftAmt6 <= xInf5 ? 1'd0 : $signed(xo5) > 1'd0 ? 1'd0 : ~xo5+2'd1;    // xo2 is negative !
222 6 robfinch
 
223 27 robfinch
// ----------------------------------------------------------------------------
224
// Clock edge #7
225
// - fogure exponent
226
// - shift mantissa
227
// ----------------------------------------------------------------------------
228 6 robfinch
 
229 27 robfinch
reg [EMSB:0] xo7;
230
wire rightOrLeft7;
231
reg [FMSB+4:0] mo7l, mo7r;
232
delay1 u71 (.clk(clk), .ce(ce), .i(rightOrLeft6), .i(rightOrLeft7));
233 6 robfinch
 
234 27 robfinch
always @(posedge clk)
235
if (ce)
236
        xo7 <= zeroMan6 ? xo6 :
237
                xInf6 ? xo6 :                                   // an infinite exponent is either a NaN or infinity; no need to change
238
                rightOrLeft6 ? 1'd0 :   // on a right shift, the exponent was negative, it's being made to zero
239
                xo6 - lshiftAmt6;                       // on a left shift, the exponent can't be decremented below zero
240 6 robfinch
 
241 27 robfinch
always @(posedge clk)
242
        if (ce) mo7r <= mo6 >> rshiftAmt6;
243
always @(posedge clk)
244
        if (ce) mo7l <= mo6 << lshiftAmt6;
245 6 robfinch
 
246
 
247 27 robfinch
// ----------------------------------------------------------------------------
248
// Clock edge #8
249
// - select mantissa
250
// ----------------------------------------------------------------------------
251
 
252
wire so;
253
wire [EMSB:0] xo;
254
reg [FMSB+4:0] mo;
255
vtdl #(1) u81 (.clk(clk), .ce(ce), .a(4'd7), .d(so0), .q(so) );
256
delay1 #(EMSB+1) u82 (.clk(clk), .ce(ce), .i(xo7), .i(xo));
257
vtdl u83 (.clk(clk), .ce(ce), .a(4'd3), .d(inexact4), .q(inexact_o));
258
delay1 u84 (.clk(clk), .ce(ce), .i(rightOrLeft7), .o(under_o));
259
 
260
always @(posedge clk)
261
        if (ce) mo <= rightOrLeft7 ? mo7r : mo7l;
262
 
263 8 robfinch
assign o = {so,xo,mo[FMSB+4:1]};
264 6 robfinch
 
265
endmodule
266 8 robfinch
 

powered by: WebSVN 2.1.0

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