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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [rtl/] [verilog/] [or1200/] [or1200_fpu_post_norm_div.v] - Diff between revs 350 and 360

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

Rev 350 Rev 360
Line 1... Line 1...
 
//////////////////////////////////////////////////////////////////////
 
////                                                              ////
 
////  or1200_fpu_post_norm_div                                    ////
 
////                                                              ////
 
////  This file is part of the OpenRISC 1200 project              ////
 
////  http://opencores.org/project,or1k                           ////
 
////                                                              ////
 
////  Description                                                 ////
 
////  post-normalization entity for the division unit             ////
 
////                                                              ////
 
////  To Do:                                                      ////
 
////                                                              ////
 
////                                                              ////
 
////  Author(s):                                                  ////
 
////      - Original design (FPU100) -                            ////
 
////        Jidan Al-eryani, jidan@gmx.net                        ////
 
////      - Conv. to Verilog and inclusion in OR1200 -            ////
 
////        Julius Baxter, julius@opencores.org                   ////
 
////                                                              ////
 
//////////////////////////////////////////////////////////////////////
 
//
 
//  Copyright (C) 2006, 2010
 
//
 
//      This source file may be used and distributed without        
 
//      restriction provided that this copyright statement is not   
 
//      removed from the file and that any derivative work contains 
 
//      the original copyright notice and the associated disclaimer.
 
//                                                           
 
//              THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     
 
//      EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   
 
//      TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   
 
//      FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      
 
//      OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         
 
//      INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    
 
//      (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   
 
//      GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        
 
//      BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
 
//      LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  
 
//      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  
 
//      OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         
 
//      POSSIBILITY OF SUCH DAMAGE. 
 
//
 
 
 
 
 
module or1200_fpu_post_norm_div
 
  (
 
   clk_i,
 
   opa_i,
 
   opb_i,
 
   qutnt_i,
 
   rmndr_i,
 
   exp_10_i,
 
   sign_i,
 
   rmode_i,
 
   output_o,
 
   ine_o
 
   );
 
 
 
   parameter FP_WIDTH = 32;
 
   parameter MUL_SERIAL = 0; // 0 for parallel multiplier, 1 for serial
 
   parameter MUL_COUNT = 11; //11 for parallel multiplier, 34 for serial
 
   parameter FRAC_WIDTH = 23;
 
   parameter EXP_WIDTH = 8;
 
   parameter ZERO_VECTOR = 31'd0;
 
   parameter INF = 31'b1111111100000000000000000000000;
 
   parameter QNAN = 31'b1111111110000000000000000000000;
 
   parameter SNAN = 31'b1111111100000000000000000000001;
 
 
 
   input clk_i;
 
   input [FP_WIDTH-1:0] opa_i;
 
   input [FP_WIDTH-1:0] opb_i;
 
   input [FRAC_WIDTH+3:0] qutnt_i;
 
   input [FRAC_WIDTH+3:0] rmndr_i;
 
   input [EXP_WIDTH+1:0]  exp_10_i;
 
   input                  sign_i;
 
   input [1:0]             rmode_i;
 
   output reg [FP_WIDTH-1:0] output_o;
 
   output reg                ine_o;
 
 
 
   // input&output register wires
 
   reg [FP_WIDTH-1:0]         s_opa_i;
 
   reg [FP_WIDTH-1:0]         s_opb_i;
 
   reg [EXP_WIDTH-1:0]        s_expa;
 
   reg [EXP_WIDTH-1:0]        s_expb;
 
   reg [FRAC_WIDTH+3:0]      s_qutnt_i;
 
   reg [FRAC_WIDTH+3:0]      s_rmndr_i;
 
   reg [5:0]                  s_r_zeros;
 
   reg [EXP_WIDTH+1:0]        s_exp_10_i;
 
   reg                       s_sign_i;
 
   reg [1:0]                  s_rmode_i;
 
   wire [FP_WIDTH-1:0]        s_output_o;
 
 
 
   wire                      s_ine_o, s_overflow;
 
   wire                      s_opa_dn, s_opb_dn;
 
   wire                      s_qutdn;
 
   wire [9:0]                 s_exp_10b;
 
   reg [5:0]                  s_shr1;
 
   reg [5:0]                  s_shl1;
 
   wire                      s_shr2;
 
   reg [8:0]                  s_expo1;
 
   wire [8:0]                 s_expo2;
 
   reg [8:0]                  s_expo3;
 
   reg [26:0]                 s_fraco1;
 
   wire [24:0]                s_frac_rnd;
 
   reg [24:0]                 s_fraco2;
 
   wire                      s_guard, s_round, s_sticky, s_roundup;
 
   wire                      s_lost;
 
   wire                      s_op_0, s_opab_0, s_opb_0;
 
   wire                      s_infa, s_infb;
 
   wire                      s_nan_in, s_nan_op, s_nan_a, s_nan_b;
 
   wire                      s_inf_result;
 
 
 
   always @(posedge clk_i)
 
     begin
 
        s_opa_i <= opa_i;
 
        s_opb_i <= opb_i;
 
        s_expa <= opa_i[30:23];
 
        s_expb <= opb_i[30:23];
 
        s_qutnt_i <= qutnt_i;
 
        s_rmndr_i <= rmndr_i;
 
        s_exp_10_i <= exp_10_i;
 
        s_sign_i <= sign_i;
 
        s_rmode_i <= rmode_i;
 
     end
 
 
 
   // Output Register
 
   always @(posedge clk_i)
 
     begin
 
        output_o <= s_output_o;
 
        ine_o   <= s_ine_o;
 
     end
 
 
 
    // qutnt_i
 
    // 26 25                    3
 
    // |  |                     | 
 
    // h  fffffffffffffffffffffff grs
 
 
 
   //*** Stage 1 ****
 
   // figure out the exponent and how far the fraction has to be shifted 
 
   // right or left
 
 
 
   assign s_opa_dn = !(|s_expa) & (|opa_i[22:0]);
 
   assign s_opb_dn = !(|s_expb) & (|opb_i[22:0]);
 
 
 
   assign s_qutdn =  !s_qutnt_i[26];
 
 
 
   assign s_exp_10b = s_exp_10_i - {9'd0,s_qutdn};
 
 
 
   wire [9:0] v_shr;
 
   wire [9:0] v_shl;
 
 
 
   assign v_shr = (s_exp_10b[9] | !(|s_exp_10b)) ?
 
                   (10'd1 - s_exp_10b) - s_qutdn : 0;
 
 
 
   assign v_shl = (s_exp_10b[9] | !(|s_exp_10b)) ?
 
                   0 :
 
                   s_exp_10b[8] ?
 
                   0 : {9'd0,s_qutdn};
 
 
 
   always @(posedge clk_i)
 
     if (s_exp_10b[9] | !(|s_exp_10b))
 
       s_expo1 <= 9'd1;
 
     else
 
       s_expo1 <= s_exp_10b[8:0];
 
 
 
   always @(posedge clk_i)
 
     s_shr1 <= v_shr[6] ? 6'b111111 : v_shr[5:0];
 
 
 
   always @(posedge clk_i)
 
     s_shl1 <= v_shl[5:0];
 
 
 
   // *** Stage 2 ***
 
   // Shifting the fraction and rounding
 
 
 
   // shift the fraction
 
   always @(posedge clk_i)
 
     if (|s_shr1)
 
       s_fraco1 <= s_qutnt_i >> s_shr1;
 
     else
 
       s_fraco1 <= s_qutnt_i << s_shl1;
 
 
 
   assign s_expo2 = s_fraco1[26] ? s_expo1 : s_expo1 - 9'd1;
 
 
 
   //s_r_zeros <= count_r_zeros(s_qutnt_i);
 
   always @(s_qutnt_i)
 
     casex(s_qutnt_i) // synopsys full_case parallel_case
 
       27'b??????????????????????????1: s_r_zeros <=  0;
 
       27'b?????????????????????????10: s_r_zeros <=  1;
 
       27'b????????????????????????100: s_r_zeros <=  2;
 
       27'b???????????????????????1000: s_r_zeros <=  3;
 
       27'b??????????????????????10000: s_r_zeros <=  4;
 
       27'b?????????????????????100000: s_r_zeros <=  5;
 
       27'b????????????????????1000000: s_r_zeros <=  6;
 
       27'b???????????????????10000000: s_r_zeros <=  7;
 
       27'b??????????????????100000000: s_r_zeros <=  8;
 
       27'b?????????????????1000000000: s_r_zeros <=  9;
 
       27'b????????????????10000000000: s_r_zeros <=  10;
 
       27'b???????????????100000000000: s_r_zeros <=  11;
 
       27'b??????????????1000000000000: s_r_zeros <=  12;
 
       27'b?????????????10000000000000: s_r_zeros <=  13;
 
       27'b????????????100000000000000: s_r_zeros <=  14;
 
       27'b???????????1000000000000000: s_r_zeros <=  15;
 
       27'b??????????10000000000000000: s_r_zeros <=  16;
 
       27'b?????????100000000000000000: s_r_zeros <=  17;
 
       27'b????????1000000000000000000: s_r_zeros <=  18;
 
       27'b???????10000000000000000000: s_r_zeros <=  19;
 
       27'b??????100000000000000000000: s_r_zeros <=  20;
 
       27'b?????1000000000000000000000: s_r_zeros <=  21;
 
       27'b????10000000000000000000000: s_r_zeros <=  22;
 
       27'b???100000000000000000000000: s_r_zeros <=  23;
 
       27'b??1000000000000000000000000: s_r_zeros <=  24;
 
       27'b?10000000000000000000000000: s_r_zeros <=  25;
 
       27'b100000000000000000000000000: s_r_zeros <=  26;
 
       27'b000000000000000000000000000: s_r_zeros <=  27;
 
     endcase // casex (s_qutnt_i)
 
 
 
   assign s_lost = (s_shr1+{5'd0,s_shr2}) > s_r_zeros;
 
 
 
   // ***Stage 3***
 
   // Rounding
 
 
 
   assign s_guard = s_fraco1[2];
 
   assign s_round = s_fraco1[1];
 
   assign s_sticky = s_fraco1[0] | (|s_rmndr_i);
 
 
 
   assign s_roundup = s_rmode_i==2'b00 ? // round to nearest even
 
                      s_guard & ((s_round | s_sticky) | s_fraco1[3]) :
 
                      s_rmode_i==2'b10 ? // round up
 
                      (s_guard | s_round | s_sticky) & !s_sign_i :
 
                      s_rmode_i==2'b11 ? // round down
 
                      (s_guard | s_round | s_sticky) & s_sign_i :
 
                      0; // round to zero(truncate = no rounding)
 
 
 
   assign s_frac_rnd = s_roundup ?{1'b0,s_fraco1[26:3]} + 1 :
 
                       {1'b0,s_fraco1[26:3]};
 
   assign s_shr2 = s_frac_rnd[24];
 
 
 
   always @(posedge clk_i)
 
     begin
 
        s_expo3 <= s_shr2 ? s_expo2 + "1" : s_expo2;
 
        s_fraco2 <= s_shr2 ? {1'b0,s_frac_rnd[24:1]} : s_frac_rnd;
 
     end
 
   //
 
   // ***Stage 4****
 
   // Output
 
 
 
   assign s_op_0 = !((|s_opa_i[30:0]) & (|s_opb_i[30:0]));
 
 
 
   assign s_opab_0 = !((|s_opa_i[30:0]) | (|s_opb_i[30:0]));
 
 
 
   assign s_opb_0 = !(|s_opb_i[30:0]);
 
 
 
   assign s_infa = &s_expa;
 
 
 
   assign s_infb = &s_expb;
 
 
 
   assign s_nan_a = s_infa & (|s_opa_i[22:0]);
 
 
 
   assign s_nan_b = s_infb & (|s_opb_i[22:0]);
 
 
 
   assign s_nan_in = s_nan_a | s_nan_b;
 
 
 
   assign s_nan_op = (s_infa & s_infb) | s_opab_0; // 0 / 0, inf / inf
 
 
 
   assign s_inf_result = (&s_expo3[7:0]) | s_expo3[8] | s_opb_0;
 
 
 
   assign s_overflow =  s_inf_result & !(s_infa) & !s_opb_0;
 
 
 
   assign s_ine_o =  !s_op_0 &
 
                     (s_lost | (|s_fraco1[2:0]) | s_overflow | (|s_rmndr_i));
 
 
 
   assign s_output_o = (s_nan_in | s_nan_op) ?
 
                       {s_sign_i,QNAN} :
 
                       s_infa  | s_overflow | s_inf_result ?
 
                       {s_sign_i,INF} :
 
                       s_op_0 | s_infb ?
 
                       {s_sign_i,ZERO_VECTOR} :
 
                       {s_sign_i,s_expo3[7:0],s_fraco2[22:0]};
 
 
 
endmodule // or1200_fpu_post_norm_div
 
 
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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