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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [verilog/] [fpUnit.v] - Blame information for rev 38

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

Line No. Rev Author Line
1 9 robfinch
// ============================================================================
2
//        __
3 26 robfinch
//   \\__/ o\    (C) 2006-2019  Robert Finch, Waterloo
4 9 robfinch
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
// This source file is free software: you can redistribute it and/or modify 
9
// it under the terms of the GNU Lesser General Public License as published 
10
// by the Free Software Foundation, either version 3 of the License, or     
11
// (at your option) any later version.                                      
12
//                                                                          
13
// This source file is distributed in the hope that it will be useful,      
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
16
// GNU General Public License for more details.                             
17
//                                                                          
18
// You should have received a copy of the GNU General Public License        
19
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
20
//
21
//
22
//      fpUnit.v
23
//  - floating point unit
24
//  - parameterized width
25
//  - IEEE 754 representation
26
//
27
//      NaN Value               Origin
28
// 31'h7FC00001    - infinity - infinity
29
// 31'h7FC00002    - infinity / infinity
30
// 31'h7FC00003    - zero / zero
31
// 31'h7FC00004    - infinity X zero
32 26 robfinch
// 31'h7FC00005    - square root of infinity
33
// 31'h7FC00006          - square root of negative number
34 9 robfinch
//
35
// Whenever the fpu encounters a NaN input, the NaN is
36
// passed through to the output.
37
//
38
// Ref: Webpack 8.2  Spartan3-4  xc3s1000-4ft256
39
// 2335 LUTS / 1260 slices / 43.4 MHz
40
// Ref: Webpack 13.1 Spartan3e   xc3s1200e-4fg320
41
// 2433 LUTs / 1301 slices / 51.6 MHz
42
//
43
// Instr.  Cyc Lat
44
// fc__    ; 1  0    compare, lt le gt ge eq ne or un
45
// fabs    ; 1  0     absolute value
46
// fnabs    ; 1  0     negative absolute value
47
// fneg    ; 1  0     negate
48
// fmov    ; 1  0     move
49
// fman    ; 1  0     get mantissa
50
// fsign    ; 1  0     get sign
51
//
52
// f2i        ; 1  1  convert float to integer
53
// i2f        ; 1  1  convert integer to float
54
//
55
// fadd    ; 1  5    addition
56
// fsub    ; 1  5  subtraction
57
// fmul    ; 1  6  multiplication
58
//
59
// fdiv    ; 43 43  division
60
//
61
// ftx        ; 1  0  trigger fp exception
62
// fcx        ; 1  0  clear fp exception
63
// fex        ; 1  0  enable fp exception
64
// fdx        ; 1  0  disable fp exception
65
// frm        ; 1  0  set rounding mode
66
// fstat    ; 1  0  get status register
67
//
68
// related integer:
69
// graf    ; 1  0  get random float (0,1]
70
//
71
// ============================================================================
72
//
73 10 robfinch
`define TRUE    1'b1
74
`define FALSE   1'b0
75 9 robfinch
 
76 10 robfinch
`define VECTOR  6'h01
77
`define VFABS       6'h03
78
`define VFADD       6'h04
79
`define VFSUB       6'h05
80
`define VFSxx       6'h06
81
`define VFNEG       6'h16
82
`define VFTOI       6'h24
83
`define VITOF       6'h25
84
`define VFMUL       6'h3A
85
`define VFDIV       6'h3E
86 26 robfinch
`define FLOAT   6'h0F
87
`define FLT1            4'h1
88
`define FLT2            4'h2
89
`define FLT3            4'h3
90
`define FLT1A           4'h5
91
`define FLT2LI  4'hA
92
`define FMA                     5'h00
93
`define FMS                     5'h01
94
`define FNMA            5'h02
95
`define FNMS            5'h03
96
`define FMOV    5'h00
97
`define FTOI    5'h02
98
`define ITOF    5'h03
99
`define FNEG    5'h04
100
`define FABS    5'h05
101
`define FSIGN   5'h06
102
`define FMAN    5'h07
103
`define FNABS   5'h08
104
`define FCVTSD  5'h09
105
//`define FCVTSQ  6'h1B
106
`define FSTAT   5'h0C
107
`define FSQRT           5'h0D
108
`define FTX     5'h10
109
`define FCX     5'h11
110
`define FEX     5'h12
111
`define FDX     5'h13
112
`define FRM     5'h14
113
`define TRUNC           5'h15
114
`define FCVTDS  5'h19
115 9 robfinch
 
116 26 robfinch
`define FSCALEB 5'h00
117
`define FADD    5'h04
118
`define FSUB    5'h05
119
`define FCMP    5'h06
120
`define FMUL    5'h08
121
`define FDIV    5'h09
122
`define FREM            5'h0A
123
`define NXTAFT  5'h0B
124
// FLT1A
125
`define FRES            5'h00
126 10 robfinch
 
127 26 robfinch
`include "fp_defines.v"
128 9 robfinch
 
129 26 robfinch
module fpUnit(rst, clk, clk4x, ce, ir, ld, a, b, c, imm, o, csr_i, status, exception, done, rm
130 10 robfinch
);
131
parameter WID = 64;
132 26 robfinch
`include "fpSize.sv"
133 9 robfinch
localparam EMSBS = 7;
134
localparam FMSBS = 22;
135
localparam FXS = (FMSBS+2)*2-1; // the MSB of the expanded fraction
136
localparam EXS = FXS + 1 + EMSBS + 1 + 1 - 1;
137
 
138
input rst;
139
input clk;
140 26 robfinch
input clk4x;
141 9 robfinch
input ce;
142 26 robfinch
input [39:0] ir;
143 9 robfinch
input ld;
144
input [MSB:0] a;
145
input [MSB:0] b;
146 26 robfinch
input [MSB:0] c;
147 9 robfinch
input [5:0] imm;
148
output tri [MSB:0] o;
149 10 robfinch
input [31:0] csr_i;
150 9 robfinch
output [31:0] status;
151
output exception;
152
output done;
153 10 robfinch
input [2:0] rm;
154 9 robfinch
 
155
reg [7:0] fpcnt;
156 26 robfinch
wire rem_done;
157
wire rem_ld;
158
wire op_done = fpcnt==8'h00;
159
assign done = op_done & rem_done;
160 9 robfinch
 
161
//------------------------------------------------------------
162
// constants
163
wire infXpq = {15{1'b1}};
164
wire infXp = {11{1'b1}};        // value for infinite exponent / nan
165
wire infXps = {8{1'b1}};
166
 
167
// Variables
168
wire divByZero;                 // attempt to divide by zero
169
wire inf;                               // result is infinite (+ or -)
170
wire zero;                              // result is zero (+ or -)
171
wire ns;                // nan sign
172
wire nss;
173
wire nso;
174
wire nsos;
175
wire isNan,isNans;
176
wire nanx,nanxs;
177
 
178 26 robfinch
wire latch_res;
179
wire [3:0] op4_r;
180
wire [5:0] func6b_r;
181
wire [2:0] srca;
182
wire [2:0] srcb;
183
wire [3:0] op4_i = ir[9:6];
184 9 robfinch
wire [5:0] op = ir[5:0];
185 26 robfinch
wire [4:0] func6b_i = ir[39:35];
186
wire fprem = {op4_i,func6b_i} == {`FLT2,`FREM};
187
wire [3:0] op4 = fprem ? op4_r : op4_i;
188
wire [5:0] func6b = fprem ? func6b_r : func6b_i;
189
wire [2:0] insn_rm = ir[30:28];
190
reg [WID-1:0] res;
191
reg [WID-1:0] aop, bop;
192
always @*
193
case(srca)
194
`RES:   aop <= res;
195
default:        aop <= a;
196
endcase
197
always @*
198
case(srcb)
199
`RES:                   bop <= res;
200
`POINT5:
201
case(WID)
202
32:     bop <= `POINT5S;
203
40:     bop <= `POINT5SX;
204
64:     bop <= `POINT5D;
205
80:     bop <= `POINT5DX;
206
endcase
207
default:        bop <= b;
208
endcase
209 9 robfinch
 
210 26 robfinch
wire [2:0] prec = 3'd4;//ir[25:24];
211 10 robfinch
 
212 26 robfinch
wire fstat      = {op4,func6b} == {`FLT1,`FSTAT};       // get status
213
wire fdiv       = {op4,func6b} == {`FLT2,`FDIV};
214
wire ftx        = {op4,func6b} == {`FLT1,`FTX};         // trigger exception
215
wire fcx        = {op4,func6b} == {`FLT1,`FCX};         // clear exception
216
wire fex        = {op4,func6b} == {`FLT1,`FEX};         // enable exception
217
wire fdx        = {op4,func6b} == {`FLT1,`FDX};         // disable exception
218
wire fcmp       = {op4,func6b} == {`FLT2,`FCMP};
219
wire frm        = {op4,func6b} == {`FLT1,`FRM};  // set rounding mode
220
 
221
wire zl_op =  (op4==`FLT1 && (
222
                    (func6b==`FABS || func6b==`FNABS || func6b==`FMOV || func6b==`FNEG || func6b==`FSIGN || func6b==`FMAN)) ||
223 10 robfinch
                    func6b==`FCMP);
224 26 robfinch
wire loo_op = (op4==`FLT1 && (func6b==`ITOF || func6b==`FTOI));
225 9 robfinch
wire loo_done;
226
 
227
wire subinf;
228
wire zerozero;
229
wire infzero;
230
wire infdiv;
231
 
232
// floating point control and status
233 10 robfinch
 
234
wire inexe_i    = csr_i[28];
235
wire dbzxe_i    = csr_i[27];
236
wire underxe_i  = csr_i[26];
237
wire overxe_i   = csr_i[25];
238
wire invopxe_i  = csr_i[24];
239
wire fractie_i  = csr_i[22];
240
wire rawayz_i   = csr_i[21];
241
wire C_i        = csr_i[20];
242
wire neg_i      = csr_i[19];
243
wire pos_i      = csr_i[18];
244
wire zero_i     = csr_i[17];
245
wire inf_i      = csr_i[16];
246
wire swt_i      = csr_i[15];
247
wire inex_i     = csr_i[14];
248
wire dbzx_i     = csr_i[13];
249
wire underx_i   = csr_i[12];
250
wire overx_i    = csr_i[11];
251
wire giopx_i    = csr_i[10];
252
wire gx_i       = csr_i[9];
253
wire sumx_i     = csr_i[8];
254
wire cvt_i      = csr_i[7];
255
wire sqrtx_i    = csr_i[6];
256
wire NaNCmpx_i  = csr_i[5];
257
wire infzerox_i = csr_i[4];
258
wire zerozerox_i= csr_i[3];
259
wire infdivx_i  = csr_i[2];
260
wire subinfx_i  = csr_i[1];
261
wire snanx_i    = csr_i[0];
262 9 robfinch
reg inexe;              // inexact exception enable
263
reg dbzxe;              // divide by zero exception enable
264
reg underxe;    // underflow exception enable
265
reg overxe;             // overflow exception enable
266
reg invopxe;    // invalid operation exception enable
267
 
268
reg nsfp;               // non-standard floating point indicator
269
 
270
reg fractie;    // fraction inexact
271
reg raz;                // rounded away from zero
272
 
273
reg inex;               // inexact exception
274
reg dbzx;               // divide by zero exception
275
reg underx;             // underflow exception
276
reg overx;              // overflow exception
277
reg giopx;              // global invalid operation exception
278
reg sx;                 // summary exception
279
 
280
reg swtx;               // software triggered exception indicator
281
 
282
wire gx = swtx|inex|dbzx|underx|overx|giopx;    // global exception indicator
283
 
284
// breakdown of invalid operation exceptions
285
reg cvtx;               // conversion exception
286
reg sqrtx;              // squareroot exception
287
reg NaNCmpx;    // NaN comparison exception
288
reg infzerox;   // multiply infinity by zero
289
reg zerozerox;  // division of zero by zero
290
reg infdivx;    // division of infinities
291
reg subinfx;    // subtraction of infinities
292
reg snanx;              // signalling nan
293
 
294 26 robfinch
wire fdivs = 1'b0;
295 9 robfinch
wire divDone;
296
wire pipe_ce = ce;// & divDone; // divide must be done in order for pipe to clock
297 26 robfinch
wire precmatch = 1'b0;//WID==32 ? ir[28:27]==2'b00 :
298
                 //WID==64 ? ir[28:27]==2'b01 : 1;
299 9 robfinch
                 /*
300
                 WID==80 ? ir[28:27]==2'b10 :
301
                 ir[28:27]==2'b11;
302
                 */
303
always @(posedge clk)
304
        // reset: disable and clear all exceptions and status
305
        if (rst) begin
306
                inex <= 1'b0;
307
                dbzx <= 1'b0;
308
                underx <= 1'b0;
309
                overx <= 1'b0;
310
                giopx <= 1'b0;
311
                swtx <= 1'b0;
312
                sx <= 1'b0;
313
                NaNCmpx <= 1'b0;
314
 
315
                inexe <= 1'b0;
316
                dbzxe <= 1'b0;
317
                underxe <= 1'b0;
318
                overxe <= 1'b0;
319
                invopxe <= 1'b0;
320
 
321
                nsfp <= 1'b0;
322
 
323
                infzerox  <= 1'b0;
324
                zerozerox <= 1'b0;
325
                subinfx   <= 1'b0;
326
                infdivx   <= 1'b0;
327
 
328
        cvtx <= 1'b0;
329
        sqrtx <= 1'b0;
330
        raz <= 1'b0;
331
        fractie <= 1'b0;
332
        snanx <= 1'b0;
333
        end
334
        else if (pipe_ce) begin
335
                if (ftx && precmatch) begin
336 10 robfinch
                        inex <= (a[4]|imm[4]);
337
                        dbzx <= (a[3]|imm[3]);
338
                        underx <= (a[2]|imm[2]);
339
                        overx <= (a[1]|imm[1]);
340
                        giopx <= (a[0]|imm[0]);
341 9 robfinch
                        swtx <= 1'b1;
342
                        sx <= 1'b1;
343
                end
344
 
345 10 robfinch
                infzerox  <= infzero & invopxe_i;
346
                zerozerox <= zerozero & invopxe_i;
347
                subinfx   <= subinf & invopxe_i;
348
                infdivx   <= infdiv & invopxe_i;
349
                dbzx <= divByZero & dbzxe_i;
350
                NaNCmpx <= nanx & fcmp & invopxe_i;     // must be a compare
351
//              sx <= sx |
352
//                              (invopxe & nanx & fcmp) |
353
//                              (invopxe & (infzero|zerozero|subinf|infdiv)) |
354
//                              (dbzxe & divByZero);
355
           snanx <= isNan & invopxe_i;
356 9 robfinch
        end
357
 
358
// Decompose operands into sign,exponent,mantissa
359
wire sa, sb, sas, sbs;
360
wire [FMSB:0] ma, mb;
361
wire [22:0] mas, mbs;
362
 
363
wire aInf, bInf, aInfs, bInfs;
364
wire aNan, bNan, aNans, bNans;
365
wire az, bz, azs, bzs;
366
wire [2:0] rmd4; // 1st stage delayed
367 26 robfinch
wire [3:0] op2;
368
wire [5:0] op1;
369 10 robfinch
wire [5:0] fn2;
370 9 robfinch
 
371
wire [MSB:0] zld_o,lood_o;
372
wire [31:0] zls_o,loos_o;
373 10 robfinch
wire [WID-1:0] zlq_o, looq_o;
374 26 robfinch
wire [WID-1:0] scaleb_o;
375
fpZLUnit #(WID) u6 (.ir(ir), .op4(op4), .func5(func6b), .a(aop), .b(bop), .c(c), .o(zlq_o), .nanx(nanx) );
376
fpLOOUnit #(WID) u7 (.clk(clk), .ce(pipe_ce), .op4(op4), .func5(func6b), .rm(insn_rm==3'b111 ? rm : insn_rm), .a(aop), .b(bop), .o(looq_o), .done() );
377
fpScaleb u16 (.clk(clk), .ce(pipe_ce), .a(aop), .b(bop), .o(scaleb_o));
378
 
379 9 robfinch
//fpLOOUnit #(32) u7s (.clk(clk), .ce(pipe_ce), .rm(rm), .op(op), .fn(fn), .a(a[31:0]), .o(loos_o), .done() );
380
 
381 26 robfinch
fp_decomp #(WID) u1 (.i(aop), .sgn(sa), .man(ma), .vz(az), .inf(aInf), .nan(aNan) );
382
fp_decomp #(WID) u2 (.i(bop), .sgn(sb), .man(mb), .vz(bz), .inf(bInf), .nan(bNan) );
383 9 robfinch
//fp_decomp #(32) u1s (.i(a[31:0]), .sgn(sas), .man(mas), .vz(azs), .inf(aInfs), .nan(aNans) );
384
//fp_decomp #(32) u2s (.i(b[31:0]), .sgn(sbs), .man(mbs), .vz(bzs), .inf(bInfs), .nan(bNans) );
385
 
386 26 robfinch
wire [2:0] rmd = ir[30:28]==3'b111 ? rm : ir[30:28];
387 9 robfinch
delay4 #(3) u3 (.clk(clk), .ce(pipe_ce), .i(rmd), .o(rmd4) );
388
delay1 #(6) u4 (.clk(clk), .ce(pipe_ce), .i(func6b), .o(op1) );
389 26 robfinch
delay2 #(4) u5 (.clk(clk), .ce(pipe_ce), .i(op4), .o(op2) );
390 10 robfinch
delay2 #(6) u5b (.clk(clk), .ce(pipe_ce), .i(func6b), .o(fn2) );
391 9 robfinch
 
392
delay5 delay5_3(.clk(clk), .ce(pipe_ce), .i((bz & !aNan & fdiv)|(bzs & !aNans & fdivs)), .o(divByZero) );
393
 
394
// Compute NaN output sign
395
wire aob_nan = aNan|bNan;       // one of the operands is a nan
396
wire bothNan = aNan&bNan;       // both of the operands are nans
397
//wire aob_nans = aNans|bNans;  // one of the operands is a nan
398
//wire bothNans = aNans&bNans;  // both of the operands are nans
399
 
400
assign ns = bothNan ?
401
                                (ma==mb ? sa & sb : ma < mb ? sb : sa) :
402
                                aNan ? sa : sb;
403
//assign nss = bothNans ?
404
//                                 (mas==mbs ? sas & sbs : mas < mbs ? sbs : sas) :
405
//                                  aNans ? sas : sbs;
406
 
407
delay5 u8(.clk(clk), .ce(ce), .i(ns), .o(nso) );
408
delay5 u9(.clk(clk), .ce(ce), .i(aob_nan), .o(isNan) );
409
//delay5 u8s(.clk(clk), .ce(ce), .i(nss), .o(nsos) );
410
//delay5 u9s(.clk(clk), .ce(ce), .i(aob_nans), .o(isNans) );
411
 
412
wire [MSB:0] fpu_o;
413
wire [MSB+3:0] fpn_o;
414
wire [EX:0] fdiv_o;
415
wire [EX:0] fmul_o;
416
wire [EX:0] fas_o;
417 26 robfinch
wire [EX:0] fsqrt_o;
418 9 robfinch
reg  [EX:0] fres;
419
wire [31:0] fpus_o;
420
wire [31+3:0] fpns_o;
421
wire [EXS:0] fdivs_o;
422
wire [EXS:0] fmuls_o;
423
wire [EXS:0] fass_o;
424 26 robfinch
wire [EXS:0] fres_o;
425 9 robfinch
reg  [EXS:0] fress;
426
wire divUnder,divUnders;
427
wire mulUnder,mulUnders;
428
reg under,unders;
429 26 robfinch
wire sqrneg;
430
wire fms = func6b==`FMS || func6b==`FNMS;
431
wire nma = func6b==`FNMA || func6b==`FNMS;
432
wire [WID-1:0] ma_aop = aop ^ (nma << WID-1);
433 9 robfinch
 
434 26 robfinch
fpAddsub #(WID) u10(.clk(clk), .ce(pipe_ce), .rm(rmd), .op(func6b[0]), .a(aop), .b(bop), .o(fas_o) );
435
fpDiv    #(WID) u11(.clk(clk), .clk4x(clk4x), .ce(pipe_ce), .ld(ld|rem_ld), .a(aop), .b(bop), .o(fdiv_o), .sign_exe(), .underflow(divUnder), .done(divDone) );
436
fpMul    #(WID) u12(.clk(clk), .ce(pipe_ce),          .a(aop), .b(bop), .o(fmul_o), .sign_exe(), .inf(), .underflow(mulUnder) );
437
fpSqrt   #(WID) u13(.rst(rst), .clk(clk4x), .ce(pipe_ce), .ld(ld), .a(aop), .o(fsqrt_o), .done(), .sqrinf(), .sqrneg(sqrneg) );
438
fpRes    #(WID) u14(.clk(clk), .ce(pipe_ce), .a(aop), .o(fres_o));
439
fpFMA    #(WID) u15(.clk(clk), .ce(pipe_ce), .op(fms), .rm(rmd), .a(ma_aop), .b(bop), .c(c), .o(fma_o), .inf());
440
 
441
fpRemainder ufpr1
442
(
443
        .rst(rst),
444
        .clk(clk),
445
        .ce(ce),
446
        .ld_i(ld),
447
        .ld_o(rem_ld),
448
        .op4_i(op4_i),
449
        .funct6b_i(func6b_i),
450
        .op4_o(op4_r),
451
        .funct6b_o(func6b_r),
452
        .op_done(op_done),
453
        .rem_done(rem_done),
454
        .srca(srca),
455
        .srcb(srcb),
456
        .latch_res(latch_res)
457
);
458 9 robfinch
/*
459
fpAddsub #(32) u10s(.clk(clk), .ce(pipe_ce), .rm(rm), .op(op[0]), .a(a[31:0]), .b(b[31:0]), .o(fass_o) );
460
fpDiv    #(32) u11s(.clk(clk), .ce(pipe_ce), .ld(ld), .a(a[31:0]), .b(b[31:0]), .o(fdivs_o), .sign_exe(), .underflow(divUnders), .done() );
461
fpMul    #(32) u12s(.clk(clk), .ce(pipe_ce),          .a(a[31:0]), .b(b[31:0]), .o(fmuls_o), .sign_exe(), .inf(), .underflow(mulUnders) );
462
*/
463 10 robfinch
always @*
464
case(op2)
465 26 robfinch
`FLT2,`FLT2LI:
466
  case (fn2)
467
  `FMUL:        under = mulUnder;
468
  `FDIV:        under = divUnder;
469
  default: begin under = 0; unders = 0; end
470 9 robfinch
        endcase
471 10 robfinch
default: begin under = 0; unders = 0; end
472
endcase
473 9 robfinch
 
474 10 robfinch
always @*
475
case(op2)
476 26 robfinch
`FLT3:
477
        case(fn2)
478
        `FMA:           fres <= fma_o;
479
        `FMS:           fres <= fma_o;
480
        `FNMA:  fres <= fma_o;
481
        `FNMS:  fres <= fma_o;
482
        default:        fres <= fma_o;
483
        endcase
484
`FLT2,`FLT2LI:
485
  case(fn2)
486
  `FADD:        fres <= fas_o;
487
  `FSUB:        fres <= fas_o;
488
  `FMUL:        fres <= fmul_o;
489
  `FDIV:        fres <= fdiv_o;
490
  `FSCALEB:     fres <= scaleb_o;
491
  default:      begin fres <= fas_o; fress <= fass_o; end
492
  endcase
493
`FLT1:
494
        case(fn2)
495
  `FSQRT:       fres <= fsqrt_o;
496
  default:      begin fres <= 1'd0; fress <= 1'd0; end
497
  endcase
498
`FLT1A:
499
        case(fn2)
500
        `FRES:  fres <= fres_o;
501
        default:        begin fres <= 1'd0; fress <= 1'd0; end
502
        endcase
503 10 robfinch
default:    begin fres <= fas_o; fress <= fass_o; end
504
endcase
505 9 robfinch
 
506
// pipeline stage
507
// one cycle latency
508
fpNormalize #(WID) fpn0(.clk(clk), .ce(pipe_ce), .under(under), .i(fres), .o(fpn_o) );
509
//fpNormalize #(32) fpns(.clk(clk), .ce(pipe_ce), .under(unders), .i(fress), .o(fpns_o) );
510
 
511
// pipeline stage
512
// one cycle latency
513 10 robfinch
fpRoundReg #(WID) fpr0(.clk(clk), .ce(pipe_ce), .rm(rmd4), .i(fpn_o), .o(fpu_o) );
514 9 robfinch
//fpRoundReg #(32) fprs(.clk(clk), .ce(pipe_ce), .rm(rm4), .i(fpns_o), .o(fpus_o) );
515
 
516
wire so = (isNan?nso:fpu_o[WID-1]);
517
            //single ? (isNans?nsos:fpus_o[31]): (isNan?nso:fpu_o[63]);
518
 
519
//fix: status should be registered
520
assign status = {
521
        rm,
522
        inexe,
523
        dbzxe,
524
        underxe,
525
        overxe,
526
        invopxe,
527
        nsfp,
528
 
529
        fractie,
530
        raz,
531
        1'b0,
532
        so & !zero,
533
        !so & !zero,
534
        zero,
535
        inf,
536
 
537
        swtx,
538
        inex,
539
        dbzx,
540
        underx,
541
        overx,
542
        giopx,
543
        gx,
544
        sx,
545
 
546 26 robfinch
        1'b0,   // cvtx
547
        sqrneg, // sqrtx
548 10 robfinch
        fcmp & nanx,
549
        infzero,
550
        zerozero,
551
        infdiv,
552
        subinf,
553
        isNan
554 9 robfinch
        };
555
 
556 26 robfinch
wire [WID-1:0] o1 =
557 10 robfinch
    (frm|fcx|fdx|fex) ? (a|imm) :
558 9 robfinch
    zl_op ? zlq_o :
559
    loo_op ? looq_o :
560 26 robfinch
    {so,fpu_o[MSB-1:0]};
561 9 robfinch
assign zero = fpu_o[MSB-1:0]==0;
562 26 robfinch
assign o = fprem ? res : o1;
563
always @(posedge clk)
564
        if (ce & latch_res) res <= o1;
565 9 robfinch
 
566
wire [7:0] maxdivcnt;
567
generate begin
568
if (WID==128) begin
569
    assign inf = &fpu_o[126:112] && fpu_o[111:0]==0;
570
    assign subinf       = fpu_o[126:0]==`QSUBINFQ;
571
    assign infdiv       = fpu_o[126:0]==`QINFDIVQ;
572
    assign zerozero = fpu_o[126:0]==`QZEROZEROQ;
573
    assign infzero      = fpu_o[126:0]==`QINFZEROQ;
574 26 robfinch
    assign maxdivcnt = 8'd128;
575 9 robfinch
end
576
else if (WID==80) begin
577
    assign inf = &fpu_o[78:64] && fpu_o[63:0]==0;
578
    assign subinf       = fpu_o[78:0]==`QSUBINFDX;
579
    assign infdiv       = fpu_o[78:0]==`QINFDIVDX;
580
    assign zerozero = fpu_o[78:0]==`QZEROZERODX;
581
    assign infzero      = fpu_o[78:0]==`QINFZERODX;
582 26 robfinch
    assign maxdivcnt = 8'd80;
583 9 robfinch
end
584
else if (WID==64) begin
585
    assign inf      = &fpu_o[62:52] && fpu_o[51:0]==0;
586
    assign subinf   = fpu_o[62:0]==`QSUBINFD;
587
    assign infdiv   = fpu_o[62:0]==`QINFDIVD;
588
    assign zerozero = fpu_o[62:0]==`QZEROZEROD;
589
    assign infzero  = fpu_o[62:0]==`QINFZEROD;
590 26 robfinch
    assign maxdivcnt = 8'd64;
591 9 robfinch
end
592
else if (WID==32) begin
593
    assign inf      = &fpu_o[30:23] && fpu_o[22:0]==0;
594
    assign subinf   = fpu_o[30:0]==`QSUBINFS;
595
    assign infdiv   = fpu_o[30:0]==`QINFDIVS;
596
    assign zerozero = fpu_o[30:0]==`QZEROZEROS;
597
    assign infzero  = fpu_o[30:0]==`QINFZEROS;
598 26 robfinch
    assign maxdivcnt = 8'd32;
599 9 robfinch
end
600
end
601
endgenerate
602
 
603
assign exception = gx;
604
 
605
// Generate a done signal. Latency varys depending on the instruction.
606
always @(posedge clk)
607
begin
608 26 robfinch
  if (rst)
609
    fpcnt <= 8'h00;
610
  else begin
611
  if (ld|rem_ld)
612
    case(op4)
613
    `FLT3:
614
        case(func6b)
615
        `FMA:           fpcnt <= 8'd22;
616
        `FMS:           fpcnt <= 8'd22;
617
        `FNMA:  fpcnt <= 8'd22;
618
        `FNMS:  fpcnt <= 8'd22;
619
        default:        fpcnt <= 8'd00;
620
        endcase
621
    `FLT2,`FLT2LI:
622
      case(func6b)
623
      `FCMP:  begin fpcnt <= 8'd0; end
624
      `FADD:  begin fpcnt <= 8'd6; end
625
      `FSUB:  begin fpcnt <= 8'd6; end
626
      `FMUL:  begin fpcnt <= 8'd6; end
627
      `FDIV:  begin fpcnt <= maxdivcnt; end
628
      `FREM:    fpcnt <= maxdivcnt+8'd23;
629
      `NXTAFT: fpcnt <= 8'd1;
630
      `FSCALEB: fpcnt <= 8'd2;
631
      default:    fpcnt <= 8'h00;
632
      endcase
633
    `FLT1:
634
      case(func6b)
635
      `FABS,`FNABS,`FNEG,`FMAN,`FMOV,`FSIGN,
636
      `FCVTSD,`FCVTDS:  begin fpcnt <= 8'd0; end
637
      `FTOI:  begin fpcnt <= 8'd1; end
638
      `ITOF:  begin fpcnt <= 8'd1; end
639
      `TRUNC:  begin fpcnt <= 8'd1; end
640
      `FSQRT: begin fpcnt <= maxdivcnt; end
641
      default:    fpcnt <= 8'h00;
642
      endcase
643
    `FLT1A:
644
        case(func6b)
645
        `FRES:  fpcnt <= 8'h03;
646
        default:        fpcnt <= 8'h00;
647
        endcase
648
    default:    fpcnt <= 8'h00;
649
    endcase
650
  else if (!op_done) begin
651
        if ((op4==`FLT2||op4==`FLT2LI) && func6b==`FDIV && divDone)
652
                fpcnt <= 8'h00;
653
        else
654
        fpcnt <= fpcnt - 1;
655
   end
656
  end
657 9 robfinch
end
658
endmodule
659
 

powered by: WebSVN 2.1.0

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