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

Subversion Repositories double_fpu

[/] [double_fpu/] [trunk/] [fpu_add.v] - Rev 13

Compare with Previous | Blame | View Log

/////////////////////////////////////////////////////////////////////
////                                                             ////
////  FPU                                                        ////
////  Floating Point Unit (Double precision)                     ////
////                                                             ////
////  Author: David Lundgren                                     ////
////          davidklun@gmail.com                                ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
//// Copyright (C) 2009 David Lundgren                           ////
////                  davidklun@gmail.com                        ////
////                                                             ////
//// 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.                                 ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
 
`timescale 1ns / 100ps
 
module fpu_add( clk, rst, enable, opa, opb, sign, sum_2, exponent_2);
input		clk;
input		rst;
input		enable;
input	[63:0]	opa, opb;
output		sign;
output  [55:0]	sum_2;
output	[10:0]	exponent_2;
 
reg   sign;
reg   [10:0] exponent_a;
reg   [10:0] exponent_b;
reg   [51:0] mantissa_a;
reg   [51:0] mantissa_b;
reg   expa_gt_expb;
reg   [10:0] exponent_small;
reg   [10:0] exponent_large;
reg   [51:0] mantissa_small;
reg   [51:0] mantissa_large;
reg   small_is_denorm;
reg   large_is_denorm;
reg   large_norm_small_denorm;
reg   [10:0] exponent_diff;
reg   [55:0] large_add;
reg   [55:0] small_add;
reg   [55:0] small_shift;
wire   small_shift_nonzero = |small_shift[55:0];
wire	small_is_nonzero = (exponent_small > 0) | |mantissa_small[51:0]; 
wire   small_fraction_enable = small_is_nonzero & !small_shift_nonzero;
wire   [55:0] small_shift_2 = { 55'b0, 1'b1 };
reg   [55:0] small_shift_3;
reg   [55:0] sum;
wire   sum_overflow = sum[55]; // sum[55] will be 0 if there was no carry from adding the 2 numbers
reg   [55:0] sum_2;
reg   [10:0] exponent;
wire   sum_leading_one = sum_2[54]; // this is where the leading one resides, unless denorm
reg   denorm_to_norm;
reg   [10:0] exponent_2;
 
always @(posedge clk) 
	begin
		if (rst) begin
			sign <= 0;
			exponent_a <= 0;
			exponent_b <= 0;
			mantissa_a <= 0;
			mantissa_b <= 0;
			expa_gt_expb <= 0;
			exponent_small  <= 0;
			exponent_large  <= 0;
			mantissa_small  <= 0;
			mantissa_large  <= 0;
			small_is_denorm <= 0;
			large_is_denorm <= 0;
			large_norm_small_denorm <= 0;
			exponent_diff <= 0;
			large_add <= 0;
			small_add <= 0;
			small_shift <= 0;
			small_shift_3 <= 0;
			sum <= 0;
			sum_2 <= 0;
			exponent <= 0;
			denorm_to_norm <= 0;
			exponent_2 <= 0;
		end
		else if (enable) begin
			sign <= opa[63];
			exponent_a <= opa[62:52];
			exponent_b <= opb[62:52];
			mantissa_a <= opa[51:0];
			mantissa_b <= opb[51:0];
			expa_gt_expb <= exponent_a > exponent_b;
			exponent_small  <= expa_gt_expb ? exponent_b : exponent_a;
			exponent_large  <= expa_gt_expb ? exponent_a : exponent_b;
			mantissa_small  <= expa_gt_expb ? mantissa_b : mantissa_a;
			mantissa_large  <= expa_gt_expb ? mantissa_a : mantissa_b;
			small_is_denorm <= !(exponent_small > 0);
			large_is_denorm <= !(exponent_large > 0);
			large_norm_small_denorm <= (small_is_denorm && !large_is_denorm);
			exponent_diff <= exponent_large - exponent_small - large_norm_small_denorm;
			large_add <= { 1'b0, !large_is_denorm, mantissa_large, 2'b0 };
			small_add <= { 1'b0, !small_is_denorm, mantissa_small, 2'b0 };
			small_shift <= small_add >> exponent_diff;
			small_shift_3 <= small_fraction_enable ? small_shift_2 : small_shift;
			sum <= large_add + small_shift_3;
			sum_2 <= sum_overflow ? sum >> 1 : sum;
			exponent <= sum_overflow ? exponent_large + 1: exponent_large;
			denorm_to_norm <= sum_leading_one & large_is_denorm;
			exponent_2 <= denorm_to_norm ? exponent + 1 : exponent;
		end
	end
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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