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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [verilog2/] [fpMul.v] - Blame information for rev 84

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

Line No. Rev Author Line
1 29 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2006-2019  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
//      fpMul.v
9
//              - floating point multiplier
10
//              - two cycle latency
11
//              - can issue every clock cycle
12
//              - parameterized FPWIDth
13
//              - IEEE 754 representation
14
//
15
//
16
// 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
//                                                                          
29
//      Floating Point Multiplier / Divider
30
//
31
//      This multiplier/divider handles denormalized numbers.
32
//      The output format is of an internal expanded representation
33
//      in preparation to be fed into a normalization unit, then
34
//      rounding. Basically, it's the same as the regular format
35
//      except the mantissa is doubled in size, the leading two
36
//      bits of which are assumed to be whole bits.
37
//
38
//
39
//      Floating Point Multiplier
40
//
41
//      Properties:
42
//      +-inf * +-inf = -+inf   (this is handled by exOver)
43
//      +-inf * 0     = QNaN
44
//      
45
//      1 sign number
46
//      8 exponent
47
//      48 mantissa
48
//
49
// ============================================================================
50
 
51
`include "fpConfig.sv"
52
 
53
module fpMul (clk, ce, a, b, o, sign_exe, inf, overflow, underflow);
54
parameter FPWID = 32;
55
`include "fpSize.sv"
56
 
57
input clk;
58
input ce;
59
input  [MSB:0] a, b;
60
output [EX:0] o;
61
output sign_exe;
62
output inf;
63
output overflow;
64
output underflow;
65
 
66
reg [EMSB:0] xo1;                // extra bit for sign
67
reg [FX:0] mo1;
68
 
69
// constants
70
wire [EMSB:0] infXp = {EMSB+1{1'b1}};    // infinite / NaN - all ones
71
// The following is the value for an exponent of zero, with the offset
72
// eg. 8'h7f for eight bit exponent, 11'h7ff for eleven bit exponent, etc.
73
wire [EMSB:0] bias = {1'b0,{EMSB{1'b1}}};        //2^0 exponent
74
// The following is a template for a quiet nan. (MSB=1)
75
wire [FMSB:0] qNaN  = {1'b1,{FMSB{1'b0}}};
76
 
77
// variables
78
reg [FX:0] fract1,fract1a;
79
wire [FX:0] fracto;
80
wire [EMSB+2:0] ex1;     // sum of exponents
81
wire [EMSB  :0] ex2;
82
 
83
// Decompose the operands
84
wire sa, sb;                    // sign bit
85
wire [EMSB:0] xa, xb;    // exponent bits
86
wire [FMSB+1:0] fracta, fractb;
87
wire a_dn, b_dn;                        // a/b is denormalized
88
wire aNan, bNan, aNan1, bNan1;
89
wire az, bz;
90
wire aInf, bInf, aInf1, bInf1;
91
 
92
 
93
// -----------------------------------------------------------
94
// First clock
95
// - decode the input operands
96
// - derive basic information
97
// - calculate exponent
98
// - calculate fraction
99
// -----------------------------------------------------------
100
 
101
fpDecomp #(FPWID) u1a (.i(a), .sgn(sa), .exp(xa), .fract(fracta), .xz(a_dn), .vz(az), .inf(aInf), .nan(aNan) );
102
fpDecomp #(FPWID) u1b (.i(b), .sgn(sb), .exp(xb), .fract(fractb), .xz(b_dn), .vz(bz), .inf(bInf), .nan(bNan) );
103
 
104
// Compute the sum of the exponents.
105
// correct the exponent for denormalized operands
106
// adjust the sum by the exponent offset (subtract 127)
107
// mul: ex1 = xa + xb,  result should always be < 1ffh
108
assign ex1 = (az|bz) ? 0 : (xa|a_dn) + (xb|b_dn) - bias;
109
 
110
generate
111
if (FPWID+`EXTRA_BITS==80) begin
112
reg [31:0] p00,p01,p02,p03;
113
reg [31:0] p10,p11,p12,p13;
114
reg [31:0] p20,p21,p22,p23;
115
reg [31:0] p30,p31,p32,p33;
116
        always @(posedge clk)
117
        if (ce) begin
118
                p00 <= fracta[15: 0] * fractb[15: 0];
119
                p01 <= fracta[31:16] * fractb[15: 0];
120
                p02 <= fracta[47:32] * fractb[15: 0];
121
                p03 <= fracta[63:48] * fractb[15: 0];
122
 
123
                p10 <= fracta[15: 0] * fractb[31:16];
124
                p11 <= fracta[31:16] * fractb[31:16];
125
                p12 <= fracta[47:32] * fractb[31:16];
126
                p13 <= fracta[63:48] * fractb[31:16];
127
 
128
                p20 <= fracta[15: 0] * fractb[47:32];
129
                p21 <= fracta[31:16] * fractb[47:32];
130
                p22 <= fracta[47:32] * fractb[47:32];
131
                p23 <= fracta[63:48] * fractb[47:32];
132
 
133
                p30 <= fracta[15: 0] * fractb[63:48];
134
                p31 <= fracta[31:16] * fractb[63:48];
135
                p32 <= fracta[47:32] * fractb[63:48];
136
                p33 <= fracta[63:48] * fractb[63:48];
137
 
138
                fract1 <=                                               {p03,48'b0} + {p02,32'b0} + {p01,16'b0} + p00 +
139
                                                                  {p13,64'b0} + {p12,48'b0} + {p11,32'b0} + {p10,16'b0} +
140
                                        {p23,80'b0} + {p22,64'b0} + {p21,48'b0} + {p20,32'b0} +
141
      {p33,96'b0} + {p32,80'b0} + {p31,64'b0} + {p30,48'b0}
142
                                ;
143
        end
144
end
145
else if (FPWID+`EXTRA_BITS==64) begin
146
reg [35:0] p00,p01,p02;
147
reg [35:0] p10,p11,p12;
148
reg [35:0] p20,p21,p22;
149
        always @(posedge clk)
150
        if (ce) begin
151
                p00 <= fracta[17: 0] * fractb[17: 0];
152
                p01 <= fracta[35:18] * fractb[17: 0];
153
                p02 <= fracta[52:36] * fractb[17: 0];
154
                p10 <= fracta[17: 0] * fractb[35:18];
155
                p11 <= fracta[35:18] * fractb[35:18];
156
                p12 <= fracta[52:36] * fractb[35:18];
157
                p20 <= fracta[17: 0] * fractb[52:36];
158
                p21 <= fracta[35:18] * fractb[52:36];
159
                p22 <= fracta[52:36] * fractb[52:36];
160
                fract1 <=                                   {p02,36'b0} + {p01,18'b0} + p00 +
161
                                                                  {p12,54'b0} + {p11,36'b0} + {p10,18'b0} +
162
                                        {p22,72'b0} + {p21,54'b0} + {p20,36'b0}
163
                                ;
164
        end
165
end
166
else if (FPWID+`EXTRA_BITS==32) begin
167
reg [23:0] p00,p01,p02;
168
reg [23:0] p10,p11,p12;
169
reg [23:0] p20,p21,p22;
170
        always @(posedge clk)
171
        if (ce) begin
172
                p00 <= fracta[11: 0] * fractb[11: 0];
173
                p01 <= fracta[23:12] * fractb[11: 0];
174
                p10 <= fracta[11: 0] * fractb[23:12];
175
                p11 <= fracta[23:12] * fractb[23:12];
176
                fract1 <= {p11,p00} + {p01,12'b0} + {p10,12'b0};
177
        end
178
end
179
else begin
180
        always @(posedge clk)
181
    if (ce) begin
182
        fract1a <= fracta * fractb;
183
        fract1 <= fract1a;
184
    end
185
end
186
endgenerate
187
 
188
// Status
189
wire under1, over1;
190
wire under = ex1[EMSB+2];       // exponent underflow
191
wire over = (&ex1[EMSB:0] | ex1[EMSB+1]) & !ex1[EMSB+2];
192
 
193
delay2 #(EMSB+1) u3 (.clk(clk), .ce(ce), .i(ex1[EMSB:0]), .o(ex2) );
194
delay2 u2a (.clk(clk), .ce(ce), .i(aInf), .o(aInf1) );
195
delay2 u2b (.clk(clk), .ce(ce), .i(bInf), .o(bInf1) );
196
delay2 u6  (.clk(clk), .ce(ce), .i(under), .o(under1) );
197
delay2 u7  (.clk(clk), .ce(ce), .i(over), .o(over1) );
198
 
199
// determine when a NaN is output
200
wire qNaNOut;
201
wire [FPWID-1:0] a1,b1;
202
delay2 u5 (.clk(clk), .ce(ce), .i((aInf&bz)|(bInf&az)), .o(qNaNOut) );
203
delay2 u14 (.clk(clk), .ce(ce), .i(aNan), .o(aNan1) );
204
delay2 u15 (.clk(clk), .ce(ce), .i(bNan), .o(bNan1) );
205
delay2 #(FPWID) u16 (.clk(clk), .ce(ce), .i(a), .o(a1) );
206
delay2 #(FPWID) u17 (.clk(clk), .ce(ce), .i(b), .o(b1) );
207
 
208
// -----------------------------------------------------------
209
// Second clock
210
// - correct xponent and mantissa for exceptional conditions
211
// -----------------------------------------------------------
212
 
213
wire so1;
214
delay3 u8 (.clk(clk), .ce(ce), .i(sa ^ sb), .o(so1) );// two clock delay!
215
 
216
always @(posedge clk)
217
        if (ce)
218
                casez({qNaNOut|aNan1|bNan1,aInf1,bInf1,over1,under1})
219
                5'b1????:       xo1 = infXp;    // qNaN - infinity * zero
220
                5'b01???:       xo1 = infXp;    // 'a' infinite
221
                5'b001??:       xo1 = infXp;    // 'b' infinite
222
                5'b0001?:       xo1 = infXp;    // result overflow
223
                5'b00001:       xo1 = ex2[EMSB:0];//0;           // underflow
224
                default:        xo1 = ex2[EMSB:0];       // situation normal
225
                endcase
226
 
227
always @(posedge clk)
228
        if (ce)
229
                casez({aNan1,bNan1,qNaNOut,aInf1,bInf1,over1})
230
                6'b1?????:  mo1 = {1'b1,1'b1,a1[FMSB-1:0],{FMSB+1{1'b0}}};
231
    6'b01????:  mo1 = {1'b1,1'b1,b1[FMSB-1:0],{FMSB+1{1'b0}}};
232
                6'b001???:      mo1 = {1'b1,qNaN|3'd4,{FMSB+1{1'b0}}};  // multiply inf * zero
233
                6'b0001??:      mo1 = 0; // mul inf's
234
                6'b00001?:      mo1 = 0; // mul inf's
235
                6'b000001:      mo1 = 0; // mul overflow
236
                default:        mo1 = fract1;
237
                endcase
238
 
239
delay3 u10 (.clk(clk), .ce(ce), .i(sa & sb), .o(sign_exe) );
240
delay1 u11 (.clk(clk), .ce(ce), .i(over1),  .o(overflow) );
241
delay1 u12 (.clk(clk), .ce(ce), .i(over1),  .o(inf) );
242
delay1 u13 (.clk(clk), .ce(ce), .i(under1), .o(underflow) );
243
 
244
assign o = {so1,xo1,mo1};
245
 
246
endmodule
247
 
248
 
249
// Multiplier with normalization and rounding.
250
 
251
module fpMulnr(clk, ce, a, b, o, rm, sign_exe, inf, overflow, underflow);
252
parameter FPWID=32;
253
`include "fpSize.sv"
254
 
255
input clk;
256
input ce;
257
input  [MSB:0] a, b;
258
output [MSB:0] o;
259
input [2:0] rm;
260
output sign_exe;
261
output inf;
262
output overflow;
263
output underflow;
264
 
265
wire [EX:0] o1;
266
wire sign_exe1, inf1, overflow1, underflow1;
267
wire [MSB+3:0] fpn0;
268
 
269
fpMul       #(FPWID) u1 (clk, ce, a, b, o1, sign_exe1, inf1, overflow1, underflow1);
270
fpNormalize #(FPWID) u2(.clk(clk), .ce(ce), .under(underflow1), .i(o1), .o(fpn0) );
271
fpRoundReg  #(FPWID) u3(.clk(clk), .ce(ce), .rm(rm), .i(fpn0), .o(o) );
272
delay2      #(1)   u4(.clk(clk), .ce(ce), .i(sign_exe1), .o(sign_exe));
273
delay2      #(1)   u5(.clk(clk), .ce(ce), .i(inf1), .o(inf));
274
delay2      #(1)   u6(.clk(clk), .ce(ce), .i(overflow1), .o(overflow));
275
delay2      #(1)   u7(.clk(clk), .ce(ce), .i(underflow1), .o(underflow));
276
endmodule
277
 

powered by: WebSVN 2.1.0

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