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

Subversion Repositories m32632

[/] [m32632/] [trunk/] [rtl/] [SP_FPU.v] - Diff between revs 11 and 23

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 11 Rev 23
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;
 
 

powered by: WebSVN 2.1.0

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