| Line 1... | 
        Line 1... | 
      
      
           | 
        `timescale 1ns / 1ps
  | 
      
      
        // ============================================================================
  | 
        // ============================================================================
  | 
      
      
        //        __
  | 
        //        __
  | 
      
      
        //   \\__/ o\    (C) 2006-2016  Robert Finch, Stratford
  | 
        //   \\__/ o\    (C) 2006-2016  Robert Finch, Waterloo
  | 
      
      
        //    \  __ /    All rights reserved.
  | 
        //    \  __ /    All rights reserved.
  | 
      
      
        //     \/_//     robfinch<remove>@finitron.ca
  | 
        //     \/_//     robfinch<remove>@finitron.ca
  | 
      
      
        //       ||
  | 
        //       ||
  | 
      
      
        //
  | 
        //
  | 
      
      
           | 
        //      fpDiv.v
  | 
      
      
           | 
        //    - floating point divider
  | 
      
      
           | 
        //    - parameterized width
  | 
      
      
           | 
        //    - IEEE 754 representation
  | 
      
      
           | 
        //
  | 
      
      
           | 
        //
  | 
      
      
        // 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 
  | 
      
      
        // it under the terms of the GNU Lesser General Public License as published 
  | 
        // it under the terms of the GNU Lesser General Public License as published 
  | 
      
      
        // by the Free Software Foundation, either version 3 of the License, or     
  | 
        // by the Free Software Foundation, either version 3 of the License, or     
  | 
      
      
        // (at your option) any later version.                                      
  | 
        // (at your option) any later version.                                      
  | 
      
      
        //                                                                          
  | 
        //                                                                          
  | 
      
      
        | Line 16... | 
        Line 23... | 
      
      
        // GNU General Public License for more details.                             
  | 
        // GNU General Public License for more details.                             
  | 
      
      
        //                                                                          
  | 
        //                                                                          
  | 
      
      
        // 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/>.    
  | 
      
      
        //
  | 
        //
  | 
      
      
        //      fpDiv.v
  | 
        //      Floating Point Multiplier / Divider
  | 
      
      
        //  - floating point divider
  | 
           | 
      
      
        //  - parameterized width
  | 
           | 
      
      
        //  - IEEE 754 representation
  | 
           | 
      
      
        //
  | 
           | 
      
      
        //      Floating Point Divider
  | 
           | 
      
      
        //
  | 
        //
  | 
      
      
        // Properties:
  | 
        // Properties:
  | 
      
      
           | 
        //+-inf * +-inf = -+inf    (this is handled by exOver)
  | 
      
      
           | 
        //+-inf * 0     = QNaN
  | 
      
      
        // +-0 / +-0    = QNaN
  | 
        // +-0 / +-0    = QNaN
  | 
      
      
        //      
  | 
           | 
      
      
        // ============================================================================
  | 
        // ============================================================================
  | 
      
      
        //
  | 
         
  | 
      
      
        module fpDiv(clk, ce, ld, a, b, o, done, sign_exe, overflow, underflow);
  | 
        module fpDiv(clk, ce, ld, a, b, o, done, sign_exe, overflow, underflow);
  | 
      
      
         
  | 
         
  | 
      
      
        parameter WID = 32;
  | 
        parameter WID = 128;
  | 
      
      
        localparam MSB = WID-1;
  | 
        localparam MSB = WID-1;
  | 
      
      
        localparam EMSB = WID==80 ? 14 :
  | 
        localparam EMSB = WID==128 ? 14 :
  | 
      
      
           | 
                          WID==96 ? 14 :
  | 
      
      
           | 
                          WID==80 ? 14 :
  | 
      
      
                          WID==64 ? 10 :
  | 
                          WID==64 ? 10 :
  | 
      
      
                                          WID==52 ? 10 :
  | 
                                          WID==52 ? 10 :
  | 
      
      
                                          WID==48 ? 10 :
  | 
                                          WID==48 ? 10 :
  | 
      
      
                                          WID==44 ? 10 :
  | 
                                          WID==44 ? 10 :
  | 
      
      
                                          WID==42 ? 10 :
  | 
                                          WID==42 ? 10 :
  | 
      
      
                                          WID==40 ?  9 :
  | 
                                          WID==40 ?  9 :
  | 
      
      
                                          WID==32 ?  7 :
  | 
                                          WID==32 ?  7 :
  | 
      
      
                                          WID==24 ?  6 : 4;
  | 
                                          WID==24 ?  6 : 4;
  | 
      
      
        localparam FMSB = WID==80 ? 63 :
  | 
        localparam FMSB = WID==128 ? 111 :
  | 
      
      
           | 
                          WID==96 ? 79 :
  | 
      
      
           | 
                          WID==80 ? 63 :
  | 
      
      
                          WID==64 ? 51 :
  | 
                          WID==64 ? 51 :
  | 
      
      
                                          WID==52 ? 39 :
  | 
                                          WID==52 ? 39 :
  | 
      
      
                                          WID==48 ? 35 :
  | 
                                          WID==48 ? 35 :
  | 
      
      
                                          WID==44 ? 31 :
  | 
                                          WID==44 ? 31 :
  | 
      
      
                                          WID==42 ? 29 :
  | 
                                          WID==42 ? 29 :
  | 
      
      
                                          WID==40 ? 28 :
  | 
                                          WID==40 ? 28 :
  | 
      
      
                                          WID==32 ? 22 :
  | 
                                          WID==32 ? 22 :
  | 
      
      
                                          WID==24 ? 15 : 9;
  | 
                                          WID==24 ? 15 : 9;
  | 
      
      
         
  | 
         
  | 
      
      
        localparam WX = 3;
  | 
        localparam FX = (FMSB+2)*2-1;   // the MSB of the expanded fraction
  | 
      
      
        localparam FX = (FMSB+1)*2-1;   // the MSB of the expanded fraction
  | 
        localparam EX = FX + 1 + EMSB + 1 + 1 - 1;
  | 
      
      
        localparam EX = FX + WX + EMSB + 1;
  | 
           | 
      
      
         
  | 
         
  | 
      
      
        input clk;
  | 
        input clk;
  | 
      
      
        input ce;
  | 
        input ce;
  | 
      
      
        input ld;
  | 
        input ld;
  | 
      
      
        input [MSB:0] a, b;
  | 
        input [MSB:0] a, b;
  | 
      
      
        output [EX+1:0] o;
  | 
        output [EX:0] o;
  | 
      
      
        output done;
  | 
        output done;
  | 
      
      
        output sign_exe;
  | 
        output sign_exe;
  | 
      
      
        output overflow;
  | 
        output overflow;
  | 
      
      
        output underflow;
  | 
        output underflow;
  | 
      
      
         
  | 
         
  | 
      
      
        | Line 73... | 
        Line 79... | 
      
      
        reg     overflow;
  | 
        reg     overflow;
  | 
      
      
        reg     underflow;
  | 
        reg     underflow;
  | 
      
      
         
  | 
         
  | 
      
      
        reg so;
  | 
        reg so;
  | 
      
      
        reg [EMSB:0] xo;
  | 
        reg [EMSB:0] xo;
  | 
      
      
        reg [FX+WX:0] mo;
  | 
        reg [FX:0] mo;
  | 
      
      
        assign o = {so,xo,mo};
  | 
        assign o = {so,xo,mo};
  | 
      
      
         
  | 
         
  | 
      
      
        // constants
  | 
        // constants
  | 
      
      
        wire [EMSB:0] infXp = {EMSB+1{1'b1}};    // infinite / NaN - all ones
  | 
        wire [EMSB:0] infXp = {EMSB+1{1'b1}};    // infinite / NaN - all ones
  | 
      
      
        // The following is the value for an exponent of zero, with the offset
  | 
        // The following is the value for an exponent of zero, with the offset
  | 
      
      
        | Line 86... | 
        Line 92... | 
      
      
        // The following is a template for a quiet nan. (MSB=1)
  | 
        // The following is a template for a quiet nan. (MSB=1)
  | 
      
      
        wire [FMSB:0] qNaN  = {1'b1,{FMSB{1'b0}}};
  | 
        wire [FMSB:0] qNaN  = {1'b1,{FMSB{1'b0}}};
  | 
      
      
         
  | 
         
  | 
      
      
        // variables
  | 
        // variables
  | 
      
      
        wire [EMSB+2:0] ex1;     // sum of exponents
  | 
        wire [EMSB+2:0] ex1;     // sum of exponents
  | 
      
      
        wire [FX+WX:0] divo;
  | 
        wire [FX:0] divo;
  | 
      
      
         
  | 
         
  | 
      
      
        // Operands
  | 
        // Operands
  | 
      
      
        wire sa, sb;                    // sign bit
  | 
        wire sa, sb;                    // sign bit
  | 
      
      
        wire [EMSB:0] xa, xb;    // exponent bits
  | 
        wire [EMSB:0] xa, xb;    // exponent bits
  | 
      
      
        wire [FMSB+1:0] fracta, fractb;
  | 
        wire [FMSB+1:0] fracta, fractb;
  | 
      
      
        wire a_dn, b_dn;                        // a/b is denormalized
  | 
        wire a_dn, b_dn;                        // a/b is denormalized
  | 
      
      
        wire az, bz;
  | 
        wire az, bz;
  | 
      
      
        wire aInf, bInf;
  | 
        wire aInf, bInf;
  | 
      
      
         
  | 
        wire aNan,bNan;
  | 
      
      
         
  | 
         
  | 
      
      
        // -----------------------------------------------------------
  | 
        // -----------------------------------------------------------
  | 
      
      
        // - decode the input operands
  | 
        // - decode the input operands
  | 
      
      
        // - derive basic information
  | 
        // - derive basic information
  | 
      
      
        // - calculate exponent
  | 
        // - calculate exponent
  | 
      
      
        // - calculate fraction
  | 
        // - calculate fraction
  | 
      
      
        // -----------------------------------------------------------
  | 
        // -----------------------------------------------------------
  | 
      
      
         
  | 
         
  | 
      
      
        fpDecompose #(WID) u1a (.i(a), .sgn(sa), .exp(xa), .fract(fracta), .xz(a_dn), .vz(az), .inf(aInf) );
  | 
        fpDecomp #(WID) u1a (.i(a), .sgn(sa), .exp(xa), .fract(fracta), .xz(a_dn), .vz(az), .inf(aInf), .nan(aNan) );
  | 
      
      
        fpDecompose #(WID) u1b (.i(b), .sgn(sb), .exp(xb), .fract(fractb), .xz(b_dn), .vz(bz), .inf(bInf) );
  | 
        fpDecomp #(WID) u1b (.i(b), .sgn(sb), .exp(xb), .fract(fractb), .xz(b_dn), .vz(bz), .inf(bInf), .nan(bNan) );
  | 
      
      
         
  | 
         
  | 
      
      
        // Compute the exponent.
  | 
        // Compute the exponent.
  | 
      
      
        // - correct the exponent for denormalized operands
  | 
        // - correct the exponent for denormalized operands
  | 
      
      
        // - adjust the difference by the bias (add 127)
  | 
        // - adjust the difference by the bias (add 127)
  | 
      
      
        // - also factor in the different decimal position for division
  | 
        // - also factor in the different decimal position for division
  | 
      
      
        assign ex1 = (xa|a_dn) - (xb|b_dn) + bias + FMSB + 1;
  | 
        assign ex1 = (xa|a_dn) - (xb|b_dn) + bias + FMSB - 1;
  | 
      
      
         
  | 
         
  | 
      
      
        // check for exponent underflow/overflow
  | 
        // check for exponent underflow/overflow
  | 
      
      
        wire under = ex1[EMSB+2];       // MSB set = negative exponent
  | 
        wire under = ex1[EMSB+2];       // MSB set = negative exponent
  | 
      
      
        wire over = (&ex1[EMSB:0] | ex1[EMSB+1]) & !ex1[EMSB+2];
  | 
        wire over = (&ex1[EMSB:0] | ex1[EMSB+1]) & !ex1[EMSB+2];
  | 
      
      
         
  | 
         
  | 
      
      
        // Perform divide
  | 
        // Perform divide
  | 
      
      
        // could take either 1 or 16 clock cycles
  | 
        // could take either 1 or 16 clock cycles
  | 
      
      
        fpdivr2 #(FMSB+2) u2 (.clk(clk), .ld(ld), .a(fracta), .b(fractb), .q(divo[(FMSB+1)*2-1:0]), .r(), .done(done));
  | 
        fpdivr8 #(FMSB+2,2) u2 (.clk(clk), .ld(ld), .a({3'b0,fracta}), .b({3'b0,fractb}), .q(divo), .r(), .done(done));
  | 
      
      
        assign divo[FX+WX:(FMSB+1)*2] = 0;
  | 
           | 
      
      
         
  | 
         
  | 
      
      
        // determine when a NaN is output
  | 
        // determine when a NaN is output
  | 
      
      
        wire qNaNOut = (az&bz)|(aInf&bInf);
  | 
        wire qNaNOut = (az&bz)|(aInf&bInf);
  | 
      
      
         
  | 
         
  | 
      
      
        always @(posedge clk)
  | 
        always @(posedge clk)
  | 
      
      
                if (ce) begin
  | 
                if (ce) begin
  | 
      
      
                        if (done) begin
  | 
                        if (done) begin
  | 
      
      
                                casex({qNaNOut,bInf,bz})
  | 
                                casex({qNaNOut|aNan|bNan,bInf,bz})
  | 
      
      
                                3'b1xx:         xo = infXp;     // NaN exponent value
  | 
                                3'b1xx:         xo = infXp;     // NaN exponent value
  | 
      
      
                                3'bx1x:         xo = 0;          // divide by inf
  | 
                                3'bx1x:         xo = 0;          // divide by inf
  | 
      
      
                                3'bxx1:         xo = infXp;     // divide by zero
  | 
                                3'bxx1:         xo = infXp;     // divide by zero
  | 
      
      
                                default:        xo = ex1;               // normal or underflow: passthru neg. exp. for normalization
  | 
                                default:        xo = ex1;               // normal or underflow: passthru neg. exp. for normalization
  | 
      
      
                                endcase
  | 
                                endcase
  | 
      
      
         
  | 
         
  | 
      
      
                                casex({qNaNOut,bInf,bz})
  | 
                                casex({aNan,bNan,qNaNOut,bInf,bz})
  | 
      
      
                                3'b1xx:         mo = {1'b0,qNaN[FMSB:0]|{aInf,1'b0}|{az,bz},{FMSB+1{1'b0}}};
  | 
                                5'b1xxxx:       mo = {1'b0,a[FMSB:0],{FMSB+1{1'b0}}};
  | 
      
      
                                3'bx1x:         mo = 0;  // div by inf
  | 
                                5'bx1xxx:       mo = {1'b0,b[FMSB:0],{FMSB+1{1'b0}}};
  | 
      
      
                                3'bxx1:         mo = 0;  // div by zero
  | 
                                5'bxx1xx:               mo = {1'b0,qNaN[FMSB:0]|{aInf,1'b0}|{az,bz},{FMSB+1{1'b0}}};
  | 
      
      
           | 
                                5'bxxx1x:               mo = 0;  // div by inf
  | 
      
      
           | 
                                5'bxxxx1:               mo = 0;  // div by zero
  | 
      
      
                                default:        mo = divo;              // plain div
  | 
                                default:        mo = divo;              // plain div
  | 
      
      
                                endcase
  | 
                                endcase
  | 
      
      
         
  | 
         
  | 
      
      
                                so              = sa ^ sb;
  | 
                                so              = sa ^ sb;
  | 
      
      
                                sign_exe        = sa & sb;
  | 
                                sign_exe        = sa & sb;
  | 
      
      
        | Line 151... | 
        Line 158... | 
      
      
                        end
  | 
                        end
  | 
      
      
                end
  | 
                end
  | 
      
      
         
  | 
         
  | 
      
      
        endmodule
  | 
        endmodule
  | 
      
      
         
  | 
         
  | 
      
      
        module fpDiv_tb();
  | 
           | 
      
      
        reg clk;
  | 
           | 
      
      
        reg ld;
  | 
           | 
      
      
        wire ce = 1'b1;
  | 
           | 
      
      
        wire sgnx1,sgnx2,sgnx3,sgnx4,sgnx5,sgnx6;
  | 
           | 
      
      
        wire inf1,inf2,inf3,inf4,inf5,inf6;
  | 
           | 
      
      
        wire of1,of2,of3,of4,of5,of6;
  | 
           | 
      
      
        wire uf1,uf2,uf3,uf4,uf5,uf6;
  | 
           | 
      
      
        wire [57:0] o1,o2,o3,o4,o5,o6;
  | 
           | 
      
      
        wire [35:0] o11,o12,o13;
  | 
           | 
      
      
        wire [31:0] o21,o22,o23;
  | 
           | 
      
      
        wire done0,done1,done2,done3,done4,done5,done6;
  | 
           | 
      
      
         
  | 
           | 
      
      
        initial begin
  | 
           | 
      
      
                clk = 0;
  | 
           | 
      
      
                ld = 0;
  | 
           | 
      
      
                #20 ld = 1;
  | 
           | 
      
      
                #40 ld = 0;
  | 
           | 
      
      
        end
  | 
           | 
      
      
        always #10 clk <= ~clk;
  | 
           | 
      
      
         
  | 
           | 
      
      
        fpDiv u1 (.clk(clk), .ce(1'b1), .ld(ld), .a(0), .b(0), .o(o1), .done(done1), .sign_exe(sgnx1), .overflow(of1), .underflow(uf1));
  | 
           | 
      
      
        fpDiv u2 (.clk(clk), .ce(1'b1), .ld(ld), .a(0), .b(0), .o(o2), .done(done2), .sign_exe(sgnx2), .overflow(of2), .underflow(uf2));
  | 
           | 
      
      
        // 10/10
  | 
           | 
      
      
        fpDiv u3 (.clk(clk), .ce(1'b1), .ld(ld), .a(32'h41200000), .b(32'h41200000), .done(done3), .o(o3), .sign_exe(sgnx2), .overflow(of2), .underflow(uf2));
  | 
           | 
      
      
        // 21/-17
  | 
           | 
      
      
        fpDiv u4 (.clk(clk), .ce(1'b1), .ld(ld), .a(32'h41a80000), .b(32'hc1880000), .done(done4), .o(o4), .sign_exe(sgnx2), .overflow(of2), .underflow(uf2));
  | 
           | 
      
      
        // -17/-15
  | 
           | 
      
      
        fpDiv u5 (.clk(clk), .ce(1'b1), .ld(ld), .a(32'hc1880000), .b(32'hc1700000), .done(done5), .o(o5), .sign_exe(sgnx2), .overflow(of2), .underflow(uf2));
  | 
           | 
      
      
         
  | 
           | 
      
      
        fpNormalize u11 (clk, ce, 1'b0, o3, o11);
  | 
           | 
      
      
        fpNormalize u12 (clk, ce, 1'b0, o4, o12);
  | 
           | 
      
      
        fpNormalize u13 (clk, ce, 1'b0, o5, o13);
  | 
           | 
      
      
         
  | 
           | 
      
      
        fpRound u21 (3'd1, o11, o21);         // zero for zero
  | 
           | 
      
      
        fpRound u22 (3'd1, o12, o22); // 
  | 
           | 
      
      
        fpRound u23 (3'd1, o13, o23); // 
  | 
           | 
      
      
         
  | 
           | 
      
      
        endmodule
  | 
           | 
      
      
         
  | 
           | 
      
      
         No newline at end of file
  | 
         No newline at end of file
  |