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

Subversion Repositories double_fpu

[/] [double_fpu/] [branches/] [avendor/] [fpu_exceptions.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_exceptions( clk, rst, enable, rmode, opa, opb, in_except,
exponent_in, mantissa_in, fpu_op, out, ex_enable, underflow, overflow, 
inexact, exception, invalid);
input		clk;
input		rst;
input		enable;
input	[1:0]	rmode;
input	[63:0]	opa;
input	[63:0]	opb;
input	[63:0]	in_except;
input	[11:0]	exponent_in;
input	[1:0]	mantissa_in;
input	[2:0]	fpu_op;
output	[63:0]	out;
output		ex_enable;
output		underflow;
output		overflow;
output		inexact;
output		exception;
output		invalid;
 
reg		[63:0]	out;
reg		ex_enable;
reg		underflow;
reg		overflow;
reg		inexact;
reg		exception;
reg		invalid;
 
reg		in_et_zero;
reg		opa_et_zero;
reg		opb_et_zero;
reg		input_et_zero;
reg		add;
reg		subtract;
reg		multiply;
reg		divide;
reg		opa_QNaN;
reg		opb_QNaN;
reg		opa_SNaN;
reg		opb_SNaN;
reg		opa_pos_inf;
reg		opb_pos_inf;
reg		opa_neg_inf;
reg		opb_neg_inf;
reg		opa_inf;
reg		opb_inf;
reg		NaN_input;
reg		SNaN_input;
reg		a_NaN;
reg		div_by_0;
reg		div_0_by_0;
reg		div_inf_by_inf;
reg		div_by_inf;
reg		mul_0_by_inf;
reg		mul_inf;
reg		div_inf;
reg		add_inf;
reg		sub_inf;
reg		addsub_inf_invalid;
reg		addsub_inf;
reg		out_inf_trigger;
reg		out_pos_inf;
reg		out_neg_inf;
reg		round_nearest;
reg		round_to_zero;
reg		round_to_pos_inf;
reg		round_to_neg_inf;
reg		inf_round_down_trigger;
reg		mul_uf;
reg		div_uf;								
reg		underflow_trigger;			
reg		invalid_trigger;
reg		overflow_trigger;
reg		inexact_trigger;
reg	 	except_trigger;
reg		enable_trigger;
reg		NaN_out_trigger;
reg		SNaN_trigger;
 
 
wire	[10:0]  exp_2047 = 11'b11111111111;
wire	[10:0]  exp_2046 = 11'b11111111110;
reg		[62:0] NaN_output_0; 
reg		[62:0] NaN_output; 
wire	[51:0]  mantissa_max = 52'b1111111111111111111111111111111111111111111111111111;
reg		[62:0]	inf_round_down;
reg		[62:0]	out_inf;
reg		[63:0]	out_0;
reg		[63:0]	out_1;
reg		[63:0]	out_2;
 
always @(posedge clk)
begin
	if (rst) begin
		in_et_zero <=    0;
		opa_et_zero <=   0;
		opb_et_zero <=   0;
		input_et_zero <= 0;
		add 	<= 	0;
		subtract <= 0;
		multiply <= 0;
		divide 	<= 	0;
		opa_QNaN <= 0;
		opb_QNaN <= 0;
		opa_SNaN <= 0;
		opb_SNaN <= 0;
		opa_pos_inf <= 0;
		opb_pos_inf <= 0;
		opa_neg_inf <= 0;
		opb_neg_inf <= 0; 
		opa_inf <= 0;
		opb_inf <= 0;
		NaN_input <= 0; 
		SNaN_input <= 0;
		a_NaN <= 0;
		div_by_0 <= 0;
		div_0_by_0 <= 0;
		div_inf_by_inf <= 0;
		div_by_inf <= 0;
		mul_0_by_inf <= 0;
		mul_inf <= 0;
		div_inf <= 0;
		add_inf <= 0;
		sub_inf <= 0;
		addsub_inf_invalid <= 0;
		addsub_inf <= 0;
		out_inf_trigger <= 0;
		out_pos_inf <= 0;
		out_neg_inf <= 0;
		round_nearest <= 0;
		round_to_zero <= 0;
		round_to_pos_inf <= 0;
		round_to_neg_inf <= 0;
		inf_round_down_trigger <= 0;
		mul_uf <= 0;
		div_uf <= 0;															
		underflow_trigger <= 0;		
		invalid_trigger <= 0;
		overflow_trigger <= 0;
		inexact_trigger <= 0;
		except_trigger <= 0;
		enable_trigger <= 0;
		NaN_out_trigger <= 0;
		SNaN_trigger <= 0;
		NaN_output_0 <= 0;
		NaN_output <= 0;
		inf_round_down <= 0;
		out_inf <= 0;
		out_0 <= 0;
		out_1 <= 0;
		out_2 <= 0;
		end
	else if (enable) begin
		in_et_zero <= !(|in_except[62:0]);
		opa_et_zero <= !(|opa[62:0]);
		opb_et_zero <= !(|opb[62:0]);
		input_et_zero <= !(|in_except[62:0]);	
		add 	<= 	fpu_op == 3'b000;
		subtract <= 	fpu_op == 3'b001;
		multiply <= 	fpu_op == 3'b010;
		divide 	<= 	fpu_op == 3'b011;
		opa_QNaN <= (opa[62:52] == 2047) & |opa[51:0] & opa[51];
		opb_QNaN <= (opb[62:52] == 2047) & |opb[51:0] & opb[51];
		opa_SNaN <= (opa[62:52] == 2047) & |opa[51:0] & !opa[51];
		opb_SNaN <= (opb[62:52] == 2047) & |opb[51:0] & !opb[51];
		opa_pos_inf <= !opa[63] & (opa[62:52] == 2047) & !(|opa[51:0]);
		opb_pos_inf <= !opb[63] & (opb[62:52] == 2047) & !(|opb[51:0]);
		opa_neg_inf <= opa[63] & (opa[62:52] == 2047) & !(|opa[51:0]);
		opb_neg_inf <= opb[63] & (opb[62:52] == 2047) & !(|opb[51:0]);
		opa_inf <= (opa[62:52] == 2047) & !(|opa[51:0]);
		opb_inf <= (opb[62:52] == 2047) & !(|opb[51:0]);
		NaN_input <= opa_QNaN | opb_QNaN | opa_SNaN | opb_SNaN;
		SNaN_input <= opa_SNaN | opb_SNaN;
		a_NaN <= opa_QNaN | opa_SNaN;
		div_by_0 <= divide & opb_et_zero & !opa_et_zero;
		div_0_by_0 <= divide & opb_et_zero & opa_et_zero;
		div_inf_by_inf <= divide & opa_inf & opb_inf;
		div_by_inf <= divide & !opa_inf & opb_inf;
		mul_0_by_inf <= multiply & ((opa_inf & opb_et_zero) | (opa_et_zero & opb_inf));
		mul_inf <= multiply & (opa_inf | opb_inf) & !mul_0_by_inf;
		div_inf <= divide & opa_inf & !opb_inf;
		add_inf <= (add & (opa_inf | opb_inf));
		sub_inf <= (subtract & (opa_inf | opb_inf));
		addsub_inf_invalid <= (add & opa_pos_inf & opb_neg_inf) | (add & opa_neg_inf & opb_pos_inf) | 
					(subtract & opa_pos_inf & opb_pos_inf) | (subtract & opa_neg_inf & opb_neg_inf);
		addsub_inf <= (add_inf | sub_inf) & !addsub_inf_invalid;
		out_inf_trigger <= addsub_inf | mul_inf | div_inf | div_by_0 | (exponent_in > 2046);
		out_pos_inf <= out_inf_trigger & !in_except[63];
		out_neg_inf <= out_inf_trigger & in_except[63];
		round_nearest <= (rmode == 2'b00);
		round_to_zero <= (rmode == 2'b01);
		round_to_pos_inf <= (rmode == 2'b10);
		round_to_neg_inf <= (rmode == 2'b11);
		inf_round_down_trigger <= (out_pos_inf & round_to_neg_inf) | 
								(out_neg_inf & round_to_pos_inf) |
								(out_inf_trigger & round_to_zero);
		mul_uf <= multiply & !opa_et_zero & !opb_et_zero & in_et_zero;
		div_uf <= divide & !opa_et_zero & in_et_zero;																
		underflow_trigger <= div_by_inf | mul_uf | div_uf;								
		invalid_trigger <= SNaN_input | addsub_inf_invalid | mul_0_by_inf |
						div_0_by_0 | div_inf_by_inf;
		overflow_trigger <= out_inf_trigger & !NaN_input;
		inexact_trigger <= (|mantissa_in[1:0] | out_inf_trigger | underflow_trigger) &
						!NaN_input;
		except_trigger <= invalid_trigger | overflow_trigger | underflow_trigger |
						inexact_trigger;
		enable_trigger <= except_trigger | out_inf_trigger | NaN_input;	
		NaN_out_trigger <= NaN_input | invalid_trigger;
		SNaN_trigger <= invalid_trigger & !SNaN_input;
		NaN_output_0 <= a_NaN ? { exp_2047, 1'b1, opa[50:0]} : { exp_2047, 1'b1, opb[50:0]};
		NaN_output <= SNaN_trigger ? { exp_2047, 2'b01, opa[49:0]} : NaN_output_0;
		inf_round_down <= { exp_2046, mantissa_max };
		out_inf <= inf_round_down_trigger ? inf_round_down : { exp_2047, 52'b0 };
		out_0 <= underflow_trigger ? { in_except[63], 63'b0 } : in_except;
		out_1 <= out_inf_trigger ? { in_except[63], out_inf } : out_0;
		out_2 <= NaN_out_trigger ? { in_except[63], NaN_output} : out_1;
		end
end 
 
always @(posedge clk)
begin
	if (rst) begin
		ex_enable <= 0;
		underflow <= 0;
		overflow <= 0;	   
		inexact <= 0;
		exception <= 0;
		invalid <= 0;
		out <= 0;
		end
	else if (enable) begin
		ex_enable <= enable_trigger;
		underflow <= underflow_trigger;
		overflow <= overflow_trigger;	   
		inexact <= inexact_trigger;
		exception <= except_trigger;
		invalid <= invalid_trigger;
		out <= out_2;
		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.