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

Subversion Repositories double_fpu

[/] [double_fpu/] [branches/] [avendor/] [fpu_double.v] - Rev 2

Go to most recent revision | 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
/* FPU Operations (fpu_op):
========================
0 = add
1 = sub
2 = mul
3 = div
 
Rounding Modes (rmode):
=======================
0 = round_nearest_even
1 = round_to_zero
2 = round_up
3 = round_down  */
 
module fpu( clk, rst, enable, rmode, fpu_op, opa, opb, out, ready, underflow,
overflow, inexact, exception, invalid);
input		clk;
input		rst;
input		enable;
input	[1:0]	rmode;
input	[2:0]	fpu_op;
input	[63:0]	opa, opb;
output	[63:0]	out;
output		ready;
output		underflow;
output		overflow;
output		inexact;
output		exception;
output		invalid;
 
reg [63:0]	opa_reg;
reg [63:0]	opb_reg;
reg [2:0]	fpu_op_reg;
reg [1:0]	rmode_reg;
reg			enable_reg;
reg			enable_reg_1; // high for one clock cycle
reg			enable_reg_2; // high for one clock cycle		 
reg			enable_reg_3; // high for two clock cycles
reg			op_enable;	  
reg [63:0]	out;
reg [6:0] 	count_cycles;
reg [6:0]	count_ready;
wire		count_busy = (count_ready <= count_cycles);
reg			ready;
reg			ready_0;
reg			ready_1;
reg		underflow;
reg		overflow;
reg		inexact;
reg		exception;
reg		invalid;
wire		underflow_0;
wire		overflow_0;
wire		inexact_0;
wire		exception_0;
wire		invalid_0;
 
wire	add_enable_0 = (fpu_op_reg == 3'b000) & !(opa_reg[63] ^ opb_reg[63]);
wire	add_enable_1 = (fpu_op_reg == 3'b001) & (opa_reg[63] ^ opb_reg[63]);
reg		add_enable; 
wire	sub_enable_0 = (fpu_op_reg == 3'b000) & (opa_reg[63] ^ opb_reg[63]);
wire	sub_enable_1 = (fpu_op_reg == 3'b001) & !(opa_reg[63] ^ opb_reg[63]);
reg		sub_enable; 
reg		mul_enable; 
reg		div_enable; 
wire	[55:0]	sum_out;
wire	[55:0]	diff_out;
reg		[55:0]	addsub_out;
wire	[55:0]	mul_out;
wire	[55:0]	div_out;
reg		[55:0]	mantissa_round;
wire	[10:0] 	exp_add_out;
wire	[10:0] 	exp_sub_out;
wire	[11:0] 	exp_mul_out;
wire	[11:0] 	exp_div_out;
reg		[11:0] 	exponent_round;
reg		[11:0] 	exp_addsub;
wire	[11:0]	exponent_post_round;
wire	add_sign;
wire	sub_sign;
wire	mul_sign;
wire	div_sign;
reg		addsub_sign;
reg		sign_round;
wire	[63:0]	out_round;
wire	[63:0]	out_except;
 
fpu_add u1(
	.clk(clk),.rst(rst),.enable(add_enable),.opa(opa_reg),.opb(opb_reg),
	.sign(add_sign),.sum_2(sum_out),.exponent_2(exp_add_out));
 
fpu_sub u2(
	.clk(clk),.rst(rst),.enable(sub_enable),.opa(opa_reg),.opb(opb_reg),
	.fpu_op(fpu_op_reg),.sign(sub_sign),.diff_2(diff_out),
	.exponent_2(exp_sub_out));
 
fpu_mul u3(
	.clk(clk),.rst(rst),.enable(mul_enable),.opa(opa_reg),.opb(opb_reg),
	.sign(mul_sign),.product_7(mul_out),.exponent_5(exp_mul_out));	
 
fpu_div u4(
	.clk(clk),.rst(rst),.enable(div_enable),.opa(opa_reg),.opb(opb_reg),
	.sign(div_sign),.mantissa_7(div_out),.exponent_out(exp_div_out));	
 
fpu_round u5(.clk(clk),.rst(rst),.enable(op_enable),	.round_mode(rmode_reg),
	.sign_term(sign_round),.mantissa_term(mantissa_round), .exponent_term(exponent_round),
	.round_out(out_round),.exponent_final(exponent_post_round));		
 
fpu_exceptions u6(.clk(clk),.rst(rst),.enable(op_enable),.rmode(rmode_reg),
	.opa(opa_reg),.opb(opb_reg),
	.in_except(out_round), .exponent_in(exponent_post_round),
	.mantissa_in(mantissa_round[1:0]),.fpu_op(fpu_op_reg),.out(out_except),
	.ex_enable(except_enable),.underflow(underflow_0),.overflow(overflow_0),
	.inexact(inexact_0),.exception(exception_0),.invalid(invalid_0));
 
 
always @(posedge clk)
begin
	case (fpu_op_reg)
	3'b000:		mantissa_round <= addsub_out;
	3'b001:		mantissa_round <= addsub_out;
	3'b010:		mantissa_round <= mul_out;
	3'b011:		mantissa_round <= div_out;
	default:	mantissa_round <= 0;
	endcase
end
 
always @(posedge clk)
begin
	case (fpu_op_reg)
	3'b000:		exponent_round <= exp_addsub;
	3'b001:		exponent_round <= exp_addsub;
	3'b010:		exponent_round <= exp_mul_out;
	3'b011:		exponent_round <= exp_div_out;
	default:	exponent_round <= 0;
	endcase
end
 
always @(posedge clk)
begin
	case (fpu_op_reg)
	3'b000:		sign_round <= addsub_sign;
	3'b001:		sign_round <= addsub_sign;
	3'b010:		sign_round <= mul_sign;
	3'b011:		sign_round <= div_sign;
	default:	sign_round <= 0;
	endcase
end
 
always @(posedge clk)
begin
	case (fpu_op_reg)
	3'b000:		count_cycles <= 20;
	3'b001:		count_cycles <= 21;
	3'b010:		count_cycles <= 24;
	3'b011:		count_cycles <= 71; 
	default:	count_cycles <= 0;
	endcase
end
 
always @(posedge clk)
begin
	if (rst) begin
		add_enable <= 0;
		sub_enable <= 0;
		mul_enable <= 0;
		div_enable <= 0;
		addsub_out <= 0;
		addsub_sign <= 0;
		exp_addsub <= 0;
		end
	else begin
		add_enable <= (add_enable_0 | add_enable_1) & op_enable;
		sub_enable <= (sub_enable_0 | sub_enable_1) & op_enable;
		mul_enable <= (fpu_op_reg == 3'b010) & op_enable;
		div_enable <= (fpu_op_reg == 3'b011) & op_enable & enable_reg_3;
			// div_enable needs to be high for two clock cycles
		addsub_out <= add_enable ? sum_out : diff_out;
		addsub_sign <= add_enable ? add_sign : sub_sign;
		exp_addsub <= add_enable ? { 1'b0, exp_add_out} : { 1'b0, exp_sub_out};
		end
end 
 
always @ (posedge clk)
begin
	if (rst)
		count_ready <= 0;
	else if (enable_reg_1) 
		count_ready <= 0;
	else if (count_busy)
		count_ready <= count_ready + 1; 
end
 
always @(posedge clk)
begin
	if (rst) begin
		enable_reg <= 0;
		enable_reg_1 <= 0;
		enable_reg_2 <= 0;	   
		enable_reg_3 <= 0;
		end
	else begin
		enable_reg <= enable;
		enable_reg_1 <= enable & !enable_reg;
		enable_reg_2 <= enable_reg_1;  
		enable_reg_3 <= enable_reg_1 | enable_reg_2;
		end
end 
 
always @(posedge clk) 
begin
	if (rst) begin
		opa_reg <= 0;
		opb_reg <= 0;
		fpu_op_reg <= 0; 
		rmode_reg <= 0;
		op_enable <= 0;
		end
	else if (enable_reg_1) begin
		opa_reg <= opa;
		opb_reg <= opb;
		fpu_op_reg <= fpu_op; 
		rmode_reg <= rmode;
		op_enable <= 1;
		end
end
 
always @(posedge clk)
begin
	if (rst) begin
		ready_0 <= 0;
		ready_1 <= 0;
		ready <= 0;	   
		end
	else if (enable_reg_1) begin
		ready_0 <= 0;
		ready_1 <= 0;
		ready <= 0;	 
		end
	else begin
		ready_0 <= !count_busy;
		ready_1 <= ready_0;
		ready <= ready_1;  
		end
end 
 
always @(posedge clk)
begin
	if (rst) begin
		underflow <= 0;
		overflow <= 0;
		inexact <= 0;
		exception <= 0;
		invalid <= 0;	   	 
		out <= 0;
		end
	else if (ready_1) begin
		underflow <= underflow_0;
		overflow <= overflow_0;
		inexact <= inexact_0;
		exception <= exception_0;
		invalid <= invalid_0; 	
		out <= except_enable ? out_except : out_round;
		end
end 
endmodule
 

Go to most recent revision | 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.