unpack.sv cleanup

This commit is contained in:
Katherine Parry 2022-03-23 01:53:37 +00:00
parent e3d01c875b
commit 23adb2dd03
2 changed files with 280 additions and 168 deletions

View File

@ -175,7 +175,7 @@ module fpu (
// unpack unit
// - splits FP inputs into their various parts
// - does some classifications (SNaN, NaN, Denorm, Norm, Zero, Infifnity)
unpack unpack (.X(FSrcXE), .Y(FSrcYE), .Z(FSrcZE), .FOpCtrlE, .FmtE,
unpack unpack (.X(FSrcXE), .Y(FSrcYE), .Z(FSrcZE), .FmtE,
.XSgnE, .YSgnE, .ZSgnE, .XExpE, .YExpE, .ZExpE, .XManE, .YManE, .ZManE,
.XNaNE, .YNaNE, .ZNaNE, .XSNaNE, .YSNaNE, .ZSNaNE, .XDenormE, .YDenormE, .ZDenormE,
.XZeroE, .YZeroE, .ZZeroE, .XInfE, .YInfE, .ZInfE, .XExpMaxE, .XNormE);

View File

@ -1,58 +1,83 @@
`include "wally-config.vh"
module unpack (
input logic [`FLEN-1:0] X, Y, Z,
input logic [`FPSIZES/3:0] FmtE,
input logic [2:0] FOpCtrlE,
output logic XSgnE, YSgnE, ZSgnE,
output logic [`NE-1:0] XExpE, YExpE, ZExpE,
output logic [`NF:0] XManE, YManE, ZManE,
output logic XNormE,
output logic XNaNE, YNaNE, ZNaNE,
output logic XSNaNE, YSNaNE, ZSNaNE,
output logic XDenormE, YDenormE, ZDenormE,
output logic XZeroE, YZeroE, ZZeroE,
output logic XInfE, YInfE, ZInfE,
output logic XExpMaxE
input logic [`FLEN-1:0] X, Y, Z, // inputs from register file
input logic [`FPSIZES/3:0] FmtE, // format signal 00 - single 10 - double 11 - quad 10 - half
output logic XSgnE, YSgnE, ZSgnE, // sign bits of XYZ
output logic [`NE-1:0] XExpE, YExpE, ZExpE, // exponents of XYZ (converted to largest supported precision)
output logic [`NF:0] XManE, YManE, ZManE, // mantissas of XYZ (converted to largest supported precision)
output logic XNormE, // is X a normalized number
output logic XNaNE, YNaNE, ZNaNE, // is XYZ a NaN
output logic XSNaNE, YSNaNE, ZSNaNE, // is XYZ a signaling NaN
output logic XDenormE, YDenormE, ZDenormE, // is XYZ denormalized
output logic XZeroE, YZeroE, ZZeroE, // is XYZ zero
output logic XInfE, YInfE, ZInfE, // is XYZ infinity
output logic XExpMaxE // does X have the maximum exponent (NaN or Inf)
);
logic [`NF-1:0] XFracE, YFracE, ZFracE;
logic XExpNonzero, YExpNonzero, ZExpNonzero;
logic XFracZero, YFracZero, ZFracZero; // input fraction zero
logic XExpZero, YExpZero, ZExpZero; // input exponent zero
logic YExpMaxE, ZExpMaxE; // input exponent all 1s
logic [`NF-1:0] XFracE, YFracE, ZFracE; //Fraction of XYZ
logic XExpNonzero, YExpNonzero, ZExpNonzero; // is the exponent of XYZ non-zero
logic XFracZero, YFracZero, ZFracZero; // is the fraction zero
logic XExpZero, YExpZero, ZExpZero; // is the exponent zero
logic YExpMaxE, ZExpMaxE; // is the exponent all 1s
if (`FPSIZES == 1) begin
if (`FPSIZES == 1) begin // if there is only one floating point format supported
// sign bit
assign XSgnE = X[`FLEN-1];
assign YSgnE = Y[`FLEN-1];
assign ZSgnE = Z[`FLEN-1];
// exponent
assign XExpE = X[`FLEN-2:`NF];
assign YExpE = Y[`FLEN-2:`NF];
assign ZExpE = Z[`FLEN-2:`NF];
// fraction (no assumed 1)
assign XFracE = X[`NF-1:0];
assign YFracE = Y[`NF-1:0];
assign ZFracE = Z[`NF-1:0];
// is the exponent non-zero
assign XExpNonzero = |XExpE;
assign YExpNonzero = |YExpE;
assign ZExpNonzero = |ZExpE;
// is the exponent all 1's
assign XExpMaxE = &XExpE;
assign YExpMaxE = &YExpE;
assign ZExpMaxE = &ZExpE;
end else if (`FPSIZES == 2) begin
end else if (`FPSIZES == 2) begin // if there are 2 floating point formats supported
logic [`LEN1-1:0] XLen1, YLen1, ZLen1; // Bottom half or NaN, if not properly NaN boxed
//***need better names for these constants
// largest format | smaller format
//----------------------------------
// `FLEN | `LEN1 length of floating point number
// `NE | `NE1 length of exponent
// `NF | `NF1 length of fraction
// `BIAS | `BIAS1 exponent's bias value
// `FMT | `FMT1 precision's format value - Q=11 D=01 S=00 H=10
// Possible combinantions specified by spec:
// double and single
// single and half
// Not needed but can also handle:
// quad and double
// quad and single
// quad and half
// double and half
logic [`LEN1-1:0] XLen1, YLen1, ZLen1; // Remove NaN boxing or NaN, if not properly NaN boxed
// Check NaN boxing, If the value is not properly NaN boxed, set the value to a quiet NaN
assign XLen1 = &X[`FLEN-1:`LEN1] ? X[`LEN1-1:0] : {1'b0, {`NE1+1{1'b1}}, (`NF1-1)'(0)};
assign YLen1 = &Y[`FLEN-1:`LEN1] ? Y[`LEN1-1:0] : {1'b0, {`NE1+1{1'b1}}, (`NF1-1)'(0)};
assign ZLen1 = &Z[`FLEN-1:`LEN1] ? Z[`LEN1-1:0] : {1'b0, {`NE1+1{1'b1}}, (`NF1-1)'(0)};
// choose sign bit depending on format - 1=larger precsion 0=smaller precision
assign XSgnE = FmtE ? X[`FLEN-1] : XLen1[`LEN1-1];
assign YSgnE = FmtE ? Y[`FLEN-1] : YLen1[`LEN1-1];
assign ZSgnE = FmtE ? Z[`FLEN-1] : ZLen1[`LEN1-1];
@ -64,63 +89,94 @@ module unpack (
// sexp = 0000 bbbb bbbb (add this) b = bit d = ~b
// dexp = 0bdd dbbb bbbb
// also need to take into account possible zero/denorm/inf/NaN values
// extract the exponent, converting the smaller exponent into the larger precision if nessisary
assign XExpE = FmtE ? X[`FLEN-2:`NF] : {XLen1[`LEN1-2], {`NE-`NE1{~XLen1[`LEN1-2]&~XExpZero|XExpMaxE}}, XLen1[`LEN1-3:`NF1]};
assign YExpE = FmtE ? Y[`FLEN-2:`NF] : {YLen1[`LEN1-2], {`NE-`NE1{~YLen1[`LEN1-2]&~YExpZero|YExpMaxE}}, YLen1[`LEN1-3:`NF1]};
assign ZExpE = FmtE ? Z[`FLEN-2:`NF] : {ZLen1[`LEN1-2], {`NE-`NE1{~ZLen1[`LEN1-2]&~ZExpZero|ZExpMaxE}}, ZLen1[`LEN1-3:`NF1]};
// extract the fraction, add trailing zeroes to the mantissa if nessisary
assign XFracE = FmtE ? X[`NF-1:0] : {XLen1[`NF1-1:0], (`NF-`NF1)'(0)};
assign YFracE = FmtE ? Y[`NF-1:0] : {YLen1[`NF1-1:0], (`NF-`NF1)'(0)};
assign ZFracE = FmtE ? Z[`NF-1:0] : {ZLen1[`NF1-1:0], (`NF-`NF1)'(0)};
// is the exponent non-zero
assign XExpNonzero = FmtE ? |X[`FLEN-2:`NF] : |XLen1[`LEN1-2:`NF1];
assign YExpNonzero = FmtE ? |Y[`FLEN-2:`NF] : |YLen1[`LEN1-2:`NF1];
assign ZExpNonzero = FmtE ? |Z[`FLEN-2:`NF] : |ZLen1[`LEN1-2:`NF1];
// is the exponent all 1's
assign XExpMaxE = FmtE ? &X[`FLEN-2:`NF] : &XLen1[`LEN1-2:`NF1];
assign YExpMaxE = FmtE ? &Y[`FLEN-2:`NF] : &YLen1[`LEN1-2:`NF1];
assign ZExpMaxE = FmtE ? &Z[`FLEN-2:`NF] : &ZLen1[`LEN1-2:`NF1];
end else if (`FPSIZES == 3) begin
logic [`LEN1-1:0] XLen1, YLen1, ZLen1; // Bottom half or NaN, if not properly NaN boxed
logic [`LEN2-1:0] XLen2, YLen2, ZLen2; // Bottom half or NaN, if not properly NaN boxed
end else if (`FPSIZES == 3) begin // three floating point precsions supported
//***need better names for these constants
// largest format | larger format | smallest format
//---------------------------------------------------
// `FLEN | `LEN1 | `LEN2 length of floating point number
// `NE | `NE1 | `NE2 length of exponent
// `NF | `NF1 | `NF2 length of fraction
// `BIAS | `BIAS1 | `BIAS2 exponent's bias value
// `FMT | `FMT1 | `FMT2 precision's format value - Q=11 D=01 S=00 H=10
// Possible combinantions specified by spec:
// quad and double and single
// double and single and half
// Not needed but can also handle:
// quad and double and half
// quad and single and half
logic [`LEN1-1:0] XLen1, YLen1, ZLen1; // Remove NaN boxing or NaN, if not properly NaN boxed for larger percision
logic [`LEN2-1:0] XLen2, YLen2, ZLen2; // Remove NaN boxing or NaN, if not properly NaN boxed for smallest precision
// Check NaN boxing, If the value is not properly NaN boxed, set the value to a quiet NaN
// Check NaN boxing, If the value is not properly NaN boxed, set the value to a quiet NaN - for larger precision
assign XLen1 = &X[`FLEN-1:`LEN1] ? X[`LEN1-1:0] : {1'b0, {`NE1+1{1'b1}}, (`NF1-1)'(0)};
assign YLen1 = &Y[`FLEN-1:`LEN1] ? Y[`LEN1-1:0] : {1'b0, {`NE1+1{1'b1}}, (`NF1-1)'(0)};
assign ZLen1 = &Z[`FLEN-1:`LEN1] ? Z[`LEN1-1:0] : {1'b0, {`NE1+1{1'b1}}, (`NF1-1)'(0)};
// Check NaN boxing, If the value is not properly NaN boxed, set the value to a quiet NaN - for smaller precision
assign XLen2 = &X[`FLEN-1:`LEN2] ? X[`LEN2-1:0] : {1'b0, {`NE2+1{1'b1}}, (`NF2-1)'(0)};
assign YLen2 = &Y[`FLEN-1:`LEN2] ? Y[`LEN2-1:0] : {1'b0, {`NE2+1{1'b1}}, (`NF2-1)'(0)};
assign ZLen2 = &Z[`FLEN-1:`LEN2] ? Z[`LEN2-1:0] : {1'b0, {`NE2+1{1'b1}}, (`NF2-1)'(0)};
always_comb begin
case (FmtE)
`FMT: begin
assign XSgnE = X[`FLEN-1];
assign YSgnE = Y[`FLEN-1];
assign ZSgnE = Z[`FLEN-1];
`FMT: begin // if input is largest precision (`FLEN - ie quad or double)
// extract the sign bit
XSgnE = X[`FLEN-1];
YSgnE = Y[`FLEN-1];
ZSgnE = Z[`FLEN-1];
assign XExpE = X[`FLEN-2:`NF];
assign YExpE = Y[`FLEN-2:`NF];
assign ZExpE = Z[`FLEN-2:`NF];
// extract the exponent
XExpE = X[`FLEN-2:`NF];
YExpE = Y[`FLEN-2:`NF];
ZExpE = Z[`FLEN-2:`NF];
assign XFracE = X[`NF-1:0];
assign YFracE = Y[`NF-1:0];
assign ZFracE = Z[`NF-1:0];
// extract the fraction
XFracE = X[`NF-1:0];
YFracE = Y[`NF-1:0];
ZFracE = Z[`NF-1:0];
assign XExpNonzero = |X[`FLEN-2:`NF];
assign YExpNonzero = |Y[`FLEN-2:`NF];
assign ZExpNonzero = |Z[`FLEN-2:`NF];
// is the exponent non-zero
XExpNonzero = |X[`FLEN-2:`NF];
YExpNonzero = |Y[`FLEN-2:`NF];
ZExpNonzero = |Z[`FLEN-2:`NF];
assign XExpMaxE = &X[`FLEN-2:`NF];
assign YExpMaxE = &Y[`FLEN-2:`NF];
assign ZExpMaxE = &Z[`FLEN-2:`NF];
// is the exponent all 1's
XExpMaxE = &X[`FLEN-2:`NF];
YExpMaxE = &Y[`FLEN-2:`NF];
ZExpMaxE = &Z[`FLEN-2:`NF];
end
`FMT1: begin
assign XSgnE = XLen1[`LEN1-1];
assign YSgnE = YLen1[`LEN1-1];
assign ZSgnE = ZLen1[`LEN1-1];
`FMT1: begin // if input is larger precsion (`LEN1 - double or single)
// extract the sign bit
XSgnE = XLen1[`LEN1-1];
YSgnE = YLen1[`LEN1-1];
ZSgnE = ZLen1[`LEN1-1];
// example double to single conversion:
// 1023 = 0011 1111 1111
@ -129,26 +185,33 @@ module unpack (
// sexp = 0000 bbbb bbbb (add this) b = bit d = ~b
// dexp = 0bdd dbbb bbbb
// also need to take into account possible zero/denorm/inf/NaN values
assign XExpE = {XLen1[`LEN1-2], {`NE-`NE1{~XLen1[`LEN1-2]&~XExpZero|XExpMaxE}}, XLen1[`LEN1-3:`NF1]};
assign YExpE = {YLen1[`LEN1-2], {`NE-`NE1{~YLen1[`LEN1-2]&~YExpZero|YExpMaxE}}, YLen1[`LEN1-3:`NF1]};
assign ZExpE = {ZLen1[`LEN1-2], {`NE-`NE1{~ZLen1[`LEN1-2]&~ZExpZero|ZExpMaxE}}, ZLen1[`LEN1-3:`NF1]};
assign XFracE = {XLen1[`NF1-1:0], (`NF-`NF1)'(0)};
assign YFracE = {YLen1[`NF1-1:0], (`NF-`NF1)'(0)};
assign ZFracE = {ZLen1[`NF1-1:0], (`NF-`NF1)'(0)};
// convert the larger precision's exponent to use the largest precision's bias
XExpE = {XLen1[`LEN1-2], {`NE-`NE1{~XLen1[`LEN1-2]&~XExpZero|XExpMaxE}}, XLen1[`LEN1-3:`NF1]};
YExpE = {YLen1[`LEN1-2], {`NE-`NE1{~YLen1[`LEN1-2]&~YExpZero|YExpMaxE}}, YLen1[`LEN1-3:`NF1]};
ZExpE = {ZLen1[`LEN1-2], {`NE-`NE1{~ZLen1[`LEN1-2]&~ZExpZero|ZExpMaxE}}, ZLen1[`LEN1-3:`NF1]};
assign XExpNonzero = |XLen1[`LEN1-2:`NF1];
assign YExpNonzero = |YLen1[`LEN1-2:`NF1];
assign ZExpNonzero = |ZLen1[`LEN1-2:`NF1];
// extract the fraction and add the nessesary trailing zeros
XFracE = {XLen1[`NF1-1:0], (`NF-`NF1)'(0)};
YFracE = {YLen1[`NF1-1:0], (`NF-`NF1)'(0)};
ZFracE = {ZLen1[`NF1-1:0], (`NF-`NF1)'(0)};
assign XExpMaxE = &XLen1[`LEN1-2:`NF1];
assign YExpMaxE = &YLen1[`LEN1-2:`NF1];
assign ZExpMaxE = &ZLen1[`LEN1-2:`NF1];
// is the exponent non-zero
XExpNonzero = |XLen1[`LEN1-2:`NF1];
YExpNonzero = |YLen1[`LEN1-2:`NF1];
ZExpNonzero = |ZLen1[`LEN1-2:`NF1];
// is the exponent all 1's
XExpMaxE = &XLen1[`LEN1-2:`NF1];
YExpMaxE = &YLen1[`LEN1-2:`NF1];
ZExpMaxE = &ZLen1[`LEN1-2:`NF1];
end
`FMT2: begin
assign XSgnE = XLen2[`LEN2-1];
assign YSgnE = YLen2[`LEN2-1];
assign ZSgnE = ZLen2[`LEN2-1];
`FMT2: begin // if input is smallest precsion (`LEN2 - single or half)
// exctract the sign bit
XSgnE = XLen2[`LEN2-1];
YSgnE = YLen2[`LEN2-1];
ZSgnE = ZLen2[`LEN2-1];
// example double to single conversion:
// 1023 = 0011 1111 1111
@ -157,87 +220,110 @@ module unpack (
// sexp = 0000 bbbb bbbb (add this) b = bit d = ~b
// dexp = 0bdd dbbb bbbb
// also need to take into account possible zero/denorm/inf/NaN values
assign XExpE = {XLen2[`LEN2-2], {`NE-`NE2{~XLen2[`LEN2-2]&~XExpZero|XExpMaxE}}, XLen2[`LEN2-3:`NF2]};
assign YExpE = {YLen2[`LEN2-2], {`NE-`NE2{~YLen2[`LEN2-2]&~YExpZero|YExpMaxE}}, YLen2[`LEN2-3:`NF2]};
assign ZExpE = {ZLen2[`LEN2-2], {`NE-`NE2{~ZLen2[`LEN2-2]&~ZExpZero|ZExpMaxE}}, ZLen2[`LEN2-3:`NF2]};
// convert the smallest precision's exponent to use the largest precision's bias
XExpE = {XLen2[`LEN2-2], {`NE-`NE2{~XLen2[`LEN2-2]&~XExpZero|XExpMaxE}}, XLen2[`LEN2-3:`NF2]};
YExpE = {YLen2[`LEN2-2], {`NE-`NE2{~YLen2[`LEN2-2]&~YExpZero|YExpMaxE}}, YLen2[`LEN2-3:`NF2]};
ZExpE = {ZLen2[`LEN2-2], {`NE-`NE2{~ZLen2[`LEN2-2]&~ZExpZero|ZExpMaxE}}, ZLen2[`LEN2-3:`NF2]};
assign XFracE = {XLen2[`NF2-1:0], (`NF-`NF2)'(0)};
assign YFracE = {YLen2[`NF2-1:0], (`NF-`NF2)'(0)};
assign ZFracE = {ZLen2[`NF2-1:0], (`NF-`NF2)'(0)};
// extract the fraction and add the nessesary trailing zeros
XFracE = {XLen2[`NF2-1:0], (`NF-`NF2)'(0)};
YFracE = {YLen2[`NF2-1:0], (`NF-`NF2)'(0)};
ZFracE = {ZLen2[`NF2-1:0], (`NF-`NF2)'(0)};
assign XExpNonzero = |XLen2[`LEN2-2:`NF2];
assign YExpNonzero = |YLen2[`LEN2-2:`NF2];
assign ZExpNonzero = |ZLen2[`LEN2-2:`NF2];
// is the exponent non-zero
XExpNonzero = |XLen2[`LEN2-2:`NF2];
YExpNonzero = |YLen2[`LEN2-2:`NF2];
ZExpNonzero = |ZLen2[`LEN2-2:`NF2];
assign XExpMaxE = &XLen2[`LEN2-2:`NF2];
assign YExpMaxE = &YLen2[`LEN2-2:`NF2];
assign ZExpMaxE = &ZLen2[`LEN2-2:`NF2];
// is the exponent all 1's
XExpMaxE = &XLen2[`LEN2-2:`NF2];
YExpMaxE = &YLen2[`LEN2-2:`NF2];
ZExpMaxE = &ZLen2[`LEN2-2:`NF2];
end
default: begin
assign XSgnE = 0;
assign YSgnE = 0;
assign ZSgnE = 0;
assign XExpE = 0;
assign YExpE = 0;
assign ZExpE = 0;
assign XFracE = 0;
assign YFracE = 0;
assign ZFracE = 0;
assign XExpNonzero = 0;
assign YExpNonzero = 0;
assign ZExpNonzero = 0;
assign XExpMaxE = 0;
assign YExpMaxE = 0;
assign ZExpMaxE = 0;
XSgnE = 0;
YSgnE = 0;
ZSgnE = 0;
XExpE = 0;
YExpE = 0;
ZExpE = 0;
XFracE = 0;
YFracE = 0;
ZFracE = 0;
XExpNonzero = 0;
YExpNonzero = 0;
ZExpNonzero = 0;
XExpMaxE = 0;
YExpMaxE = 0;
ZExpMaxE = 0;
end
endcase
end
end else begin
logic [`LEN1-1:0] XLen1, YLen1, ZLen1; // Bottom half or NaN, if not properly NaN boxed
logic [`LEN2-1:0] XLen2, YLen2, ZLen2; // Bottom half or NaN, if not properly NaN boxed
logic [`LEN2-1:0] XLen3, YLen3, ZLen3; // Bottom half or NaN, if not properly NaN boxed
end else begin // if all precsisons are supported - quad, double, single, and half
// quad | double | single | half
//-------------------------------------------------------------------
// `Q_LEN | `D_LEN | `S_LEN | `H_LEN length of floating point number
// `Q_NE | `D_NE | `S_NE | `H_NE length of exponent
// `Q_NF | `D_NF | `S_NF | `H_NF length of fraction
// `Q_BIAS | `D_BIAS | `S_BIAS | `H_BIAS exponent's bias value
// `Q_FMT | `D_FMT | `S_FMT | `H_FMT precision's format value - Q=11 D=01 S=00 H=10
logic [`LEN1-1:0] XLen1, YLen1, ZLen1; // Remove NaN boxing or NaN, if not properly NaN boxed for double percision
logic [`LEN2-1:0] XLen2, YLen2, ZLen2; // Remove NaN boxing or NaN, if not properly NaN boxed for single percision
logic [`LEN2-1:0] XLen3, YLen3, ZLen3; // Remove NaN boxing or NaN, if not properly NaN boxed for half percision
// Check NaN boxing, If the value is not properly NaN boxed, set the value to a quiet NaN
assign XLen1 = &X[`FLEN-1:`D_LEN] ? X[`D_LEN-1:0] : {1'b0, {`D_NE+1{1'b1}}, (`D_NF-1)'(0)};
assign YLen1 = &Y[`FLEN-1:`D_LEN] ? Y[`D_LEN-1:0] : {1'b0, {`D_NE+1{1'b1}}, (`D_NF-1)'(0)};
assign ZLen1 = &Z[`FLEN-1:`D_LEN] ? Z[`D_LEN-1:0] : {1'b0, {`D_NE+1{1'b1}}, (`D_NF-1)'(0)};
// Check NaN boxing, If the value is not properly NaN boxed, set the value to a quiet NaN - for double precision
assign XLen1 = &X[`Q_LEN-1:`D_LEN] ? X[`D_LEN-1:0] : {1'b0, {`D_NE+1{1'b1}}, (`D_NF-1)'(0)};
assign YLen1 = &Y[`Q_LEN-1:`D_LEN] ? Y[`D_LEN-1:0] : {1'b0, {`D_NE+1{1'b1}}, (`D_NF-1)'(0)};
assign ZLen1 = &Z[`Q_LEN-1:`D_LEN] ? Z[`D_LEN-1:0] : {1'b0, {`D_NE+1{1'b1}}, (`D_NF-1)'(0)};
assign XLen2 = &X[`FLEN-1:`S_LEN] ? X[`S_LEN-1:0] : {1'b0, {`S_NE+1{1'b1}}, (`S_NF-1)'(0)};
assign YLen2 = &Y[`FLEN-1:`S_LEN] ? Y[`S_LEN-1:0] : {1'b0, {`S_NE+1{1'b1}}, (`S_NF-1)'(0)};
assign ZLen2 = &Z[`FLEN-1:`S_LEN] ? Z[`S_LEN-1:0] : {1'b0, {`S_NE+1{1'b1}}, (`S_NF-1)'(0)};
// Check NaN boxing, If the value is not properly NaN boxed, set the value to a quiet NaN - for single precision
assign XLen2 = &X[`Q_LEN-1:`S_LEN] ? X[`S_LEN-1:0] : {1'b0, {`S_NE+1{1'b1}}, (`S_NF-1)'(0)};
assign YLen2 = &Y[`Q_LEN-1:`S_LEN] ? Y[`S_LEN-1:0] : {1'b0, {`S_NE+1{1'b1}}, (`S_NF-1)'(0)};
assign ZLen2 = &Z[`Q_LEN-1:`S_LEN] ? Z[`S_LEN-1:0] : {1'b0, {`S_NE+1{1'b1}}, (`S_NF-1)'(0)};
assign XLen3 = &X[`FLEN-1:`H_LEN] ? X[`H_LEN-1:0] : {1'b0, {`H_NE+1{1'b1}}, (`H_NF-1)'(0)};
assign YLen3 = &Y[`FLEN-1:`H_LEN] ? Y[`H_LEN-1:0] : {1'b0, {`H_NE+1{1'b1}}, (`H_NF-1)'(0)};
assign ZLen3 = &Z[`FLEN-1:`H_LEN] ? Z[`H_LEN-1:0] : {1'b0, {`H_NE+1{1'b1}}, (`H_NF-1)'(0)};
// Check NaN boxing, If the value is not properly NaN boxed, set the value to a quiet NaN - for half precision
assign XLen3 = &X[`Q_LEN-1:`H_LEN] ? X[`H_LEN-1:0] : {1'b0, {`H_NE+1{1'b1}}, (`H_NF-1)'(0)};
assign YLen3 = &Y[`Q_LEN-1:`H_LEN] ? Y[`H_LEN-1:0] : {1'b0, {`H_NE+1{1'b1}}, (`H_NF-1)'(0)};
assign ZLen3 = &Z[`Q_LEN-1:`H_LEN] ? Z[`H_LEN-1:0] : {1'b0, {`H_NE+1{1'b1}}, (`H_NF-1)'(0)};
always_comb begin
case (FmtE)
2'b11: begin
assign XSgnE = X[`FLEN-1];
assign YSgnE = Y[`FLEN-1];
assign ZSgnE = Z[`FLEN-1];
`Q_BIAS: begin // if input is quad percision
// extract sign bit
XSgnE = X[`Q_LEN-1];
YSgnE = Y[`Q_LEN-1];
ZSgnE = Z[`Q_LEN-1];
assign XExpE = X[`FLEN-2:`NF];
assign YExpE = Y[`FLEN-2:`NF];
assign ZExpE = Z[`FLEN-2:`NF];
// extract the exponent
XExpE = X[`Q_LEN-2:`Q_NF];
YExpE = Y[`Q_LEN-2:`Q_NF];
ZExpE = Z[`Q_LEN-2:`Q_NF];
assign XFracE = X[`NF-1:0];
assign YFracE = Y[`NF-1:0];
assign ZFracE = Z[`NF-1:0];
// extract the fraction
XFracE = X[`Q_NF-1:0];
YFracE = Y[`Q_NF-1:0];
ZFracE = Z[`Q_NF-1:0];
assign XExpNonzero = |X[`FLEN-2:`NF];
assign YExpNonzero = |Y[`FLEN-2:`NF];
assign ZExpNonzero = |Z[`FLEN-2:`NF];
// is the exponent non-zero
XExpNonzero = |X[`Q_LEN-2:`Q_NF];
YExpNonzero = |Y[`Q_LEN-2:`Q_NF];
ZExpNonzero = |Z[`Q_LEN-2:`Q_NF];
assign XExpMaxE = &X[`FLEN-2:`NF];
assign YExpMaxE = &Y[`FLEN-2:`NF];
assign ZExpMaxE = &Z[`FLEN-2:`NF];
// is the exponent all 1's
XExpMaxE = &X[`Q_LEN-2:`Q_NF];
YExpMaxE = &Y[`Q_LEN-2:`Q_NF];
ZExpMaxE = &Z[`Q_LEN-2:`Q_NF];
end
2'b01: begin
assign XSgnE = XLen1[`LEN1-1];
assign YSgnE = YLen1[`LEN1-1];
assign ZSgnE = ZLen1[`LEN1-1];
`D_BIAS: begin // if input is double percision
// extract sign bit
XSgnE = XLen1[`D_LEN-1];
YSgnE = YLen1[`D_LEN-1];
ZSgnE = ZLen1[`D_LEN-1];
// example double to single conversion:
// 1023 = 0011 1111 1111
@ -246,26 +332,32 @@ module unpack (
// sexp = 0000 bbbb bbbb (add this) b = bit d = ~b
// dexp = 0bdd dbbb bbbb
// also need to take into account possible zero/denorm/inf/NaN values
assign XExpE = {XLen1[`D_LEN-2], {`NE-`D_NE{~XLen1[`D_LEN-2]&~XExpZero|XExpMaxE}}, XLen1[`D_LEN-3:`D_NF]};
assign YExpE = {YLen1[`D_LEN-2], {`NE-`D_NE{~YLen1[`D_LEN-2]&~YExpZero|YExpMaxE}}, YLen1[`D_LEN-3:`D_NF]};
assign ZExpE = {ZLen1[`D_LEN-2], {`NE-`D_NE{~ZLen1[`D_LEN-2]&~ZExpZero|ZExpMaxE}}, ZLen1[`D_LEN-3:`D_NF]};
// convert the double precsion exponent into quad precsion
XExpE = {XLen1[`D_LEN-2], {`Q_NE-`D_NE{~XLen1[`D_LEN-2]&~XExpZero|XExpMaxE}}, XLen1[`D_LEN-3:`D_NF]};
YExpE = {YLen1[`D_LEN-2], {`Q_NE-`D_NE{~YLen1[`D_LEN-2]&~YExpZero|YExpMaxE}}, YLen1[`D_LEN-3:`D_NF]};
ZExpE = {ZLen1[`D_LEN-2], {`Q_NE-`D_NE{~ZLen1[`D_LEN-2]&~ZExpZero|ZExpMaxE}}, ZLen1[`D_LEN-3:`D_NF]};
assign XFracE = {XLen1[`D_NE-1:0], (`NF-`D_NE)'(0)};
assign YFracE = {YLen1[`D_NE-1:0], (`NF-`D_NE)'(0)};
assign ZFracE = {ZLen1[`D_NE-1:0], (`NF-`D_NE)'(0)};
// extract the fraction and add the nessesary trailing zeros
XFracE = {XLen1[`D_NE-1:0], (`Q_NF-`D_NE)'(0)};
YFracE = {YLen1[`D_NE-1:0], (`Q_NF-`D_NE)'(0)};
ZFracE = {ZLen1[`D_NE-1:0], (`Q_NF-`D_NE)'(0)};
assign XExpNonzero = |XLen1[`D_LEN-2:`D_NE];
assign YExpNonzero = |YLen1[`D_LEN-2:`D_NE];
assign ZExpNonzero = |ZLen1[`D_LEN-2:`D_NE];
// is the exponent non-zero
XExpNonzero = |XLen1[`D_LEN-2:`D_NE];
YExpNonzero = |YLen1[`D_LEN-2:`D_NE];
ZExpNonzero = |ZLen1[`D_LEN-2:`D_NE];
assign XExpMaxE = &XLen1[`D_LEN-2:`D_NE];
assign YExpMaxE = &YLen1[`D_LEN-2:`D_NE];
assign ZExpMaxE = &ZLen1[`D_LEN-2:`D_NE];
// is the exponent all 1's
XExpMaxE = &XLen1[`D_LEN-2:`D_NE];
YExpMaxE = &YLen1[`D_LEN-2:`D_NE];
ZExpMaxE = &ZLen1[`D_LEN-2:`D_NE];
end
2'b00: begin
assign XSgnE = XLen2[`S_LEN-1];
assign YSgnE = YLen2[`S_LEN-1];
assign ZSgnE = ZLen2[`S_LEN-1];
`S_BIAS: begin // if input is single percision
// extract sign bit
XSgnE = XLen2[`S_LEN-1];
YSgnE = YLen2[`S_LEN-1];
ZSgnE = ZLen2[`S_LEN-1];
// example double to single conversion:
// 1023 = 0011 1111 1111
@ -274,26 +366,32 @@ module unpack (
// sexp = 0000 bbbb bbbb (add this) b = bit d = ~b
// dexp = 0bdd dbbb bbbb
// also need to take into account possible zero/denorm/inf/NaN values
assign XExpE = {XLen2[`S_LEN-2], {`NE-`S_NE{~XLen2[`S_LEN-2]&~XExpZero|XExpMaxE}}, XLen2[`S_LEN-3:`S_NF]};
assign YExpE = {YLen2[`S_LEN-2], {`NE-`S_NE{~YLen2[`S_LEN-2]&~YExpZero|YExpMaxE}}, YLen2[`S_LEN-3:`S_NF]};
assign ZExpE = {ZLen2[`S_LEN-2], {`NE-`S_NE{~ZLen2[`S_LEN-2]&~ZExpZero|ZExpMaxE}}, ZLen2[`S_LEN-3:`S_NF]};
// convert the single precsion exponent into quad precsion
XExpE = {XLen2[`S_LEN-2], {`Q_NE-`S_NE{~XLen2[`S_LEN-2]&~XExpZero|XExpMaxE}}, XLen2[`S_LEN-3:`S_NF]};
YExpE = {YLen2[`S_LEN-2], {`Q_NE-`S_NE{~YLen2[`S_LEN-2]&~YExpZero|YExpMaxE}}, YLen2[`S_LEN-3:`S_NF]};
ZExpE = {ZLen2[`S_LEN-2], {`Q_NE-`S_NE{~ZLen2[`S_LEN-2]&~ZExpZero|ZExpMaxE}}, ZLen2[`S_LEN-3:`S_NF]};
assign XFracE = {XLen2[`S_NF-1:0], (`NF-`S_NF)'(0)};
assign YFracE = {YLen2[`S_NF-1:0], (`NF-`S_NF)'(0)};
assign ZFracE = {ZLen2[`S_NF-1:0], (`NF-`S_NF)'(0)};
// extract the fraction and add the nessesary trailing zeros
XFracE = {XLen2[`S_NF-1:0], (`Q_NF-`S_NF)'(0)};
YFracE = {YLen2[`S_NF-1:0], (`Q_NF-`S_NF)'(0)};
ZFracE = {ZLen2[`S_NF-1:0], (`Q_NF-`S_NF)'(0)};
assign XExpNonzero = |XLen2[`S_LEN-2:`S_NF];
assign YExpNonzero = |YLen2[`S_LEN-2:`S_NF];
assign ZExpNonzero = |ZLen2[`S_LEN-2:`S_NF];
// is the exponent non-zero
XExpNonzero = |XLen2[`S_LEN-2:`S_NF];
YExpNonzero = |YLen2[`S_LEN-2:`S_NF];
ZExpNonzero = |ZLen2[`S_LEN-2:`S_NF];
assign XExpMaxE = &XLen2[`S_LEN-2:`S_NF];
assign YExpMaxE = &YLen2[`S_LEN-2:`S_NF];
assign ZExpMaxE = &ZLen2[`S_LEN-2:`S_NF];
// is the exponent all 1's
XExpMaxE = &XLen2[`S_LEN-2:`S_NF];
YExpMaxE = &YLen2[`S_LEN-2:`S_NF];
ZExpMaxE = &ZLen2[`S_LEN-2:`S_NF];
end
2'b10: begin
assign XSgnE = XLen3[`H_LEN-1];
assign YSgnE = YLen3[`H_LEN-1];
assign ZSgnE = ZLen3[`H_LEN-1];
`H_BIAS: begin // if input is half percision
// extract sign bit
XSgnE = XLen3[`H_LEN-1];
YSgnE = YLen3[`H_LEN-1];
ZSgnE = ZLen3[`H_LEN-1];
// example double to single conversion:
// 1023 = 0011 1111 1111
@ -302,58 +400,72 @@ module unpack (
// sexp = 0000 bbbb bbbb (add this) b = bit d = ~b
// dexp = 0bdd dbbb bbbb
// also need to take into account possible zero/denorm/inf/NaN values
assign XExpE = {XLen3[`H_LEN-2], {`NE-`H_NE{~XLen3[`H_LEN-2]&~XExpZero|XExpMaxE}}, XLen3[`H_LEN-3:`H_NF]};
assign YExpE = {YLen3[`H_LEN-2], {`NE-`H_NE{~YLen3[`H_LEN-2]&~YExpZero|YExpMaxE}}, YLen3[`H_LEN-3:`H_NF]};
assign ZExpE = {ZLen3[`H_LEN-2], {`NE-`H_NE{~ZLen3[`H_LEN-2]&~ZExpZero|ZExpMaxE}}, ZLen3[`H_LEN-3:`H_NF]};
// convert the half precsion exponent into quad precsion
XExpE = {XLen3[`H_LEN-2], {`Q_NE-`H_NE{~XLen3[`H_LEN-2]&~XExpZero|XExpMaxE}}, XLen3[`H_LEN-3:`H_NF]};
YExpE = {YLen3[`H_LEN-2], {`Q_NE-`H_NE{~YLen3[`H_LEN-2]&~YExpZero|YExpMaxE}}, YLen3[`H_LEN-3:`H_NF]};
ZExpE = {ZLen3[`H_LEN-2], {`Q_NE-`H_NE{~ZLen3[`H_LEN-2]&~ZExpZero|ZExpMaxE}}, ZLen3[`H_LEN-3:`H_NF]};
assign XFracE = {XLen3[`H_NF-1:0], (`NF-`H_NF)'(0)};
assign YFracE = {YLen3[`H_NF-1:0], (`NF-`H_NF)'(0)};
assign ZFracE = {ZLen3[`H_NF-1:0], (`NF-`H_NF)'(0)};
// extract the fraction and add the nessesary trailing zeros
XFracE = {XLen3[`H_NF-1:0], (`Q_NF-`H_NF)'(0)};
YFracE = {YLen3[`H_NF-1:0], (`Q_NF-`H_NF)'(0)};
ZFracE = {ZLen3[`H_NF-1:0], (`Q_NF-`H_NF)'(0)};
assign XExpNonzero = |XLen3[`H_LEN-2:`H_NF];
assign YExpNonzero = |YLen3[`H_LEN-2:`H_NF];
assign ZExpNonzero = |ZLen3[`H_LEN-2:`H_NF];
// is the exponent non-zero
XExpNonzero = |XLen3[`H_LEN-2:`H_NF];
YExpNonzero = |YLen3[`H_LEN-2:`H_NF];
ZExpNonzero = |ZLen3[`H_LEN-2:`H_NF];
assign XExpMaxE = &XLen3[`H_LEN-2:`H_NF];
assign YExpMaxE = &YLen3[`H_LEN-2:`H_NF];
assign ZExpMaxE = &ZLen3[`H_LEN-2:`H_NF];
// is the exponent all 1's
XExpMaxE = &XLen3[`H_LEN-2:`H_NF];
YExpMaxE = &YLen3[`H_LEN-2:`H_NF];
ZExpMaxE = &ZLen3[`H_LEN-2:`H_NF];
end
endcase
end
end
// is the exponent all 0's
assign XExpZero = ~XExpNonzero;
assign YExpZero = ~YExpNonzero;
assign ZExpZero = ~ZExpNonzero;
// is the fraction zero
assign XFracZero = ~|XFracE;
assign YFracZero = ~|YFracE;
assign ZFracZero = ~|ZFracE;
// add the assumed one (or zero if denormal or zero) to create the mantissa
assign XManE = {XExpNonzero, XFracE};
assign YManE = {YExpNonzero, YFracE};
assign ZManE = {ZExpNonzero, ZFracE};
// is X normalized
assign XNormE = ~(XExpMaxE|XExpZero);
// force single precision input to be a NaN if it isn't properly Nan Boxed
// is the input a NaN
// - force to be a NaN if it isn't properly Nan Boxed
assign XNaNE = XExpMaxE & ~XFracZero;
assign YNaNE = YExpMaxE & ~YFracZero;
assign ZNaNE = ZExpMaxE & ~ZFracZero;
// is the input a singnaling NaN
assign XSNaNE = XNaNE&~XFracE[`NF-1];
assign YSNaNE = YNaNE&~YFracE[`NF-1];
assign ZSNaNE = ZNaNE&~ZFracE[`NF-1];
// is the input denormalized
assign XDenormE = XExpZero & ~XFracZero;
assign YDenormE = YExpZero & ~YFracZero;
assign ZDenormE = ZExpZero & ~ZFracZero;
// is the input infinity
assign XInfE = XExpMaxE & XFracZero;
assign YInfE = YExpMaxE & YFracZero;
assign ZInfE = ZExpMaxE & ZFracZero;
// is the input zero
assign XZeroE = XExpZero & XFracZero;
assign YZeroE = YExpZero & YFracZero;
assign ZZeroE = ZExpZero & ZFracZero;