Line 1... |
Line 1... |
// ============================================================================
|
// ============================================================================
|
// __
|
// __
|
// \\__/ o\ (C) 2006-2018 Robert Finch, Waterloo
|
// \\__/ o\ (C) 2006-2019 Robert Finch, Waterloo
|
// \ __ / All rights reserved.
|
// \ __ / All rights reserved.
|
// \/_// robfinch<remove>@finitron.ca
|
// \/_// robfinch<remove>@finitron.ca
|
// ||
|
// ||
|
//
|
//
|
// This source file is free software: you can redistribute it and/or modify
|
// This source file is free software: you can redistribute it and/or modify
|
Line 17... |
Line 17... |
//
|
//
|
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
//
|
//
|
// DSD
|
|
// fpUnit.v
|
// fpUnit.v
|
// - floating point unit
|
// - floating point unit
|
// - parameterized width
|
// - parameterized width
|
// - IEEE 754 representation
|
// - IEEE 754 representation
|
//
|
//
|
// NaN Value Origin
|
// NaN Value Origin
|
// 31'h7FC00001 - infinity - infinity
|
// 31'h7FC00001 - infinity - infinity
|
// 31'h7FC00002 - infinity / infinity
|
// 31'h7FC00002 - infinity / infinity
|
// 31'h7FC00003 - zero / zero
|
// 31'h7FC00003 - zero / zero
|
// 31'h7FC00004 - infinity X zero
|
// 31'h7FC00004 - infinity X zero
|
|
// 31'h7FC00005 - square root of infinity
|
|
// 31'h7FC00006 - square root of negative number
|
//
|
//
|
// Whenever the fpu encounters a NaN input, the NaN is
|
// Whenever the fpu encounters a NaN input, the NaN is
|
// passed through to the output.
|
// passed through to the output.
|
//
|
//
|
// Ref: Webpack 8.2 Spartan3-4 xc3s1000-4ft256
|
// Ref: Webpack 8.2 Spartan3-4 xc3s1000-4ft256
|
Line 80... |
Line 81... |
`define VFNEG 6'h16
|
`define VFNEG 6'h16
|
`define VFTOI 6'h24
|
`define VFTOI 6'h24
|
`define VITOF 6'h25
|
`define VITOF 6'h25
|
`define VFMUL 6'h3A
|
`define VFMUL 6'h3A
|
`define VFDIV 6'h3E
|
`define VFDIV 6'h3E
|
`define FLOAT 6'h0B
|
`define FLOAT 6'h0F
|
`define FMOV 6'h10
|
`define FLT1 4'h1
|
`define FTOI 6'h12
|
`define FLT2 4'h2
|
`define ITOF 6'h13
|
`define FLT3 4'h3
|
`define FNEG 6'h14
|
`define FLT1A 4'h5
|
`define FABS 6'h15
|
`define FLT2LI 4'hA
|
`define FSIGN 6'h16
|
`define FMA 5'h00
|
`define FMAN 6'h17
|
`define FMS 5'h01
|
`define FNABS 6'h18
|
`define FNMA 5'h02
|
`define FCVTSD 6'h19
|
`define FNMS 5'h03
|
`define FCVTSQ 6'h1B
|
`define FMOV 5'h00
|
`define FSTAT 6'h1C
|
`define FTOI 5'h02
|
`define FTX 6'h20
|
`define ITOF 5'h03
|
`define FCX 6'h21
|
`define FNEG 5'h04
|
`define FEX 6'h22
|
`define FABS 5'h05
|
`define FDX 6'h23
|
`define FSIGN 5'h06
|
`define FRM 6'h24
|
`define FMAN 5'h07
|
`define FCVTDS 6'h29
|
`define FNABS 5'h08
|
|
`define FCVTSD 5'h09
|
`define FADD 6'h04
|
//`define FCVTSQ 6'h1B
|
`define FSUB 6'h05
|
`define FSTAT 5'h0C
|
`define FCMP 6'h06
|
`define FSQRT 5'h0D
|
`define FMUL 6'h08
|
`define FTX 5'h10
|
`define FDIV 6'h09
|
`define FCX 5'h11
|
|
`define FEX 5'h12
|
`define QINFOS 23'h7FC000 // info
|
`define FDX 5'h13
|
`define QSUBINFS 31'h7FC00001 // - infinity - infinity
|
`define FRM 5'h14
|
`define QINFDIVS 31'h7FC00002 // - infinity / infinity
|
`define TRUNC 5'h15
|
`define QZEROZEROS 31'h7FC00003 // - zero / zero
|
`define FCVTDS 5'h19
|
`define QINFZEROS 31'h7FC00004 // - infinity X zero
|
|
|
`define FSCALEB 5'h00
|
`define QINFOD 52'hFF80000000000 // info
|
`define FADD 5'h04
|
`define QSUBINFD 63'h7FF0000000000001 // - infinity - infinity
|
`define FSUB 5'h05
|
`define QINFDIVD 63'h7FF0000000000002 // - infinity / infinity
|
`define FCMP 5'h06
|
`define QZEROZEROD 63'h7FF0000000000003 // - zero / zero
|
`define FMUL 5'h08
|
`define QINFZEROD 63'h7FF0000000000004 // - infinity X zero
|
`define FDIV 5'h09
|
|
`define FREM 5'h0A
|
`define QINFODX 64'hFF800000_00000000 // info
|
`define NXTAFT 5'h0B
|
`define QSUBINFDX 79'h7FFF000000_0000000001 // - infinity - infinity
|
// FLT1A
|
`define QINFDIVDX 79'h7FFF000000_0000000002 // - infinity / infinity
|
`define FRES 5'h00
|
`define QZEROZERODX 79'h7FFF000000_0000000003 // - zero / zero
|
|
`define QINFZERODX 79'h7FFF000000_0000000004 // - infinity X zero
|
|
|
|
`define QINFOQ 112'hFF800000_0000000000_0000000000 // info
|
|
`define QSUBINFQ 127'h7F_FF00000000_0000000000_0000000001 // - infinity - infinity
|
|
`define QINFDIVQ 127'h7F_FF00000000_0000000000_0000000002 // - infinity / infinity
|
|
`define QZEROZEROQ 127'h7F_FF00000000_0000000000_0000000003 // - zero / zero
|
|
`define QINFZEROQ 127'h7F_FF00000000_0000000000_0000000004 // - infinity X zero
|
|
|
|
module fpUnit(rst, clk, ce, ir, ld, a, b, imm, o, csr_i, status, exception, done, rm
|
`include "fp_defines.v"
|
);
|
|
|
|
|
module fpUnit(rst, clk, clk4x, ce, ir, ld, a, b, c, imm, o, csr_i, status, exception, done, rm
|
|
);
|
parameter WID = 64;
|
parameter WID = 64;
|
localparam MSB = WID-1;
|
`include "fpSize.sv"
|
localparam EMSB = WID==128 ? 14 :
|
|
WID==96 ? 14 :
|
|
WID==80 ? 14 :
|
|
WID==64 ? 10 :
|
|
WID==52 ? 10 :
|
|
WID==48 ? 10 :
|
|
WID==44 ? 10 :
|
|
WID==42 ? 10 :
|
|
WID==40 ? 9 :
|
|
WID==32 ? 7 :
|
|
WID==24 ? 6 : 4;
|
|
localparam FMSB = WID==128 ? 111 :
|
|
WID==96 ? 79 :
|
|
WID==80 ? 63 :
|
|
WID==64 ? 51 :
|
|
WID==52 ? 39 :
|
|
WID==48 ? 35 :
|
|
WID==44 ? 31 :
|
|
WID==42 ? 29 :
|
|
WID==40 ? 28 :
|
|
WID==32 ? 22 :
|
|
WID==24 ? 15 : 9;
|
|
localparam EMSBS = 7;
|
localparam EMSBS = 7;
|
localparam FMSBS = 22;
|
localparam FMSBS = 22;
|
localparam FX = (FMSB+2)*2-1; // the MSB of the expanded fraction
|
|
localparam EX = FX + 1 + EMSB + 1 + 1 - 1;
|
|
localparam FXS = (FMSBS+2)*2-1; // the MSB of the expanded fraction
|
localparam FXS = (FMSBS+2)*2-1; // the MSB of the expanded fraction
|
localparam EXS = FXS + 1 + EMSBS + 1 + 1 - 1;
|
localparam EXS = FXS + 1 + EMSBS + 1 + 1 - 1;
|
|
|
input rst;
|
input rst;
|
input clk;
|
input clk;
|
|
input clk4x;
|
input ce;
|
input ce;
|
input [31:0] ir;
|
input [39:0] ir;
|
input ld;
|
input ld;
|
input [MSB:0] a;
|
input [MSB:0] a;
|
input [MSB:0] b;
|
input [MSB:0] b;
|
|
input [MSB:0] c;
|
input [5:0] imm;
|
input [5:0] imm;
|
output tri [MSB:0] o;
|
output tri [MSB:0] o;
|
input [31:0] csr_i;
|
input [31:0] csr_i;
|
output [31:0] status;
|
output [31:0] status;
|
output exception;
|
output exception;
|
output done;
|
output done;
|
input [2:0] rm;
|
input [2:0] rm;
|
|
|
reg [7:0] fpcnt;
|
reg [7:0] fpcnt;
|
assign done = fpcnt==8'h00;
|
wire rem_done;
|
|
wire rem_ld;
|
|
wire op_done = fpcnt==8'h00;
|
|
assign done = op_done & rem_done;
|
|
|
//------------------------------------------------------------
|
//------------------------------------------------------------
|
// constants
|
// constants
|
wire infXpq = {15{1'b1}};
|
wire infXpq = {15{1'b1}};
|
wire infXp = {11{1'b1}}; // value for infinite exponent / nan
|
wire infXp = {11{1'b1}}; // value for infinite exponent / nan
|
Line 198... |
Line 173... |
wire nso;
|
wire nso;
|
wire nsos;
|
wire nsos;
|
wire isNan,isNans;
|
wire isNan,isNans;
|
wire nanx,nanxs;
|
wire nanx,nanxs;
|
|
|
// Decode fp operation
|
wire latch_res;
|
|
wire [3:0] op4_r;
|
|
wire [5:0] func6b_r;
|
|
wire [2:0] srca;
|
|
wire [2:0] srcb;
|
|
wire [3:0] op4_i = ir[9:6];
|
wire [5:0] op = ir[5:0];
|
wire [5:0] op = ir[5:0];
|
wire [5:0] func6b = ir[31:26];
|
wire [4:0] func6b_i = ir[39:35];
|
wire [1:0] prec = ir[25:24];
|
wire fprem = {op4_i,func6b_i} == {`FLT2,`FREM};
|
|
wire [3:0] op4 = fprem ? op4_r : op4_i;
|
|
wire [5:0] func6b = fprem ? func6b_r : func6b_i;
|
|
wire [2:0] insn_rm = ir[30:28];
|
|
reg [WID-1:0] res;
|
|
reg [WID-1:0] aop, bop;
|
|
always @*
|
|
case(srca)
|
|
`RES: aop <= res;
|
|
default: aop <= a;
|
|
endcase
|
|
always @*
|
|
case(srcb)
|
|
`RES: bop <= res;
|
|
`POINT5:
|
|
case(WID)
|
|
32: bop <= `POINT5S;
|
|
40: bop <= `POINT5SX;
|
|
64: bop <= `POINT5D;
|
|
80: bop <= `POINT5DX;
|
|
endcase
|
|
default: bop <= b;
|
|
endcase
|
|
|
wire fstat = {op,func6b} == {`FLOAT,`FSTAT}; // get status
|
wire [2:0] prec = 3'd4;//ir[25:24];
|
wire fdiv = {op,func6b} == {`FLOAT,`FDIV};
|
|
wire ftx = {op,func6b} == {`FLOAT,`FTX}; // trigger exception
|
|
wire fcx = {op,func6b} == {`FLOAT,`FCX}; // clear exception
|
|
wire fex = {op,func6b} == {`FLOAT,`FEX}; // enable exception
|
|
wire fdx = {op,func6b} == {`FLOAT,`FDX}; // disable exception
|
|
wire fcmp = {op,func6b} == {`FLOAT,`FCMP};
|
|
wire frm = {op,func6b} == {`FLOAT,`FRM}; // set rounding mode
|
|
|
|
wire zl_op = (op==`FLOAT && (
|
wire fstat = {op4,func6b} == {`FLT1,`FSTAT}; // get status
|
(func6b==`FABS || func6b==`FNABS || func6b==`FMOV || func6b==`FNEG || func6b==`FSIGN || func6b==`FMAN || func6b==`FCVTSQ)) ||
|
wire fdiv = {op4,func6b} == {`FLT2,`FDIV};
|
|
wire ftx = {op4,func6b} == {`FLT1,`FTX}; // trigger exception
|
|
wire fcx = {op4,func6b} == {`FLT1,`FCX}; // clear exception
|
|
wire fex = {op4,func6b} == {`FLT1,`FEX}; // enable exception
|
|
wire fdx = {op4,func6b} == {`FLT1,`FDX}; // disable exception
|
|
wire fcmp = {op4,func6b} == {`FLT2,`FCMP};
|
|
wire frm = {op4,func6b} == {`FLT1,`FRM}; // set rounding mode
|
|
|
|
wire zl_op = (op4==`FLT1 && (
|
|
(func6b==`FABS || func6b==`FNABS || func6b==`FMOV || func6b==`FNEG || func6b==`FSIGN || func6b==`FMAN)) ||
|
func6b==`FCMP);
|
func6b==`FCMP);
|
wire loo_op = (op==`FLOAT && (func6b==`ITOF || func6b==`FTOI));
|
wire loo_op = (op4==`FLT1 && (func6b==`ITOF || func6b==`FTOI));
|
wire loo_done;
|
wire loo_done;
|
|
|
wire subinf;
|
wire subinf;
|
wire zerozero;
|
wire zerozero;
|
wire infzero;
|
wire infzero;
|
Line 285... |
Line 289... |
reg zerozerox; // division of zero by zero
|
reg zerozerox; // division of zero by zero
|
reg infdivx; // division of infinities
|
reg infdivx; // division of infinities
|
reg subinfx; // subtraction of infinities
|
reg subinfx; // subtraction of infinities
|
reg snanx; // signalling nan
|
reg snanx; // signalling nan
|
|
|
|
wire fdivs = 1'b0;
|
wire divDone;
|
wire divDone;
|
wire pipe_ce = ce;// & divDone; // divide must be done in order for pipe to clock
|
wire pipe_ce = ce;// & divDone; // divide must be done in order for pipe to clock
|
wire precmatch = WID==32 ? ir[28:27]==2'b00 :
|
wire precmatch = 1'b0;//WID==32 ? ir[28:27]==2'b00 :
|
WID==64 ? ir[28:27]==2'b01 : 1;
|
//WID==64 ? ir[28:27]==2'b01 : 1;
|
/*
|
/*
|
WID==80 ? ir[28:27]==2'b10 :
|
WID==80 ? ir[28:27]==2'b10 :
|
ir[28:27]==2'b11;
|
ir[28:27]==2'b11;
|
*/
|
*/
|
always @(posedge clk)
|
always @(posedge clk)
|
Line 357... |
Line 362... |
|
|
wire aInf, bInf, aInfs, bInfs;
|
wire aInf, bInf, aInfs, bInfs;
|
wire aNan, bNan, aNans, bNans;
|
wire aNan, bNan, aNans, bNans;
|
wire az, bz, azs, bzs;
|
wire az, bz, azs, bzs;
|
wire [2:0] rmd4; // 1st stage delayed
|
wire [2:0] rmd4; // 1st stage delayed
|
wire [5:0] op1, op2;
|
wire [3:0] op2;
|
|
wire [5:0] op1;
|
wire [5:0] fn2;
|
wire [5:0] fn2;
|
|
|
wire [MSB:0] zld_o,lood_o;
|
wire [MSB:0] zld_o,lood_o;
|
wire [31:0] zls_o,loos_o;
|
wire [31:0] zls_o,loos_o;
|
wire [WID-1:0] zlq_o, looq_o;
|
wire [WID-1:0] zlq_o, looq_o;
|
fpZLUnit #(WID) u6 (.ir(ir), .a(a), .b(b), .o(zlq_o), .nanx(nanx) );
|
wire [WID-1:0] scaleb_o;
|
fpLOOUnit #(WID) u7 (.clk(clk), .ce(pipe_ce), .ir(ir), .a(a), .o(looq_o), .done() );
|
fpZLUnit #(WID) u6 (.ir(ir), .op4(op4), .func5(func6b), .a(aop), .b(bop), .c(c), .o(zlq_o), .nanx(nanx) );
|
|
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() );
|
|
fpScaleb u16 (.clk(clk), .ce(pipe_ce), .a(aop), .b(bop), .o(scaleb_o));
|
|
|
//fpLOOUnit #(32) u7s (.clk(clk), .ce(pipe_ce), .rm(rm), .op(op), .fn(fn), .a(a[31:0]), .o(loos_o), .done() );
|
//fpLOOUnit #(32) u7s (.clk(clk), .ce(pipe_ce), .rm(rm), .op(op), .fn(fn), .a(a[31:0]), .o(loos_o), .done() );
|
|
|
fp_decomp #(WID) u1 (.i(a), .sgn(sa), .man(ma), .vz(az), .inf(aInf), .nan(aNan) );
|
fp_decomp #(WID) u1 (.i(aop), .sgn(sa), .man(ma), .vz(az), .inf(aInf), .nan(aNan) );
|
fp_decomp #(WID) u2 (.i(b), .sgn(sb), .man(mb), .vz(bz), .inf(bInf), .nan(bNan) );
|
fp_decomp #(WID) u2 (.i(bop), .sgn(sb), .man(mb), .vz(bz), .inf(bInf), .nan(bNan) );
|
//fp_decomp #(32) u1s (.i(a[31:0]), .sgn(sas), .man(mas), .vz(azs), .inf(aInfs), .nan(aNans) );
|
//fp_decomp #(32) u1s (.i(a[31:0]), .sgn(sas), .man(mas), .vz(azs), .inf(aInfs), .nan(aNans) );
|
//fp_decomp #(32) u2s (.i(b[31:0]), .sgn(sbs), .man(mbs), .vz(bzs), .inf(bInfs), .nan(bNans) );
|
//fp_decomp #(32) u2s (.i(b[31:0]), .sgn(sbs), .man(mbs), .vz(bzs), .inf(bInfs), .nan(bNans) );
|
|
|
wire [2:0] rmd = ir[26:24]==3'b111 ? rm : ir[26:24];
|
wire [2:0] rmd = ir[30:28]==3'b111 ? rm : ir[30:28];
|
delay4 #(3) u3 (.clk(clk), .ce(pipe_ce), .i(rmd), .o(rmd4) );
|
delay4 #(3) u3 (.clk(clk), .ce(pipe_ce), .i(rmd), .o(rmd4) );
|
delay1 #(6) u4 (.clk(clk), .ce(pipe_ce), .i(func6b), .o(op1) );
|
delay1 #(6) u4 (.clk(clk), .ce(pipe_ce), .i(func6b), .o(op1) );
|
delay2 #(6) u5 (.clk(clk), .ce(pipe_ce), .i(func6b), .o(op2) );
|
delay2 #(4) u5 (.clk(clk), .ce(pipe_ce), .i(op4), .o(op2) );
|
delay2 #(6) u5b (.clk(clk), .ce(pipe_ce), .i(func6b), .o(fn2) );
|
delay2 #(6) u5b (.clk(clk), .ce(pipe_ce), .i(func6b), .o(fn2) );
|
|
|
delay5 delay5_3(.clk(clk), .ce(pipe_ce), .i((bz & !aNan & fdiv)|(bzs & !aNans & fdivs)), .o(divByZero) );
|
delay5 delay5_3(.clk(clk), .ce(pipe_ce), .i((bz & !aNan & fdiv)|(bzs & !aNans & fdivs)), .o(divByZero) );
|
|
|
// Compute NaN output sign
|
// Compute NaN output sign
|
Line 403... |
Line 412... |
wire [MSB:0] fpu_o;
|
wire [MSB:0] fpu_o;
|
wire [MSB+3:0] fpn_o;
|
wire [MSB+3:0] fpn_o;
|
wire [EX:0] fdiv_o;
|
wire [EX:0] fdiv_o;
|
wire [EX:0] fmul_o;
|
wire [EX:0] fmul_o;
|
wire [EX:0] fas_o;
|
wire [EX:0] fas_o;
|
|
wire [EX:0] fsqrt_o;
|
reg [EX:0] fres;
|
reg [EX:0] fres;
|
wire [31:0] fpus_o;
|
wire [31:0] fpus_o;
|
wire [31+3:0] fpns_o;
|
wire [31+3:0] fpns_o;
|
wire [EXS:0] fdivs_o;
|
wire [EXS:0] fdivs_o;
|
wire [EXS:0] fmuls_o;
|
wire [EXS:0] fmuls_o;
|
wire [EXS:0] fass_o;
|
wire [EXS:0] fass_o;
|
|
wire [EXS:0] fres_o;
|
reg [EXS:0] fress;
|
reg [EXS:0] fress;
|
wire divUnder,divUnders;
|
wire divUnder,divUnders;
|
wire mulUnder,mulUnders;
|
wire mulUnder,mulUnders;
|
reg under,unders;
|
reg under,unders;
|
|
wire sqrneg;
|
fpAddsub #(WID) u10(.clk(clk), .ce(pipe_ce), .rm(rmd), .op(func6b[0]), .a(a), .b(b), .o(fas_o) );
|
wire fms = func6b==`FMS || func6b==`FNMS;
|
fpDiv #(WID) u11(.clk(clk), .ce(pipe_ce), .ld(ld), .a(a), .b(b), .o(fdiv_o), .sign_exe(), .underflow(divUnder), .done(divDone) );
|
wire nma = func6b==`FNMA || func6b==`FNMS;
|
fpMul #(WID) u12(.clk(clk), .ce(pipe_ce), .a(a), .b(b), .o(fmul_o), .sign_exe(), .inf(), .underflow(mulUnder) );
|
wire [WID-1:0] ma_aop = aop ^ (nma << WID-1);
|
|
|
|
fpAddsub #(WID) u10(.clk(clk), .ce(pipe_ce), .rm(rmd), .op(func6b[0]), .a(aop), .b(bop), .o(fas_o) );
|
|
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) );
|
|
fpMul #(WID) u12(.clk(clk), .ce(pipe_ce), .a(aop), .b(bop), .o(fmul_o), .sign_exe(), .inf(), .underflow(mulUnder) );
|
|
fpSqrt #(WID) u13(.rst(rst), .clk(clk4x), .ce(pipe_ce), .ld(ld), .a(aop), .o(fsqrt_o), .done(), .sqrinf(), .sqrneg(sqrneg) );
|
|
fpRes #(WID) u14(.clk(clk), .ce(pipe_ce), .a(aop), .o(fres_o));
|
|
fpFMA #(WID) u15(.clk(clk), .ce(pipe_ce), .op(fms), .rm(rmd), .a(ma_aop), .b(bop), .c(c), .o(fma_o), .inf());
|
|
|
|
fpRemainder ufpr1
|
|
(
|
|
.rst(rst),
|
|
.clk(clk),
|
|
.ce(ce),
|
|
.ld_i(ld),
|
|
.ld_o(rem_ld),
|
|
.op4_i(op4_i),
|
|
.funct6b_i(func6b_i),
|
|
.op4_o(op4_r),
|
|
.funct6b_o(func6b_r),
|
|
.op_done(op_done),
|
|
.rem_done(rem_done),
|
|
.srca(srca),
|
|
.srcb(srcb),
|
|
.latch_res(latch_res)
|
|
);
|
/*
|
/*
|
fpAddsub #(32) u10s(.clk(clk), .ce(pipe_ce), .rm(rm), .op(op[0]), .a(a[31:0]), .b(b[31:0]), .o(fass_o) );
|
fpAddsub #(32) u10s(.clk(clk), .ce(pipe_ce), .rm(rm), .op(op[0]), .a(a[31:0]), .b(b[31:0]), .o(fass_o) );
|
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() );
|
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() );
|
fpMul #(32) u12s(.clk(clk), .ce(pipe_ce), .a(a[31:0]), .b(b[31:0]), .o(fmuls_o), .sign_exe(), .inf(), .underflow(mulUnders) );
|
fpMul #(32) u12s(.clk(clk), .ce(pipe_ce), .a(a[31:0]), .b(b[31:0]), .o(fmuls_o), .sign_exe(), .inf(), .underflow(mulUnders) );
|
*/
|
*/
|
always @*
|
always @*
|
case(op2)
|
case(op2)
|
`FLOAT:
|
`FLT2,`FLT2LI:
|
case (fn2)
|
case (fn2)
|
`FMUL: under = mulUnder;
|
`FMUL: under = mulUnder;
|
`FDIV: under = divUnder;
|
`FDIV: under = divUnder;
|
default: begin under = 0; unders = 0; end
|
default: begin under = 0; unders = 0; end
|
endcase
|
endcase
|
`VECTOR:
|
|
case (fn2)
|
|
`VFMUL: under = mulUnder;
|
|
`VFDIV: under = divUnder;
|
|
default: begin under = 0; unders = 0; end
|
|
endcase
|
|
default: begin under = 0; unders = 0; end
|
default: begin under = 0; unders = 0; end
|
endcase
|
endcase
|
|
|
always @*
|
always @*
|
case(op2)
|
case(op2)
|
`FLOAT:
|
`FLT3:
|
|
case(fn2)
|
|
`FMA: fres <= fma_o;
|
|
`FMS: fres <= fma_o;
|
|
`FNMA: fres <= fma_o;
|
|
`FNMS: fres <= fma_o;
|
|
default: fres <= fma_o;
|
|
endcase
|
|
`FLT2,`FLT2LI:
|
case(fn2)
|
case(fn2)
|
`FADD: fres <= fas_o;
|
`FADD: fres <= fas_o;
|
`FSUB: fres <= fas_o;
|
`FSUB: fres <= fas_o;
|
`FMUL: fres <= fmul_o;
|
`FMUL: fres <= fmul_o;
|
`FDIV: fres <= fdiv_o;
|
`FDIV: fres <= fdiv_o;
|
|
`FSCALEB: fres <= scaleb_o;
|
default: begin fres <= fas_o; fress <= fass_o; end
|
default: begin fres <= fas_o; fress <= fass_o; end
|
endcase
|
endcase
|
`VECTOR:
|
`FLT1:
|
case(fn2)
|
case(fn2)
|
`VFADD: fres <= fas_o;
|
`FSQRT: fres <= fsqrt_o;
|
`VFSUB: fres <= fas_o;
|
default: begin fres <= 1'd0; fress <= 1'd0; end
|
`VFMUL: fres <= fmul_o;
|
endcase
|
`VFDIV: fres <= fdiv_o;
|
`FLT1A:
|
default: begin fres <= fas_o; fress <= fass_o; end
|
case(fn2)
|
|
`FRES: fres <= fres_o;
|
|
default: begin fres <= 1'd0; fress <= 1'd0; end
|
endcase
|
endcase
|
default: begin fres <= fas_o; fress <= fass_o; end
|
default: begin fres <= fas_o; fress <= fass_o; end
|
endcase
|
endcase
|
|
|
// pipeline stage
|
// pipeline stage
|
Line 501... |
Line 542... |
giopx,
|
giopx,
|
gx,
|
gx,
|
sx,
|
sx,
|
|
|
1'b0, // cvtx
|
1'b0, // cvtx
|
1'b0, // sqrtx
|
sqrneg, // sqrtx
|
fcmp & nanx,
|
fcmp & nanx,
|
infzero,
|
infzero,
|
zerozero,
|
zerozero,
|
infdiv,
|
infdiv,
|
subinf,
|
subinf,
|
isNan
|
isNan
|
};
|
};
|
|
|
assign o = (!fstat) ?
|
wire [WID-1:0] o1 =
|
(frm|fcx|fdx|fex) ? (a|imm) :
|
(frm|fcx|fdx|fex) ? (a|imm) :
|
zl_op ? zlq_o :
|
zl_op ? zlq_o :
|
loo_op ? looq_o :
|
loo_op ? looq_o :
|
{so,fpu_o[MSB-1:0]} : 'bz;
|
{so,fpu_o[MSB-1:0]};
|
assign zero = fpu_o[MSB-1:0]==0;
|
assign zero = fpu_o[MSB-1:0]==0;
|
|
assign o = fprem ? res : o1;
|
|
always @(posedge clk)
|
|
if (ce & latch_res) res <= o1;
|
|
|
wire [7:0] maxdivcnt;
|
wire [7:0] maxdivcnt;
|
generate begin
|
generate begin
|
if (WID==128) begin
|
if (WID==128) begin
|
assign inf = &fpu_o[126:112] && fpu_o[111:0]==0;
|
assign inf = &fpu_o[126:112] && fpu_o[111:0]==0;
|
assign subinf = fpu_o[126:0]==`QSUBINFQ;
|
assign subinf = fpu_o[126:0]==`QSUBINFQ;
|
assign infdiv = fpu_o[126:0]==`QINFDIVQ;
|
assign infdiv = fpu_o[126:0]==`QINFDIVQ;
|
assign zerozero = fpu_o[126:0]==`QZEROZEROQ;
|
assign zerozero = fpu_o[126:0]==`QZEROZEROQ;
|
assign infzero = fpu_o[126:0]==`QINFZEROQ;
|
assign infzero = fpu_o[126:0]==`QINFZEROQ;
|
assign maxdivcnt = 8'd250;
|
assign maxdivcnt = 8'd128;
|
end
|
end
|
else if (WID==80) begin
|
else if (WID==80) begin
|
assign inf = &fpu_o[78:64] && fpu_o[63:0]==0;
|
assign inf = &fpu_o[78:64] && fpu_o[63:0]==0;
|
assign subinf = fpu_o[78:0]==`QSUBINFDX;
|
assign subinf = fpu_o[78:0]==`QSUBINFDX;
|
assign infdiv = fpu_o[78:0]==`QINFDIVDX;
|
assign infdiv = fpu_o[78:0]==`QINFDIVDX;
|
assign zerozero = fpu_o[78:0]==`QZEROZERODX;
|
assign zerozero = fpu_o[78:0]==`QZEROZERODX;
|
assign infzero = fpu_o[78:0]==`QINFZERODX;
|
assign infzero = fpu_o[78:0]==`QINFZERODX;
|
assign maxdivcnt = 8'd136;
|
assign maxdivcnt = 8'd80;
|
end
|
end
|
else if (WID==64) begin
|
else if (WID==64) begin
|
assign inf = &fpu_o[62:52] && fpu_o[51:0]==0;
|
assign inf = &fpu_o[62:52] && fpu_o[51:0]==0;
|
assign subinf = fpu_o[62:0]==`QSUBINFD;
|
assign subinf = fpu_o[62:0]==`QSUBINFD;
|
assign infdiv = fpu_o[62:0]==`QINFDIVD;
|
assign infdiv = fpu_o[62:0]==`QINFDIVD;
|
assign zerozero = fpu_o[62:0]==`QZEROZEROD;
|
assign zerozero = fpu_o[62:0]==`QZEROZEROD;
|
assign infzero = fpu_o[62:0]==`QINFZEROD;
|
assign infzero = fpu_o[62:0]==`QINFZEROD;
|
assign maxdivcnt = 8'd112;
|
assign maxdivcnt = 8'd64;
|
end
|
end
|
else if (WID==32) begin
|
else if (WID==32) begin
|
assign inf = &fpu_o[30:23] && fpu_o[22:0]==0;
|
assign inf = &fpu_o[30:23] && fpu_o[22:0]==0;
|
assign subinf = fpu_o[30:0]==`QSUBINFS;
|
assign subinf = fpu_o[30:0]==`QSUBINFS;
|
assign infdiv = fpu_o[30:0]==`QINFDIVS;
|
assign infdiv = fpu_o[30:0]==`QINFDIVS;
|
assign zerozero = fpu_o[30:0]==`QZEROZEROS;
|
assign zerozero = fpu_o[30:0]==`QZEROZEROS;
|
assign infzero = fpu_o[30:0]==`QINFZEROS;
|
assign infzero = fpu_o[30:0]==`QINFZEROS;
|
assign maxdivcnt = 8'd54;
|
assign maxdivcnt = 8'd32;
|
end
|
end
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
assign exception = gx;
|
assign exception = gx;
|
Line 562... |
Line 606... |
always @(posedge clk)
|
always @(posedge clk)
|
begin
|
begin
|
if (rst)
|
if (rst)
|
fpcnt <= 8'h00;
|
fpcnt <= 8'h00;
|
else begin
|
else begin
|
if (ld)
|
if (ld|rem_ld)
|
case(ir[5:0])
|
case(op4)
|
`FLOAT:
|
`FLT3:
|
begin
|
case(func6b)
|
|
`FMA: fpcnt <= 8'd22;
|
|
`FMS: fpcnt <= 8'd22;
|
|
`FNMA: fpcnt <= 8'd22;
|
|
`FNMS: fpcnt <= 8'd22;
|
|
default: fpcnt <= 8'd00;
|
|
endcase
|
|
`FLT2,`FLT2LI:
|
|
case(func6b)
|
|
`FCMP: begin fpcnt <= 8'd0; end
|
|
`FADD: begin fpcnt <= 8'd6; end
|
|
`FSUB: begin fpcnt <= 8'd6; end
|
|
`FMUL: begin fpcnt <= 8'd6; end
|
|
`FDIV: begin fpcnt <= maxdivcnt; end
|
|
`FREM: fpcnt <= maxdivcnt+8'd23;
|
|
`NXTAFT: fpcnt <= 8'd1;
|
|
`FSCALEB: fpcnt <= 8'd2;
|
|
default: fpcnt <= 8'h00;
|
|
endcase
|
|
`FLT1:
|
case(func6b)
|
case(func6b)
|
`FABS,`FNABS,`FNEG,`FMAN,`FMOV,`FSIGN,
|
`FABS,`FNABS,`FNEG,`FMAN,`FMOV,`FSIGN,
|
`FCVTSD,`FCVTSQ,`FCVTDS: begin fpcnt <= 8'd0; end
|
`FCVTSD,`FCVTDS: begin fpcnt <= 8'd0; end
|
`FTOI: begin fpcnt <= 8'd1; end
|
`FTOI: begin fpcnt <= 8'd1; end
|
`ITOF: begin fpcnt <= 8'd1; end
|
`ITOF: begin fpcnt <= 8'd1; end
|
`FCMP: begin fpcnt <= 8'd0; end
|
`TRUNC: begin fpcnt <= 8'd1; end
|
`FADD: begin fpcnt <= 8'd8; end
|
`FSQRT: begin fpcnt <= maxdivcnt; end
|
`FSUB: begin fpcnt <= 8'd8; end
|
|
`FMUL: begin fpcnt <= 8'd10; end
|
|
`FDIV: begin fpcnt <= maxdivcnt; end
|
|
default: fpcnt <= 8'h00;
|
default: fpcnt <= 8'h00;
|
endcase
|
endcase
|
end
|
`FLT1A:
|
`VECTOR:
|
|
case(func6b)
|
case(func6b)
|
`VFNEG: begin fpcnt <= 8'd0; end
|
`FRES: fpcnt <= 8'h03;
|
`VFADD: begin fpcnt <= 8'd8; end
|
|
`VFSUB: begin fpcnt <= 8'd8; end
|
|
`VFSxx: begin fpcnt <= 8'd0; end
|
|
`VFMUL: begin fpcnt <= 8'd10; end
|
|
`VFDIV: begin fpcnt <= maxdivcnt; end
|
|
`VFTOI: begin fpcnt <= 8'd1; end
|
|
`VITOF: begin fpcnt <= 8'd1; end
|
|
default: fpcnt <= 8'h00;
|
default: fpcnt <= 8'h00;
|
endcase
|
endcase
|
default: fpcnt <= 8'h00;
|
default: fpcnt <= 8'h00;
|
endcase
|
endcase
|
else if (!done)
|
else if (!op_done) begin
|
|
if ((op4==`FLT2||op4==`FLT2LI) && func6b==`FDIV && divDone)
|
|
fpcnt <= 8'h00;
|
|
else
|
fpcnt <= fpcnt - 1;
|
fpcnt <= fpcnt - 1;
|
end
|
end
|
end
|
end
|
|
end
|
endmodule
|
endmodule
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|