From 23adb2dd03d385cd1d09d19ccec0b4aae0fe791f Mon Sep 17 00:00:00 2001 From: Katherine Parry Date: Wed, 23 Mar 2022 01:53:37 +0000 Subject: [PATCH] unpack.sv cleanup --- pipelined/src/fpu/fpu.sv | 2 +- pipelined/src/fpu/unpack.sv | 446 ++++++++++++++++++++++-------------- 2 files changed, 280 insertions(+), 168 deletions(-) diff --git a/pipelined/src/fpu/fpu.sv b/pipelined/src/fpu/fpu.sv index f9472c9b..2ffcb126 100755 --- a/pipelined/src/fpu/fpu.sv +++ b/pipelined/src/fpu/fpu.sv @@ -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); diff --git a/pipelined/src/fpu/unpack.sv b/pipelined/src/fpu/unpack.sv index 0db63fe9..1625b2fc 100644 --- a/pipelined/src/fpu/unpack.sv +++ b/pipelined/src/fpu/unpack.sv @@ -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;