Parameterized fpu's unpack and fma using Lim's method.

This commit is contained in:
Ross Thompson 2023-05-26 14:12:25 -05:00
parent c7e515634d
commit 81491e85e5
12 changed files with 166 additions and 186 deletions

View File

@ -26,8 +26,6 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module fhazard( module fhazard(
input logic [4:0] Adr1D, Adr2D, Adr3D, // read data adresses input logic [4:0] Adr1D, Adr2D, Adr3D, // read data adresses
input logic [4:0] Adr1E, Adr2E, Adr3E, // read data adresses input logic [4:0] Adr1E, Adr2E, Adr3E, // read data adresses

View File

@ -26,22 +26,20 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module fma import cvw::*; #(parameter cvw_t P) (
module fma(
input logic Xs, Ys, Zs, // input's signs input logic Xs, Ys, Zs, // input's signs
input logic [`NE-1:0] Xe, Ye, Ze, // input's biased exponents in B(NE.0) format input logic [P.NE-1:0] Xe, Ye, Ze, // input's biased exponents in B(NE.0) format
input logic [`NF:0] Xm, Ym, Zm, // input's significands in U(0.NF) format input logic [P.NF:0] Xm, Ym, Zm, // input's significands in U(0.NF) format
input logic XZero, YZero, ZZero, // is the input zero input logic XZero, YZero, ZZero, // is the input zero
input logic [2:0] OpCtrl, // operation control input logic [2:0] OpCtrl, // operation control
output logic ASticky, // sticky bit that is calculated during alignment output logic ASticky, // sticky bit that is calculated during alignment
output logic [3*`NF+3:0] Sm, // the positive sum's significand output logic [3*P.NF+3:0] Sm, // the positive sum's significand
output logic InvA, // Was A inverted for effective subtraction (P-A or -P+A) output logic InvA, // Was A inverted for effective subtraction (P-A or -P+A)
output logic As, // the aligned addend's sign (modified Z sign for other opperations) output logic As, // the aligned addend's sign (modified Z sign for other opperations)
output logic Ps, // the product's sign output logic Ps, // the product's sign
output logic Ss, // the sum's sign output logic Ss, // the sum's sign
output logic [`NE+1:0] Se, // the sum's exponent output logic [P.NE+1:0] Se, // the sum's exponent
output logic [$clog2(3*`NF+5)-1:0] SCnt // normalization shift count output logic [$clog2(3*P.NF+5)-1:0] SCnt // normalization shift count
); );
// OpCtrl: // OpCtrl:
@ -54,12 +52,12 @@ module fma(
// 110 - add // 110 - add
// 111 - sub // 111 - sub
logic [2*`NF+1:0] Pm; // the product's significand in U(2.2Nf) format logic [2*P.NF+1:0] Pm; // the product's significand in U(2.2Nf) format
logic [3*`NF+3:0] Am; // addend aligned's mantissa for addition in U(NF+4.2NF) logic [3*P.NF+3:0] Am; // addend aligned's mantissa for addition in U(NF+4.2NF)
logic [3*`NF+3:0] AmInv; // aligned addend's mantissa possibly inverted logic [3*P.NF+3:0] AmInv; // aligned addend's mantissa possibly inverted
logic [2*`NF+1:0] PmKilled; // the product's mantissa possibly killed U(2.2Nf) logic [2*P.NF+1:0] PmKilled; // the product's mantissa possibly killed U(2.2Nf)
logic KillProd; // set the product to zero before addition if the product is too small to matter logic KillProd; // set the product to zero before addition if the product is too small to matter
logic [`NE+1:0] Pe; // the product's exponent B(NE+2.0) format; adds 2 bits to allow for size of number and negative sign logic [P.NE+1:0] Pe; // the product's exponent B(NE+2.0) format; adds 2 bits to allow for size of number and negative sign
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Calculate the product // Calculate the product
@ -71,10 +69,10 @@ module fma(
// calculate the product's exponent // calculate the product's exponent
fmaexpadd expadd(.Xe, .Ye, .XZero, .YZero, .Pe); fmaexpadd #(P) expadd(.Xe, .Ye, .XZero, .YZero, .Pe);
// multiplication of the mantissa's // multiplication of the mantissa's
fmamult mult(.Xm, .Ym, .Pm); fmamult #(P) mult(.Xm, .Ym, .Pm);
// calculate the signs and take the opperation into account // calculate the signs and take the opperation into account
fmasign sign(.OpCtrl, .Xs, .Ys, .Zs, .Ps, .As, .InvA); fmasign sign(.OpCtrl, .Xs, .Ys, .Zs, .Ps, .As, .InvA);
@ -82,15 +80,15 @@ module fma(
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Alignment shifter // Alignment shifter
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
fmaalign align(.Ze, .Zm, .XZero, .YZero, .ZZero, .Xe, .Ye, .Am, .ASticky, .KillProd); fmaalign #(P) align(.Ze, .Zm, .XZero, .YZero, .ZZero, .Xe, .Ye, .Am, .ASticky, .KillProd);
// /////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////
// // Addition/LZA // // Addition/LZA
// /////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////
fmaadd add(.Am, .Pm, .Ze, .Pe, .Ps, .KillProd, .ASticky, .AmInv, .PmKilled, .InvA, .Sm, .Se, .Ss); fmaadd #(P) add(.Am, .Pm, .Ze, .Pe, .Ps, .KillProd, .ASticky, .AmInv, .PmKilled, .InvA, .Sm, .Se, .Ss);
fmalza #(3*`NF+4) lza(.A(AmInv), .Pm(PmKilled), .Cin(InvA & (~ASticky | KillProd)), .sub(InvA), .SCnt); fmalza #(3*P.NF+4, P.NF) lza(.A(AmInv), .Pm(PmKilled), .Cin(InvA & (~ASticky | KillProd)), .sub(InvA), .SCnt);
endmodule endmodule

View File

@ -26,25 +26,23 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module fmaadd import cvw::*; #(parameter cvw_t P) (
input logic [3*P.NF+3:0] Am, // aligned addend's mantissa for addition in U(NF+5.2NF+1)
module fmaadd( input logic [P.NE-1:0] Ze, // exponent of Z
input logic [3*`NF+3:0] Am, // aligned addend's mantissa for addition in U(NF+5.2NF+1)
input logic [`NE-1:0] Ze, // exponent of Z
input logic Ps, // the product sign and the alligend addeded's sign (Modified Z sign for other opperations) input logic Ps, // the product sign and the alligend addeded's sign (Modified Z sign for other opperations)
input logic [`NE+1:0] Pe, // product's exponet input logic [P.NE+1:0] Pe, // product's exponet
input logic [2*`NF+1:0] Pm, // the product's mantissa input logic [2*P.NF+1:0] Pm, // the product's mantissa
input logic InvA, // invert the aligned addend input logic InvA, // invert the aligned addend
input logic KillProd, // should the product be set to 0 input logic KillProd, // should the product be set to 0
input logic ASticky, // Alighed addend's sticky bit input logic ASticky, // Alighed addend's sticky bit
output logic [3*`NF+3:0] AmInv, // aligned addend possibly inverted output logic [3*P.NF+3:0] AmInv, // aligned addend possibly inverted
output logic [2*`NF+1:0] PmKilled, // the product's mantissa possibly killed output logic [2*P.NF+1:0] PmKilled, // the product's mantissa possibly killed
output logic Ss, // sum's sign output logic Ss, // sum's sign
output logic [`NE+1:0] Se, // sum's exponent output logic [P.NE+1:0] Se, // sum's exponent
output logic [3*`NF+3:0] Sm // the positive sum output logic [3*P.NF+3:0] Sm // the positive sum
); );
logic [3*`NF+3:0] PreSum, NegPreSum; // possibly negitive sum logic [3*P.NF+3:0] PreSum, NegPreSum; // possibly negitive sum
logic NegSum; // was the sum negitive logic NegSum; // was the sum negitive
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -52,9 +50,9 @@ module fmaadd(
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Choose an inverted or non-inverted addend. Put carry into adder/LZA for addition // Choose an inverted or non-inverted addend. Put carry into adder/LZA for addition
assign AmInv = {3*`NF+4{InvA}}^Am; assign AmInv = {3*P.NF+4{InvA}}^Am;
// Kill the product if the product is too small to effect the addition (determined in fma1.sv) // Kill the product if the product is too small to effect the addition (determined in fma1.sv)
assign PmKilled = {2*`NF+2{~KillProd}}&Pm; assign PmKilled = {2*P.NF+2{~KillProd}}&Pm;
// Do the addition // Do the addition
// - calculate a positive and negitive sum in parallel // - calculate a positive and negitive sum in parallel
// if there was a small negitive number killed in the alignment stage one needs to be subtracted from the sum // if there was a small negitive number killed in the alignment stage one needs to be subtracted from the sum
@ -63,8 +61,8 @@ module fmaadd(
// addend - prod where product is killed (and not exactly zero) then don't add +1 from negation // addend - prod where product is killed (and not exactly zero) then don't add +1 from negation
// ie ~(InvA&ASticky&KillProd)&InvA = (~ASticky|~KillProd)&InvA // ie ~(InvA&ASticky&KillProd)&InvA = (~ASticky|~KillProd)&InvA
// in this case this result is only ever selected when InvA=1 so we can remove &InvA // in this case this result is only ever selected when InvA=1 so we can remove &InvA
assign {NegSum, PreSum} = {{`NF+2{1'b0}}, PmKilled, 1'b0} + {InvA, AmInv} + {{3*`NF+4{1'b0}}, (~ASticky|KillProd)&InvA}; assign {NegSum, PreSum} = {{P.NF+2{1'b0}}, PmKilled, 1'b0} + {InvA, AmInv} + {{3*P.NF+4{1'b0}}, (~ASticky|KillProd)&InvA};
assign NegPreSum = Am + {{`NF+1{1'b1}}, ~PmKilled, 1'b0} + {(3*`NF+2)'(0), ~ASticky|~KillProd, 1'b0}; assign NegPreSum = Am + {{P.NF+1{1'b1}}, ~PmKilled, 1'b0} + {(3*P.NF+2)'(0), ~ASticky|~KillProd, 1'b0};
// Choose the positive sum and accompanying LZA result. // Choose the positive sum and accompanying LZA result.
assign Sm = NegSum ? NegPreSum : PreSum; assign Sm = NegSum ? NegPreSum : PreSum;

View File

@ -27,20 +27,18 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module fmaalign import cvw::*; #(parameter cvw_t P) (
input logic [P.NE-1:0] Xe, Ye, Ze, // biased exponents in B(NE.0) format
module fmaalign( input logic [P.NF:0] Zm, // significand in U(0.NF) format]
input logic [`NE-1:0] Xe, Ye, Ze, // biased exponents in B(NE.0) format
input logic [`NF:0] Zm, // significand in U(0.NF) format]
input logic XZero, YZero, ZZero,// is the input zero input logic XZero, YZero, ZZero,// is the input zero
output logic [3*`NF+3:0] Am, // addend aligned for addition in U(NF+5.2NF+1) output logic [3*P.NF+3:0] Am, // addend aligned for addition in U(NF+5.2NF+1)
output logic ASticky, // Sticky bit calculated from the aliged addend output logic ASticky, // Sticky bit calculated from the aliged addend
output logic KillProd // should the product be set to zero output logic KillProd // should the product be set to zero
); );
logic [`NE+1:0] ACnt; // how far to shift the addend to align with the product in Q(NE+2.0) format logic [P.NE+1:0] ACnt; // how far to shift the addend to align with the product in Q(NE+2.0) format
logic [4*`NF+3:0] ZmShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1) logic [4*P.NF+3:0] ZmShifted; // output of the alignment shifter including sticky bits U(NF+5.3NF+1)
logic [4*`NF+3:0] ZmPreshifted; // input to the alignment shifter U(NF+5.3NF+1) logic [4*P.NF+3:0] ZmPreshifted; // input to the alignment shifter U(NF+5.3NF+1)
logic KillZ; // should the addend be killed logic KillZ; // should the addend be killed
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -51,16 +49,16 @@ module fmaalign(
// - negitive means Z is larger, so shift Z left // - negitive means Z is larger, so shift Z left
// - positive means the product is larger, so shift Z right // - positive means the product is larger, so shift Z right
// This could have been done using Pe, but ACnt is on the critical path so we replicate logic for speed // This could have been done using Pe, but ACnt is on the critical path so we replicate logic for speed
assign ACnt = {2'b0, Xe} + {2'b0, Ye} - {2'b0, (`NE)'(`BIAS)} + (`NE+2)'(`NF+2) - {2'b0, Ze}; assign ACnt = {2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)} + (P.NE+2)'(P.NF+2) - {2'b0, Ze};
// Defualt Addition with only inital left shift // Defualt Addition with only inital left shift
// | 53'b0 | 106'b(product) | 1'b0 | // | 53'b0 | 106'b(product) | 1'b0 |
// | addnend | // | addnend |
assign ZmPreshifted = {Zm,(3*`NF+3)'(0)}; assign ZmPreshifted = {Zm,(3*P.NF+3)'(0)};
assign KillProd = (ACnt[`NE+1]&~ZZero)|XZero|YZero; assign KillProd = (ACnt[P.NE+1]&~ZZero)|XZero|YZero;
assign KillZ = $signed(ACnt)>$signed((`NE+2)'(3)*(`NE+2)'(`NF)+(`NE+2)'(3)); assign KillZ = $signed(ACnt)>$signed((P.NE+2)'(3)*(P.NE+2)'(P.NF)+(P.NE+2)'(3));
always_comb begin always_comb begin
// If the product is too small to effect the sum, kill the product // If the product is too small to effect the sum, kill the product
@ -68,7 +66,7 @@ module fmaalign(
// | 53'b0 | 106'b(product) | 1'b0 | // | 53'b0 | 106'b(product) | 1'b0 |
// | addnend | // | addnend |
if (KillProd) begin if (KillProd) begin
ZmShifted = {(`NF+2)'(0), Zm, (2*`NF+1)'(0)}; ZmShifted = {(P.NF+2)'(0), Zm, (2*P.NF+1)'(0)};
ASticky = ~(XZero|YZero); ASticky = ~(XZero|YZero);
// If the addend is too small to effect the addition // If the addend is too small to effect the addition
@ -86,12 +84,12 @@ module fmaalign(
// | addnend | // | addnend |
end else begin end else begin
ZmShifted = ZmPreshifted >> ACnt; ZmShifted = ZmPreshifted >> ACnt;
ASticky = |(ZmShifted[`NF-1:0]); ASticky = |(ZmShifted[P.NF-1:0]);
end end
end end
assign Am = ZmShifted[4*`NF+3:`NF]; assign Am = ZmShifted[4*P.NF+3:P.NF];
endmodule endmodule

View File

@ -26,18 +26,16 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module fmaexpadd import cvw::*; #(parameter cvw_t P) (
input logic [P.NE-1:0] Xe, Ye, // input's exponents
module fmaexpadd(
input logic [`NE-1:0] Xe, Ye, // input's exponents
input logic XZero, YZero, // are the inputs zero input logic XZero, YZero, // are the inputs zero
output logic [`NE+1:0] Pe // product's exponent B^(1023)NE+2 output logic [P.NE+1:0] Pe // product's exponent B^(1023)NE+2
); );
logic PZero; // is the product zero? logic PZero; // is the product zero?
// kill the exponent if the product is zero - either X or Y is 0 // kill the exponent if the product is zero - either X or Y is 0
assign PZero = XZero | YZero; assign PZero = XZero | YZero;
assign Pe = PZero ? '0 : ({2'b0, Xe} + {2'b0, Ye} - {2'b0, (`NE)'(`BIAS)}); assign Pe = PZero ? '0 : ({2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)});
endmodule endmodule

View File

@ -27,11 +27,9 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module fmalza #(WIDTH, NF) (
module fmalza #(WIDTH) (
input logic [WIDTH-1:0] A, // addend input logic [WIDTH-1:0] A, // addend
input logic [2*`NF+1:0] Pm, // product input logic [2*NF+1:0] Pm, // product
input logic Cin, // carry in input logic Cin, // carry in
input logic sub, // subtraction input logic sub, // subtraction
output logic [$clog2(WIDTH+1)-1:0] SCnt // normalization shift count for the positive result output logic [$clog2(WIDTH+1)-1:0] SCnt // normalization shift count for the positive result
@ -42,7 +40,7 @@ module fmalza #(WIDTH) (
logic [WIDTH-1:0] P, G, K; // propagate, generate, kill for each column logic [WIDTH-1:0] P, G, K; // propagate, generate, kill for each column
logic [WIDTH-1:0] Pp1, Gm1, Km1; // propagate shifted right by 1, generate/kill shifted left 1 logic [WIDTH-1:0] Pp1, Gm1, Km1; // propagate shifted right by 1, generate/kill shifted left 1
assign B = {{(`NF+1){1'b0}}, Pm, 1'b0}; // Zero extend product assign B = {{(NF+1){1'b0}}, Pm, 1'b0}; // Zero extend product
assign P = A^B; assign P = A^B;
assign G = A&B; assign G = A&B;

View File

@ -26,11 +26,9 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module fmamult import cvw::*; #(parameter cvw_t P) (
input logic [P.NF:0] Xm, Ym, // x and y significand
module fmamult( output logic [2*P.NF+1:0] Pm // product's significand
input logic [`NF:0] Xm, Ym, // x and y significand
output logic [2*`NF+1:0] Pm // product's significand
); );
assign Pm = Xm * Ym; assign Pm = Xm * Ym;

View File

@ -26,8 +26,6 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module fmasign( module fmasign(
input logic [2:0] OpCtrl, // opperation contol input logic [2:0] OpCtrl, // opperation contol
input logic Xs, Ys, Zs, // sign of the inputs input logic Xs, Ys, Zs, // sign of the inputs

View File

@ -175,7 +175,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
.Adr1D, .Adr2D, .Adr3D, .Adr1E, .Adr2E, .Adr3E); .Adr1D, .Adr2D, .Adr3D, .Adr1E, .Adr2E, .Adr3E);
// FP register file // FP register file
fregfile fregfile (.clk, .reset, .we4(FRegWriteW), fregfile #(P.FLEN) fregfile (.clk, .reset, .we4(FRegWriteW),
.a1(InstrD[19:15]), .a2(InstrD[24:20]), .a3(InstrD[31:27]), .a1(InstrD[19:15]), .a2(InstrD[24:20]), .a3(InstrD[31:27]),
.a4(RdW), .wd4(FResultW), .a4(RdW), .wd4(FResultW),
.rd1(FRD1D), .rd2(FRD2D), .rd3(FRD3D)); .rd1(FRD1D), .rd2(FRD2D), .rd3(FRD3D));
@ -225,7 +225,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
mux3 #(P.FLEN) fzmulmux (PreZE, BoxedZeroE, PreYE, FmaZSelE, ZE); mux3 #(P.FLEN) fzmulmux (PreZE, BoxedZeroE, PreYE, FmaZSelE, ZE);
// unpack unit: splits FP inputs into their parts and classifies SNaN, NaN, Subnorm, Norm, Zero, Infifnity // unpack unit: splits FP inputs into their parts and classifies SNaN, NaN, Subnorm, Norm, Zero, Infifnity
unpack unpack (.X(XE), .Y(YE), .Z(ZE), .Fmt(FmtE), .Xs(XsE), .Ys(YsE), .Zs(ZsE), unpack #(P) unpack (.X(XE), .Y(YE), .Z(ZE), .Fmt(FmtE), .Xs(XsE), .Ys(YsE), .Zs(ZsE),
.Xe(XeE), .Ye(YeE), .Ze(ZeE), .Xm(XmE), .Ym(YmE), .Zm(ZmE), .YEn(YEnE), .Xe(XeE), .Ye(YeE), .Ze(ZeE), .Xm(XmE), .Ym(YmE), .Zm(ZmE), .YEn(YEnE),
.XNaN(XNaNE), .YNaN(YNaNE), .ZNaN(ZNaNE), .XSNaN(XSNaNE), .XEn(XEnE), .XNaN(XNaNE), .YNaN(YNaNE), .ZNaN(ZNaNE), .XSNaN(XSNaNE), .XEn(XEnE),
.YSNaN(YSNaNE), .ZSNaN(ZSNaNE), .XSubnorm(XSubnormE), .YSNaN(YSNaNE), .ZSNaN(ZSNaNE), .XSubnorm(XSubnormE),
@ -233,7 +233,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
.ZEn(ZEnE), .ZInf(ZInfE), .XExpMax(XExpMaxE), .XPostBox(XPostBoxE)); .ZEn(ZEnE), .ZInf(ZInfE), .XExpMax(XExpMaxE), .XPostBox(XPostBoxE));
// fused multiply add: fadd/sub, fmul, fmadd/fnmadd/fmsub/fnmsub // fused multiply add: fadd/sub, fmul, fmadd/fnmadd/fmsub/fnmsub
fma fma (.Xs(XsE), .Ys(YsE), .Zs(ZsE), .Xe(XeE), .Ye(YeE), .Ze(ZeE), .Xm(XmE), .Ym(YmE), .Zm(ZmE), fma #(P) fma (.Xs(XsE), .Ys(YsE), .Zs(ZsE), .Xe(XeE), .Ye(YeE), .Ze(ZeE), .Xm(XmE), .Ym(YmE), .Zm(ZmE),
.XZero(XZeroE), .YZero(YZeroE), .ZZero(ZZeroE), .OpCtrl(OpCtrlE), .XZero(XZeroE), .YZero(YZeroE), .ZZero(ZZeroE), .OpCtrl(OpCtrlE),
.As(AsE), .Ps(PsE), .Ss(SsE), .Se(SeE), .Sm(SmE), .InvA(InvAE), .SCnt(SCntE), .ASticky(FmaAStickyE)); .As(AsE), .Ps(PsE), .Ss(SsE), .Se(SeE), .Sm(SmE), .InvA(InvAE), .SCnt(SCntE), .ASticky(FmaAStickyE));

View File

@ -26,17 +26,15 @@
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh" module fregfile #(parameter FLEN) (
module fregfile (
input logic clk, reset, input logic clk, reset,
input logic we4, // write enable input logic we4, // write enable
input logic [4:0] a1, a2, a3, a4, // adresses input logic [4:0] a1, a2, a3, a4, // adresses
input logic [`FLEN-1:0] wd4, // write data input logic [FLEN-1:0] wd4, // write data
output logic [`FLEN-1:0] rd1, rd2, rd3 // read data output logic [FLEN-1:0] rd1, rd2, rd3 // read data
); );
logic [`FLEN-1:0] rf[31:0]; logic [FLEN-1:0] rf[31:0];
integer i; integer i;
// three ported register file // three ported register file

View File

@ -25,41 +25,40 @@
// either express or implied. See the License for the specific language governing permissions // either express or implied. See the License for the specific language governing permissions
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module unpack ( module unpack import cvw::*; #(parameter cvw_t P) (
input logic [`FLEN-1:0] X, Y, Z, // inputs from register file input logic [P.FLEN-1:0] X, Y, Z, // inputs from register file
input logic [`FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half input logic [P.FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half
input logic XEn, YEn, ZEn, // input enables input logic XEn, YEn, ZEn, // input enables
output logic Xs, Ys, Zs, // sign bits of XYZ output logic Xs, Ys, Zs, // sign bits of XYZ
output logic [`NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision) output logic [P.NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
output logic [`NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision) output logic [P.NF:0] Xm, Ym, Zm, // mantissas of XYZ (converted to largest supported precision)
output logic XNaN, YNaN, ZNaN, // is XYZ a NaN output logic XNaN, YNaN, ZNaN, // is XYZ a NaN
output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN output logic XSNaN, YSNaN, ZSNaN, // is XYZ a signaling NaN
output logic XSubnorm, // is X subnormal output logic XSubnorm, // is X subnormal
output logic XZero, YZero, ZZero, // is XYZ zero output logic XZero, YZero, ZZero, // is XYZ zero
output logic XInf, YInf, ZInf, // is XYZ infinity output logic XInf, YInf, ZInf, // is XYZ infinity
output logic XExpMax, // does X have the maximum exponent (NaN or Inf) output logic XExpMax, // does X have the maximum exponent (NaN or Inf)
output logic [`FLEN-1:0] XPostBox // X after being properly NaN-boxed output logic [P.FLEN-1:0] XPostBox // X after being properly NaN-boxed
); );
logic XExpNonZero, YExpNonZero, ZExpNonZero; // is the exponent of XYZ non-zero logic XExpNonZero, YExpNonZero, ZExpNonZero; // is the exponent of XYZ non-zero
logic XFracZero, YFracZero, ZFracZero; // is the fraction zero logic XFracZero, YFracZero, ZFracZero; // is the fraction zero
logic YExpMax, ZExpMax; // is the exponent all 1s logic YExpMax, ZExpMax; // is the exponent all 1s
unpackinput unpackinputX (.In(X), .Fmt, .Sgn(Xs), .Exp(Xe), .Man(Xm), .En(XEn), unpackinput #(P) unpackinputX (.In(X), .Fmt, .Sgn(Xs), .Exp(Xe), .Man(Xm), .En(XEn),
.NaN(XNaN), .SNaN(XSNaN), .ExpNonZero(XExpNonZero), .NaN(XNaN), .SNaN(XSNaN), .ExpNonZero(XExpNonZero),
.Zero(XZero), .Inf(XInf), .ExpMax(XExpMax), .FracZero(XFracZero), .Zero(XZero), .Inf(XInf), .ExpMax(XExpMax), .FracZero(XFracZero),
.Subnorm(XSubnorm), .PostBox(XPostBox)); .Subnorm(XSubnorm), .PostBox(XPostBox));
unpackinput unpackinputY (.In(Y), .Fmt, .Sgn(Ys), .Exp(Ye), .Man(Ym), .En(YEn), unpackinput #(P) unpackinputY (.In(Y), .Fmt, .Sgn(Ys), .Exp(Ye), .Man(Ym), .En(YEn),
.NaN(YNaN), .SNaN(YSNaN), .ExpNonZero(YExpNonZero), .NaN(YNaN), .SNaN(YSNaN), .ExpNonZero(YExpNonZero),
.Zero(YZero), .Inf(YInf), .ExpMax(YExpMax), .FracZero(YFracZero), .Zero(YZero), .Inf(YInf), .ExpMax(YExpMax), .FracZero(YFracZero),
.Subnorm(), .PostBox()); .Subnorm(), .PostBox());
unpackinput unpackinputZ (.In(Z), .Fmt, .Sgn(Zs), .Exp(Ze), .Man(Zm), .En(ZEn), unpackinput #(P) unpackinputZ (.In(Z), .Fmt, .Sgn(Zs), .Exp(Ze), .Man(Zm), .En(ZEn),
.NaN(ZNaN), .SNaN(ZSNaN), .ExpNonZero(ZExpNonZero), .NaN(ZNaN), .SNaN(ZSNaN), .ExpNonZero(ZExpNonZero),
.Zero(ZZero), .Inf(ZInf), .ExpMax(ZExpMax), .FracZero(ZFracZero), .Zero(ZZero), .Inf(ZInf), .ExpMax(ZExpMax), .FracZero(ZFracZero),
.Subnorm(), .PostBox()); .Subnorm(), .PostBox());
endmodule endmodule

View File

@ -25,15 +25,14 @@
// either express or implied. See the License for the specific language governing permissions // either express or implied. See the License for the specific language governing permissions
// and limitations under the License. // and limitations under the License.
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module unpackinput ( module unpackinput import cvw::*; #(parameter cvw_t P) (
input logic [`FLEN-1:0] In, // inputs from register file input logic [P.FLEN-1:0] In, // inputs from register file
input logic En, // enable the input input logic En, // enable the input
input logic [`FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half input logic [P.FMTBITS-1:0] Fmt, // format signal 00 - single 01 - double 11 - quad 10 - half
output logic Sgn, // sign bits of the number output logic Sgn, // sign bits of the number
output logic [`NE-1:0] Exp, // exponent of the number (converted to largest supported precision) output logic [P.NE-1:0] Exp, // exponent of the number (converted to largest supported precision)
output logic [`NF:0] Man, // mantissa of the number (converted to largest supported precision) output logic [P.NF:0] Man, // mantissa of the number (converted to largest supported precision)
output logic NaN, // is the number a NaN output logic NaN, // is the number a NaN
output logic SNaN, // is the number a signaling NaN output logic SNaN, // is the number a signaling NaN
output logic Zero, // is the number zero output logic Zero, // is the number zero
@ -42,29 +41,29 @@ module unpackinput (
output logic FracZero, // is the fraction zero output logic FracZero, // is the fraction zero
output logic ExpMax, // does In have the maximum exponent (NaN or Inf) output logic ExpMax, // does In have the maximum exponent (NaN or Inf)
output logic Subnorm, // is the number subnormal output logic Subnorm, // is the number subnormal
output logic [`FLEN-1:0] PostBox // Number reboxed correctly as a NaN output logic [P.FLEN-1:0] PostBox // Number reboxed correctly as a NaN
); );
logic [`NF-1:0] Frac; // Fraction of XYZ logic [P.NF-1:0] Frac; // Fraction of XYZ
logic BadNaNBox; // incorrectly NaN Boxed logic BadNaNBox; // incorrectly NaN Boxed
if (`FPSIZES == 1) begin // if there is only one floating point format supported if (P.FPSIZES == 1) begin // if there is only one floating point format supported
assign BadNaNBox = 0; assign BadNaNBox = 0;
assign Sgn = In[`FLEN-1]; // sign bit assign Sgn = In[P.FLEN-1]; // sign bit
assign Frac = In[`NF-1:0]; // fraction (no assumed 1) assign Frac = In[P.NF-1:0]; // fraction (no assumed 1)
assign ExpNonZero = |In[`FLEN-2:`NF]; // is the exponent non-zero assign ExpNonZero = |In[P.FLEN-2:P.NF]; // is the exponent non-zero
assign Exp = {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero}; // exponent. subnormal numbers have effective biased exponent of 1 assign Exp = {In[P.FLEN-2:P.NF+1], In[P.NF]|~ExpNonZero}; // exponent. subnormal numbers have effective biased exponent of 1
assign ExpMax = &In[`FLEN-2:`NF]; // is the exponent all 1's assign ExpMax = &In[P.FLEN-2:P.NF]; // is the exponent all 1's
assign PostBox = In; assign PostBox = In;
end else if (`FPSIZES == 2) begin // if there are 2 floating point formats supported end else if (P.FPSIZES == 2) begin // if there are 2 floating point formats supported
// largest format | smaller format // largest format | smaller format
//---------------------------------- //----------------------------------
// `FLEN | `LEN1 length of floating point number // P.FLEN | P.LEN1 length of floating point number
// `NE | `NE1 length of exponent // P.NE | P.NE1 length of exponent
// `NF | `NF1 length of fraction // P.NF | P.NF1 length of fraction
// `BIAS | `BIAS1 exponent's bias value // P.BIAS | P.BIAS1 exponent's bias value
// `FMT | `FMT1 precision's format value - Q=11 D=01 Sticky=00 H=10 // P.FMT | P.FMT1 precision's format value - Q=11 D=01 Sticky=00 H=10
// Possible combinantions specified by spec: // Possible combinantions specified by spec:
// double and single // double and single
@ -76,22 +75,22 @@ module unpackinput (
// quad and half // quad and half
// double and half // double and half
assign BadNaNBox = ~(Fmt|(&In[`FLEN-1:`LEN1])); // Check NaN boxing assign BadNaNBox = ~(Fmt|(&In[P.FLEN-1:P.LEN1])); // Check NaN boxing
always_comb always_comb
if (BadNaNBox) begin if (BadNaNBox) begin
// PostBox = {{(`FLEN-`LEN1){1'b1}}, 1'b1, {(`NE1+1){1'b1}}, In[`LEN1-`NE1-3:0]}; // PostBox = {{(P.FLEN-P.LEN1){1'b1}}, 1'b1, {(P.NE1+1){1'b1}}, In[P.LEN1-P.NE1-3:0]};
PostBox = {{(`FLEN-`LEN1){1'b1}}, 1'b1, {(`NE1+1){1'b1}}, {(`LEN1-`NE1-2){1'b0}}}; PostBox = {{(P.FLEN-P.LEN1){1'b1}}, 1'b1, {(P.NE1+1){1'b1}}, {(P.LEN1-P.NE1-2){1'b0}}};
end else end else
PostBox = In; PostBox = In;
// choose sign bit depending on format - 1=larger precsion 0=smaller precision // choose sign bit depending on format - 1=larger precsion 0=smaller precision
assign Sgn = Fmt ? In[`FLEN-1] : (BadNaNBox ? 0 : In[`LEN1-1]); // improperly boxed NaNs are treated as positive assign Sgn = Fmt ? In[P.FLEN-1] : (BadNaNBox ? 0 : In[P.LEN1-1]); // improperly boxed NaNs are treated as positive
// extract the fraction, add trailing zeroes to the mantissa if nessisary // extract the fraction, add trailing zeroes to the mantissa if nessisary
assign Frac = Fmt ? In[`NF-1:0] : {In[`NF1-1:0], (`NF-`NF1)'(0)}; assign Frac = Fmt ? In[P.NF-1:0] : {In[P.NF1-1:0], (P.NF-P.NF1)'(0)};
// is the exponent non-zero // is the exponent non-zero
assign ExpNonZero = Fmt ? |In[`FLEN-2:`NF] : |In[`LEN1-2:`NF1]; assign ExpNonZero = Fmt ? |In[P.FLEN-2:P.NF] : |In[P.LEN1-2:P.NF1];
// example double to single conversion: // example double to single conversion:
// 1023 = 0011 1111 1111 // 1023 = 0011 1111 1111
@ -103,21 +102,21 @@ module unpackinput (
// extract the exponent, converting the smaller exponent into the larger precision if nessisary // extract the exponent, converting the smaller exponent into the larger precision if nessisary
// - if the original precision had a Subnormal number convert the exponent value 1 // - if the original precision had a Subnormal number convert the exponent value 1
assign Exp = Fmt ? {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero} : {In[`LEN1-2], {`NE-`NE1{~In[`LEN1-2]}}, In[`LEN1-3:`NF1+1], In[`NF1]|~ExpNonZero}; assign Exp = Fmt ? {In[P.FLEN-2:P.NF+1], In[P.NF]|~ExpNonZero} : {In[P.LEN1-2], {P.NE-P.NE1{~In[P.LEN1-2]}}, In[P.LEN1-3:P.NF1+1], In[P.NF1]|~ExpNonZero};
// is the exponent all 1's // is the exponent all 1's
assign ExpMax = Fmt ? &In[`FLEN-2:`NF] : &In[`LEN1-2:`NF1]; assign ExpMax = Fmt ? &In[P.FLEN-2:P.NF] : &In[P.LEN1-2:P.NF1];
end else if (`FPSIZES == 3) begin // three floating point precsions supported end else if (P.FPSIZES == 3) begin // three floating point precsions supported
// largest format | larger format | smallest format // largest format | larger format | smallest format
//--------------------------------------------------- //---------------------------------------------------
// `FLEN | `LEN1 | `LEN2 length of floating point number // P.FLEN | P.LEN1 | P.LEN2 length of floating point number
// `NE | `NE1 | `NE2 length of exponent // P.NE | P.NE1 | P.NE2 length of exponent
// `NF | `NF1 | `NF2 length of fraction // P.NF | P.NF1 | P.NF2 length of fraction
// `BIAS | `BIAS1 | `BIAS2 exponent's bias value // P.BIAS | P.BIAS1 | P.BIAS2 exponent's bias value
// `FMT | `FMT1 | `FMT2 precision's format value - Q=11 D=01 Sticky=00 H=10 // P.FMT | P.FMT1 | P.FMT2 precision's format value - Q=11 D=01 Sticky=00 H=10
// Possible combinantions specified by spec: // Possible combinantions specified by spec:
// quad and double and single // quad and double and single
@ -130,20 +129,20 @@ module unpackinput (
// Check NaN boxing // Check NaN boxing
always_comb always_comb
case (Fmt) case (Fmt)
`FMT: BadNaNBox = 0; P.FMT: BadNaNBox = 0;
`FMT1: BadNaNBox = ~&In[`FLEN-1:`LEN1]; P.FMT1: BadNaNBox = ~&In[P.FLEN-1:P.LEN1];
`FMT2: BadNaNBox = ~&In[`FLEN-1:`LEN2]; P.FMT2: BadNaNBox = ~&In[P.FLEN-1:P.LEN2];
default: BadNaNBox = 1'bx; default: BadNaNBox = 1'bx;
endcase endcase
always_comb always_comb
if (BadNaNBox) begin if (BadNaNBox) begin
case (Fmt) case (Fmt)
`FMT: PostBox = In; P.FMT: PostBox = In;
// `FMT1: PostBox = {{(`FLEN-`LEN1){1'b1}}, 1'b1, {(`NE1+1){1'b1}}, In[`LEN1-`NE1-3:0]}; // P.FMT1: PostBox = {{(P.FLEN-P.LEN1){1'b1}}, 1'b1, {(P.NE1+1){1'b1}}, In[P.LEN1-P.NE1-3:0]};
// `FMT2: PostBox = {{(`FLEN-`LEN2){1'b1}}, 1'b1, {(`NE2+1){1'b1}}, In[`LEN2-`NE2-3:0]}; // P.FMT2: PostBox = {{(P.FLEN-P.LEN2){1'b1}}, 1'b1, {(P.NE2+1){1'b1}}, In[P.LEN2-P.NE2-3:0]};
`FMT1: PostBox = {{(`FLEN-`LEN1){1'b1}}, 1'b1, {(`NE1+1){1'b1}}, {(`LEN1-`NE1-2){1'b0}}}; P.FMT1: PostBox = {{(P.FLEN-P.LEN1){1'b1}}, 1'b1, {(P.NE1+1){1'b1}}, {(P.LEN1-P.NE1-2){1'b0}}};
`FMT2: PostBox = {{(`FLEN-`LEN2){1'b1}}, 1'b1, {(`NE2+1){1'b1}}, {(`LEN2-`NE2-2){1'b0}}}; P.FMT2: PostBox = {{(P.FLEN-P.LEN2){1'b1}}, 1'b1, {(P.NE2+1){1'b1}}, {(P.LEN2-P.NE2-2){1'b0}}};
default: PostBox = 'x; default: PostBox = 'x;
endcase endcase
end else end else
@ -154,27 +153,27 @@ module unpackinput (
if (BadNaNBox) Sgn = 0; // improperly boxed NaNs are treated as positive if (BadNaNBox) Sgn = 0; // improperly boxed NaNs are treated as positive
else else
case (Fmt) case (Fmt)
`FMT: Sgn = In[`FLEN-1]; P.FMT: Sgn = In[P.FLEN-1];
`FMT1: Sgn = In[`LEN1-1]; P.FMT1: Sgn = In[P.LEN1-1];
`FMT2: Sgn = In[`LEN2-1]; P.FMT2: Sgn = In[P.LEN2-1];
default: Sgn = 1'bx; default: Sgn = 1'bx;
endcase endcase
// extract the fraction // extract the fraction
always_comb always_comb
case (Fmt) case (Fmt)
`FMT: Frac = In[`NF-1:0]; P.FMT: Frac = In[P.NF-1:0];
`FMT1: Frac = {In[`NF1-1:0], (`NF-`NF1)'(0)}; P.FMT1: Frac = {In[P.NF1-1:0], (P.NF-P.NF1)'(0)};
`FMT2: Frac = {In[`NF2-1:0], (`NF-`NF2)'(0)}; P.FMT2: Frac = {In[P.NF2-1:0], (P.NF-P.NF2)'(0)};
default: Frac = {`NF{1'bx}}; default: Frac = {P.NF{1'bx}};
endcase endcase
// is the exponent non-zero // is the exponent non-zero
always_comb always_comb
case (Fmt) case (Fmt)
`FMT: ExpNonZero = |In[`FLEN-2:`NF]; // if input is largest precision (`FLEN - ie quad or double) P.FMT: ExpNonZero = |In[P.FLEN-2:P.NF]; // if input is largest precision (P.FLEN - ie quad or double)
`FMT1: ExpNonZero = |In[`LEN1-2:`NF1]; // if input is larger precsion (`LEN1 - double or single) P.FMT1: ExpNonZero = |In[P.LEN1-2:P.NF1]; // if input is larger precsion (P.LEN1 - double or single)
`FMT2: ExpNonZero = |In[`LEN2-2:`NF2]; // if input is smallest precsion (`LEN2 - single or half) P.FMT2: ExpNonZero = |In[P.LEN2-2:P.NF2]; // if input is smallest precsion (P.LEN2 - single or half)
default: ExpNonZero = 1'bx; default: ExpNonZero = 1'bx;
endcase endcase
@ -189,50 +188,50 @@ module unpackinput (
// convert the larger precision's exponent to use the largest precision's bias // convert the larger precision's exponent to use the largest precision's bias
always_comb always_comb
case (Fmt) case (Fmt)
`FMT: Exp = {In[`FLEN-2:`NF+1], In[`NF]|~ExpNonZero}; P.FMT: Exp = {In[P.FLEN-2:P.NF+1], In[P.NF]|~ExpNonZero};
`FMT1: Exp = {In[`LEN1-2], {`NE-`NE1{~In[`LEN1-2]}}, In[`LEN1-3:`NF1+1], In[`NF1]|~ExpNonZero}; P.FMT1: Exp = {In[P.LEN1-2], {P.NE-P.NE1{~In[P.LEN1-2]}}, In[P.LEN1-3:P.NF1+1], In[P.NF1]|~ExpNonZero};
`FMT2: Exp = {In[`LEN2-2], {`NE-`NE2{~In[`LEN2-2]}}, In[`LEN2-3:`NF2+1], In[`NF2]|~ExpNonZero}; P.FMT2: Exp = {In[P.LEN2-2], {P.NE-P.NE2{~In[P.LEN2-2]}}, In[P.LEN2-3:P.NF2+1], In[P.NF2]|~ExpNonZero};
default: Exp = {`NE{1'bx}}; default: Exp = {P.NE{1'bx}};
endcase endcase
// is the exponent all 1's // is the exponent all 1's
always_comb always_comb
case (Fmt) case (Fmt)
`FMT: ExpMax = &In[`FLEN-2:`NF]; P.FMT: ExpMax = &In[P.FLEN-2:P.NF];
`FMT1: ExpMax = &In[`LEN1-2:`NF1]; P.FMT1: ExpMax = &In[P.LEN1-2:P.NF1];
`FMT2: ExpMax = &In[`LEN2-2:`NF2]; P.FMT2: ExpMax = &In[P.LEN2-2:P.NF2];
default: ExpMax = 1'bx; default: ExpMax = 1'bx;
endcase endcase
end else if (`FPSIZES == 4) begin // if all precsisons are supported - quad, double, single, and half end else if (P.FPSIZES == 4) begin // if all precsisons are supported - quad, double, single, and half
// quad | double | single | half // quad | double | single | half
//------------------------------------------------------------------- //-------------------------------------------------------------------
// `Q_LEN | `D_LEN | `S_LEN | `H_LEN length of floating point number // P.Q_LEN | P.D_LEN | P.S_LEN | P.H_LEN length of floating point number
// `Q_NE | `D_NE | `S_NE | `H_NE length of exponent // P.Q_NE | P.D_NE | P.S_NE | P.H_NE length of exponent
// `Q_NF | `D_NF | `S_NF | `H_NF length of fraction // P.Q_NF | P.D_NF | P.S_NF | P.H_NF length of fraction
// `Q_BIAS | `D_BIAS | `S_BIAS | `H_BIAS exponent's bias value // P.Q_BIAS | P.D_BIAS | P.S_BIAS | P.H_BIAS exponent's bias value
// `Q_FMT | `D_FMT | `S_FMT | `H_FMT precision's format value - Q=11 D=01 Sticky=00 H=10 // P.Q_FMT | P.D_FMT | P.S_FMT | P.H_FMT precision's format value - Q=11 D=01 Sticky=00 H=10
// Check NaN boxing // Check NaN boxing
always_comb always_comb
case (Fmt) case (Fmt)
2'b11: BadNaNBox = 0; 2'b11: BadNaNBox = 0;
2'b01: BadNaNBox = ~&In[`Q_LEN-1:`D_LEN]; 2'b01: BadNaNBox = ~&In[P.Q_LEN-1:P.D_LEN];
2'b00: BadNaNBox = ~&In[`Q_LEN-1:`S_LEN]; 2'b00: BadNaNBox = ~&In[P.Q_LEN-1:P.S_LEN];
2'b10: BadNaNBox = ~&In[`Q_LEN-1:`H_LEN]; 2'b10: BadNaNBox = ~&In[P.Q_LEN-1:P.H_LEN];
endcase endcase
always_comb always_comb
if (BadNaNBox) begin if (BadNaNBox) begin
case (Fmt) case (Fmt)
2'b11: PostBox = In; 2'b11: PostBox = In;
// 2'b01: PostBox = {{(`Q_LEN-`D_LEN){1'b1}}, 1'b1, {(`D_NE+1){1'b1}}, In[`D_LEN-`D_NE-3:0]}; // 2'b01: PostBox = {{(P.Q_LEN-P.D_LEN){1'b1}}, 1'b1, {(P.D_NE+1){1'b1}}, In[P.D_LEN-P.D_NE-3:0]};
// 2'b00: PostBox = {{(`Q_LEN-`S_LEN){1'b1}}, 1'b1, {(`S_NE+1){1'b1}}, In[`S_LEN-`S_NE-3:0]}; // 2'b00: PostBox = {{(P.Q_LEN-P.S_LEN){1'b1}}, 1'b1, {(P.S_NE+1){1'b1}}, In[P.S_LEN-P.S_NE-3:0]};
// 2'b10: PostBox = {{(`Q_LEN-`H_LEN){1'b1}}, 1'b1, {(`H_NE+1){1'b1}}, In[`H_LEN-`H_NE-3:0]}; // 2'b10: PostBox = {{(P.Q_LEN-P.H_LEN){1'b1}}, 1'b1, {(P.H_NE+1){1'b1}}, In[P.H_LEN-P.H_NE-3:0]};
2'b01: PostBox = {{(`Q_LEN-`D_LEN){1'b1}}, 1'b1, {(`D_NE+1){1'b1}}, {(`D_LEN-`D_NE-2){1'b0}}}; 2'b01: PostBox = {{(P.Q_LEN-P.D_LEN){1'b1}}, 1'b1, {(P.D_NE+1){1'b1}}, {(P.D_LEN-P.D_NE-2){1'b0}}};
2'b00: PostBox = {{(`Q_LEN-`S_LEN){1'b1}}, 1'b1, {(`S_NE+1){1'b1}}, {(`S_LEN-`S_NE-2){1'b0}}}; 2'b00: PostBox = {{(P.Q_LEN-P.S_LEN){1'b1}}, 1'b1, {(P.S_NE+1){1'b1}}, {(P.S_LEN-P.S_NE-2){1'b0}}};
2'b10: PostBox = {{(`Q_LEN-`H_LEN){1'b1}}, 1'b1, {(`H_NE+1){1'b1}}, {(`H_LEN-`H_NE-2){1'b0}}}; 2'b10: PostBox = {{(P.Q_LEN-P.H_LEN){1'b1}}, 1'b1, {(P.H_NE+1){1'b1}}, {(P.H_LEN-P.H_NE-2){1'b0}}};
endcase endcase
end else end else
PostBox = In; PostBox = In;
@ -242,29 +241,29 @@ module unpackinput (
if (BadNaNBox) Sgn = 0; // improperly boxed NaNs are treated as positive if (BadNaNBox) Sgn = 0; // improperly boxed NaNs are treated as positive
else else
case (Fmt) case (Fmt)
2'b11: Sgn = In[`Q_LEN-1]; 2'b11: Sgn = In[P.Q_LEN-1];
2'b01: Sgn = In[`D_LEN-1]; 2'b01: Sgn = In[P.D_LEN-1];
2'b00: Sgn = In[`S_LEN-1]; 2'b00: Sgn = In[P.S_LEN-1];
2'b10: Sgn = In[`H_LEN-1]; 2'b10: Sgn = In[P.H_LEN-1];
endcase endcase
// extract the fraction // extract the fraction
always_comb always_comb
case (Fmt) case (Fmt)
2'b11: Frac = In[`Q_NF-1:0]; 2'b11: Frac = In[P.Q_NF-1:0];
2'b01: Frac = {In[`D_NF-1:0], (`Q_NF-`D_NF)'(0)}; 2'b01: Frac = {In[P.D_NF-1:0], (P.Q_NF-P.D_NF)'(0)};
2'b00: Frac = {In[`S_NF-1:0], (`Q_NF-`S_NF)'(0)}; 2'b00: Frac = {In[P.S_NF-1:0], (P.Q_NF-P.S_NF)'(0)};
2'b10: Frac = {In[`H_NF-1:0], (`Q_NF-`H_NF)'(0)}; 2'b10: Frac = {In[P.H_NF-1:0], (P.Q_NF-P.H_NF)'(0)};
endcase endcase
// is the exponent non-zero // is the exponent non-zero
always_comb always_comb
case (Fmt) case (Fmt)
2'b11: ExpNonZero = |In[`Q_LEN-2:`Q_NF]; 2'b11: ExpNonZero = |In[P.Q_LEN-2:P.Q_NF];
2'b01: ExpNonZero = |In[`D_LEN-2:`D_NF]; 2'b01: ExpNonZero = |In[P.D_LEN-2:P.D_NF];
2'b00: ExpNonZero = |In[`S_LEN-2:`S_NF]; 2'b00: ExpNonZero = |In[P.S_LEN-2:P.S_NF];
2'b10: ExpNonZero = |In[`H_LEN-2:`H_NF]; 2'b10: ExpNonZero = |In[P.H_LEN-2:P.H_NF];
endcase endcase
@ -280,20 +279,20 @@ module unpackinput (
// 1 is added to the exponent if the input is zero or subnormal // 1 is added to the exponent if the input is zero or subnormal
always_comb always_comb
case (Fmt) case (Fmt)
2'b11: Exp = {In[`Q_LEN-2:`Q_NF+1], In[`Q_NF]|~ExpNonZero}; 2'b11: Exp = {In[P.Q_LEN-2:P.Q_NF+1], In[P.Q_NF]|~ExpNonZero};
2'b01: Exp = {In[`D_LEN-2], {`Q_NE-`D_NE{~In[`D_LEN-2]}}, In[`D_LEN-3:`D_NF+1], In[`D_NF]|~ExpNonZero}; 2'b01: Exp = {In[P.D_LEN-2], {P.Q_NE-P.D_NE{~In[P.D_LEN-2]}}, In[P.D_LEN-3:P.D_NF+1], In[P.D_NF]|~ExpNonZero};
2'b00: Exp = {In[`S_LEN-2], {`Q_NE-`S_NE{~In[`S_LEN-2]}}, In[`S_LEN-3:`S_NF+1], In[`S_NF]|~ExpNonZero}; 2'b00: Exp = {In[P.S_LEN-2], {P.Q_NE-P.S_NE{~In[P.S_LEN-2]}}, In[P.S_LEN-3:P.S_NF+1], In[P.S_NF]|~ExpNonZero};
2'b10: Exp = {In[`H_LEN-2], {`Q_NE-`H_NE{~In[`H_LEN-2]}}, In[`H_LEN-3:`H_NF+1], In[`H_NF]|~ExpNonZero}; 2'b10: Exp = {In[P.H_LEN-2], {P.Q_NE-P.H_NE{~In[P.H_LEN-2]}}, In[P.H_LEN-3:P.H_NF+1], In[P.H_NF]|~ExpNonZero};
endcase endcase
// is the exponent all 1's // is the exponent all 1's
always_comb always_comb
case (Fmt) case (Fmt)
2'b11: ExpMax = &In[`Q_LEN-2:`Q_NF]; 2'b11: ExpMax = &In[P.Q_LEN-2:P.Q_NF];
2'b01: ExpMax = &In[`D_LEN-2:`D_NF]; 2'b01: ExpMax = &In[P.D_LEN-2:P.D_NF];
2'b00: ExpMax = &In[`S_LEN-2:`S_NF]; 2'b00: ExpMax = &In[P.S_LEN-2:P.S_NF];
2'b10: ExpMax = &In[`H_LEN-2:`H_NF]; 2'b10: ExpMax = &In[P.H_LEN-2:P.H_NF];
endcase endcase
end end
@ -302,9 +301,9 @@ module unpackinput (
assign FracZero = ~|Frac & ~BadNaNBox; // is the fraction zero? assign FracZero = ~|Frac & ~BadNaNBox; // is the fraction zero?
assign Man = {ExpNonZero, Frac}; // add the assumed one (or zero if Subnormal or zero) to create the significand assign Man = {ExpNonZero, Frac}; // add the assumed one (or zero if Subnormal or zero) to create the significand
assign NaN = ((ExpMax & ~FracZero)|BadNaNBox)&En; // is the input a NaN? assign NaN = ((ExpMax & ~FracZero)|BadNaNBox)&En; // is the input a NaN?
assign SNaN = NaN&~Frac[`NF-1]&~BadNaNBox; // is the input a singnaling NaN? assign SNaN = NaN&~Frac[P.NF-1]&~BadNaNBox; // is the input a singnaling NaN?
assign Inf = ExpMax & FracZero & En; // is the input infinity? assign Inf = ExpMax & FracZero & En; // is the input infinity?
assign Zero = ~ExpNonZero & FracZero; // is the input zero? assign Zero = ~ExpNonZero & FracZero; // is the input zero?
assign Subnorm = ~ExpNonZero & ~FracZero & ~BadNaNBox; // is the input subnormal assign Subnorm = ~ExpNonZero & ~FracZero & ~BadNaNBox; // is the input subnormal
endmodule endmodule