/*============================================================================ | |
This Verilog source file is part of the Berkeley HardFloat IEEE Floating-Point | |
Arithmetic Package, Release 1, by John R. Hauser. | |
Copyright 2019 The Regents of the University of California. All rights | |
reserved. | |
Redistribution and use in source and binary forms, with or without | |
modification, are permitted provided that the following conditions are met: | |
1. Redistributions of source code must retain the above copyright notice, | |
this list of conditions, and the following disclaimer. | |
2. Redistributions in binary form must reproduce the above copyright notice, | |
this list of conditions, and the following disclaimer in the documentation | |
and/or other materials provided with the distribution. | |
3. Neither the name of the University nor the names of its contributors may | |
be used to endorse or promote products derived from this software without | |
specific prior written permission. | |
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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. | |
=============================================================================*/ | |
//`include "HardFloat_consts.vi" | |
/*---------------------------------------------------------------------------- | |
*----------------------------------------------------------------------------*/ | |
`define round_near_even 3'b000 | |
`define round_minMag 3'b001 | |
`define round_min 3'b010 | |
`define round_max 3'b011 | |
`define round_near_maxMag 3'b100 | |
`define round_odd 3'b110 | |
/*---------------------------------------------------------------------------- | |
*----------------------------------------------------------------------------*/ | |
`define floatControlWidth 1 | |
`define flControl_tininessBeforeRounding 1'b0 | |
`define flControl_tininessAfterRounding 1'b1 | |
/*---------------------------------------------------------------------------- | |
*----------------------------------------------------------------------------*/ | |
`define flRoundOpt_sigMSBitAlwaysZero 1 | |
`define flRoundOpt_subnormsAlwaysExact 2 | |
`define flRoundOpt_neverUnderflows 4 | |
`define flRoundOpt_neverOverflows 8 | |
//`include "HardFloat_specialize.vi" | |
`define HardFloat_signDefaultNaN 0 | |
`define HardFloat_fractDefaultNaN(sigWidth) {1'b1, {((sigWidth) - 2){1'b0}}} | |
/*---------------------------------------------------------------------------- | |
*----------------------------------------------------------------------------*/ | |
/*---------------------------------------------------------------------------- | |
| Computes a division or square root for floating-point in recoded form. | |
| Multiple clock cycles are needed for each division or square-root operation, | |
| except possibly in special cases. | |
*----------------------------------------------------------------------------*/ | |
module | |
divSqrtRecFNToRaw_small#( | |
parameter expWidth = 3, parameter sigWidth = 3, parameter options = 0 | |
) ( | |
/*-------------------------------------------------------------------- | |
*--------------------------------------------------------------------*/ | |
input nReset, | |
input clock, | |
/*-------------------------------------------------------------------- | |
*--------------------------------------------------------------------*/ | |
input [(`floatControlWidth - 1):0] control, | |
/*-------------------------------------------------------------------- | |
*--------------------------------------------------------------------*/ | |
output inReady, | |
input inValid, | |
input sqrtOp, | |
input [(expWidth + sigWidth):0] a, | |
input [(expWidth + sigWidth):0] b, | |
input [2:0] roundingMode, | |
/*-------------------------------------------------------------------- | |
*--------------------------------------------------------------------*/ | |
output outValid, | |
output sqrtOpOut, | |
output [2:0] roundingModeOut, | |
output invalidExc, | |
output infiniteExc, | |
output out_isNaN, | |
output out_isInf, | |
output out_isZero, | |
output out_sign, | |
output signed [(expWidth + 1):0] out_sExp, | |
output [(sigWidth + 2):0] out_sig | |
); | |
//`include "HardFloat_localFuncs.vi" | |
function integer clog2; | |
input integer a; | |
begin | |
a = a - 1; | |
for (clog2 = 0; a > 0; clog2 = clog2 + 1) a = a>>1; | |
end | |
endfunction | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire isNaNA_S, isInfA_S, isZeroA_S, signA_S; | |
wire signed [(expWidth + 1):0] sExpA_S; | |
wire [sigWidth:0] sigA_S; | |
recFNToRawFN#(expWidth, sigWidth) | |
recFNToRawFN_a( | |
a, isNaNA_S, isInfA_S, isZeroA_S, signA_S, sExpA_S, sigA_S); | |
wire isSigNaNA_S; | |
isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_a(a, isSigNaNA_S); | |
wire isNaNB_S, isInfB_S, isZeroB_S, signB_S; | |
wire signed [(expWidth + 1):0] sExpB_S; | |
wire [sigWidth:0] sigB_S; | |
recFNToRawFN#(expWidth, sigWidth) | |
recFNToRawFN_b( | |
b, isNaNB_S, isInfB_S, isZeroB_S, signB_S, sExpB_S, sigB_S); | |
wire isSigNaNB_S; | |
isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_b(b, isSigNaNB_S); | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire notSigNaNIn_invalidExc_S_div = | |
(isZeroA_S && isZeroB_S) || (isInfA_S && isInfB_S); | |
wire notSigNaNIn_invalidExc_S_sqrt = !isNaNA_S && !isZeroA_S && signA_S; | |
wire majorExc_S = | |
sqrtOp ? isSigNaNA_S || notSigNaNIn_invalidExc_S_sqrt | |
: isSigNaNA_S || isSigNaNB_S || notSigNaNIn_invalidExc_S_div | |
|| (!isNaNA_S && !isInfA_S && isZeroB_S); | |
wire isNaN_S = | |
sqrtOp ? isNaNA_S || notSigNaNIn_invalidExc_S_sqrt | |
: isNaNA_S || isNaNB_S || notSigNaNIn_invalidExc_S_div; | |
`ifdef HardFloat_propagateNaNPayloads | |
wire signNaN_S; | |
wire [(sigWidth - 2):0] fractNaN_S; | |
propagateFloatNaN_divSqrt#(sigWidth) | |
propagateNaN( | |
control, | |
sqrtOp, | |
isNaNA_S, | |
signA_S, | |
sigA_S[(sigWidth - 2):0], | |
isNaNB_S, | |
signB_S, | |
sigB_S[(sigWidth - 2):0], | |
signNaN_S, | |
fractNaN_S | |
); | |
`endif | |
wire isInf_S = sqrtOp ? isInfA_S : isInfA_S || isZeroB_S; | |
wire isZero_S = sqrtOp ? isZeroA_S : isZeroA_S || isInfB_S; | |
wire sign_S = signA_S ^ (!sqrtOp && signB_S); | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire specialCaseA_S = isNaNA_S || isInfA_S || isZeroA_S; | |
wire specialCaseB_S = isNaNB_S || isInfB_S || isZeroB_S; | |
wire normalCase_S_div = !specialCaseA_S && !specialCaseB_S; | |
wire normalCase_S_sqrt = !specialCaseA_S && !signA_S; | |
wire normalCase_S = sqrtOp ? normalCase_S_sqrt : normalCase_S_div; | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire signed [(expWidth + 2):0] sExpQuot_S_div = | |
sExpA_S + {{3{sExpB_S[expWidth]}}, ~sExpB_S[(expWidth - 1):0]}; | |
wire signed [(expWidth + 1):0] sSatExpQuot_S_div = | |
{(7<<(expWidth - 2) <= sExpQuot_S_div) ? 4'b0110 | |
: sExpQuot_S_div[(expWidth + 1):(expWidth - 2)], | |
sExpQuot_S_div[(expWidth - 3): 0]}; | |
wire evenSqrt_S = sqrtOp && !sExpA_S[0]; | |
wire oddSqrt_S = sqrtOp && sExpA_S[0]; | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
reg [(clog2(sigWidth + 3) - 1):0] cycleNum; | |
reg sqrtOp_Z, majorExc_Z; | |
reg isNaN_Z, isInf_Z, isZero_Z, sign_Z; | |
reg signed [(expWidth + 1):0] sExp_Z; | |
reg [(sigWidth - 2):0] fractB_Z; | |
reg [2:0] roundingMode_Z; | |
/*------------------------------------------------------------------------ | |
| (The most-significant and least-significant bits of 'rem_Z' are needed | |
| only for square roots.) | |
*------------------------------------------------------------------------*/ | |
reg [(sigWidth + 1):0] rem_Z; | |
reg notZeroRem_Z; | |
reg [(sigWidth + 1):0] sigX_Z; | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire idle = (cycleNum == 0); | |
assign inReady = (cycleNum <= 1); | |
wire entering = inReady && inValid; | |
wire entering_normalCase = entering && normalCase_S; | |
wire skipCycle2 = (cycleNum == 3) && sigX_Z[sigWidth + 1]; | |
always @(negedge nReset, posedge clock) begin | |
if (!nReset) begin | |
cycleNum <= 0; | |
end else begin | |
if (!idle || inValid) begin | |
cycleNum <= | |
(entering && !normalCase_S ? 1 : 0) | |
| (entering_normalCase | |
? (sqrtOp ? (sExpA_S[0] ? sigWidth : sigWidth + 1) | |
: sigWidth + 2) | |
: 0) | |
| (!idle && !skipCycle2 ? cycleNum - 1 : 0) | |
| (!idle && skipCycle2 ? 1 : 0); | |
end | |
end | |
end | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
always @(posedge clock) begin | |
if (entering) begin | |
sqrtOp_Z <= sqrtOp; | |
majorExc_Z <= majorExc_S; | |
isNaN_Z <= isNaN_S; | |
isInf_Z <= isInf_S; | |
isZero_Z <= isZero_S; | |
`ifdef HardFloat_propagateNaNPayloads | |
sign_Z <= isNaN_S ? signNaN_S : sign_S; | |
`else | |
sign_Z <= sign_S; | |
`endif | |
end | |
if (entering_normalCase) begin | |
sExp_Z <= | |
sqrtOp ? (sExpA_S>>>1) + (1<<(expWidth - 1)) | |
: sSatExpQuot_S_div; | |
roundingMode_Z <= roundingMode; | |
end | |
if (entering_normalCase && !sqrtOp) begin | |
fractB_Z <= sigB_S[(sigWidth - 2):0]; | |
end | |
end | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire [1:0] decHiSigA_S = sigA_S[(sigWidth - 1):(sigWidth - 2)] - 1; | |
wire [(sigWidth + 2):0] rem = | |
(inReady && !oddSqrt_S ? sigA_S<<1 : 0) | |
| (inReady && oddSqrt_S | |
? {decHiSigA_S, sigA_S[(sigWidth - 3):0], 3'b0} : 0) | |
| (!inReady ? rem_Z<<1 : 0); | |
wire [sigWidth:0] bitMask = ({{(sigWidth + 2){1'b0}}, 1'b1}<<cycleNum)>>2; | |
wire [(sigWidth + 1):0] trialTerm = | |
( inReady && !sqrtOp ? sigB_S<<1 : 0) | |
| ( inReady && evenSqrt_S ? 1<<sigWidth : 0) | |
| ( inReady && oddSqrt_S ? 5<<(sigWidth - 1) : 0) | |
| (!inReady && !sqrtOp_Z ? {1'b1, fractB_Z}<<1 : 0) | |
| (!inReady && sqrtOp_Z ? sigX_Z<<1 | bitMask : 0); | |
wire signed [(sigWidth + 3):0] trialRem = rem - trialTerm; | |
wire newBit = (0 <= trialRem); | |
always @(posedge clock) begin | |
if (entering_normalCase || (cycleNum > 2)) begin | |
rem_Z <= newBit ? trialRem : rem; | |
end | |
`ifdef HardFloat_propagateNaNPayloads | |
if ( | |
(entering && isNaN_S) || entering_normalCase | |
|| (!inReady && newBit) | |
) begin | |
notZeroRem_Z <= (trialRem != 0); | |
sigX_Z <= | |
(inReady && isNaN_S ? {1'b1, fractNaN_S, 2'b00} : 0) | |
| (inReady && !isNaN_S && !sqrtOp ? newBit<<(sigWidth + 1) : 0) | |
| (inReady && !isNaN_S && sqrtOp ? 1<<sigWidth : 0) | |
| (inReady && !isNaN_S && oddSqrt_S | |
? newBit<<(sigWidth - 1) : 0) | |
| (!inReady ? sigX_Z | bitMask : 0); | |
end | |
`else | |
if (entering_normalCase || (!inReady && newBit)) begin | |
notZeroRem_Z <= (trialRem != 0); | |
sigX_Z <= | |
( inReady && !sqrtOp ? newBit<<(sigWidth + 1) : 0) | |
| ( inReady && sqrtOp ? 1<<sigWidth : 0) | |
| ( inReady && oddSqrt_S ? newBit<<(sigWidth - 1) : 0) | |
| (!inReady ? sigX_Z | bitMask : 0); | |
end | |
`endif | |
end | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
assign outValid = (cycleNum == 1); | |
assign sqrtOpOut = sqrtOp_Z; | |
assign roundingModeOut = roundingMode_Z; | |
assign invalidExc = majorExc_Z && isNaN_Z; | |
assign infiniteExc = majorExc_Z && !isNaN_Z; | |
assign out_isNaN = isNaN_Z; | |
assign out_isInf = isInf_Z; | |
assign out_isZero = isZero_Z; | |
assign out_sign = sign_Z; | |
assign out_sExp = sExp_Z; | |
assign out_sig = {sigX_Z, notZeroRem_Z}; | |
endmodule | |
/*---------------------------------------------------------------------------- | |
*----------------------------------------------------------------------------*/ | |
module | |
divSqrtRecFN_small#( | |
parameter expWidth = 3, parameter sigWidth = 3, parameter options = 0 | |
) ( | |
/*-------------------------------------------------------------------- | |
*--------------------------------------------------------------------*/ | |
input nReset, | |
input clock, | |
/*-------------------------------------------------------------------- | |
*--------------------------------------------------------------------*/ | |
input [(`floatControlWidth - 1):0] control, | |
/*-------------------------------------------------------------------- | |
*--------------------------------------------------------------------*/ | |
output inReady, | |
input inValid, | |
input sqrtOp, | |
input [(expWidth + sigWidth):0] a, | |
input [(expWidth + sigWidth):0] b, | |
input [2:0] roundingMode, | |
/*-------------------------------------------------------------------- | |
*--------------------------------------------------------------------*/ | |
output outValid, | |
output sqrtOpOut, | |
output [(expWidth + sigWidth):0] out, | |
output [4:0] exceptionFlags | |
); | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire sqrtOpOut; | |
wire [2:0] roundingModeOut; | |
wire invalidExc, infiniteExc, out_isNaN, out_isInf, out_isZero, out_sign; | |
wire signed [(expWidth + 1):0] out_sExp; | |
wire [(sigWidth + 2):0] out_sig; | |
divSqrtRecFNToRaw_small#(expWidth, sigWidth, options) | |
divSqrtRecFNToRaw( | |
nReset, | |
clock, | |
control, | |
inReady, | |
inValid, | |
sqrtOp, | |
a, | |
b, | |
roundingMode, | |
outValid, | |
sqrtOpOut, | |
roundingModeOut, | |
invalidExc, | |
infiniteExc, | |
out_isNaN, | |
out_isInf, | |
out_isZero, | |
out_sign, | |
out_sExp, | |
out_sig | |
); | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
roundRawFNToRecFN#(expWidth, sigWidth, 0) | |
roundRawOut( | |
control, | |
invalidExc, | |
infiniteExc, | |
out_isNaN, | |
out_isInf, | |
out_isZero, | |
out_sign, | |
out_sExp, | |
out_sig, | |
roundingModeOut, | |
out, | |
exceptionFlags | |
); | |
endmodule | |