URL
https://opencores.org/ocsvn/ft816float/ft816float/trunk
Subversion Repositories ft816float
[/] [ft816float/] [trunk/] [rtl/] [verilog/] [fpNormalize.v] - Rev 7
Go to most recent revision | Compare with Previous | Blame | View Log
// ============================================================================ // __ // \\__/ o\ (C) 2006-2016 Robert Finch, Stratford // \ __ / All rights reserved. // \/_// robfinch<remove>@finitron.ca // || // // This source file is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This source file is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // fpNormalize.v // - floating point normalization unit // - two cycle latency // - parameterized width // // This unit takes a floating point number in an intermediate // format and normalizes it. No normalization occurs // for NaN's or infinities. The unit has a two cycle latency. // // The mantissa is assumed to start with three whole bits on // the left. The remaining bits are fractional. The three whole bits // result from a MAC (multiply accumulate) operation. The result from // a MAC can vary from 0 to 8 which requires three whole digits. // // The width of the incoming format is reduced via a generation // of sticky bit in place of the low order fractional bits. // // On an underflowed input, the incoming exponent is assumed // to be negative. A right shift is needed. // ============================================================================ // module fpNormalize(clk, ce, under, 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; localparam WX = 3; // Three whole digits localparam FX = (FMSB+1)*2-1; // the MSB of the expanded fraction // Fraction + Three whole bits localparam EX = FX + WX + EMSB + 1; // The MSB of the exponent input clk; input ce; input under; input [EX+1:0] i; // expanded format input output [WID+3:0] o; // normalized output + guard, sticky and round bits, + 1 whole digit wire [EMSB:0] infXp = {EMSB+1{1'b1}}; // simple constant - value of exp for inifinity // variables wire so; wire so1 = i[EX+1]; // sign doesn't change // Since the there are *three* whole digits in the incoming format // the number of whole digits needs to be reduced. If the MSB is // set, then increment the exponent by two and no shift is needed. // Otherwise if the next MSB is set, increment the exponent by one, // and shift left once. wire [EMSB:0] xo; wire [EMSB:0] xo1a = i[EX:FX+WX+1]; wire incExp2 = i[FX+WX-1]|i[FX+WX-2]; // Allow an extra bit for exponent overflow // Add two to exponent to shift the decimal place left twice. // (Gives 1 leading whole digit). wire [EMSB+1:0] xo1b = xo1a + 2; wire [EMSB:0] xo1; wire [EMSB:0] xo2; wire xInf1a = &xo1a[EMSB:0]; // If there was a carry from the addition and we were in the underflow // state, then the number became normal again. Clear the carry bit. // Otherwise if the exponent overflowed and it's not the underflow // state, then set the exponent to infinity. Othwerise just keep the // remaining exponent bits - the result is still underflowed. assign xo1 = (under & xo1b[EMSB+1]) ? xo1b[EMSB:0] : (xInf1a & !under) ? infXp : xo1b[EMSB+1] ? infXp : xo1b; wire xInf = &xo1 & !under; wire under1 = under & !xo1b[EMSB+1]; // keep trakc of renormallzation // shift mantissa left by one to reduce to a single whole digit // if there is no exponent increment wire [FMSB+1+3:0] mo; //GRS+1whole digit wire [FX+WX:0] mo1 = xInf & incExp2 ? 0 : // set mantissa to zero for infinity i[FX+WX:0]; wire [FX+WX:0] mo2; wire [7:0] leadingZeros2; // Adjust the operand to the leading zero counter by left aligning it // by padding trailing zeros. This is a constant shift that doesn't take // any hardware. generate begin if (WID==64) begin wire [127:0] mo1a = {mo1,{127-(FX+3){1'b0}}}; cntlz128Reg clz0 (.clk(clk), .ce(ce), .i(mo1a), .o(leadingZeros2) ); end else begin // 32 bits wire [63:0] mo1a = {mo1,{63-(FX+3){1'b0}}}; cntlz64Reg clz0 (.clk(clk), .ce(ce), .i(mo1a), .o(leadingZeros2) ); assign leadingZeros2[7] = 1'b0; end end endgenerate // compensate for leadingZeros delay wire xInf2; delay1 #(EMSB+1) d2(.clk(clk), .ce(ce), .i(xo1), .o(xo2) ); delay1 #(1) d3(.clk(clk), .ce(ce), .i(xInf), .o(xInf2) ); // If the exponent underflowed, then the shift direction must be to the // right regardless of mantissa bits; the number is denormalized. // Otherwise the shift direction must be to the left. wire rightOrLeft2; // 0=left,1=right delay1 #(1) d8(.clk(clk), .ce(ce), .i(under1), .o(rightOrLeft2) ); // Compute how much we want to decrement by. We can't decrement by // more than the exponent as the number becomes denormal when the // exponent reaches zero. wire [7:0] lshiftAmt2 = leadingZeros2 > xo2 ? xo2 : leadingZeros2; // compute amount to shift right // at infinity the exponent can't be incremented, so we can't shift right // otherwise it was an underflow situation so the exponent was negative // shift amount needs to be negated for shift register wire [EMSB:0] nxo2 = -xo2; wire [7:0] rshiftAmt2 = xInf2 ? 0 : nxo2 > FMSB+WX ? FMSB+WX+1 : nxo2; // xo2 is negative ! // sign // the output sign is the same as the input sign delay1 #(1) d7(.clk(clk), .ce(ce), .i(so1), .o(so) ); // exponent // always @(posedge clk) // if (ce) assign xo = xInf2 ? xo2 : // an infinite exponent is either a NaN or infinity; no need to change rightOrLeft2 ? 0 : // on a right shift, the exponent was negative, it's being made to zero xo2 - lshiftAmt2; // on a left shift, the exponent can't be decremented below zero // mantissa delay1 #(FX+WX+1) d4(.clk(clk), .ce(ce), .i(mo1), .o(mo2) ); wire [FX+WX:0] mo2a; // Now do the shifting assign mo2a = rightOrLeft2 ? mo2 >> rshiftAmt2 : mo2 << lshiftAmt2; // always @(posedge clk) // if (ce) // If infinity is reached then set the mantissa to zero wire gbit = mo2a[FMSB+3]; wire rbit = mo2a[FMSB+2]; wire sbit = |mo2a[FMSB+1:0]; assign mo = {mo2a[FX+WX:FMSB+3],gbit,rbit,sbit}; assign o = {so,xo,mo}; endmodule module fpNormalize_tb(); reg clk; wire [35:0] o1,o2,o3,o4,o5,o6; initial begin clk = 0; end always #10 clk = ~clk; // input = // 23*2 + 3 + 8 + 1 = 58 bits fpNormalize #(32) u1 (clk, 1'b1, 1'b0, 58'h0, o1); // zeor should result in a zero fpNormalize #(32) u2 (clk, 1'b1, 1'b0, 58'h1FE123456781234, o2); // Nan should be a Nan fpNormalize #(32) u3 (clk, 1'b1, 1'b1, 58'h000001234567890, o3); // denomral should be denormal fpNormalize #(32) u4 (clk, 1'b1, 1'b1, 58'h1F0001234567890, o4); // denomral should be denormal (underflow exp is neg) fpNormalize #(32) u5 (clk, 1'b1, 1'b0, 58'h0FF000000000000, o5); // the value 4 fpNormalize #(32) u6 (clk, 1'b1, 1'b0, 58'h104900000000000, o6); // the value 100 endmodule
Go to most recent revision | Compare with Previous | Blame | View Log