/* -------------------------------------------------------------------- -- -- -- Copyright©2003 by the Institute of Electrical and Electronics Engineers, Inc. -- Three Park Avenue -- New York, NY 10016-5997, USA -- All rights reserved. -- -- This document is an unapproved draft of a proposed IEEE Standard. As such, -- this document is subject to change. USE AT YOUR OWN RISK! Because this -- is an unapproved draft, this document must not be utilized for any -- conformance/compliance purposes. Permission is hereby granted for IEEE -- Standards Committee participants to reproduce this document for purposes -- of IEEE standardization activities only. Prior to submitting this document -- to another standards development organization for standardization -- activities, permission must first be obtained from the Manager, Standards -- Licensing and Contracts, IEEE Standards Activities Department. Other -- entities seeking permission to reproduce this document, in whole or in -- part, must obtain permission from the Manager, Standards Licensing and -- Contracts, IEEE Standard Activities Department. -- -- IEEE Standards Activities Department -- Standards Licensing and Contracts -- 445 Hoes Lane, P.O. Box 1331 -- Piscataway, NJ 08855-1331, USA -- -- Title : fphdl_convert_functions.inc < IEEE std # 1076.3 > -- -- Developers: VHDL Synthesis working group, PAR 1076.3 -- -- Purpose : conversion functions -- -- Limitation: -- -- -------------------------------------------------------------------- -- Last Modified $Date: 2003-01-15 09:50:19-05 $ -- $Id: fphdl_convert_functions.inc,v 1.1 2003-01-15 09:50:19-05 bishop Exp $ -- $Log: fphdl_convert_functions.inc,v $ -- Revision 1.1 2003-01-15 09:50:19-05 bishop -- Initial revision -- -- -------------------------------------------------------------------- */ // by Kurt Baty function [`fp_two_exponent_width:-`fp_two_fraction_width] fp_one_to_fp_two; input [exponent_width:-fraction_width] arg; reg [1:0] fp_one_code; reg sign_bit; parameter signed_exp_one_width = (ieee_extend != 1)? exponent_width : (fraction_width < {1'b1,{(exponent_width-1){1'b0}}})? exponent_width + 1 : (fraction_width < {1'b1,{exponent_width {1'b0}}})? exponent_width + 2 : exponent_width + fraction_width; parameter use_fp_two_fraction_width = (fraction_width >= `fp_two_fraction_width )? `fp_two_fraction_width : fraction_width ; reg signed [signed_exp_one_width-1:0] signed_exp_one,test_exp; reg [-1:-fraction_width] fraction_one; integer i,a,b; reg [`fp_two_exponent_width-1:0] signed_exp_two; reg [1:-`fp_two_fraction_width-3] fraction_two_roundable; reg [`fp_two_exponent_width:-`fp_two_fraction_width] result; begin sign_bit = arg[exponent_width]; signed_exp_one = arg[exponent_width-1:0] - {1'b1,{(exponent_width-1){1'b0}}}; fraction_one = arg[-1:-fraction_width]; if(&arg[exponent_width-1:0]) begin fp_one_code = 2'b11; fraction_one[-use_fp_two_fraction_width] = |arg[-use_fp_two_fraction_width:-fraction_width]; end else begin if(~|arg[exponent_width-1:0]) begin if(ieee_extend != 1) begin fp_one_code = 2'b00; fraction_one = 0; end else begin if(~|arg[-1:-fraction_width]) fp_one_code = 2'b00; else begin // ieee extended fp_one_code = 2'b10; for(i=1;i<=fraction_width;i=i+1) begin if(arg[-i]) begin signed_exp_one = signed_exp_one - i + 1; fraction_one = fraction_one << i; i = fraction_width+1; end end end end end else fp_one_code = 2'b10; end // half time fraction_two_roundable = 0; fraction_two_roundable[0] = 1'b1; fraction_two_roundable[-1:-use_fp_two_fraction_width] = fraction_one[-1:-use_fp_two_fraction_width]; if(fraction_width > `fp_two_fraction_width) begin fraction_two_roundable[-`fp_two_fraction_width-1:-`fp_two_fraction_width-3] = {fraction_one,3'b0} >> (fraction_width - `fp_two_fraction_width); end if( (signed_exp_one_width > `fp_two_exponent_width) && (fp_one_code == 2'b10)) begin test_exp = {(`fp_two_exponent_width-1){1'b1}}; if( (~signed_exp_one[signed_exp_one_width-1]) && (signed_exp_one >= test_exp)) begin fp_one_code = 2'b11; fraction_two_roundable = 0; end if(`fp_two_ieee_extend != 1) begin if( signed_exp_one[signed_exp_one_width-1] && ((~signed_exp_one) >= test_exp)) begin fp_one_code = 2'b00; fraction_two_roundable = 0; end end else begin // ieee extended if( signed_exp_one[signed_exp_one_width-1] && ((~signed_exp_one) >= `fp_two_fraction_width + test_exp)) begin fp_one_code = 2'b00; fraction_two_roundable = 0; end else if( signed_exp_one[signed_exp_one_width-1] && ((~signed_exp_one) >= test_exp)) begin fp_one_code = 2'b00; fraction_two_roundable = fraction_two_roundable >> (-signed_exp_one-test_exp); signed_exp_one = -test_exp -1; end end end // type round_type // round_nearest = 0 -- default, nearest LSB '0' // round_inf = 1 -- Round to positive // round_neginf = 2 -- Round to negate // round_zero = 3 -- Round towards zero // if(`fp_two_round_style == 0) begin // round_nearest if (fraction_two_roundable[-`fp_two_fraction_width-1]) begin // -- round if (~|fraction_two_roundable[-`fp_two_fraction_width-2:-`fp_two_fraction_width-3]) begin // -- Make the bottom bit zero if possible if (fraction_two_roundable[-`fp_two_fraction_width]) begin // -- if we are at 1/2, make the bottom bit zero if possible. (ieee 754) if (&fraction_two_roundable[-1:-`fp_two_fraction_width]) begin // -- Fraction is all "1" ?? fp_one_code = 2'b10; signed_exp_one = signed_exp_one + 1; fraction_two_roundable = 0; end else begin fraction_two_roundable = fraction_two_roundable + 4'b1000; end end end else begin // -- then round up if (&fraction_two_roundable[-1:-`fp_two_fraction_width]) begin // -- Fraction is all "1" ?? fp_one_code = 2'b10; signed_exp_one = signed_exp_one + 1; fraction_two_roundable = 0; end else begin fraction_two_roundable = fraction_two_roundable + 4'b1000; end end end end else if ( (`fp_two_round_style == 1) // round_inf || ( (`fp_two_round_style == 3) // round_zero && sign_bit )) begin // -- Add 1 to the fract if (&fraction_two_roundable[-1:-`fp_two_fraction_width]) begin // -- Fraction is all "1" ?? fp_one_code = 2'b10; signed_exp_one = signed_exp_one + 1; fraction_two_roundable = 0; end else begin fraction_two_roundable = fraction_two_roundable + 4'b1000; end end result = 0; case(fp_one_code) 2'b11: begin result = {sign_bit, {`fp_two_exponent_width {1'b1}}, fraction_two_roundable[-1:-`fp_two_fraction_width]}; end 2'b00: begin result = {sign_bit, {`fp_two_exponent_width{1'b0}}, fraction_two_roundable[-1:-`fp_two_fraction_width]}; end default: begin signed_exp_two = signed_exp_one; result = {sign_bit, ~signed_exp_two[`fp_two_exponent_width-1], // exponent base bit signed_exp_two[`fp_two_exponent_width-2:0], fraction_two_roundable[-1:-`fp_two_fraction_width]}; end endcase fp_one_to_fp_two = result; end endfunction // fp_one_to_fp_two function [exponent_width:-fraction_width] fp_two_to_fp_one; input [`fp_two_exponent_width:-`fp_two_fraction_width] arg; reg [1:0] fp_two_code; reg sign_bit; parameter signed_exp_two_width = (`fp_two_ieee_extend != 1)? `fp_two_exponent_width : (`fp_two_fraction_width < {1'b1,{(`fp_two_exponent_width-1){1'b0}}})? `fp_two_exponent_width + 1 : (`fp_two_fraction_width < {1'b1,{`fp_two_exponent_width {1'b0}}})? `fp_two_exponent_width + 2 : `fp_two_exponent_width + `fp_two_fraction_width; parameter use_fp_one_fraction_width = (`fp_two_fraction_width >= fraction_width )? fraction_width : `fp_two_fraction_width ; reg signed [signed_exp_two_width-1:0] signed_exp_two,test_exp; reg [-1:-`fp_two_fraction_width] fraction_two; integer i,a,b; reg [exponent_width-1:0] signed_exp_one; reg [1:-fraction_width-3] fraction_one_roundable; reg [exponent_width:-fraction_width] result; begin sign_bit = arg[`fp_two_exponent_width]; signed_exp_two = arg[`fp_two_exponent_width-1:0] - {1'b1,{(`fp_two_exponent_width-1){1'b0}}}; fraction_two = arg[-1:-`fp_two_fraction_width]; if(&arg[`fp_two_exponent_width-1:0]) begin fp_two_code = 2'b11; fraction_two[-use_fp_one_fraction_width] = |arg[-use_fp_one_fraction_width:-`fp_two_fraction_width]; end else begin if(~|arg[`fp_two_exponent_width-1:0]) begin if(`fp_two_ieee_extend != 1) begin fp_two_code = 2'b00; fraction_two = 0; end else begin if(~|arg[-1:-`fp_two_fraction_width]) fp_two_code = 2'b00; else begin // ieee extended fp_two_code = 2'b10; for(i=1;i<=`fp_two_fraction_width;i=i+1) begin if(arg[-i]) begin signed_exp_two = signed_exp_two - i + 1; fraction_two = fraction_two << i; i = `fp_two_fraction_width+1; end end end end end else fp_two_code = 2'b10; end // half time fraction_one_roundable = 0; fraction_one_roundable[0] = 1'b1; fraction_one_roundable[-1:-use_fp_one_fraction_width] = fraction_two[-1:-use_fp_one_fraction_width]; if(`fp_two_fraction_width > fraction_width) begin fraction_one_roundable[-fraction_width-1:-fraction_width-3] = {fraction_two,3'b0} >> (`fp_two_fraction_width - fraction_width); end if( (signed_exp_two_width > exponent_width) && (fp_two_code == 2'b10)) begin test_exp = {(exponent_width-1){1'b1}}; if( (~signed_exp_two[signed_exp_two_width-1]) && (signed_exp_two >= test_exp)) begin fp_two_code = 2'b11; fraction_one_roundable = 0; end if(ieee_extend != 1) begin if( signed_exp_two[signed_exp_two_width-1] && ((~signed_exp_two) >= test_exp)) begin fp_two_code = 2'b00; fraction_one_roundable = 0; end end else begin // ieee extended if( signed_exp_two[signed_exp_two_width-1] && ((~signed_exp_two) >= fraction_width + test_exp)) begin fp_two_code = 2'b00; fraction_one_roundable = 0; end else if( signed_exp_two[signed_exp_two_width-1] && ((~signed_exp_two) >= test_exp)) begin fp_two_code = 2'b00; fraction_one_roundable = fraction_one_roundable >> (-signed_exp_two-test_exp); signed_exp_two = -test_exp -1; end end end // type round_type // round_nearest = 0 -- default, nearest LSB '0' // round_inf = 1 -- Round to positive // round_neginf = 2 -- Round to negate // round_zero = 3 -- Round towards zero // if(round_style == 0) begin // round_nearest if (fraction_one_roundable[-fraction_width-1]) begin // -- round if (~|fraction_one_roundable[-fraction_width-2:-fraction_width-3]) begin // -- Make the bottom bit zero if possible if (fraction_one_roundable[-fraction_width]) begin // -- if we are at 1/2, make the bottom bit zero if possible. (ieee 754) if (&fraction_one_roundable[-1:-fraction_width]) begin // -- Fraction is all "1" ?? fp_two_code = 2'b10; signed_exp_two = signed_exp_two + 1; fraction_one_roundable = 0; end else begin fraction_one_roundable = fraction_one_roundable + 4'b1000; end end end else begin // -- then round up if (&fraction_one_roundable[-1:-fraction_width]) begin // -- Fraction is all "1" ?? fp_two_code = 2'b10; signed_exp_two = signed_exp_two + 1; fraction_one_roundable = 0; end else begin fraction_one_roundable = fraction_one_roundable + 4'b1000; end end end end else if ( (round_style == 1) // round_inf || ( (round_style == 3) // round_zero && sign_bit )) begin // -- Add 1 to the fract if (&fraction_one_roundable[-1:-fraction_width]) begin // -- Fraction is all "1" ?? fp_two_code = 2'b10; signed_exp_two = signed_exp_two + 1; fraction_one_roundable = 0; end else begin fraction_one_roundable = fraction_one_roundable + 4'b1000; end end result = 0; case(fp_two_code) 2'b11: begin result = {sign_bit, {exponent_width {1'b1}}, fraction_one_roundable[-1:-fraction_width]}; end 2'b00: begin result = {sign_bit, {exponent_width{1'b0}}, fraction_one_roundable[-1:-fraction_width]}; end default: begin signed_exp_one = signed_exp_two; result = {sign_bit, ~signed_exp_one[exponent_width-1], // exponent base bit signed_exp_one[exponent_width-2:0], fraction_one_roundable[-1:-fraction_width]}; end endcase fp_two_to_fp_one = result; end endfunction // fp_two_to_fp_one