unpack.sv cleanup

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

View File

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

View File

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