Line 2... |
Line 2... |
//
|
//
|
// This file is part of the M32632 project
|
// This file is part of the M32632 project
|
// http://opencores.org/project,m32632
|
// http://opencores.org/project,m32632
|
//
|
//
|
// Filename: SP_FPU.v
|
// Filename: SP_FPU.v
|
// Version: 1.0
|
// Version: 2.0
|
// Date: 30 May 2015
|
// History: 1.0 first release of 30 Mai 2015
|
|
// Date: 14 August 2016
|
//
|
//
|
// Copyright (C) 2015 Udo Moeller
|
// Copyright (C) 2016 Udo Moeller
|
//
|
//
|
// This source file may be used and distributed without
|
// This source file may be used and distributed without
|
// restriction provided that this copyright statement is not
|
// restriction provided that this copyright statement is not
|
// removed from the file and that any derivative work contains
|
// removed from the file and that any derivative work contains
|
// the original copyright notice and the associated disclaimer.
|
// the original copyright notice and the associated disclaimer.
|
Line 30... |
Line 31... |
// Public License along with this source; if not, download it
|
// Public License along with this source; if not, download it
|
// from http://www.opencores.org/lgpl.shtml
|
// from http://www.opencores.org/lgpl.shtml
|
//
|
//
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
|
// Testversion mit Pipeline Register in SFPU_ADDSUB **************
|
|
//
|
// Modules contained in this file:
|
// Modules contained in this file:
|
// 1. ADDSUB Adder and Subtractor for 36 bit
|
// 1. ADDSUB Adder and Subtractor for 36 bit
|
// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter
|
// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter
|
// 3. SFPU_MUL Single Precision Floating Point Multiplier
|
// 3. SFPU_MUL Single Precision Floating Point Multiplier
|
// 4. SP_FPU Top Level of Single Precision Floating Point Unit
|
// 4. SP_FPU Top Level of Single Precision Floating Point Unit
|
Line 58... |
Line 61... |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter
|
// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module SFPU_ADDSUB ( SRC1, SRC2, NZEXP, BWD, SELECT, OUT, IOUT, CMPRES );
|
module SFPU_ADDSUB ( BCLK, SRC1, SRC2, NZEXP, BWD, SELECT, OUT, IOUT, CMPRES );
|
|
|
|
input BCLK;
|
input [31:0] SRC1,SRC2; // Input data
|
input [31:0] SRC1,SRC2; // Input data
|
input [2:1] NZEXP;
|
input [2:1] NZEXP;
|
input [1:0] BWD; // size of integer
|
input [1:0] BWD; // size of integer
|
input [3:0] SELECT;
|
input [3:0] SELECT;
|
|
|
output [36:0] OUT; // the result
|
output [36:0] OUT; // the result
|
output [31:0] IOUT; // result of ROUNDFi/TRUNCFi/FLOORFi
|
output reg [31:0] IOUT; // result of ROUNDFi/TRUNCFi/FLOORFi
|
output [1:0] CMPRES;
|
output reg [1:0] CMPRES;
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// MOViF : 1. step
|
// MOViF : 1. step
|
|
|
reg [31:8] movdat;
|
reg [31:0] movdat;
|
wire [31:0] movif;
|
wire [31:0] movif;
|
|
|
always @(BWD or SRC1)
|
always @(BWD or SRC1)
|
casex({BWD,SRC1[15],SRC1[7]})
|
casex(BWD)
|
4'b00x0 : movdat = 24'h0000_00; // Byte
|
2'b00 : movdat = {{24{SRC1[7]}}, SRC1[7:0]}; // Byte
|
4'b00x1 : movdat = 24'hFFFF_FF;
|
2'b01 : movdat = {{16{SRC1[15]}},SRC1[15:0]}; // Word
|
4'b010x : movdat = {16'h0000,SRC1[15:8]}; // Word
|
default : movdat = SRC1[31:0]; // Double
|
4'b011x : movdat = {16'hFFFF,SRC1[15:8]};
|
|
default : movdat = SRC1[31:8]; // Double
|
|
endcase
|
endcase
|
|
|
assign movif = movdat[31] ? (32'h0 - {movdat,SRC1[7:0]}) : {movdat,SRC1[7:0]};
|
assign movif = ({32{movdat[31]}} ^ movdat) + {31'h0,movdat[31]};
|
// -2^31 is kept
|
// -2^31 is kept
|
|
|
// ROUNDFi/TRUNCFi/FLOORFi : 1. step
|
// ROUNDFi/TRUNCFi/FLOORFi : 1. step
|
|
|
reg ovflag,ovflag2;
|
reg ovflag,ovflag2;
|
wire [8:0] rexdiff,rexo;
|
wire [8:0] rexdiff,rexo;
|
wire rovfl,minint;
|
reg rovfl;
|
|
wire minint;
|
wire ganzklein; // Flag for 0
|
wire ganzklein; // Flag for 0
|
|
|
assign rexdiff = 9'h09D - {1'b0,SRC1[30:23]}; // 4..0 is the right shift value
|
assign rexdiff = 9'h09D - {1'b0,SRC1[30:23]}; // 4..0 is the right shift value
|
assign rovfl = (ovflag | ovflag2) & (SELECT[1:0] == 2'b11) & ~minint;
|
always @(posedge BCLK) rovfl <= (ovflag | ovflag2) & (SELECT[1:0] == 2'b11) & ~minint;
|
assign ganzklein = (~rexdiff[8] & (rexdiff[7:5] != 3'b000)); // 0 is implicit via SRC1[30:23]=0
|
assign ganzklein = (~rexdiff[8] & (rexdiff[7:5] != 3'b000)); // 0 is implicit via SRC1[30:23]=0
|
|
|
// Detection of Overflow
|
// Detection of Overflow
|
assign rexo = ({1'b0,SRC1[30:23]} - {8'h3F,~BWD[1]}); // subtract B/W = 7F , D = 7E
|
assign rexo = ({1'b0,SRC1[30:23]} - {8'h3F,~BWD[1]}); // subtract B/W = 7F , D = 7E
|
|
|
Line 116... |
Line 119... |
// ADD/SUB : 1. step : which operand ist bigger ? if required exchange
|
// ADD/SUB : 1. step : which operand ist bigger ? if required exchange
|
// SUB/CMP : SRC2 - SRC1
|
// SUB/CMP : SRC2 - SRC1
|
|
|
wire [8:0] exdiff;
|
wire [8:0] exdiff;
|
wire [23:0] madiff;
|
wire [23:0] madiff;
|
wire switch,sign,sign1,sign2;
|
wire switch,sign1,sign2;
|
wire variante;
|
reg variante;
|
wire vorz,addflag;
|
wire vorz,addflag;
|
wire [35:0] result_sw,result_nosw;
|
wire [35:0] result,result_sw,result_nosw;
|
wire [24:0] value1,value2;
|
wire [24:0] value1,value2;
|
|
wire cmp_res;
|
wire [35:0] result;
|
|
|
|
assign exdiff = {1'b0,SRC2[30:23]} - {1'b0,SRC1[30:23]}; // Difference of Exponents
|
assign exdiff = {1'b0,SRC2[30:23]} - {1'b0,SRC1[30:23]}; // Difference of Exponents
|
assign madiff = {1'b0,SRC2[22:0]} - {1'b0,SRC1[22:0]}; // Difference of Mantissas
|
assign madiff = {1'b0,SRC2[22:0]} - {1'b0,SRC1[22:0]}; // Difference of Mantissas
|
|
|
// if exdiff = 0 the shifter to the right is not needed !
|
// if exdiff = 0 the shifter to the right is not needed ! MUX at the end, ROUND/TRUNC/MOViF uses case 1
|
assign variante = (exdiff[8:1] == 8'h00) | (exdiff == 9'h1FF) | SELECT[1]; // MUX at the end, ROUND/TRUNC/MOViF uses case 1
|
always @(posedge BCLK) variante <= (exdiff[8:1] == 8'h00) | (exdiff == 9'h1FF) | SELECT[1];
|
|
|
// ++++++++++++++++++++++++++ 1. case works on MOViF +++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++ 1. case works on MOViF +++++++++++++++++++++++++++++++++++++++
|
|
|
assign switch = exdiff[8] | ((exdiff[7:0] == 8'h0) & madiff[23]); // exchange ?
|
assign switch = exdiff[8] | ((exdiff[7:0] == 8'h0) & madiff[23]); // exchange ?
|
|
|
Line 167... |
Line 169... |
assign vorz = switch ? (SELECT[0] ^ sign1) : sign2;
|
assign vorz = switch ? (SELECT[0] ^ sign1) : sign2;
|
assign addflag = ~(SELECT[0] ^ (sign1 ^ sign2));
|
assign addflag = ~(SELECT[0] ^ (sign1 ^ sign2));
|
|
|
// CMPF : 1. step : what happend if Invalid Operand occurs - no Flag update !
|
// CMPF : 1. step : what happend if Invalid Operand occurs - no Flag update !
|
|
|
assign CMPRES[1] = ~CMPRES[0] & (switch ? ~sign1 : sign2); // see table above : N-Bit=1 if SRC1 > SRC2
|
assign cmp_res = (SRC1 == SRC2) | (~NZEXP[2] & ~NZEXP[1]); // Z-Bit : SRC1=SRC2, +0.0 = -0.0
|
assign CMPRES[0] = (SRC1 == SRC2) | (~NZEXP[2] & ~NZEXP[1]); // Z-Bit : SRC1=SRC2, +0.0 = -0.0
|
always @(posedge BCLK) CMPRES <= {(~cmp_res & (switch ? ~sign1 : sign2)),cmp_res}; // see table above : N-Bit=1 if SRC1 > SRC2
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// ADD/SUB : 3. step : prepare of Barrelshifter Left
|
// ADD/SUB : 3. step : prepare of Barrelshifter Left
|
|
|
wire [31:0] blshift;
|
wire [31:0] blshift;
|
wire [9:0] shiftl;
|
reg [9:0] shiftl;
|
wire shift_16;
|
wire shift_16;
|
wire [33:0] add_q;
|
reg [33:0] add_q;
|
wire [31:0] muxsrc2;
|
wire [31:0] muxsrc2;
|
wire [1:0] inex;
|
wire [1:0] inex;
|
|
|
assign blshift = SELECT[1] ? movif : {result[26:0],5'h00}; // Feeding of MOViF
|
assign blshift = SELECT[1] ? movif : {result[26:0],5'h00}; // Feeding of MOViF
|
|
|
assign shiftl = SELECT[1] ? 10'h09E : {1'b0,result[35:27]}; // MOViF
|
always @(posedge BCLK) shiftl <= SELECT[1] ? 10'h09E : {1'b0,result[35:27]}; // MOViF
|
|
|
assign shift_16 = (blshift[31:16] == 16'h0000);
|
assign shift_16 = (blshift[31:16] == 16'h0000);
|
|
|
// In case of ADD the result bypasses the Barrelshifter left
|
// In case of ADD the result bypasses the Barrelshifter left
|
assign add_q = (muxsrc2[24] != result[27]) ? {result[35:3],(result[2:0] != 3'b000)}
|
always @(posedge BCLK) add_q <= (muxsrc2[24] != result[27]) ? {result[35:3],(result[2:0] != 3'b000)}
|
: {result[35:27],result[25:2],(result[1:0] != 2'b00)} ;
|
: {result[35:27],result[25:2],(result[1:0] != 2'b00)} ;
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// ADD/SUB : 4. step : Barrelshifter left for SUB and MOViF :
|
// ADD/SUB : 4. step : Barrelshifter left for SUB and MOViF :
|
|
|
wire shift_8,shift_4,shift_2,shift_1,zero;
|
wire shift_8,shift_4,shift_2,shift_1;
|
wire [1:0] lsb_bl;
|
wire [1:0] lsb_bl;
|
wire [31:0] blshifta,blshiftb,blshiftc,blshiftd,blshifte;
|
wire [31:0] blshifta,blshiftc,blshiftd,blshifte;
|
|
reg [31:0] blshiftb;
|
wire [9:0] expol;
|
wire [9:0] expol;
|
wire [36:0] out_v1;
|
wire [36:0] out_v1;
|
|
reg [1:0] rinex;
|
|
reg zero,sign,select_v1;
|
|
reg [4:3] pshift;
|
|
|
assign blshifta = shift_16 ? {blshift[15:0],16'h0000} : blshift;
|
assign blshifta = shift_16 ? {blshift[15:0],16'd0} : blshift;
|
assign shift_8 = (blshifta[31:24] == 8'h00);
|
assign shift_8 = (blshifta[31:24] == 8'h00);
|
assign blshiftb = shift_8 ? {blshifta[23:0],8'h00} : blshifta;
|
always @(posedge BCLK)
|
|
blshiftb <= shift_8 ? {blshifta[23:0],8'd0} : blshifta;
|
assign shift_4 = (blshiftb[31:28] == 4'h0);
|
assign shift_4 = (blshiftb[31:28] == 4'h0);
|
assign blshiftc = shift_4 ? {blshiftb[27:0],4'h0} : blshiftb;
|
assign blshiftc = shift_4 ? {blshiftb[27:0],4'd0} : blshiftb;
|
assign shift_2 = (blshiftc[31:30] == 2'b00);
|
assign shift_2 = (blshiftc[31:30] == 2'b00);
|
assign blshiftd = shift_2 ? {blshiftc[29:0],2'b00} : blshiftc;
|
assign blshiftd = shift_2 ? {blshiftc[29:0],2'd0} : blshiftc;
|
assign shift_1 = ~blshiftd[31];
|
assign shift_1 = ~blshiftd[31];
|
assign blshifte = shift_1 ? {blshiftd[30:0],1'b0} : blshiftd;
|
assign blshifte = shift_1 ? {blshiftd[30:0],1'b0} : blshiftd;
|
|
|
|
always @(posedge BCLK) pshift <= {shift_16,shift_8};
|
|
|
// Overflow at ROUNDFi/TRUNCFi/FLOORFi via overflow in exponent shown, SELECT[1] is then 1 !
|
// Overflow at ROUNDFi/TRUNCFi/FLOORFi via overflow in exponent shown, SELECT[1] is then 1 !
|
assign expol = (shiftl - {5'h00,shift_16,shift_8,shift_4,shift_2,shift_1}) | {1'b0,rovfl,8'h00};
|
assign expol = (shiftl - {5'h00,pshift,shift_4,shift_2,shift_1}) | {1'b0,rovfl,8'd0};
|
|
|
|
always @(posedge BCLK) rinex <= inex;
|
// Inexact at ROUNDFi/TRUNCFi/FLOORFi : evaluation for all one level higher
|
// Inexact at ROUNDFi/TRUNCFi/FLOORFi : evaluation for all one level higher
|
assign lsb_bl = (SELECT[1:0] == 2'b11) ? inex : {blshifte[7],(blshifte[6:0] != 7'h00)};
|
assign lsb_bl = (SELECT[1:0] == 2'b11) ? rinex : {blshifte[7],(blshifte[6:0] != 7'd0)};
|
|
|
assign zero = (~SELECT[1] & ~NZEXP[2] & ~NZEXP[1])
|
always @(posedge BCLK) zero <= (~SELECT[1] & ~NZEXP[2] & ~NZEXP[1])
|
| ((blshift == 32'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10)));
|
| ((blshift == 32'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10)));
|
|
|
assign sign = SELECT[1] ? movdat[31] : vorz;
|
always @(posedge BCLK) sign <= SELECT[1] ? movdat[31] : vorz;
|
|
|
|
always @(posedge BCLK) select_v1 <= addflag & ~SELECT[1];
|
|
|
assign out_v1 = (addflag & ~SELECT[1]) ? {zero,sign,1'b0,add_q}
|
assign out_v1 = select_v1 ? {zero,sign,1'b0,add_q}
|
: {zero,sign,expol,blshifte[30:8],lsb_bl};
|
: {zero,sign,expol,blshifte[30:8],lsb_bl};
|
|
|
// +++++++++++++++++++++++++ 2. case works on ROUND/TRUNC/FLOOR ++++++++++++++++++++++++++++++++++
|
// +++++++++++++++++++++++++ 2. case works on ROUND/TRUNC/FLOOR ++++++++++++++++++++++++++++++++++
|
|
|
wire vswitch;
|
wire vswitch;
|
Line 267... |
Line 279... |
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// ROUNDFi/TRUNCFi/FLOORFi : 3. step : round to integer
|
// ROUNDFi/TRUNCFi/FLOORFi : 3. step : round to integer
|
|
|
reg car_ry;
|
reg car_ry;
|
wire [30:0] compl;
|
wire [32:0] iadder;
|
wire [31:0] iadder;
|
|
|
|
assign inex = brshifte[1:0]; // Inexact-Flag-Data via multiplexer at the end
|
assign inex = brshifte[1:0]; // Inexact-Flag-Data via multiplexer at the end
|
|
|
always @(SELECT or sign1 or brshifte or inex or ganzklein)
|
always @(SELECT or sign1 or brshifte or inex or ganzklein)
|
casex (SELECT[3:2])
|
casex (SELECT[3:2])
|
2'b00 : car_ry = sign1 ^ ((brshifte[2:0] == 3'b110) | (inex == 2'b11)); // ROUNDLi
|
2'b00 : car_ry = sign1 ^ ((brshifte[2:0] == 3'b110) | (inex == 2'b11)); // ROUNDLi
|
2'b1x : car_ry = sign1 ? (~ganzklein & (inex == 2'b00)) : 1'b0; // +numbers like TRUNCLi, -numbers round to "-infinity"
|
2'b1x : car_ry = sign1 ? (~ganzklein & (inex == 2'b00)) : 1'b0; // +numbers like TRUNCLi, -numbers round to "-infinity"
|
default : car_ry = sign1; // TRUNCLi , simple cut
|
default : car_ry = sign1; // TRUNCLi , simple cut
|
endcase
|
endcase
|
|
|
assign compl = sign1 ? ~brshifte[32:2] : brshifte[32:2];
|
assign iadder = (sign1 ? {2'b11,~brshifte[32:2]} : {2'b0,brshifte[32:2]}) + {32'h0,car_ry};
|
|
|
assign iadder = {sign1,compl} + {31'h0,car_ry};
|
|
|
|
assign IOUT = minint ? 32'h8000_0000 : iadder;
|
always @(posedge BCLK) IOUT <= minint ? 32'h8000_0000 : iadder[31:0];
|
|
|
always @(iadder or BWD or sign1) // special overflow detection i.e. -129 bis -255 bei Byte
|
always @(iadder or BWD or sign1) // special overflow detection i.e. -129 bis -255 bei Byte
|
casex (BWD) // or 127.9 -> 128 = Fehler !
|
casex (BWD) // or 127.9 -> 128 = Fehler !
|
2'b00 : ovflag2 = (iadder[8] != iadder[7]); // Byte
|
2'b00 : ovflag2 = (iadder[8] != iadder[7]); // Byte
|
2'b01 : ovflag2 = (iadder[16] != iadder[15]); // Word
|
2'b01 : ovflag2 = (iadder[16] != iadder[15]); // Word
|
default : ovflag2 = 1'b0;
|
default : ovflag2 = (iadder[32] != iadder[31]); // Double
|
endcase
|
endcase
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// only ADD/SUB : 3. step : Add or Subtract
|
// only ADD/SUB : 3. step : Add or Subtract
|
// the modul ADDSUB integrates the carry from the mantissa : 35 Bit
|
// the modul ADDSUB integrates the carry from the mantissa : 35 Bit
|
Line 301... |
Line 310... |
wire lsb;
|
wire lsb;
|
wire [35:0] vresult;
|
wire [35:0] vresult;
|
wire [7:0] eminus1;
|
wire [7:0] eminus1;
|
wire [33:0] vadd_q,vsub_q;
|
wire [33:0] vadd_q,vsub_q;
|
wire vzero;
|
wire vzero;
|
wire [36:0] out_v0;
|
reg [36:0] out_v0;
|
|
|
assign lsb = (brshifte[6:0] != 7'h00);
|
assign lsb = (brshifte[6:0] != 7'h00);
|
|
|
// Adder-Definition : "0"(8 Bit Exponent)"1"(23 Bit Mantissa)"000"
|
// Adder-Definition : "0"(8 Bit Exponent)"1"(23 Bit Mantissa)"000"
|
|
|
Line 322... |
Line 331... |
// Case SUB : Bit 26 : "hidden" MSB of mantissa
|
// Case SUB : Bit 26 : "hidden" MSB of mantissa
|
assign vsub_q = vresult[26] ? {vresult[35:27], vresult[25:2],(vresult[1:0] != 2'b00)} // like the vadd_q "0" case
|
assign vsub_q = vresult[26] ? {vresult[35:27], vresult[25:2],(vresult[1:0] != 2'b00)} // like the vadd_q "0" case
|
: {vresult[35],eminus1,vresult[24:0]} ;
|
: {vresult[35],eminus1,vresult[24:0]} ;
|
|
|
// SELECT[1] has here no meaning
|
// SELECT[1] has here no meaning
|
assign vzero = (vresult[26:0] == 27'h0) & ~addflag; // only if "-" can be the result 0
|
assign vzero = (vresult[26:0] == 27'h0); // only if "-" can be the result 0
|
|
|
assign out_v0 = addflag ? {vzero,vorz,1'b0,vadd_q}
|
always @(posedge BCLK) out_v0 <= addflag ? { 1'b0,vorz,1'b0,vadd_q}
|
: {vzero,vorz,1'b0,vsub_q} ;
|
: {vzero,vorz,1'b0,vsub_q} ;
|
|
|
assign OUT = variante ? out_v1 : out_v0; // Last multiplexer
|
assign OUT = variante ? out_v1 : out_v0; // Last multiplexer
|
|
|
endmodule
|
endmodule
|
Line 336... |
Line 345... |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 3. SFPU_MUL Single Precision Floating Point Multiplier
|
// 3. SFPU_MUL Single Precision Floating Point Multiplier
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module SFPU_MUL ( SRC1, SRC2, MRESULT, NZEXP, OUT);
|
module SFPU_MUL ( BCLK, SRC1, SRC2, MRESULT, NZEXP, OUT);
|
|
|
|
input BCLK;
|
input [31:0] SRC1,SRC2; // only exponent of input data used
|
input [31:0] SRC1,SRC2; // only exponent of input data used
|
input [47:0] MRESULT;
|
input [47:0] MRESULT;
|
input [2:1] NZEXP; // Flags of input data
|
input [2:1] NZEXP; // Flags of input data
|
|
|
output [36:0] OUT; // The result
|
output reg [36:0] OUT; // The result
|
|
|
wire [9:0] exponent,expoh,expol;
|
wire [9:0] exponent,expoh,expol;
|
wire [1:0] restlow,resthigh;
|
wire [1:0] restlow,resthigh;
|
wire zero,sign,orlow;
|
wire zero,sign,orlow;
|
|
|
Line 359... |
Line 369... |
|
|
assign exponent = {2'b00,SRC1[30:23]} + {2'b00,SRC2[30:23]};
|
assign exponent = {2'b00,SRC1[30:23]} + {2'b00,SRC2[30:23]};
|
assign expoh = exponent - 10'h07E;
|
assign expoh = exponent - 10'h07E;
|
assign expol = exponent - 10'h07F; // for MSB if MRESULT=0
|
assign expol = exponent - 10'h07F; // for MSB if MRESULT=0
|
|
|
assign OUT = MRESULT[47] ? {zero,sign,expoh,MRESULT[46:24],resthigh}
|
always @(posedge BCLK) OUT <= MRESULT[47] ? {zero,sign,expoh,MRESULT[46:24],resthigh}
|
: {zero,sign,expol,MRESULT[45:23],restlow};
|
: {zero,sign,expol,MRESULT[45:23],restlow};
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 4. SP_FPU Top Level of Single Precision Floating Point Unit
|
// 4. SP_FPU Top Level of Single Precision Floating Point Unit
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module SP_FPU (BCLK, OPCODE, SRC1, SRC2, FSR, MRESULT, BWD, FL, FP_OUT, I_OUT, TT_SP, SP_CMP, SP_MUX, LD_FSR, UP_SP);
|
module SP_FPU (BCLK, START, OPCODE, SRC1, SRC2, FSR, MRESULT, BWD, FL, FP_OUT, I_OUT, TT_SP, SP_CMP, SP_MUX, LD_FSR, UP_SP);
|
|
|
input BCLK; // is not used !
|
input BCLK; // is not used !
|
|
input START;
|
input [7:0] OPCODE;
|
input [7:0] OPCODE;
|
input [31:0] SRC1,SRC2; // Input data
|
input [31:0] SRC1,SRC2; // Input data
|
input [8:3] FSR; // Floating Point Status Register
|
input [8:3] FSR; // Floating Point Status Register
|
input [47:0] MRESULT; // Multiplier result
|
input [47:0] MRESULT; // Multiplier result
|
input [1:0] BWD; // Size of integer
|
input [1:0] BWD; // Size of integer
|
input FL;
|
input FL;
|
|
|
output [31:0] FP_OUT,I_OUT; // The results
|
output [31:0] FP_OUT,I_OUT; // The results
|
output [4:0] TT_SP; // Trap-Type
|
output [4:0] TT_SP; // Trap-Type
|
output [2:0] SP_CMP; // CMPF result
|
output [2:0] SP_CMP; // CMPF result
|
output SP_MUX,LD_FSR,UP_SP;
|
output SP_MUX,LD_FSR;
|
|
output reg UP_SP;
|
|
|
reg [2:0] tt;
|
reg [2:0] tt;
|
reg [3:0] select;
|
reg [3:0] select;
|
|
reg nan;
|
reg car_ry;
|
reg car_ry;
|
|
|
wire [36:0] mulout,addout,fpout;
|
wire [36:0] mulout,addout,fpout;
|
wire [2:1] nzexp;
|
wire [2:1] nzexp;
|
wire [34:2] rund; // Indexnumbers like xxxout
|
wire [34:2] rund; // Indexnumbers like xxxout
|
wire overflow,underflow,inexact;
|
wire overflow,underflow,inexact;
|
wire op_cmp;
|
wire op_cmp;
|
wire nan,nan_1,nan_2;
|
wire nan_1,nan_2;
|
|
|
// Control of datapath
|
// Control of datapath
|
|
|
always @(OPCODE)
|
always @(OPCODE)
|
casex (OPCODE)
|
casex (OPCODE)
|
Line 413... |
Line 426... |
endcase
|
endcase
|
|
|
assign SP_MUX = select[3] & (select[1:0] != 2'b11) & FL; // Output multiplexer
|
assign SP_MUX = select[3] & (select[1:0] != 2'b11) & FL; // Output multiplexer
|
|
|
assign LD_FSR = (OPCODE[7:4] == 4'h9) & (OPCODE[3:1] == 3'b001); // LFSR does only Double (according datasheet NS32016)
|
assign LD_FSR = (OPCODE[7:4] == 4'h9) & (OPCODE[3:1] == 3'b001); // LFSR does only Double (according datasheet NS32016)
|
assign UP_SP = select[3] & FL; // All FPU opcodes of SP_FPU
|
always @(posedge BCLK) UP_SP = select[3] & FL & START; // All FPU opcodes of SP_FPU, all are using 2 Clock
|
assign op_cmp = (OPCODE == 8'hB2) & FL;
|
assign op_cmp = (OPCODE == 8'hB2) & FL;
|
|
|
// SRCFLAGS
|
// SRCFLAGS
|
|
|
assign nzexp[2] = (SRC2[30:23] != 8'd0); // only exponent 0 ,denormalized Number => NAN !
|
assign nzexp[2] = (SRC2[30:23] != 8'd0); // only exponent 0 ,denormalized Number => NAN !
|
assign nzexp[1] = (SRC1[30:23] != 8'd0); // only exponent 0 ,denormalized Number => NAN !
|
assign nzexp[1] = (SRC1[30:23] != 8'd0); // only exponent 0 ,denormalized Number => NAN !
|
assign nan_2 = (SRC2[30:23] == 8'hFF) | (~nzexp[2] & (SRC2[22:0] != 23'd0)); // NAN
|
assign nan_2 = (SRC2[30:23] == 8'hFF) | (~nzexp[2] & (SRC2[22:0] != 23'd0)); // NAN
|
assign nan_1 = (SRC1[30:23] == 8'hFF) | (~nzexp[1] & (SRC1[22:0] != 23'd0)); // NAN
|
assign nan_1 = (SRC1[30:23] == 8'hFF) | (~nzexp[1] & (SRC1[22:0] != 23'd0)); // NAN
|
|
|
assign nan = (select[1:0] == 2'b11) ? nan_1 : (~select[1] & (nan_2 | nan_1));
|
always @(posedge BCLK) nan <= (select[1:0] == 2'b11) ? nan_1 : (~select[1] & (nan_2 | nan_1));
|
|
|
// 001 : ADDF,... + 011 : CMPF
|
// 001 : ADDF,... + 011 : CMPF
|
SFPU_ADDSUB IADDSUB ( .SRC1(SRC1), .SRC2(SRC2), .NZEXP(nzexp), .BWD(BWD),
|
SFPU_ADDSUB IADDSUB ( .BCLK(BCLK), .SRC1(SRC1), .SRC2(SRC2), .NZEXP(nzexp), .BWD(BWD),
|
.SELECT({OPCODE[2:1],select[1:0]}), .OUT(addout), .IOUT(I_OUT), .CMPRES(SP_CMP[1:0]) );
|
.SELECT({OPCODE[2:1],select[1:0]}), .OUT(addout), .IOUT(I_OUT), .CMPRES(SP_CMP[1:0]) );
|
|
|
// 100 : MULF
|
// 100 : MULF
|
SFPU_MUL IMUL ( .SRC1(SRC1), .SRC2(SRC2), .MRESULT(MRESULT), .OUT(mulout), .NZEXP(nzexp) );
|
SFPU_MUL IMUL ( .BCLK(BCLK), .SRC1(SRC1), .SRC2(SRC2), .MRESULT(MRESULT), .OUT(mulout), .NZEXP(nzexp) );
|
|
|
// FP - Pfad : selection of result and rounding :
|
// FP - Pfad : selection of result and rounding :
|
|
|
assign fpout = (OPCODE[5] & OPCODE[3]) ? mulout : addout;
|
assign fpout = (OPCODE[5] & OPCODE[3]) ? mulout : addout;
|
|
|