From 4ed7933aa3de3821b4829d50d5cff2f0cbe1c954 Mon Sep 17 00:00:00 2001 From: Katherine Parry Date: Tue, 31 May 2022 16:18:50 +0000 Subject: [PATCH] added unpackinput.sv --- addins/riscv-arch-test | 2 +- pipelined/regression/sim-fp-batch | 2 +- pipelined/src/fpu/fcvt.sv | 14 +- pipelined/src/fpu/unpack.sv | 538 +----------------------------- pipelined/src/fpu/unpackinput.sv | 402 ++++++++++++++++++++++ pipelined/src/generic/lzc.sv | 6 +- 6 files changed, 424 insertions(+), 540 deletions(-) create mode 100644 pipelined/src/fpu/unpackinput.sv diff --git a/addins/riscv-arch-test b/addins/riscv-arch-test index 307c77b26..be67c99bd 160000 --- a/addins/riscv-arch-test +++ b/addins/riscv-arch-test @@ -1 +1 @@ -Subproject commit 307c77b26e070ae85ffea665ad9b642b40e33c86 +Subproject commit be67c99bd461742aa1c100bcc0732657faae2230 diff --git a/pipelined/regression/sim-fp-batch b/pipelined/regression/sim-fp-batch index 7e2c6a341..ca0ba3d38 100755 --- a/pipelined/regression/sim-fp-batch +++ b/pipelined/regression/sim-fp-batch @@ -7,4 +7,4 @@ # sqrt - test square root # all - test everything -vsim -c -do "do fp.do rv64fp fma" \ No newline at end of file +vsim -c -do "do fp.do rv64fp cvtfp" \ No newline at end of file diff --git a/pipelined/src/fpu/fcvt.sv b/pipelined/src/fpu/fcvt.sv index bebd0ef1d..227b0098e 100644 --- a/pipelined/src/fpu/fcvt.sv +++ b/pipelined/src/fpu/fcvt.sv @@ -42,7 +42,7 @@ module fcvt ( logic [`XLEN-1:0] TrimInt; // integer trimmed to the correct size logic [`LGLEN-1:0] LzcIn; // input to the Leading Zero Counter (priority encoder) logic [`NE:0] CalcExp; // the calculated expoent - logic [$clog2(`LGLEN)-1:0] ShiftAmt; // how much to shift by + logic [$clog2(`LGLEN+1)-1:0] ShiftAmt; // how much to shift by logic [`LGLEN+`NF:0] ShiftIn; // number to be shifted logic ResDenormUf;// does the result underflow or is denormalized logic ResUf; // does the result underflow @@ -72,7 +72,7 @@ module fcvt ( logic Int64; // is the integer 64 bits? logic IntToFp; // is the opperation an int->fp conversion? logic ToInt; // is the opperation an fp->int conversion? - logic [$clog2(`LGLEN)-1:0] ZeroCnt; // output from the LZC + logic [$clog2(`LGLEN+1)-1:0] ZeroCnt; // output from the LZC // seperate OpCtrl for code readability @@ -143,9 +143,9 @@ module fcvt ( // - only shift fp -> fp if the intital value is denormalized // - this is a problem because the input to the lzc was the fraction rather than the mantissa // - rather have a few and-gates than an extra bit in the priority encoder??? *** is this true? - assign ShiftAmt = ToInt ? CalcExp[$clog2(`LGLEN)-1:0]&{$clog2(`LGLEN){~CalcExp[`NE]}} : - ResDenormUf&~IntToFp ? ($clog2(`LGLEN))'(`NF-1)+CalcExp[$clog2(`LGLEN)-1:0] : - (ZeroCnt+1)&{$clog2(`LGLEN){XDenormE|IntToFp}}; + assign ShiftAmt = ToInt ? CalcExp[$clog2(`LGLEN+1)-1:0]&{$clog2(`LGLEN+1){~CalcExp[`NE]}} : + ResDenormUf&~IntToFp ? ($clog2(`LGLEN+1))'(`NF-1)+CalcExp[$clog2(`LGLEN+1)-1:0] : + (ZeroCnt+1)&{$clog2(`LGLEN+1){XDenormE|IntToFp}}; // shift // fp -> int: | `XLEN zeros | Mantissa | 0's if nessisary | << CalcExp @@ -255,13 +255,13 @@ module fcvt ( // | keep | // // - if the input is denormalized then we dont shift... so the "- (ZeroCnt+1)" is just leftovers from other options - // int -> fp : largest bias XLEN - Largest bias + new bias - 1 - ZeroCnt = XLEN + NewBias - 1 - ZeroCnt + // int -> fp : largest bias + XLEN - Largest bias + new bias - 1 - ZeroCnt = XLEN + NewBias - 1 - ZeroCnt // Process: // - shifted right by XLEN (XLEN) // - shift left to normilize (-1-ZeroCnt) // - newBias to make the biased exponent // - assign CalcExp = {1'b0, OldExp} - (`NE+1)'(`BIAS) + {2'b0, NewBias} - {{`NE{1'b0}}, XDenormE|IntToFp} - {{`NE-$clog2(`LGLEN)+1{1'b0}}, (ZeroCnt&{$clog2(`LGLEN){XDenormE|IntToFp}})}; + assign CalcExp = {1'b0, OldExp} - (`NE+1)'(`BIAS) + {2'b0, NewBias} - {{`NE{1'b0}}, XDenormE|IntToFp} - {{`NE-$clog2(`LGLEN+1)+1{1'b0}}, (ZeroCnt&{$clog2(`LGLEN+1){XDenormE|IntToFp}})}; // find if the result is dnormal or underflows // - if Calculated expoenent is 0 or negitive (and the input/result is not exactaly 0) // - can't underflow an integer to Fp conversion diff --git a/pipelined/src/fpu/unpack.sv b/pipelined/src/fpu/unpack.sv index a10d1f8ca..9e691e27f 100644 --- a/pipelined/src/fpu/unpack.sv +++ b/pipelined/src/fpu/unpack.sv @@ -21,538 +21,20 @@ module unpack ( logic XExpZero, YExpZero, ZExpZero; // is the exponent zero logic YExpMaxE, ZExpMaxE; // is the exponent all 1s - if (`FPSIZES == 1) begin // if there is only one floating point format supported + unpackinput unpackinputX (.In(X), .FmtE, .Sgn(XSgnE), .Exp(XExpE), .Man(XManE), + .NaN(XNaNE), .SNaN(XSNaNE), .Denorm(XDenormE), + .Zero(XZeroE), .Inf(XInfE), .ExpMax(XExpMaxE), .ExpZero(XExpZero)); - // sign bit - assign XSgnE = X[`FLEN-1]; - assign YSgnE = Y[`FLEN-1]; - assign ZSgnE = Z[`FLEN-1]; + unpackinput unpackinputY (.In(Y), .FmtE, .Sgn(YSgnE), .Exp(YExpE), .Man(YManE), + .NaN(YNaNE), .SNaN(YSNaNE), .Denorm(YDenormE), + .Zero(YZeroE), .Inf(YInfE), .ExpMax(YExpMaxE), .ExpZero(YExpZero)); - // exponent - assign XExpE = {X[`FLEN-2:`NF+1], X[`NF]|XDenormE}; - assign YExpE = {Y[`FLEN-2:`NF+1], Y[`NF]|YDenormE}; - assign ZExpE = {Z[`FLEN-2:`NF+1], Z[`NF]|ZDenormE}; - - // 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; - - - // is the input (in it's original format) denormalized - assign XDenormE = ~|X[`FLEN-2:`NF] & ~XFracZero; - assign YDenormE = ~|Y[`FLEN-2:`NF] & ~YFracZero; - assign ZDenormE = ~|Z[`FLEN-2:`NF] & ~ZFracZero; - - - end else if (`FPSIZES == 2) begin // if there are 2 floating point formats supported - //***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]; - - // example double to single conversion: - // 1023 = 0011 1111 1111 - // 127 = 0000 0111 1111 (subtract this) - // 896 = 0011 1000 0000 - // 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 - // - if the original precision had a denormal number convert the exponent value 1 - assign XExpE = FmtE ? {X[`FLEN-2:`NF+1], X[`NF]|XDenormE} : {XLen1[`LEN1-2], {`NE-`NE1{~XLen1[`LEN1-2]}}, XLen1[`LEN1-3:`NF1+1], XLen1[`NF1]|XDenormE}; - assign YExpE = FmtE ? {Y[`FLEN-2:`NF+1], Y[`NF]|YDenormE} : {YLen1[`LEN1-2], {`NE-`NE1{~YLen1[`LEN1-2]}}, YLen1[`LEN1-3:`NF1+1], YLen1[`NF1]|YDenormE}; - assign ZExpE = FmtE ? {Z[`FLEN-2:`NF+1], Z[`NF]|ZDenormE} : {ZLen1[`LEN1-2], {`NE-`NE1{~ZLen1[`LEN1-2]}}, ZLen1[`LEN1-3:`NF1+1], ZLen1[`NF1]|ZDenormE}; - - // is the input (in it's original format) denormalized - - // is the input (in it's original format) denormalized - assign XDenormE = (FmtE ? ~|X[`FLEN-2:`NF] : ~|XLen1[`LEN1-2:`NF1]) & ~XFracZero; - assign YDenormE = (FmtE ? ~|Y[`FLEN-2:`NF] : ~|YLen1[`LEN1-2:`NF1]) & ~YFracZero; - assign ZDenormE = (FmtE ? ~|Z[`FLEN-2:`NF] : ~|ZLen1[`LEN1-2:`NF1]) & ~ZFracZero; - - // 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 // 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 - 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)}; - - // There are 2 case statements - // - one for other singals and one for sgn/exp/frac - // - need two for the dependencies in the expoenent calculation - //*** pull out the ~FracZero and and it at the end - always_comb begin - case (FmtE) - `FMT: begin // if input is largest precision (`FLEN - ie quad or double) - - // This is the original format so set OrigDenorm to 0 - XDenormE = ~|X[`FLEN-2:`NF] & ~XFracZero; - YDenormE = ~|Y[`FLEN-2:`NF] & ~YFracZero; - ZDenormE = ~|Z[`FLEN-2:`NF] & ~ZFracZero; - - // is the exponent non-zero - XExpNonzero = |X[`FLEN-2:`NF]; - YExpNonzero = |Y[`FLEN-2:`NF]; - ZExpNonzero = |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 // if input is larger precsion (`LEN1 - double or single) - - // is the input (in it's original format) denormalized - XDenormE = ~|XLen1[`LEN1-2:`NF1] & ~XFracZero; - YDenormE = ~|YLen1[`LEN1-2:`NF1] & ~YFracZero; - ZDenormE = ~|ZLen1[`LEN1-2:`NF1] & ~ZFracZero; - - // 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 // if input is smallest precsion (`LEN2 - single or half) - - // is the input (in it's original format) denormalized - XDenormE = ~|XLen2[`LEN2-2:`NF2] & ~XFracZero; - YDenormE = ~|YLen2[`LEN2-2:`NF2] & ~YFracZero; - ZDenormE = ~|ZLen2[`LEN2-2:`NF2] & ~ZFracZero; - - // is the exponent non-zero - XExpNonzero = |XLen2[`LEN2-2:`NF2]; - YExpNonzero = |YLen2[`LEN2-2:`NF2]; - ZExpNonzero = |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 - XDenormE = 0; - YDenormE = 0; - ZDenormE = 0; - XExpNonzero = 0; - YExpNonzero = 0; - ZExpNonzero = 0; - XExpMaxE = 0; - YExpMaxE = 0; - ZExpMaxE = 0; - end - endcase - end - always_comb begin - case (FmtE) - `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]; - - // extract the exponent - XExpE = {X[`FLEN-2:`NF+1], X[`NF]|XDenormE}; - YExpE = {Y[`FLEN-2:`NF+1], Y[`NF]|YDenormE}; - ZExpE = {Z[`FLEN-2:`NF+1], Z[`NF]|ZDenormE}; - - // extract the fraction - XFracE = X[`NF-1:0]; - YFracE = Y[`NF-1:0]; - ZFracE = Z[`NF-1:0]; - end - `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 - // 127 = 0000 0111 1111 (subtract this) - // 896 = 0011 1000 0000 - // 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 - - // convert the larger precision's exponent to use the largest precision's bias - XExpE = {XLen1[`LEN1-2], {`NE-`NE1{~XLen1[`LEN1-2]}}, XLen1[`LEN1-3:`NF1+1], XLen1[`NF1]|XDenormE}; - YExpE = {YLen1[`LEN1-2], {`NE-`NE1{~YLen1[`LEN1-2]}}, YLen1[`LEN1-3:`NF1+1], YLen1[`NF1]|YDenormE}; - ZExpE = {ZLen1[`LEN1-2], {`NE-`NE1{~ZLen1[`LEN1-2]}}, ZLen1[`LEN1-3:`NF1+1], ZLen1[`NF1]|ZDenormE}; - - // 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)}; - end - `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 - // 127 = 0000 0111 1111 (subtract this) - // 896 = 0011 1000 0000 - // 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 - - // convert the smallest precision's exponent to use the largest precision's bias - XExpE = XDenormE ? {1'b0, {`NE-`NE2{1'b1}}, (`NE2-1)'(1)} : {XLen2[`LEN2-2], {`NE-`NE2{~XLen2[`LEN2-2]}}, XLen2[`LEN2-3:`NF2]}; - YExpE = YDenormE ? {1'b0, {`NE-`NE2{1'b1}}, (`NE2-1)'(1)} : {YLen2[`LEN2-2], {`NE-`NE2{~YLen2[`LEN2-2]}}, YLen2[`LEN2-3:`NF2]}; - ZExpE = ZDenormE ? {1'b0, {`NE-`NE2{1'b1}}, (`NE2-1)'(1)} : {ZLen2[`LEN2-2], {`NE-`NE2{~ZLen2[`LEN2-2]}}, ZLen2[`LEN2-3:`NF2]}; - - // 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)}; - end - default: begin - XSgnE = 0; - YSgnE = 0; - ZSgnE = 0; - XExpE = 0; - YExpE = 0; - ZExpE = 0; - XFracE = 0; - YFracE = 0; - ZFracE = 0; - end - endcase - end - - end else if (`FPSIZES == 4) 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 [`D_LEN-1:0] XLen1, YLen1, ZLen1; // Remove NaN boxing or NaN, if not properly NaN boxed for double percision - logic [`S_LEN-1:0] XLen2, YLen2, ZLen2; // Remove NaN boxing or NaN, if not properly NaN boxed for single percision - logic [`H_LEN-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 - 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)}; - - // 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)}; - - // 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)}; - - - // There are 2 case statements - // - one for other singals and one for sgn/exp/frac - // - need two for the dependencies in the expoenent calculation - always_comb begin - case (FmtE) - 2'b11: begin // if input is quad percision - - // is the input (in it's original format) denormalized - XDenormE = ~|X[`Q_LEN-2:`Q_NF] & ~XFracZero; - YDenormE = ~|Y[`Q_LEN-2:`Q_NF] & ~YFracZero; - ZDenormE = ~|Z[`Q_LEN-2:`Q_NF] & ~ZFracZero; - - // 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]; - - // 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 // if input is double percision - - // is the exponent all 1's - XExpMaxE = &XLen1[`D_LEN-2:`D_NF]; - YExpMaxE = &YLen1[`D_LEN-2:`D_NF]; - ZExpMaxE = &ZLen1[`D_LEN-2:`D_NF]; - - // is the input (in it's original format) denormalized - XDenormE = ~|XLen1[`D_LEN-2:`D_NF] & ~XFracZero; - YDenormE = ~|YLen1[`D_LEN-2:`D_NF] & ~YFracZero; - ZDenormE = ~|ZLen1[`D_LEN-2:`D_NF] & ~ZFracZero; - - // is the exponent non-zero - XExpNonzero = |XLen1[`D_LEN-2:`D_NF]; - YExpNonzero = |YLen1[`D_LEN-2:`D_NF]; - ZExpNonzero = |ZLen1[`D_LEN-2:`D_NF]; - end - 2'b00: begin // if input is single percision - - // 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]; - - // is the input (in it's original format) denormalized - XDenormE = ~|XLen2[`S_LEN-2:`S_NF] & ~XFracZero; - YDenormE = ~|YLen2[`S_LEN-2:`S_NF] & ~YFracZero; - ZDenormE = ~|ZLen2[`S_LEN-2:`S_NF] & ~ZFracZero; - - // 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]; - end - 2'b10: begin // if input is half percision - - // 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]; - - // is the input (in it's original format) denormalized - XDenormE = ~|XLen3[`H_LEN-2:`H_NF] & ~XFracZero; - YDenormE = ~|YLen3[`H_LEN-2:`H_NF] & ~YFracZero; - ZDenormE = ~|ZLen3[`H_LEN-2:`H_NF] & ~ZFracZero; - - // 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]; - end - endcase - end - - always_comb begin - case (FmtE) - 2'b11: begin // if input is quad percision - // extract sign bit - XSgnE = X[`Q_LEN-1]; - YSgnE = Y[`Q_LEN-1]; - ZSgnE = Z[`Q_LEN-1]; - - // extract the exponent - XExpE = {X[`Q_LEN-2:`Q_NF+1], X[`Q_NF]|XDenormE}; - YExpE = {Y[`Q_LEN-2:`Q_NF+1], Y[`Q_NF]|YDenormE}; - ZExpE = {Z[`Q_LEN-2:`Q_NF+1], Z[`Q_NF]|ZDenormE}; - - // extract the fraction - XFracE = X[`Q_NF-1:0]; - YFracE = Y[`Q_NF-1:0]; - ZFracE = Z[`Q_NF-1:0]; - end - 2'b01: 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 - // 127 = 0000 0111 1111 (subtract this) - // 896 = 0011 1000 0000 - // 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 - - // convert the double precsion exponent into quad precsion - - XExpE = {XLen1[`D_LEN-2], {`Q_NE-`D_NE{~XLen1[`D_LEN-2]}}, XLen1[`D_LEN-3:`D_NF+1], XLen1[`D_NF]|XDenormE}; - YExpE = {YLen1[`D_LEN-2], {`Q_NE-`D_NE{~YLen1[`D_LEN-2]}}, YLen1[`D_LEN-3:`D_NF+1], YLen1[`D_NF]|YDenormE}; - ZExpE = {ZLen1[`D_LEN-2], {`Q_NE-`D_NE{~ZLen1[`D_LEN-2]}}, ZLen1[`D_LEN-3:`D_NF+1], ZLen1[`D_NF]|ZDenormE}; - - // extract the fraction and add the nessesary trailing zeros - XFracE = {XLen1[`D_NF-1:0], (`Q_NF-`D_NF)'(0)}; - YFracE = {YLen1[`D_NF-1:0], (`Q_NF-`D_NF)'(0)}; - ZFracE = {ZLen1[`D_NF-1:0], (`Q_NF-`D_NF)'(0)}; - end - 2'b00: 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 - // 127 = 0000 0111 1111 (subtract this) - // 896 = 0011 1000 0000 - // 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 - - // convert the single precsion exponent into quad precsion - XExpE = {XLen2[`S_LEN-2], {`Q_NE-`S_NE{~XLen2[`S_LEN-2]}}, XLen2[`S_LEN-3:`S_NF+1], XLen2[`S_NF]|XDenormE}; - YExpE = {YLen2[`S_LEN-2], {`Q_NE-`S_NE{~YLen2[`S_LEN-2]}}, YLen2[`S_LEN-3:`S_NF+1], YLen2[`S_NF]|YDenormE}; - ZExpE = {ZLen2[`S_LEN-2], {`Q_NE-`S_NE{~ZLen2[`S_LEN-2]}}, ZLen2[`S_LEN-3:`S_NF+1], ZLen2[`S_NF]|ZDenormE}; - - // 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)}; - end - 2'b10: 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 - // 127 = 0000 0111 1111 (subtract this) - // 896 = 0011 1000 0000 - // 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 - - // convert the half precsion exponent into quad precsion - XExpE = {XLen3[`H_LEN-2], {`Q_NE-`H_NE{~XLen3[`H_LEN-2]}}, XLen3[`H_LEN-3:`H_NF+1], XLen3[`H_NF]|XDenormE}; - YExpE = {YLen3[`H_LEN-2], {`Q_NE-`H_NE{~YLen3[`H_LEN-2]}}, YLen3[`H_LEN-3:`H_NF+1], YLen3[`H_NF]|YDenormE}; - ZExpE = {ZLen3[`H_LEN-2], {`Q_NE-`H_NE{~ZLen3[`H_LEN-2]}}, ZLen3[`H_LEN-3:`H_NF+1], ZLen3[`H_NF]|ZDenormE}; - - // 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)}; - 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}; + unpackinput unpackinputZ (.In(Z), .FmtE, .Sgn(ZSgnE), .Exp(ZExpE), .Man(ZManE), + .NaN(ZNaNE), .SNaN(ZSNaNE), .Denorm(ZDenormE), + .Zero(ZZeroE), .Inf(ZInfE), .ExpMax(ZExpMaxE), .ExpZero(ZExpZero)); + // is X normalized assign XNormE = ~(XExpMaxE|XExpZero); - // 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; - endmodule \ No newline at end of file diff --git a/pipelined/src/fpu/unpackinput.sv b/pipelined/src/fpu/unpackinput.sv new file mode 100644 index 000000000..e8bd22fbf --- /dev/null +++ b/pipelined/src/fpu/unpackinput.sv @@ -0,0 +1,402 @@ +`include "wally-config.vh" + +module unpackinput ( + input logic [`FLEN-1:0] In, // inputs from register file + input logic [`FPSIZES/3:0] FmtE, // format signal 00 - single 01 - double 11 - quad 10 - half + output logic Sgn, // sign bits of XYZ + output logic [`NE-1:0] Exp, // exponents of XYZ (converted to largest supported precision) + output logic [`NF:0] Man, // mantissas of XYZ (converted to largest supported precision) + output logic NaN, // is XYZ a NaN + output logic SNaN, // is XYZ a signaling NaN + output logic Denorm, // is XYZ denormalized + output logic Zero, // is XYZ zero + output logic Inf, // is XYZ infinity + output logic ExpMax, // does In have the maximum exponent (NaN or Inf) + output logic ExpZero // is the exponent zero +); + + logic [`NF-1:0] Frac; //Fraction of XYZ + logic ExpNonZero; // is the exponent of XYZ non-zero + logic FracZero; // is the fraction zero + + if (`FPSIZES == 1) begin // if there is only one floating point format supported + + // sign bit + assign Sgn = In[`FLEN-1]; + + // exponent + assign Exp = {In[`FLEN-2:`NF+1], In[`NF]|Denorm}; + + // fraction (no assumed 1) + assign Frac = In[`NF-1:0]; + + // is the exponent non-zero + assign ExpNonZero = |Exp; + + // is the exponent all 1's + assign ExpMax = &Exp; + + + // is the input (in it's original format) denormalized + assign Denorm = ~|In[`FLEN-2:`NF] & ~FracZero; + + + end else if (`FPSIZES == 2) begin // if there are 2 floating point formats supported + //***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] Len1; // 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 Len1 = &In[`FLEN-1:`LEN1] ? In[`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 Sgn = FmtE ? In[`FLEN-1] : Len1[`LEN1-1]; + + // example double to single conversion: + // 1023 = 0011 1111 1111 + // 127 = 0000 0111 1111 (subtract this) + // 896 = 0011 1000 0000 + // 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 + // - if the original precision had a denormal number convert the exponent value 1 + assign Exp = FmtE ? {In[`FLEN-2:`NF+1], In[`NF]|Denorm} : {Len1[`LEN1-2], {`NE-`NE1{~Len1[`LEN1-2]}}, Len1[`LEN1-3:`NF1+1], Len1[`NF1]|Denorm}; + + // is the input (in it's original format) denormalized + + // is the input (in it's original format) denormalized + assign Denorm = (FmtE ? ~|In[`FLEN-2:`NF] : ~|Len1[`LEN1-2:`NF1]) & ~FracZero; + + // extract the fraction, add trailing zeroes to the mantissa if nessisary + assign Frac = FmtE ? In[`NF-1:0] : {Len1[`NF1-1:0], (`NF-`NF1)'(0)}; + + // is the exponent non-zero + assign ExpNonZero = FmtE ? |In[`FLEN-2:`NF] : |Len1[`LEN1-2:`NF1]; + + // is the exponent all 1's + assign ExpMax = FmtE ? &In[`FLEN-2:`NF] : &Len1[`LEN1-2:`NF1]; + + + 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] Len1; // Remove NaN boxing or NaN, if not properly NaN boxed for larger percision + logic [`LEN2-1:0] Len2; // 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 - for larger precision + assign Len1 = &In[`FLEN-1:`LEN1] ? In[`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 Len2 = &In[`FLEN-1:`LEN2] ? In[`LEN2-1:0] : {1'b0, {`NE2+1{1'b1}}, (`NF2-1)'(0)}; + + // There are 2 case statements + // - one for other singals and one for sgn/exp/frac + // - need two for the dependencies in the expoenent calculation + //*** pull out the ~FracZero and and it at the end + always_comb begin + case (FmtE) + `FMT: begin // if input is largest precision (`FLEN - ie quad or double) + + // This is the original format so set OrigDenorm to 0 + Denorm = ~|In[`FLEN-2:`NF] & ~FracZero; + + // is the exponent non-zero + ExpNonZero = |In[`FLEN-2:`NF]; + + // is the exponent all 1's + ExpMax = &In[`FLEN-2:`NF]; + end + `FMT1: begin // if input is larger precsion (`LEN1 - double or single) + + // is the input (in it's original format) denormalized + Denorm = ~|Len1[`LEN1-2:`NF1] & ~FracZero; + + // is the exponent non-zero + ExpNonZero = |Len1[`LEN1-2:`NF1]; + + // is the exponent all 1's + ExpMax = &Len1[`LEN1-2:`NF1]; + end + `FMT2: begin // if input is smallest precsion (`LEN2 - single or half) + + // is the input (in it's original format) denormalized + Denorm = ~|Len2[`LEN2-2:`NF2] & ~FracZero; + + // is the exponent non-zero + ExpNonZero = |Len2[`LEN2-2:`NF2]; + + // is the exponent all 1's + ExpMax = &Len2[`LEN2-2:`NF2]; + end + default: begin + Denorm = 0; + ExpNonZero = 0; + ExpMax = 0; + end + endcase + end + always_comb begin + case (FmtE) + `FMT: begin // if input is largest precision (`FLEN - ie quad or double) + // extract the sign bit + Sgn = In[`FLEN-1]; + + // extract the exponent + Exp = {In[`FLEN-2:`NF+1], In[`NF]|Denorm}; + + // extract the fraction + Frac = In[`NF-1:0]; + end + `FMT1: begin // if input is larger precsion (`LEN1 - double or single) + + // extract the sign bit + Sgn = Len1[`LEN1-1]; + + // example double to single conversion: + // 1023 = 0011 1111 1111 + // 127 = 0000 0111 1111 (subtract this) + // 896 = 0011 1000 0000 + // 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 + + // convert the larger precision's exponent to use the largest precision's bias + Exp = {Len1[`LEN1-2], {`NE-`NE1{~Len1[`LEN1-2]}}, Len1[`LEN1-3:`NF1+1], Len1[`NF1]|Denorm}; + + // extract the fraction and add the nessesary trailing zeros + Frac = {Len1[`NF1-1:0], (`NF-`NF1)'(0)}; + end + `FMT2: begin // if input is smallest precsion (`LEN2 - single or half) + + // exctract the sign bit + Sgn = Len2[`LEN2-1]; + + // example double to single conversion: + // 1023 = 0011 1111 1111 + // 127 = 0000 0111 1111 (subtract this) + // 896 = 0011 1000 0000 + // 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 + + // convert the smallest precision's exponent to use the largest precision's bias + Exp = Denorm ? {1'b0, {`NE-`NE2{1'b1}}, (`NE2-1)'(1)} : {Len2[`LEN2-2], {`NE-`NE2{~Len2[`LEN2-2]}}, Len2[`LEN2-3:`NF2]}; + + // extract the fraction and add the nessesary trailing zeros + Frac = {Len2[`NF2-1:0], (`NF-`NF2)'(0)}; + end + default: begin + Sgn = 0; + Exp = 0; + Frac = 0; + end + endcase + end + + end else if (`FPSIZES == 4) 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 [`D_LEN-1:0] Len1; // Remove NaN boxing or NaN, if not properly NaN boxed for double percision + logic [`S_LEN-1:0] Len2; // Remove NaN boxing or NaN, if not properly NaN boxed for single percision + logic [`H_LEN-1:0] Len3; // 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 - for double precision + assign Len1 = &In[`Q_LEN-1:`D_LEN] ? In[`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 single precision + assign Len2 = &In[`Q_LEN-1:`S_LEN] ? In[`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 half precision + assign Len3 = &In[`Q_LEN-1:`H_LEN] ? In[`H_LEN-1:0] : {1'b0, {`H_NE+1{1'b1}}, (`H_NF-1)'(0)}; + + + // There are 2 case statements + // - one for other singals and one for sgn/exp/frac + // - need two for the dependencies in the expoenent calculation + always_comb begin + case (FmtE) + 2'b11: begin // if input is quad percision + + // is the input (in it's original format) denormalized + Denorm = ~|In[`Q_LEN-2:`Q_NF] & ~FracZero; + + // is the exponent non-zero + ExpNonZero = |In[`Q_LEN-2:`Q_NF]; + + // is the exponent all 1's + ExpMax = &In[`Q_LEN-2:`Q_NF]; + end + 2'b01: begin // if input is double percision + + // is the exponent all 1's + ExpMax = &Len1[`D_LEN-2:`D_NF]; + + // is the input (in it's original format) denormalized + Denorm = ~|Len1[`D_LEN-2:`D_NF] & ~FracZero; + + // is the exponent non-zero + ExpNonZero = |Len1[`D_LEN-2:`D_NF]; + end + 2'b00: begin // if input is single percision + + // is the exponent all 1's + ExpMax = &Len2[`S_LEN-2:`S_NF]; + + // is the input (in it's original format) denormalized + Denorm = ~|Len2[`S_LEN-2:`S_NF] & ~FracZero; + + // is the exponent non-zero + ExpNonZero = |Len2[`S_LEN-2:`S_NF]; + end + 2'b10: begin // if input is half percision + + // is the exponent all 1's + ExpMax = &Len3[`H_LEN-2:`H_NF]; + + // is the input (in it's original format) denormalized + Denorm = ~|Len3[`H_LEN-2:`H_NF] & ~FracZero; + + // is the exponent non-zero + ExpNonZero = |Len3[`H_LEN-2:`H_NF]; + end + endcase + end + + always_comb begin + case (FmtE) + 2'b11: begin // if input is quad percision + // extract sign bit + Sgn = In[`Q_LEN-1]; + + // extract the exponent + Exp = {In[`Q_LEN-2:`Q_NF+1], In[`Q_NF]|Denorm}; + + // extract the fraction + Frac = In[`Q_NF-1:0]; + end + 2'b01: begin // if input is double percision + // extract sign bit + Sgn = Len1[`D_LEN-1]; + + // example double to single conversion: + // 1023 = 0011 1111 1111 + // 127 = 0000 0111 1111 (subtract this) + // 896 = 0011 1000 0000 + // 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 + + // convert the double precsion exponent into quad precsion + + Exp = {Len1[`D_LEN-2], {`Q_NE-`D_NE{~Len1[`D_LEN-2]}}, Len1[`D_LEN-3:`D_NF+1], Len1[`D_NF]|Denorm}; + + // extract the fraction and add the nessesary trailing zeros + Frac = {Len1[`D_NF-1:0], (`Q_NF-`D_NF)'(0)}; + end + 2'b00: begin // if input is single percision + // extract sign bit + Sgn = Len2[`S_LEN-1]; + + // example double to single conversion: + // 1023 = 0011 1111 1111 + // 127 = 0000 0111 1111 (subtract this) + // 896 = 0011 1000 0000 + // 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 + + // convert the single precsion exponent into quad precsion + Exp = {Len2[`S_LEN-2], {`Q_NE-`S_NE{~Len2[`S_LEN-2]}}, Len2[`S_LEN-3:`S_NF+1], Len2[`S_NF]|Denorm}; + + // extract the fraction and add the nessesary trailing zeros + Frac = {Len2[`S_NF-1:0], (`Q_NF-`S_NF)'(0)}; + end + 2'b10: begin // if input is half percision + // extract sign bit + Sgn = Len3[`H_LEN-1]; + + // example double to single conversion: + // 1023 = 0011 1111 1111 + // 127 = 0000 0111 1111 (subtract this) + // 896 = 0011 1000 0000 + // 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 + + // convert the half precsion exponent into quad precsion + Exp = {Len3[`H_LEN-2], {`Q_NE-`H_NE{~Len3[`H_LEN-2]}}, Len3[`H_LEN-3:`H_NF+1], Len3[`H_NF]|Denorm}; + + // extract the fraction and add the nessesary trailing zeros + Frac = {Len3[`H_NF-1:0], (`Q_NF-`H_NF)'(0)}; + end + endcase + end + + end + + // is the exponent all 0's + assign ExpZero = ~ExpNonZero; + + // is the fraction zero + assign FracZero = ~|Frac; + + // add the assumed one (or zero if denormal or zero) to create the mantissa + assign Man = {ExpNonZero, Frac}; + + // is the input a NaN + // - force to be a NaN if it isn't properly Nan Boxed + assign NaN = ExpMax & ~FracZero; + + // is the input a singnaling NaN + assign SNaN = NaN&~Frac[`NF-1]; + + // is the input infinity + assign Inf = ExpMax & FracZero; + + // is the input zero + assign Zero = ExpZero & FracZero; + +endmodule \ No newline at end of file diff --git a/pipelined/src/generic/lzc.sv b/pipelined/src/generic/lzc.sv index 5b1c22f91..1ce082475 100644 --- a/pipelined/src/generic/lzc.sv +++ b/pipelined/src/generic/lzc.sv @@ -1,14 +1,14 @@ //leading zero counter i.e. priority encoder module lzc #(parameter WIDTH=1) ( input logic [WIDTH-1:0] num, - output logic [$clog2(WIDTH)-1:0] ZeroCnt + output logic [$clog2(WIDTH+1)-1:0] ZeroCnt ); /* verilator lint_off CMPCONST */ - logic [$clog2(WIDTH)-1:0] i; + logic [$clog2(WIDTH+1)-1:0] i; always_comb begin i = 0; - while (~num[WIDTH-1-(32)'(i)] & $unsigned(i) <= $unsigned(($clog2(WIDTH))'(WIDTH-1))) i = i+1; // search for leading one + while (~num[WIDTH-1-(32)'(i)] & $unsigned(i) <= $unsigned(($clog2(WIDTH+1))'(WIDTH-1))) i = i+1; // search for leading one ZeroCnt = i; end /* verilator lint_on CMPCONST */