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

Subversion Repositories thor

[/] [thor/] [trunk/] [rtl/] [verilog/] [fpUnit/] [fpRound.v] - Rev 21

Go to most recent revision | Compare with Previous | Blame | View Log

/* ===============================================================
	(C) 2006  Robert Finch
	All rights reserved.
	rob@birdcomputer.ca
 
	fpRound.v
		- floating point rounding unit
		- parameterized width
		- IEEE 754 representation
 
	This source code is free for use and modification for
	non-commercial or evaluation purposes, provided this
	copyright statement and disclaimer remains present in
	the file.
 
	If the code is modified, please state the origin and
	note that the code has been modified.
 
	NO WARRANTY.
	THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF
	ANY KIND, WHETHER EXPRESS OR IMPLIED. The user must assume
	the entire risk of using the Work.
 
	IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
	ANY INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES
	WHATSOEVER RELATING TO THE USE OF THIS WORK, OR YOUR
	RELATIONSHIP WITH THE AUTHOR.
 
	IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU
	TO USE THE WORK IN APPLICATIONS OR SYSTEMS WHERE THE
	WORK'S FAILURE TO PERFORM CAN REASONABLY BE EXPECTED
	TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN LOSS
	OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK,
	AND YOU AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS
	FROM ANY CLAIMS OR LOSSES RELATING TO SUCH UNAUTHORIZED
	USE.
 
 
	This unit takes a normalized floating point number in an
	expanded format and rounds it according to the IEEE-754
	standard. NaN's and infinities are not rounded.
	This module has a single cycle latency.
 
	Mode
	0:		round to nearest even
	1:		round to zero (truncate)
	2:		round towards +infinity
	3:		round towards -infinity
 
	Ref: Webpack 8.1i  Spartan3-4 xc3s1000-4ft256
	69 slices / 129 LUTS / 21.3 ns  (32 bit)
=============================================================== */
 
module fpRound(rm, i, o);
parameter WID = 32;
localparam MSB = WID-1;
localparam EMSB = WID==80 ? 14 :
                  WID==64 ? 10 :
				  WID==52 ? 10 :
				  WID==48 ? 10 :
				  WID==44 ? 10 :
				  WID==42 ? 10 :
				  WID==40 ?  9 :
				  WID==32 ?  7 :
				  WID==24 ?  6 : 4;
localparam FMSB = WID==80 ? 63 :
                  WID==64 ? 51 :
				  WID==52 ? 39 :
				  WID==48 ? 35 :
				  WID==44 ? 31 :
				  WID==42 ? 29 :
				  WID==40 ? 28 :
				  WID==32 ? 22 :
				  WID==24 ? 15 : 9;
 
input [1:0] rm;			// rounding mode
input [MSB+2:0] i;		// intermediate format input
output [WID-1:0] o;		// rounded output
 
//------------------------------------------------------------
// variables
wire so;
wire [EMSB:0] xo;
reg  [FMSB:0] mo;
wire [EMSB:0] xo1 = i[MSB+1:FMSB+4];
wire [FMSB+3:0] mo1 = i[FMSB+3:0];
wire xInf = &xo1;
wire dn = !(|xo1);			// denormalized input
assign o = {so,xo,mo};
 
wire g = i[2];	// guard bit: always the same bit for all operations
wire r = i[1];	// rounding bit
wire s = i[0];	// sticky bit
reg rnd;
 
// Compute the round bit
// Infinities and NaNs are not rounded!
always @(xInf,rm,g,r,s,so)
	case ({xInf,rm})
	3'd0:	rnd = (g & r) | (r & s);	// round to nearest even
	3'd1:	rnd = 0;					// round to zero (truncate)
	3'd2:	rnd = (r | s) & !so;		// round towards +infinity
	3'd3:	rnd = (r | s) & so;			// round towards -infinity
	default:	rnd = 0;				// no rounding if exponent indicates infinite or NaN
	endcase
 
// round the number, check for carry
// note: inf. exponent checked above (if the exponent was infinite already, then no rounding occurs as rnd = 0)
// note: exponent increments if there is a carry (can only increment to infinity)
// performance note: use the carry chain to increment the exponent
wire [MSB:0] rounded = {xo1,mo1[FMSB+3:2]} + rnd;
wire carry = mo1[FMSB+3] & !rounded[FMSB+1];
 
assign so = i[MSB+2];
assign xo = rounded[MSB:FMSB+2];
 
always @(rnd or xo or carry or dn or rounded or mo1)
	casex({rnd,&xo,carry,dn})
	4'b0xx0:	mo = mo1[FMSB+2:1];		// not rounding, not denormalized, => hide MSB
	4'b0xx1:	mo = mo1[FMSB+3:2];		// not rounding, denormalized
	4'b1000:	mo = rounded[FMSB  :0];	// exponent didn't change, number was normalized, => hide MSB
	4'b1001:	mo = rounded[FMSB+1:1];	// exponent didn't change, but number was denormalized, => retain MSB
	4'b1010:	mo = rounded[FMSB+1:1];	// exponent incremented (new MSB generated), number was normalized, => hide 'extra (FMSB+2)' MSB
	4'b1011:	mo = rounded[FMSB+1:1];	// exponent incremented (new MSB generated), number was denormalized, number became normalized, => hide 'extra (FMSB+2)' MSB
	4'b11xx:	mo = 0;					// number became infinite, no need to check carry etc., rnd would be zero if input was NaN or infinite
	endcase
 
endmodule
 
 
// Round and register the output
 
module fpRoundReg(clk, ce, rm, i, o);
parameter WID = 32;
localparam MSB = WID-1;
localparam EMSB = WID==80 ? 14 :
                  WID==64 ? 10 :
				  WID==52 ? 10 :
				  WID==48 ? 10 :
				  WID==44 ? 10 :
				  WID==42 ? 10 :
				  WID==40 ?  9 :
				  WID==32 ?  7 :
				  WID==24 ?  6 : 4;
localparam FMSB = WID==80 ? 63 :
                  WID==64 ? 51 :
				  WID==52 ? 39 :
				  WID==48 ? 35 :
				  WID==44 ? 31 :
				  WID==42 ? 29 :
				  WID==40 ? 28 :
				  WID==32 ? 22 :
				  WID==24 ? 15 : 9;
 
input clk;
input ce;
input [1:0] rm;			// rounding mode
input [MSB+2:0] i;		// expanded format input
output reg [WID-1:0] o;		// rounded output
 
wire [WID-1:0] o1;
fpRound #(WID) u1 (.rm(rm), .i(i), .o(o1) );
 
always @(posedge clk)
	if (ce)
		o <= o1;
 
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.