/*============================================================================ | |
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}}} | |
/*---------------------------------------------------------------------------- | |
*----------------------------------------------------------------------------*/ | |
module | |
mulRecFNToFullRaw#(parameter expWidth = 3, parameter sigWidth = 3) ( | |
input [(`floatControlWidth - 1):0] control, | |
input [(expWidth + sigWidth):0] a, | |
input [(expWidth + sigWidth):0] b, | |
output invalidExc, | |
output out_isNaN, | |
output out_isInf, | |
output out_isZero, | |
output out_sign, | |
output signed [(expWidth + 1):0] out_sExp, | |
output [(sigWidth*2 - 1):0] out_sig | |
); | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire isNaNA, isInfA, isZeroA, signA; | |
wire signed [(expWidth + 1):0] sExpA; | |
wire [sigWidth:0] sigA; | |
recFNToRawFN#(expWidth, sigWidth) | |
recFNToRawFN_a(a, isNaNA, isInfA, isZeroA, signA, sExpA, sigA); | |
wire isSigNaNA; | |
isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_a(a, isSigNaNA); | |
wire isNaNB, isInfB, isZeroB, signB; | |
wire signed [(expWidth + 1):0] sExpB; | |
wire [sigWidth:0] sigB; | |
recFNToRawFN#(expWidth, sigWidth) | |
recFNToRawFN_b(b, isNaNB, isInfB, isZeroB, signB, sExpB, sigB); | |
wire isSigNaNB; | |
isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_b(b, isSigNaNB); | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire notSigNaN_invalidExc = (isInfA && isZeroB) || (isZeroA && isInfB); | |
wire notNaN_isInfOut = isInfA || isInfB; | |
wire notNaN_isZeroOut = isZeroA || isZeroB; | |
wire notNaN_signOut = signA ^ signB; | |
wire signed [(expWidth + 1):0] common_sExpOut = | |
sExpA + sExpB - (1<<expWidth); | |
wire [(sigWidth*2 - 1):0] common_sigOut = sigA * sigB; | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
assign invalidExc = isSigNaNA || isSigNaNB || notSigNaN_invalidExc; | |
assign out_isInf = notNaN_isInfOut; | |
assign out_isZero = notNaN_isZeroOut; | |
assign out_sExp = common_sExpOut; | |
`ifdef HardFloat_propagateNaNPayloads | |
assign out_isNaN = isNaNA || isNaNB || notSigNaN_invalidExc; | |
wire signNaN; | |
wire [(sigWidth - 2):0] fractNaN; | |
propagateFloatNaN_mul#(sigWidth) | |
propagateNaN( | |
control, | |
isNaNA, | |
signA, | |
sigA[(sigWidth - 2):0], | |
isNaNB, | |
signB, | |
sigB[(sigWidth - 2):0], | |
signNaN, | |
fractNaN | |
); | |
assign out_sign = out_isNaN ? signNaN : notNaN_signOut; | |
assign out_sig = | |
out_isNaN ? {1'b1, fractNaN}<<(sigWidth - 1) : common_sigOut; | |
`else | |
assign out_isNaN = isNaNA || isNaNB; | |
assign out_sign = notNaN_signOut; | |
assign out_sig = common_sigOut; | |
`endif | |
endmodule | |
/*---------------------------------------------------------------------------- | |
*----------------------------------------------------------------------------*/ | |
module | |
mulRecFNToRaw#(parameter expWidth = 3, parameter sigWidth = 3) ( | |
input [(`floatControlWidth - 1):0] control, | |
input [(expWidth + sigWidth):0] a, | |
input [(expWidth + sigWidth):0] b, | |
output invalidExc, | |
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 | |
); | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire isNaNA, isInfA, isZeroA, signA; | |
wire signed [(expWidth + 1):0] sExpA; | |
wire [sigWidth:0] sigA; | |
recFNToRawFN#(expWidth, sigWidth) | |
recFNToRawFN_a(a, isNaNA, isInfA, isZeroA, signA, sExpA, sigA); | |
wire isSigNaNA; | |
isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_a(a, isSigNaNA); | |
wire isNaNB, isInfB, isZeroB, signB; | |
wire signed [(expWidth + 1):0] sExpB; | |
wire [sigWidth:0] sigB; | |
recFNToRawFN#(expWidth, sigWidth) | |
recFNToRawFN_b(b, isNaNB, isInfB, isZeroB, signB, sExpB, sigB); | |
wire isSigNaNB; | |
isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_b(b, isSigNaNB); | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
wire notSigNaN_invalidExc = (isInfA && isZeroB) || (isZeroA && isInfB); | |
wire notNaN_isInfOut = isInfA || isInfB; | |
wire notNaN_isZeroOut = isZeroA || isZeroB; | |
wire notNaN_signOut = signA ^ signB; | |
wire signed [(expWidth + 1):0] common_sExpOut = | |
sExpA + sExpB - (1<<expWidth); | |
wire [(sigWidth*2 - 1):0] sigProd = sigA * sigB; | |
wire [(sigWidth + 2):0] common_sigOut = | |
{sigProd[(sigWidth*2 - 1):(sigWidth - 2)], |sigProd[(sigWidth - 3):0]}; | |
/*------------------------------------------------------------------------ | |
*------------------------------------------------------------------------*/ | |
assign invalidExc = isSigNaNA || isSigNaNB || notSigNaN_invalidExc; | |
assign out_isInf = notNaN_isInfOut; | |
assign out_isZero = notNaN_isZeroOut; | |
assign out_sExp = common_sExpOut; | |
`ifdef HardFloat_propagateNaNPayloads | |
assign out_isNaN = isNaNA || isNaNB || notSigNaN_invalidExc; | |
wire signNaN; | |
wire [(sigWidth - 2):0] fractNaN; | |
propagateFloatNaN_mul#(sigWidth) | |
propagateNaN( | |
control, | |
isNaNA, | |
signA, | |
sigA[(sigWidth - 2):0], | |
isNaNB, | |
signB, | |
sigB[(sigWidth - 2):0], | |
signNaN, | |
fractNaN | |
); | |
assign out_sign = out_isNaN ? signNaN : notNaN_signOut; | |
assign out_sig = out_isNaN ? {1'b1, fractNaN, 2'b00} : common_sigOut; | |
`else | |
assign out_isNaN = isNaNA || isNaNB; | |
assign out_sign = notNaN_signOut; | |
assign out_sig = common_sigOut; | |
`endif | |
endmodule | |
/*---------------------------------------------------------------------------- | |
*----------------------------------------------------------------------------*/ | |
module | |
mulRecFN#(parameter expWidth = 3, parameter sigWidth = 3) ( | |
input [(`floatControlWidth - 1):0] control, | |
input [(expWidth + sigWidth):0] a, | |
input [(expWidth + sigWidth):0] b, | |
input [2:0] roundingMode, | |
output [(expWidth + sigWidth):0] out, | |
output [4:0] exceptionFlags | |
); | |
wire invalidExc, out_isNaN, out_isInf, out_isZero, out_sign; | |
wire signed [(expWidth + 1):0] out_sExp; | |
wire [(sigWidth + 2):0] out_sig; | |
mulRecFNToRaw#(expWidth, sigWidth) | |
mulRecFNToRaw( | |
control, | |
a, | |
b, | |
invalidExc, | |
out_isNaN, | |
out_isInf, | |
out_isZero, | |
out_sign, | |
out_sExp, | |
out_sig | |
); | |
roundRawFNToRecFN#(expWidth, sigWidth, 0) | |
roundRawOut( | |
control, | |
invalidExc, | |
1'b0, | |
out_isNaN, | |
out_isInf, | |
out_isZero, | |
out_sign, | |
out_sExp, | |
out_sig, | |
roundingMode, | |
out, | |
exceptionFlags | |
); | |
endmodule | |