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

Subversion Repositories openrisc

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

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 360 Rev 364
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
////  OR1200's FPU Wrapper                                        ////
////  OR1200's FPU Wrapper                                        ////
////                                                              ////
////                                                              ////
////  This file is part of the OpenRISC 1200 project              ////
////  This file is part of the OpenRISC 1200 project              ////
////  http://opencores.org/project,or1k                           ////
////  http://opencores.org/project,or1k                           ////
////                                                              ////
////                                                              ////
////  Description                                                 ////
////  Description                                                 ////
////  Wrapper for floating point unit.                            ////
////  Wrapper for floating point unit.                            ////
////  Interface based on MULT/MAC unit.                           ////
////  Interface based on MULT/MAC unit.                           ////
////                                                              ////
////                                                              ////
////  To Do:                                                      ////
////  To Do:                                                      ////
////   - lf.rem.s and lf.madd.s instruction support               ////
////   - lf.rem.s and lf.madd.s instruction support               ////
////   - implement FP SPRs as needed                              ////
////   - implement FP SPRs as needed                              ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////  Author(s):                                                  ////
////      - Julius Baxter, julius@opencores.org                   ////
////      - Julius Baxter, julius@opencores.org                   ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
//// Copyright (C) 2009,2010 Authors and OPENCORES.ORG            ////
//// Copyright (C) 2009,2010 Authors and OPENCORES.ORG            ////
////                                                              ////
////                                                              ////
//// 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. ////
////                                                              ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
//// later version.                                               ////
////                                                              ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
//// details.                                                     ////
////                                                              ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// You should have received a copy of the GNU Lesser General    ////
//// 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                     ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
 
 
// synopsys translate_off
// synopsys translate_off
`include "timescale.v"
`include "timescale.v"
// synopsys translate_on
// synopsys translate_on
`include "or1200_defines.v"
`include "or1200_defines.v"
 
 
module or1200_fpu(
module or1200_fpu(
                  // Clock and reset
                  // Clock and reset
                  clk, rst,
                  clk, rst,
 
 
                  // FPU interface
                  // FPU interface
                  ex_freeze, a, b, fpu_op, result, done,
                  ex_freeze, a, b, fpu_op, result, done,
 
 
                  // Flag controls
                  // Flag controls
                  flagforw, flag_we,
                  flagforw, flag_we,
 
 
                  // Exception signal
                  // Exception signal
                  sig_fp, except_started,
                  sig_fp, except_started,
 
 
                  // FPCSR system register
                  // FPCSR system register
                  fpcsr_we, fpcsr,
                  fpcsr_we, fpcsr,
 
 
                  // SPR interface -- currently unused
                  // SPR interface -- currently unused
                  spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
                  spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
                  );
                  );
 
 
   parameter width = `OR1200_OPERAND_WIDTH;
   parameter width = `OR1200_OPERAND_WIDTH;
 
 
   //
   //
   // I/O
   // I/O
   //
   //
 
 
   //
   //
   // Clock and reset
   // Clock and reset
   //
   //
   input                                clk;
   input                                clk;
   input                                rst;
   input                                rst;
 
 
   //
   //
   // FPU interface
   // FPU interface
   //
   //
   input                                ex_freeze;
   input                                ex_freeze;
   input [width-1:0]                     a;
   input [width-1:0]                     a;
   input [width-1:0]                     b;
   input [width-1:0]                     b;
   input [`OR1200_FPUOP_WIDTH-1:0]       fpu_op;
   input [`OR1200_FPUOP_WIDTH-1:0]       fpu_op;
   output [width-1:0]                    result;
   output [width-1:0]                    result;
   output                               done;
   output                               done;
 
 
   //
   //
   // Flag signals
   // Flag signals
   //
   //
   output                               flagforw;
   output                               flagforw;
   output                               flag_we;
   output                               flag_we;
 
 
   //
   //
   // FPCSR interface
   // FPCSR interface
   //  
   //  
   input                                fpcsr_we;
   input                                fpcsr_we;
   output [`OR1200_FPCSR_WIDTH-1:0]      fpcsr;
   output [`OR1200_FPCSR_WIDTH-1:0]      fpcsr;
 
 
   //
   //
   // Exception signal
   // Exception signal
   //   
   //   
   output                               sig_fp;
   output                               sig_fp;
   input                                except_started;
   input                                except_started;
 
 
 
 
   //
   //
   // SPR interface
   // SPR interface
   //
   //
   input                                spr_cs;
   input                                spr_cs;
   input                                spr_write;
   input                                spr_write;
   input [31:0]                  spr_addr;
   input [31:0]                  spr_addr;
   input [31:0]                  spr_dat_i;
   input [31:0]                  spr_dat_i;
   output [31:0]                         spr_dat_o;
   output [31:0]                         spr_dat_o;
 
 
 
 
`ifndef OR1200_FPU_IMPLEMENTED
`ifndef OR1200_FPU_IMPLEMENTED
 
 
   // No FPU needed
   // No FPU needed
   assign result = 0;
   assign result = 0;
   assign flagforw  = 0;
   assign flagforw  = 0;
   assign flag_we = 0;
   assign flag_we = 0;
   assign sig_fp = 0;
   assign sig_fp = 0;
   assign spr_dat_o = 0;
   assign spr_dat_o = 0;
   assign fpcsr = 0;
   assign fpcsr = 0;
   assign done = 1;
   assign done = 1;
`else
`else
 
 
 
 
   //
   //
   // Internals
   // Internals
   //
   //
   wire                                 fpu_op_is_arith, fpu_op_is_conv,
   wire                                 fpu_op_is_arith, fpu_op_is_conv,
                                        fpu_op_is_comp;
                                        fpu_op_is_comp;
   wire                                 fpu_op_r_is_arith, fpu_op_r_is_conv,
   wire                                 fpu_op_r_is_arith, fpu_op_r_is_conv,
                                        fpu_op_r_is_comp;
                                        fpu_op_r_is_comp;
   wire                                 fpu_arith_done, fpu_conv_done,
   wire                                 fpu_arith_done, fpu_conv_done,
                                        fpu_comp_done;
                                        fpu_comp_done;
   wire [width-1:0]                      result_arith, result_conv;
   wire [width-1:0]                      result_arith, result_conv;
 
 
   reg [`OR1200_FPUOP_WIDTH:0]           fpu_op_r;
   reg [`OR1200_FPUOP_WIDTH-1:0]         fpu_op_r;
   reg [`OR1200_FPCSR_WIDTH-1:0]         fpcsr_r;
   reg [`OR1200_FPCSR_WIDTH-1:0]         fpcsr_r;
   wire                                 fpu_op_valid;
   wire                                 fpu_op_valid;
   reg                                  fpu_op_valid_re;
   reg                                  fpu_op_valid_re;
   wire                                 fpu_check_op;
   wire                                 fpu_check_op;
   wire                                 inf, inv_inf_op_in,snan, snan_in,qnan,
   wire                                 inf, inv_inf_op_in,snan, snan_in,qnan,
                                        ine, overflow, underflow, zero, dbz,
                                        ine, overflow, underflow, zero, dbz,
                                        dbz_in, mul_z_inf, nan_in;
                                        dbz_in, mul_z_inf, nan_in;
   wire                                 altb, blta, aeqb, inf_cmp, zero_cmp,
   wire                                 altb, blta, aeqb, inf_cmp, zero_cmp,
                                        unordered ;
                                        unordered ;
   wire                                 snan_conv, ine_conv, inv_conv,
   wire                                 snan_conv, ine_conv, inv_conv,
                                        zero_conv, underflow_conv,
                                        zero_conv, underflow_conv,
                                        overflow_conv;
                                        overflow_conv;
   wire                                 inv_comp;
   wire                                 inv_comp;
   reg                                  flag;
   reg                                  flag;
 
 
 
 
   assign spr_dat_o = 0;
   assign spr_dat_o = 0;
 
 
   assign fpcsr = fpcsr_r;
   assign fpcsr = fpcsr_r;
 
 
   assign sig_fp = fpcsr_r[`OR1200_FPCSR_FPEE]
   assign sig_fp = fpcsr_r[`OR1200_FPCSR_FPEE]
            & (|fpcsr_r[`OR1200_FPCSR_WIDTH-1:`OR1200_FPCSR_OVF]);
            & (|fpcsr_r[`OR1200_FPCSR_WIDTH-1:`OR1200_FPCSR_OVF]);
 
 
   // Top bit indicates FPU instruction
   // Top bit indicates FPU instruction
   assign fpu_op_valid = fpu_op[`OR1200_FPUOP_WIDTH-1];
   assign fpu_op_valid = fpu_op[`OR1200_FPUOP_WIDTH-1];
 
 
   assign fpu_check_op = !ex_freeze & fpu_op_valid;
   assign fpu_check_op = !ex_freeze & fpu_op_valid;
 
 
   // Generate signals to latch fpu_op from decode instruction, then latch 
   // Generate signals to latch fpu_op from decode instruction, then latch 
   // operands when they appear during execute stage
   // operands when they appear during execute stage
 
 
   assign fpu_op_is_arith = !(|fpu_op[3:2]);
   assign fpu_op_is_arith = !(|fpu_op[3:2]);
   assign fpu_op_is_conv = fpu_op[2] & !fpu_op[3];
   assign fpu_op_is_conv = fpu_op[2] & !fpu_op[3];
   assign fpu_op_is_comp = fpu_op[3];
   assign fpu_op_is_comp = fpu_op[3];
 
 
   assign fpu_op_r_is_arith = !(|fpu_op_r[3:2]);
   assign fpu_op_r_is_arith = !(|fpu_op_r[3:2]);
   assign fpu_op_r_is_conv = fpu_op_r[2] & !fpu_op_r[3];
   assign fpu_op_r_is_conv = fpu_op_r[2] & !fpu_op_r[3];
   assign fpu_op_r_is_comp = fpu_op_r[3];
   assign fpu_op_r_is_comp = fpu_op_r[3];
 
 
   assign done = (fpu_op_r_is_arith & fpu_arith_done) |
   assign done = (fpu_op_r_is_arith & fpu_arith_done) |
                 (fpu_op_r_is_conv & fpu_conv_done)   |
                 (fpu_op_r_is_conv & fpu_conv_done)   |
                 (fpu_op_r_is_comp & fpu_comp_done)   ;
                 (fpu_op_r_is_comp & fpu_comp_done)   ;
 
 
   // Register fpu_op (remove FPU op valid bit [7], replace with 0)
   // Register fpu_op (remove FPU op valid bit [7], replace with 0)
   always @(posedge clk)
   always @(posedge clk)
     if (fpu_check_op)
     if (fpu_check_op)
       fpu_op_r <= {1'b0,fpu_op[`OR1200_FPUOP_WIDTH-2:0]};
       fpu_op_r <= {1'b0,fpu_op[`OR1200_FPUOP_WIDTH-2:0]};
 
 
   // Indicate new FPU op
   // Indicate new FPU op
   always @(posedge clk or `OR1200_RST_EVENT rst)
   always @(posedge clk or `OR1200_RST_EVENT rst)
     if (rst == `OR1200_RST_VALUE)
     if (rst == `OR1200_RST_VALUE)
       fpu_op_valid_re <= 0;
       fpu_op_valid_re <= 0;
     else if (fpu_op_valid_re)
     else if (fpu_op_valid_re)
       fpu_op_valid_re <= 0;
       fpu_op_valid_re <= 0;
     else if (fpu_check_op)
     else if (fpu_check_op)
       fpu_op_valid_re <= 1;
       fpu_op_valid_re <= 1;
 
 
   //
   //
   // FPCSR system group register implementation
   // FPCSR system group register implementation
   //   
   //   
   always @(posedge clk or `OR1200_RST_EVENT rst) begin
   always @(posedge clk or `OR1200_RST_EVENT rst) begin
      if (rst == `OR1200_RST_VALUE)
      if (rst == `OR1200_RST_VALUE)
        fpcsr_r <= 0;
        fpcsr_r <= 0;
      else
      else
        begin
        begin
           if (fpcsr_we)
           if (fpcsr_we)
             fpcsr_r <= b[`OR1200_FPCSR_WIDTH-1:0];
             fpcsr_r <= b[`OR1200_FPCSR_WIDTH-1:0];
           else if (done)
           else if (done)
             begin
             begin
                fpcsr_r[`OR1200_FPCSR_OVF] <= (overflow & fpu_op_r_is_arith);
                fpcsr_r[`OR1200_FPCSR_OVF] <= (overflow & fpu_op_r_is_arith);
                fpcsr_r[`OR1200_FPCSR_UNF] <= (underflow & fpu_op_r_is_arith) |
                fpcsr_r[`OR1200_FPCSR_UNF] <= (underflow & fpu_op_r_is_arith) |
                                          (underflow_conv  & fpu_op_r_is_conv);
                                          (underflow_conv  & fpu_op_r_is_conv);
                fpcsr_r[`OR1200_FPCSR_SNF] <= (snan  & fpu_op_r_is_arith)|
                fpcsr_r[`OR1200_FPCSR_SNF] <= (snan  & fpu_op_r_is_arith)|
                                              (snan_conv & fpu_op_r_is_conv);
                                              (snan_conv & fpu_op_r_is_conv);
                fpcsr_r[`OR1200_FPCSR_QNF] <= (qnan  & fpu_op_r_is_arith);
                fpcsr_r[`OR1200_FPCSR_QNF] <= (qnan  & fpu_op_r_is_arith);
                fpcsr_r[`OR1200_FPCSR_ZF]  <= (zero  & fpu_op_r_is_arith) |
                fpcsr_r[`OR1200_FPCSR_ZF]  <= (zero  & fpu_op_r_is_arith) |
                                              (zero_cmp & fpu_op_r_is_comp) |
                                              (zero_cmp & fpu_op_r_is_comp) |
                                              (zero_conv & fpu_op_r_is_conv);
                                              (zero_conv & fpu_op_r_is_conv);
                fpcsr_r[`OR1200_FPCSR_IXF] <= (ine  & fpu_op_r_is_arith) |
                fpcsr_r[`OR1200_FPCSR_IXF] <= (ine  & fpu_op_r_is_arith) |
                                              (ine_conv & fpu_op_r_is_conv);
                                              (ine_conv & fpu_op_r_is_conv);
                fpcsr_r[`OR1200_FPCSR_IVF] <=
                fpcsr_r[`OR1200_FPCSR_IVF] <=
                                ((snan_in | dbz_in | inv_inf_op_in | mul_z_inf) &
                                ((snan_in | dbz_in | inv_inf_op_in | mul_z_inf) &
                                           fpu_op_r_is_arith) |
                                           fpu_op_r_is_arith) |
                                  ((inv_conv | snan_conv) & fpu_op_r_is_conv) |
                                  ((inv_conv | snan_conv) & fpu_op_r_is_conv) |
                                              (inv_comp & fpu_op_r_is_comp);
                                              (inv_comp & fpu_op_r_is_comp);
                fpcsr_r[`OR1200_FPCSR_INF] <= (inf  & fpu_op_r_is_arith) |
                fpcsr_r[`OR1200_FPCSR_INF] <= (inf  & fpu_op_r_is_arith) |
                                              (inf_cmp & fpu_op_r_is_comp);
                                              (inf_cmp & fpu_op_r_is_comp);
                fpcsr_r[`OR1200_FPCSR_DZF] <= (dbz & fpu_op_r_is_arith);
                fpcsr_r[`OR1200_FPCSR_DZF] <= (dbz & fpu_op_r_is_arith);
             end // if (fpu_arith_done | fpu_conv_done)    
             end // if (fpu_arith_done | fpu_conv_done)    
           if (except_started)
           if (except_started)
             fpcsr_r[`OR1200_FPCSR_FPEE] <= 0;
             fpcsr_r[`OR1200_FPCSR_FPEE] <= 0;
        end // else: !if(rst)
        end // else: !if(rst)
   end // always @ (posedge clk or `OR1200_RST_EVENT rst)
   end // always @ (posedge clk or `OR1200_RST_EVENT rst)
 
 
   //
   //
   // Comparison flag generation
   // Comparison flag generation
   //
   //
   always @*
   always @*
     begin
     begin
        // Get rid of top bit - is FPU op valid bit
        // Get rid of top bit - is FPU op valid bit
        case({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]})
        case({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]})
          `OR1200_FPCOP_SFEQ: begin
          `OR1200_FPCOP_SFEQ: begin
             flag = aeqb;
             flag = aeqb;
          end
          end
          `OR1200_FPCOP_SFNE: begin
          `OR1200_FPCOP_SFNE: begin
             flag = !aeqb;
             flag = !aeqb;
               end
               end
          `OR1200_FPCOP_SFGT: begin
          `OR1200_FPCOP_SFGT: begin
             flag = blta & !aeqb;
             flag = blta & !aeqb;
          end
          end
          `OR1200_FPCOP_SFGE: begin
          `OR1200_FPCOP_SFGE: begin
             flag = blta | aeqb;
             flag = blta | aeqb;
          end
          end
          `OR1200_FPCOP_SFLT: begin
          `OR1200_FPCOP_SFLT: begin
             flag = altb & !aeqb;
             flag = altb & !aeqb;
          end
          end
          `OR1200_FPCOP_SFLE: begin
          `OR1200_FPCOP_SFLE: begin
             flag = altb | aeqb;
             flag = altb | aeqb;
          end
          end
          default: begin
          default: begin
             flag = 0;
             flag = 0;
          end
          end
        endcase // case (fpu_op_r)
        endcase // case (fpu_op_r)
     end // always@ (posedge clk)
     end // always@ (posedge clk)
 
 
   assign flagforw = flag;
   assign flagforw = flag;
 
 
   // Determine here where we do the write, ie how much we pipeline the 
   // Determine here where we do the write, ie how much we pipeline the 
   // comparison
   // comparison
   assign flag_we = fpu_op_r_is_comp & fpu_comp_done;
   assign flag_we = fpu_op_r_is_comp & fpu_comp_done;
 
 
   // MUX for outputs from arith and conversion modules
   // MUX for outputs from arith and conversion modules
   assign result = fpu_op_r_is_conv ? result_conv : result_arith;
   assign result = fpu_op_r_is_conv ? result_conv : result_arith;
 
 
   //
   //
   // Instantiate FPU modules
   // Instantiate FPU modules
   //
   //
 
 
   // FPU 100 VHDL core from OpenCores.org: http://opencores.org/project,fpu100
   // FPU 100 VHDL core from OpenCores.org: http://opencores.org/project,fpu100
   // Used only for add,sub,mul,div
   // Used only for add,sub,mul,div
   or1200_fpu_arith fpu_arith
   or1200_fpu_arith fpu_arith
     (
     (
      .clk_i(clk),
      .clk_i(clk),
      .opa_i(a),
      .opa_i(a),
      .opb_i(b),
      .opb_i(b),
      .fpu_op_i({1'b0,fpu_op_r[1:0]}), // Only bottom 2 bits
      .fpu_op_i({1'b0,fpu_op_r[1:0]}), // Only bottom 2 bits
      .rmode_i(fpcsr_r[`OR1200_FPCSR_RM]),
      .rmode_i(fpcsr_r[`OR1200_FPCSR_RM]),
      .output_o(result_arith),
      .output_o(result_arith),
      .start_i(fpu_op_valid_re & fpu_op_r_is_arith),
      .start_i(fpu_op_valid_re & fpu_op_r_is_arith),
      .ready_o(fpu_arith_done),
      .ready_o(fpu_arith_done),
      .ine_o(ine),
      .ine_o(ine),
      .overflow_o(overflow),
      .overflow_o(overflow),
      .underflow_o(underflow),
      .underflow_o(underflow),
      .div_zero_o(dbz),
      .div_zero_o(dbz),
      .inf_o(inf),
      .inf_o(inf),
      .zero_o(zero),
      .zero_o(zero),
      .qnan_o(qnan),
      .qnan_o(qnan),
      .snan_o(snan)
      .snan_o(snan)
      );
      );
 
 
   // Logic for detection of signaling NaN on input
   // Logic for detection of signaling NaN on input
   // signaling NaN: exponent is 8hff, [22] is zero, rest of fract is non-zero
   // signaling NaN: exponent is 8hff, [22] is zero, rest of fract is non-zero
   // quiet NaN: exponent is 8hff, [22] is 1
   // quiet NaN: exponent is 8hff, [22] is 1
   reg a_is_snan, b_is_snan;
   reg a_is_snan, b_is_snan;
   reg a_is_qnan, b_is_qnan;
   reg a_is_qnan, b_is_qnan;
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        a_is_snan <= (a[30:23]==8'hff) & !a[22] & (|a[21:0]);
        a_is_snan <= (a[30:23]==8'hff) & !a[22] & (|a[21:0]);
        b_is_snan <= (b[30:23]==8'hff) & !b[22] & (|b[21:0]);
        b_is_snan <= (b[30:23]==8'hff) & !b[22] & (|b[21:0]);
        a_is_qnan <= (a[30:23]==8'hff) & a[22];
        a_is_qnan <= (a[30:23]==8'hff) & a[22];
        b_is_qnan <= (b[30:23]==8'hff) & b[22];
        b_is_qnan <= (b[30:23]==8'hff) & b[22];
     end
     end
   // Signal to indicate there was a signaling NaN on input
   // Signal to indicate there was a signaling NaN on input
   assign snan_in = a_is_snan | b_is_snan;
   assign snan_in = a_is_snan | b_is_snan;
 
 
   // Check for, add with opposite signed infinities, or subtract with 
   // Check for, add with opposite signed infinities, or subtract with 
   // same signed infinities.
   // same signed infinities.
   reg a_is_inf, b_is_inf, a_b_sign_xor;
   reg a_is_inf, b_is_inf, a_b_sign_xor;
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        a_is_inf <= (a[30:23]==8'hff) & !(|a[22:0]);
        a_is_inf <= (a[30:23]==8'hff) & !(|a[22:0]);
        b_is_inf <= (b[30:23]==8'hff) & !(|a[22:0]);
        b_is_inf <= (b[30:23]==8'hff) & !(|a[22:0]);
        a_b_sign_xor <= a[31] ^ b[31];
        a_b_sign_xor <= a[31] ^ b[31];
     end
     end
 
 
   assign inv_inf_op_in = (a_is_inf & b_is_inf) &
   assign inv_inf_op_in = (a_is_inf & b_is_inf) &
                          ((a_b_sign_xor &
                          ((a_b_sign_xor &
                            ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
                            ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
                             `OR1200_FPUOP_ADD)) |
                             `OR1200_FPUOP_ADD)) |
                           (!a_b_sign_xor &
                           (!a_b_sign_xor &
                            ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
                            ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
                             `OR1200_FPUOP_SUB))) ;
                             `OR1200_FPUOP_SUB))) ;
 
 
   // Check if it's 0.0/0.0 to generate invalid signal (ignore sign bit)
   // Check if it's 0.0/0.0 to generate invalid signal (ignore sign bit)
   reg a_is_zero, b_is_zero;
   reg a_is_zero, b_is_zero;
 
 
   always @(posedge clk)
   always @(posedge clk)
     begin
     begin
        a_is_zero <= !(|a[30:0]);
        a_is_zero <= !(|a[30:0]);
        b_is_zero <= !(|b[30:0]);
        b_is_zero <= !(|b[30:0]);
     end
     end
   assign dbz_in = ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
   assign dbz_in = ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
                    `OR1200_FPUOP_DIV) & (a_is_zero & b_is_zero);
                    `OR1200_FPUOP_DIV) & (a_is_zero & b_is_zero);
 
 
 
 
   assign mul_z_inf = ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
   assign mul_z_inf = ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]} ==
                       `OR1200_FPUOP_MUL) &
                       `OR1200_FPUOP_MUL) &
                      ((a_is_zero & b_is_inf) | (b_is_zero & a_is_inf));
                      ((a_is_zero & b_is_inf) | (b_is_zero & a_is_inf));
 
 
   assign nan_in = (a_is_snan | b_is_snan | a_is_qnan | b_is_qnan);
   assign nan_in = (a_is_snan | b_is_snan | a_is_qnan | b_is_qnan);
 
 
   // 32-bit integer <-> single precision floating point conversion unit
   // 32-bit integer <-> single precision floating point conversion unit
   or1200_fpu_intfloat_conv fpu_intfloat_conv
   or1200_fpu_intfloat_conv fpu_intfloat_conv
     (
     (
       .clk(clk),
       .clk(clk),
       .rmode(fpcsr_r[`OR1200_FPCSR_RM]),
       .rmode(fpcsr_r[`OR1200_FPCSR_RM]),
       .fpu_op(fpu_op_r[2:0]),
       .fpu_op(fpu_op_r[2:0]),
       .opa(a),
       .opa(a),
       .out(result_conv),
       .out(result_conv),
       .snan(snan_conv),
       .snan(snan_conv),
       .ine(ine_conv),
       .ine(ine_conv),
       .inv(inv_conv),
       .inv(inv_conv),
       .overflow(overflow_conv),
       .overflow(overflow_conv),
       .underflow(underflow_conv),
       .underflow(underflow_conv),
       .zero(zero_conv)
       .zero(zero_conv)
       );
       );
 
 
   // 5-long shift reg for conversion ready counter
   // 5-long shift reg for conversion ready counter
   reg [6:0] fpu_conv_shr;
   reg [6:0] fpu_conv_shr;
   always @(posedge clk)
   always @(posedge clk)
     fpu_conv_shr <= {fpu_conv_shr[5:0],fpu_check_op & fpu_op_is_conv};
     fpu_conv_shr <= {fpu_conv_shr[5:0],fpu_check_op & fpu_op_is_conv};
   assign fpu_conv_done = fpu_conv_shr[6];
   assign fpu_conv_done = fpu_conv_shr[6];
 
 
   // Single precision floating point number comparison module
   // Single precision floating point number comparison module
   or1200_fpu_fcmp fpu_fcmp
   or1200_fpu_fcmp fpu_fcmp
     (
     (
      .opa(a),
      .opa(a),
      .opb(b),
      .opb(b),
      .unordered(unordered),
      .unordered(unordered),
      // I am convinced the comparison logic is wrong way around in this 
      // I am convinced the comparison logic is wrong way around in this 
      // module, simplest to swap them on output -- julius       
      // module, simplest to swap them on output -- julius       
      .altb(blta),
      .altb(blta),
      .blta(altb),
      .blta(altb),
      .aeqb(aeqb),
      .aeqb(aeqb),
      .inf(inf_cmp),
      .inf(inf_cmp),
      .zero(zero_cmp));
      .zero(zero_cmp));
 
 
   reg       fpu_op_valid_re_r;
   reg       fpu_op_valid_re_r;
   always @(posedge clk)
   always @(posedge clk)
     fpu_op_valid_re_r  <= fpu_op_valid_re;
     fpu_op_valid_re_r  <= fpu_op_valid_re;
 
 
   assign fpu_comp_done = fpu_op_valid_re_r & fpu_op_r_is_comp;
   assign fpu_comp_done = fpu_op_valid_re_r & fpu_op_r_is_comp;
 
 
   // Comparison invalid when sNaN in on an equal comparison, or any NaN 
   // Comparison invalid when sNaN in on an equal comparison, or any NaN 
   // for any other comparison.
   // for any other comparison.
   assign inv_comp =  (snan_in & ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]}
   assign inv_comp =  (snan_in & ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]}
                                  == `OR1200_FPCOP_SFEQ)) |
                                  == `OR1200_FPCOP_SFEQ)) |
                      (nan_in & ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]}
                      (nan_in & ({1'b0,fpu_op_r[`OR1200_FPUOP_WIDTH-2:0]}
                                 != `OR1200_FPCOP_SFEQ));
                                 != `OR1200_FPCOP_SFEQ));
 
 
`endif // !`ifndef OR1200_FPU_IMPLEMENTED
`endif // !`ifndef OR1200_FPU_IMPLEMENTED
 
 
endmodule // or1200_fpu
endmodule // or1200_fpu
 
 

powered by: WebSVN 2.1.0

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