2021-05-24 13:28:16 +00:00
///////////////////////////////////////////
2022-09-20 10:57:57 +00:00
// fpu.sv
2021-05-24 13:28:16 +00:00
//
2022-07-07 23:01:33 +00:00
// Written: me@KatherineParry.com, James Stine, Brett Mathis
2021-06-23 20:42:40 +00:00
// Modified: 6/23/2021
2021-05-24 13:28:16 +00:00
//
// Purpose: FPU
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
2022-01-07 12:58:40 +00:00
// MIT LICENSE
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
2021-05-24 13:28:16 +00:00
//
2022-01-07 12:58:40 +00:00
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
2021-05-24 13:28:16 +00:00
//
2022-01-07 12:58:40 +00:00
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////////////////////
2021-04-08 18:03:21 +00:00
`include " wally-config.vh "
2021-04-04 18:09:13 +00:00
module fpu (
2022-09-29 23:08:27 +00:00
input logic clk ,
input logic reset ,
input logic [ 2 : 0 ] FRM_REGW , // Rounding mode (from CSR)
input logic [ 31 : 0 ] InstrD , // instruction (from IFU)
input logic [ `FLEN - 1 : 0 ] ReadDataW , // Read data (from LSU)
input logic [ `XLEN - 1 : 0 ] ForwardedSrcAE , ForwardedSrcBE , // Integer input (from IEU)
input logic StallE , StallM , StallW , // stall signals (from HZU)
2022-12-15 18:56:18 +00:00
//input logic TrapM,
2022-09-29 23:08:27 +00:00
input logic FlushE , FlushM , FlushW , // flush signals (from HZU)
2022-12-23 18:47:18 +00:00
input logic [ 4 : 0 ] RdE , RdM , RdW , // which FP register to write to (from IEU)
2022-09-29 23:08:27 +00:00
input logic [ 1 : 0 ] STATUS_FS , // Is floating-point enabled? (From privileged unit)
input logic [ 2 : 0 ] Funct3E , Funct3M ,
input logic MDUE , W64E ,
output logic FRegWriteM , // FP register write enable (to privileged unit)
output logic FpLoadStoreM , // Fp load instruction? (to LSU)
2022-12-19 15:28:45 +00:00
output logic FPUStallD , // Stall the decode stage (To HZU)
2022-09-29 23:08:27 +00:00
output logic FWriteIntE , // integer register write enable (to IEU)
output logic FCvtIntE , // Convert to int (to IEU)
output logic [ `FLEN - 1 : 0 ] FWriteDataM , // Data to be written to memory (to LSU)
output logic [ `XLEN - 1 : 0 ] FIntResM , // data to be written to integer register (to IEU)
output logic [ `XLEN - 1 : 0 ] FCvtIntResW , // convert result to to be written to integer register (to IEU)
output logic FCvtIntW , // select FCvtIntRes (to IEU)
output logic FDivBusyE , // Is the divide/sqrt unit busy (stall execute stage) (to HZU)
output logic IllegalFPUInstrM , // Is the instruction an illegal fpu instruction (to privileged unit)
2022-12-15 01:03:13 +00:00
output logic [ 4 : 0 ] SetFflagsM , // FPU flags (to privileged unit)
output logic [ `XLEN - 1 : 0 ] FPIntDivResultW
2021-07-24 18:59:57 +00:00
) ;
2021-12-20 00:53:41 +00:00
// FPU specifics:
// - uses NaN-blocking format
// - if there are any unsused bits the most significant bits are filled with 1s
// single stored in a double: | 32 1s | single precision value |
// - sets the underflow after rounding
2022-08-22 20:43:04 +00:00
2021-12-20 00:53:41 +00:00
// control signals
2022-07-20 02:27:39 +00:00
logic FRegWriteW ; // FP register write enable
logic [ 2 : 0 ] FrmM ; // FP rounding mode
logic [ `FMTBITS - 1 : 0 ] FmtE , FmtM ; // FP precision 0-single 1-double
2022-11-16 18:00:07 +00:00
logic FDivStartE , IDivStartE ; // Start division or squareroot
2022-07-20 02:27:39 +00:00
logic FWriteIntM ; // Write to integer register
logic [ 1 : 0 ] ForwardXE , ForwardYE , ForwardZE ; // forwarding mux control signals
logic [ 2 : 0 ] OpCtrlE , OpCtrlM ; // Select which opperation to do in each component
2022-08-23 19:17:19 +00:00
logic [ 1 : 0 ] FResSelE , FResSelM , FResSelW ; // Select one of the results that finish in the memory stage
2022-07-20 02:27:39 +00:00
logic [ 1 : 0 ] PostProcSelE , PostProcSelM ; // select result in the post processing unit
2022-12-23 18:47:18 +00:00
logic [ 4 : 0 ] Adr1D , Adr2D , Adr3D ; // adresses of each input
2022-07-20 02:27:39 +00:00
logic [ 4 : 0 ] Adr1E , Adr2E , Adr3E ; // adresses of each input
2022-12-23 18:47:18 +00:00
logic XEnD , YEnD , ZEnD ;
2022-07-21 01:20:06 +00:00
logic XEnE , YEnE , ZEnE ;
2022-12-23 18:47:18 +00:00
logic FRegWriteE ;
2021-12-20 00:53:41 +00:00
// regfile signals
2022-07-20 02:27:39 +00:00
logic [ `FLEN - 1 : 0 ] FRD1D , FRD2D , FRD3D ; // Read Data from FP register - decode stage
logic [ `FLEN - 1 : 0 ] FRD1E , FRD2E , FRD3E ; // Read Data from FP register - execute stage
logic [ `FLEN - 1 : 0 ] XE ; // Input 1 to the various units (after forwarding)
logic [ `XLEN - 1 : 0 ] IntSrcXE ; // Input 1 to the various units (after forwarding)
logic [ `FLEN - 1 : 0 ] PreYE , YE ; // Input 2 to the various units (after forwarding)
logic [ `FLEN - 1 : 0 ] PreZE , ZE ; // Input 3 to the various units (after forwarding)
2021-12-20 00:53:41 +00:00
// unpacking signals
2022-07-20 02:27:39 +00:00
logic XsE , YsE , ZsE ; // input's sign - execute stage
logic XsM , YsM ; // input's sign - memory stage
logic [ `NE - 1 : 0 ] XeE , YeE , ZeE ; // input's exponent - execute stage
2022-12-23 07:58:14 +00:00
logic [ `NE - 1 : 0 ] ZeM ; // input's exponent - memory stage
2022-07-20 02:27:39 +00:00
logic [ `NF : 0 ] XmE , YmE , ZmE ; // input's fraction - execute stage
logic [ `NF : 0 ] XmM , YmM , ZmM ; // input's fraction - memory stage
logic XNaNE , YNaNE , ZNaNE ; // is the input a NaN - execute stage
logic XNaNM , YNaNM , ZNaNM ; // is the input a NaN - memory stage
logic XNaNQ , YNaNQ ; // is the input a NaN - divide
logic XSNaNE , YSNaNE , ZSNaNE ; // is the input a signaling NaN - execute stage
logic XSNaNM , YSNaNM , ZSNaNM ; // is the input a signaling NaN - memory stage
2023-01-06 16:35:23 +00:00
logic XSubnormE , ZSubnormE , ZSubnormM ; // is the input Subnormalized
2022-07-20 02:27:39 +00:00
logic XZeroE , YZeroE , ZZeroE ; // is the input zero - execute stage
logic XZeroM , YZeroM , ZZeroM ; // is the input zero - memory stage
logic XInfE , YInfE , ZInfE ; // is the input infinity - execute stage
logic XInfM , YInfM , ZInfM ; // is the input infinity - memory stage
logic XExpMaxE ; // is the exponent all ones (max value)
2022-06-13 22:47:51 +00:00
// Fma Signals
2022-12-30 18:07:44 +00:00
logic [ 3 * `NF + 3 : 0 ] SmE , SmM ;
logic FmaAStickyE , FmaAStickyM ;
2022-07-20 02:27:39 +00:00
logic [ `NE + 1 : 0 ] SeE , SeM ;
logic InvAE , InvAM ;
logic AsE , AsM ;
logic PsE , PsM ;
logic SsE , SsM ;
2022-12-30 18:07:44 +00:00
logic [ $clog2 ( 3 * `NF + 5 ) - 1 : 0 ] SCntE , SCntM ;
2022-06-13 22:47:51 +00:00
// Cvt Signals
2022-07-20 02:27:39 +00:00
logic [ `NE : 0 ] CeE , CeM ; // the calculated expoent
logic [ `LOGCVTLEN - 1 : 0 ] CvtShiftAmtE , CvtShiftAmtM ; // how much to shift by
2023-01-06 16:35:23 +00:00
logic CvtResSubnormUfE , CvtResSubnormUfM ; // does the result underflow or is Subnormalized
2022-07-20 02:27:39 +00:00
logic CsE , CsM ; // the result's sign
2022-06-23 16:11:50 +00:00
logic IntZeroE , IntZeroM ; // is the integer zero?
2022-07-20 02:27:39 +00:00
logic [ `CVTLEN - 1 : 0 ] CvtLzcInE , CvtLzcInM ; // input to the Leading Zero Counter (priority encoder)
2022-06-23 16:11:50 +00:00
//divide signals
2022-09-20 10:25:09 +00:00
logic [ `DIVb : 0 ] QmM ;
2022-07-20 02:27:39 +00:00
logic [ `NE + 1 : 0 ] QeE , QeM ;
2022-12-26 15:29:19 +00:00
logic DivSM ;
2022-12-02 19:11:53 +00:00
// logic DivDoneM;
2022-12-02 19:30:49 +00:00
logic FDivDoneE , IFDivStartE ;
2021-12-20 00:53:41 +00:00
// result and flag signals
2022-07-20 02:27:39 +00:00
logic [ `XLEN - 1 : 0 ] ClassResE ; // classify result
logic [ `XLEN - 1 : 0 ] FIntResE ; // classify result
logic [ `FLEN - 1 : 0 ] FpResM , FpResW ; // classify result
logic [ `FLEN - 1 : 0 ] PostProcResM ; // classify result
logic [ 4 : 0 ] PostProcFlgM ; // classify result
2022-06-13 22:47:51 +00:00
logic [ `XLEN - 1 : 0 ] FCvtIntResM ;
2022-07-20 02:27:39 +00:00
logic [ `FLEN - 1 : 0 ] CmpFpResE ; // compare result
logic [ `XLEN - 1 : 0 ] CmpIntResE ; // compare result
logic CmpNVE ; // compare invalid flag (Not Valid)
logic [ `FLEN - 1 : 0 ] SgnResE ; // sign injection result
logic [ `FLEN - 1 : 0 ] PreFpResE , PreFpResM ; // selected result that is ready in the memory stage
logic PreNVE , PreNVM ; // selected flag that is ready in the memory stage
logic [ `FLEN - 1 : 0 ] FPUResultW ; // final FP result being written to the FP register
2021-12-20 00:53:41 +00:00
// other signals
2022-07-20 02:27:39 +00:00
logic [ `FLEN - 1 : 0 ] AlignedSrcAE ; // align SrcA to the floating point format
2022-06-02 19:50:28 +00:00
logic [ `FLEN - 1 : 0 ] BoxedZeroE ; // Zero value for Z for multiplication, with NaN boxing if needed
logic [ `FLEN - 1 : 0 ] BoxedOneE ; // Zero value for Z for multiplication, with NaN boxing if needed
2022-12-02 19:30:49 +00:00
logic StallUnpackedM ;
2022-12-15 01:03:13 +00:00
logic [ `XLEN - 1 : 0 ] FPIntDivResultM ;
2022-08-23 19:17:19 +00:00
2021-12-20 00:53:41 +00:00
// DECODE STAGE
2022-06-13 22:47:51 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// |||||||||||
// ||| |||
// ||| |||
// ||| |||
// ||| |||
// ||| |||
// |||||||||||
//////////////////////////////////////////////////////////////////////////////////////////
2021-12-20 00:53:41 +00:00
// calculate FP control signals
2022-09-29 23:30:25 +00:00
fctrl fctrl ( . Funct7D ( InstrD [ 31 : 25 ] ) , . OpD ( InstrD [ 6 : 0 ] ) , . Rs2D ( InstrD [ 24 : 20 ] ) , . Funct3D ( InstrD [ 14 : 12 ] ) ,
. Funct3E , . MDUE , . InstrD ,
2022-07-20 02:27:39 +00:00
. StallE , . StallM , . StallW , . FlushE , . FlushM , . FlushW , . FRM_REGW , . STATUS_FS , . FDivBusyE ,
2022-12-23 18:47:18 +00:00
. reset , . clk , . FRegWriteE , . FRegWriteM , . FRegWriteW , . FrmM , . FmtE , . FmtM ,
. FDivStartE , . IDivStartE , . FWriteIntE , . FCvtIntE , . FWriteIntM , . OpCtrlE , . OpCtrlM , . IllegalFPUInstrM , . XEnD , . YEnD , . ZEnD , . XEnE , . YEnE , . ZEnE ,
. FResSelE , . FResSelM , . FResSelW , . PostProcSelE , . PostProcSelM , . FCvtIntW , . Adr1D , . Adr2D , . Adr3D , . Adr1E , . Adr2E , . Adr3E ) ;
2021-12-20 00:53:41 +00:00
// FP register file
fregfile fregfile ( . clk , . reset , . we4 ( FRegWriteW ) ,
. a1 ( InstrD [ 19 : 15 ] ) , . a2 ( InstrD [ 24 : 20 ] ) , . a3 ( InstrD [ 31 : 27 ] ) ,
. a4 ( RdW ) , . wd4 ( FPUResultW ) ,
. rd1 ( FRD1D ) , . rd2 ( FRD2D ) , . rd3 ( FRD3D ) ) ;
2022-12-02 19:11:53 +00:00
// D/E pipeline registers
2022-06-02 19:50:28 +00:00
flopenrc # ( `FLEN ) DEReg1 ( clk , reset , FlushE , ~ StallE , FRD1D , FRD1E ) ;
flopenrc # ( `FLEN ) DEReg2 ( clk , reset , FlushE , ~ StallE , FRD2D , FRD2E ) ;
flopenrc # ( `FLEN ) DEReg3 ( clk , reset , FlushE , ~ StallE , FRD3D , FRD3E ) ;
2021-12-20 00:53:41 +00:00
// EXECUTION STAGE
2022-06-13 22:47:51 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// ||||||||||||
// |||
// |||
// |||||||||
// |||
// |||
// ||||||||||||
//////////////////////////////////////////////////////////////////////////////////////////
2021-12-20 00:53:41 +00:00
// Hazard unit for FPU
// - determines if any forwarding or stalls are needed
2022-12-23 18:47:18 +00:00
fhazard fhazard ( . Adr1D , . Adr2D , . Adr3D , . Adr1E , . Adr2E , . Adr3E , . FRegWriteE , . FRegWriteM , . FRegWriteW , . RdE , . RdM , . RdW , . FResSelM ,
2022-12-23 20:24:20 +00:00
. XEnD , . YEnD , . ZEnD , . FPUStallD , . ForwardXE , . ForwardYE , . ForwardZE ) ;
2021-12-20 00:53:41 +00:00
// forwarding muxs
2022-07-20 02:27:39 +00:00
mux3 # ( `FLEN ) fxemux ( FRD1E , FPUResultW , PreFpResM , ForwardXE , XE ) ;
mux3 # ( `FLEN ) fyemux ( FRD2E , FPUResultW , PreFpResM , ForwardYE , PreYE ) ;
mux3 # ( `FLEN ) fzemux ( FRD3E , FPUResultW , PreFpResM , ForwardZE , PreZE ) ;
2022-06-02 19:50:28 +00:00
generate
if ( `FPSIZES = = 1 ) assign BoxedOneE = { 2 'b0 , { `NE - 1 { 1 'b1 } } , ( `NF ) ' ( 0 ) } ;
else if ( `FPSIZES = = 2 )
mux2 # ( `FLEN ) fonemux ( { { `FLEN - `LEN1 { 1 'b1 } } , 2 'b0 , { `NE1 - 1 { 1 'b1 } } , ( `NF1 ) ' ( 0 ) } , { 2 'b0 , { `NE - 1 { 1 'b1 } } , ( `NF ) ' ( 0 ) } , FmtE , BoxedOneE ) ; // NaN boxing zeroes
else if ( `FPSIZES = = 3 | `FPSIZES = = 4 )
mux4 # ( `FLEN ) fonemux ( { { `FLEN - `S_LEN { 1 'b1 } } , 2 'b0 , { `S_NE - 1 { 1 'b1 } } , ( `S_NF ) ' ( 0 ) } ,
{ { `FLEN - `D_LEN { 1 'b1 } } , 2 'b0 , { `D_NE - 1 { 1 'b1 } } , ( `D_NF ) ' ( 0 ) } ,
{ { `FLEN - `H_LEN { 1 'b1 } } , 2 'b0 , { `H_NE - 1 { 1 'b1 } } , ( `H_NF ) ' ( 0 ) } ,
{ 2 'b0 , { `NE - 1 { 1 'b1 } } , ( `NF ) ' ( 0 ) } , FmtE , BoxedOneE ) ; // NaN boxing zeroes
endgenerate
2022-07-20 02:27:39 +00:00
mux2 # ( `FLEN ) fyaddmux ( PreYE , BoxedOneE , OpCtrlE [ 2 ] & OpCtrlE [ 1 ] & ( FResSelE = = 2 'b01 ) & ( PostProcSelE = = 2 'b10 ) , YE ) ; // Force Z to be 0 for multiply instructions
2022-06-02 19:50:28 +00:00
2022-01-06 23:03:29 +00:00
// Force Z to be 0 for multiply instructions
2022-06-02 19:50:28 +00:00
generate
if ( `FPSIZES = = 1 ) assign BoxedZeroE = 0 ;
else if ( `FPSIZES = = 2 )
2022-06-06 16:06:04 +00:00
mux2 # ( `FLEN ) fmulzeromux ( { { `FLEN - `LEN1 { 1 'b1 } } , { `LEN1 { 1 'b0 } } } , ( `FLEN ) ' ( 0 ) , FmtE , BoxedZeroE ) ; // NaN boxing zeroes
2022-06-02 19:50:28 +00:00
else if ( `FPSIZES = = 3 | `FPSIZES = = 4 )
2022-06-06 16:06:04 +00:00
mux4 # ( `FLEN ) fmulzeromux ( { { `FLEN - `S_LEN { 1 'b1 } } , { `S_LEN { 1 'b0 } } } ,
{ { `FLEN - `D_LEN { 1 'b1 } } , { `D_LEN { 1 'b0 } } } ,
{ { `FLEN - `H_LEN { 1 'b1 } } , { `H_LEN { 1 'b0 } } } ,
2022-06-02 19:50:28 +00:00
( `FLEN ) ' ( 0 ) , FmtE , BoxedZeroE ) ; // NaN boxing zeroes
endgenerate
2022-07-20 02:27:39 +00:00
mux3 # ( `FLEN ) fzmulmux ( PreZE , BoxedZeroE , PreYE , { OpCtrlE [ 2 ] & OpCtrlE [ 1 ] , OpCtrlE [ 2 ] & ~ OpCtrlE [ 1 ] } , ZE ) ;
2022-06-02 19:50:28 +00:00
2022-02-28 20:50:51 +00:00
// unpack unit
2021-12-20 00:53:41 +00:00
// - splits FP inputs into their various parts
2023-01-06 16:35:23 +00:00
// - does some classifications (SNaN, NaN, Subnorm, Norm, Zero, Infifnity)
2022-07-20 02:27:39 +00:00
unpack unpack ( . X ( XE ) , . Y ( YE ) , . Z ( ZE ) , . Fmt ( FmtE ) , . Xs ( XsE ) , . Ys ( YsE ) , . Zs ( ZsE ) ,
2022-07-21 01:20:06 +00:00
. Xe ( XeE ) , . Ye ( YeE ) , . Ze ( ZeE ) , . Xm ( XmE ) , . Ym ( YmE ) , . Zm ( ZmE ) , . YEn ( YEnE ) ,
. XNaN ( XNaNE ) , . YNaN ( YNaNE ) , . ZNaN ( ZNaNE ) , . XSNaN ( XSNaNE ) , . XEn ( XEnE ) ,
2023-01-06 16:35:23 +00:00
. YSNaN ( YSNaNE ) , . ZSNaN ( ZSNaNE ) , . XSubnorm ( XSubnormE ) , . ZSubnorm ( ZSubnormE ) ,
2022-07-20 02:27:39 +00:00
. XZero ( XZeroE ) , . YZero ( YZeroE ) , . ZZero ( ZZeroE ) , . XInf ( XInfE ) , . YInf ( YInfE ) ,
2022-07-21 01:20:06 +00:00
. ZEn ( ZEnE ) , . ZInf ( ZInfE ) , . XExpMax ( XExpMaxE ) ) ;
2022-06-13 22:47:51 +00:00
2022-07-20 02:27:39 +00:00
// fused multiply add
// - fadd/fsub
// - 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 ) ,
2022-07-07 23:01:33 +00:00
. XZero ( XZeroE ) , . YZero ( YZeroE ) , . ZZero ( ZZeroE ) ,
2022-12-23 08:18:39 +00:00
. OpCtrl ( OpCtrlE ) ,
2022-07-20 02:27:39 +00:00
. As ( AsE ) , . Ps ( PsE ) , . Ss ( SsE ) , . Se ( SeE ) ,
2022-12-21 19:31:22 +00:00
. Sm ( SmE ) ,
2022-12-20 22:43:30 +00:00
. InvA ( InvAE ) , . SCnt ( SCntE ) ,
2022-12-30 18:07:44 +00:00
. ASticky ( FmaAStickyE ) ) ;
2022-07-20 02:27:39 +00:00
// divide and squareroot
// - fdiv
// - fsqrt
// *** add other opperations
2022-08-29 11:04:05 +00:00
fdivsqrt fdivsqrt ( . clk , . reset , . FmtE , . XmE , . YmE , . XeE , . YeE , . SqrtE ( OpCtrlE [ 0 ] ) , . SqrtM ( OpCtrlM [ 0 ] ) ,
2022-11-16 18:00:07 +00:00
. XInfE , . YInfE , . XZeroE , . YZeroE , . XNaNE , . YNaNE , . FDivStartE , . IDivStartE , . XsE ,
2022-09-29 23:08:27 +00:00
. ForwardedSrcAE , . ForwardedSrcBE , . Funct3E , . Funct3M , . MDUE , . W64E ,
2022-12-23 08:18:39 +00:00
. StallM , . FlushE , . DivSM , . FDivBusyE , . IFDivStartE , . FDivDoneE , . QeM ,
2022-12-15 01:03:13 +00:00
. QmM , . FPIntDivResultM /*, .DivDone(DivDoneM) */ ) ;
2022-09-29 23:08:27 +00:00
//
2022-07-20 02:27:39 +00:00
// compare
// - fmin/fmax
// - flt/fle/feq
fcmp fcmp ( . Fmt ( FmtE ) , . OpCtrl ( OpCtrlE ) , . Xs ( XsE ) , . Ys ( YsE ) , . Xe ( XeE ) , . Ye ( YeE ) ,
. Xm ( XmE ) , . Ym ( YmE ) , . XZero ( XZeroE ) , . YZero ( YZeroE ) , . XNaN ( XNaNE ) , . YNaN ( YNaNE ) ,
. XSNaN ( XSNaNE ) , . YSNaN ( YSNaNE ) , . X ( XE ) , . Y ( YE ) , . CmpNV ( CmpNVE ) ,
. CmpFpRes ( CmpFpResE ) , . CmpIntRes ( CmpIntResE ) ) ;
// sign injection
// - fsgnj/fsgnjx/fsgnjn
fsgninj fsgninj ( . OpCtrl ( OpCtrlE [ 1 : 0 ] ) , . Xs ( XsE ) , . Ys ( YsE ) , . X ( XE ) , . Fmt ( FmtE ) , . SgnRes ( SgnResE ) ) ;
// classify
// - fclass
2023-01-06 16:35:23 +00:00
fclassify fclassify ( . Xs ( XsE ) , . XSubnorm ( XSubnormE ) , . XZero ( XZeroE ) , . XNaN ( XNaNE ) ,
2022-07-20 02:27:39 +00:00
. XInf ( XInfE ) , . XSNaN ( XSNaNE ) , . ClassRes ( ClassResE ) ) ;
// convert
// - fcvt.*.*
fcvt fcvt ( . Xs ( XsE ) , . Xe ( XeE ) , . Xm ( XmE ) , . Int ( ForwardedSrcAE ) , . OpCtrl ( OpCtrlE ) ,
2023-01-07 13:34:58 +00:00
. ToInt ( FWriteIntE ) , . XZero ( XZeroE ) , . Fmt ( FmtE ) , . Ce ( CeE ) ,
2023-01-06 16:35:23 +00:00
. ShiftAmt ( CvtShiftAmtE ) , . ResSubnormUf ( CvtResSubnormUfE ) , . Cs ( CsE ) , . IntZero ( IntZeroE ) ,
2022-07-08 19:30:43 +00:00
. LzcIn ( CvtLzcInE ) ) ;
2021-12-20 00:53:41 +00:00
// data to be stored in memory - to IEU
// - FP uses NaN-blocking format
// - if there are any unsused bits the most significant bits are filled with 1s
2022-08-03 22:16:51 +00:00
2022-08-23 15:46:03 +00:00
flopenrc # ( `FLEN ) FWriteDataMReg ( clk , reset , FlushM , ~ StallM , YE , FWriteDataM ) ;
2021-12-20 00:53:41 +00:00
2022-06-02 19:50:28 +00:00
// NaN Block SrcA
generate
if ( `FPSIZES = = 1 ) assign AlignedSrcAE = { { `FLEN - `XLEN { 1 'b1 } } , ForwardedSrcAE } ;
else if ( `FPSIZES = = 2 )
mux2 # ( `FLEN ) SrcAMux ( { { `FLEN - `LEN1 { 1 'b1 } } , ForwardedSrcAE [ `LEN1 - 1 : 0 ] } , { { `FLEN - `XLEN { 1 'b1 } } , ForwardedSrcAE } , FmtE , AlignedSrcAE ) ;
else if ( `FPSIZES = = 3 | `FPSIZES = = 4 )
mux4 # ( `FLEN ) SrcAMux ( { { `FLEN - `S_LEN { 1 'b1 } } , ForwardedSrcAE [ `S_LEN - 1 : 0 ] } ,
{ { `FLEN - `D_LEN { 1 'b1 } } , ForwardedSrcAE [ `D_LEN - 1 : 0 ] } ,
{ { `FLEN - `H_LEN { 1 'b1 } } , ForwardedSrcAE [ `H_LEN - 1 : 0 ] } ,
{ { `FLEN - `XLEN { 1 'b1 } } , ForwardedSrcAE } , FmtE , AlignedSrcAE ) ; // NaN boxing zeroes
endgenerate
2022-08-03 22:16:51 +00:00
2021-12-20 00:53:41 +00:00
// select a result that may be written to the FP register
2022-07-20 02:27:39 +00:00
mux3 # ( `FLEN ) FResMux ( SgnResE , AlignedSrcAE , CmpFpResE , { OpCtrlE [ 2 ] , & OpCtrlE [ 1 : 0 ] } , PreFpResE ) ;
assign PreNVE = CmpNVE & ( OpCtrlE [ 2 ] | FWriteIntE ) ;
2021-12-20 00:53:41 +00:00
// select the result that may be written to the integer register - to IEU
2022-08-01 19:56:25 +00:00
logic [ `FLEN - 1 : 0 ] SgnExtXE ;
generate
if ( `FPSIZES = = 1 )
assign SgnExtXE = XE ;
else if ( `FPSIZES = = 2 )
mux2 # ( `FLEN ) sgnextmux ( { { `FLEN - `LEN1 { XsE } } , XE [ `LEN1 - 1 : 0 ] } , XE , FmtE , SgnExtXE ) ;
else if ( `FPSIZES = = 3 | `FPSIZES = = 4 )
mux4 # ( `FLEN ) fmulzeromux ( { { `FLEN - `H_LEN { XsE } } , XE [ `H_LEN - 1 : 0 ] } ,
{ { `FLEN - `S_LEN { XsE } } , XE [ `S_LEN - 1 : 0 ] } ,
{ { `FLEN - `D_LEN { XsE } } , XE [ `D_LEN - 1 : 0 ] } ,
XE , FmtE , SgnExtXE ) ; // NaN boxing zeroes
endgenerate
2022-06-28 21:33:31 +00:00
if ( `FLEN > `XLEN )
2022-08-01 19:56:25 +00:00
assign IntSrcXE = SgnExtXE [ `XLEN - 1 : 0 ] ;
2022-06-06 16:06:04 +00:00
else
2022-08-01 19:56:25 +00:00
assign IntSrcXE = { { `XLEN - `FLEN { XsE } } , SgnExtXE } ;
2022-06-13 22:47:51 +00:00
mux3 # ( `XLEN ) IntResMux ( ClassResE , IntSrcXE , CmpIntResE , { ~ FResSelE [ 1 ] , FResSelE [ 0 ] } , FIntResE ) ;
2022-05-28 09:41:48 +00:00
// *** DH 5/25/22: CvtRes will move to mem stage. Premux in execute to save area, then make sure stalls are ok
2022-05-28 09:44:55 +00:00
// *** make sure the fpu matches the chapter diagram
2021-12-20 00:53:41 +00:00
// E/M pipe registers
2022-12-02 19:30:49 +00:00
assign StallUnpackedM = StallM | ( FDivBusyE & ~ IFDivStartE | FDivDoneE ) ; // Need to stall during divsqrt iterations to avoid capturing bad flags from stale forwarded sources
2022-12-02 19:11:53 +00:00
flopenrc # ( `NF + 1 ) EMFpReg2 ( clk , reset , FlushM , ~ StallM , XmE , XmM ) ;
flopenrc # ( `NF + 1 ) EMFpReg3 ( clk , reset , FlushM , ~ StallM , YmE , YmM ) ;
2022-12-23 07:58:14 +00:00
flopenrc # ( `FLEN ) EMFpReg4 ( clk , reset , FlushM , ~ StallM , { ZeE , ZmE } , { ZeM , ZmM } ) ;
2022-06-13 22:47:51 +00:00
flopenrc # ( `XLEN ) EMFpReg6 ( clk , reset , FlushM , ~ StallM , FIntResE , FIntResM ) ;
flopenrc # ( `FLEN ) EMFpReg7 ( clk , reset , FlushM , ~ StallM , PreFpResE , PreFpResM ) ;
2022-12-02 19:30:49 +00:00
flopenr # ( 15 ) EMFpReg5 ( clk , reset , ~ StallUnpackedM ,
2023-01-06 16:35:23 +00:00
{ XsE , YsE , XZeroE , YZeroE , ZZeroE , XInfE , YInfE , ZInfE , XNaNE , YNaNE , ZNaNE , XSNaNE , YSNaNE , ZSNaNE , ZSubnormE } ,
{ XsM , YsM , XZeroM , YZeroM , ZZeroM , XInfM , YInfM , ZInfM , XNaNM , YNaNM , ZNaNM , XSNaNM , YSNaNM , ZSNaNM , ZSubnormM } ) ;
2022-06-13 22:47:51 +00:00
flopenrc # ( 1 ) EMRegCmpFlg ( clk , reset , FlushM , ~ StallM , PreNVE , PreNVM ) ;
2022-12-30 18:07:44 +00:00
flopenrc # ( 3 * `NF + 4 ) EMRegFma2 ( clk , reset , FlushM , ~ StallM , SmE , SmM ) ;
flopenrc # ( $clog2 ( 3 * `NF + 5 ) + 7 + `NE ) EMRegFma4 ( clk , reset , FlushM , ~ StallM ,
{ FmaAStickyE , InvAE , SCntE , AsE , PsE , SsE , SeE } ,
{ FmaAStickyM , InvAM , SCntM , AsM , PsM , SsM , SeM } ) ;
2022-06-23 00:07:34 +00:00
flopenrc # ( `NE + `LOGCVTLEN + `CVTLEN + 4 ) EMRegCvt ( clk , reset , FlushM , ~ StallM ,
2023-01-06 16:35:23 +00:00
{ CeE , CvtShiftAmtE , CvtResSubnormUfE , CsE , IntZeroE , CvtLzcInE } ,
{ CeM , CvtShiftAmtM , CvtResSubnormUfM , CsM , IntZeroM , CvtLzcInM } ) ;
2021-12-20 00:53:41 +00:00
// BEGIN MEMORY STAGE
2022-06-13 22:47:51 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// ||| |||
// |||||| ||||||
// ||| ||| ||| |||
// ||| ||||| |||
// ||| ||| |||
// ||| |||
// ||| |||
//////////////////////////////////////////////////////////////////////////////////////////
2022-06-28 21:33:31 +00:00
assign FpLoadStoreM = FResSelM [ 1 ] ;
2022-06-20 22:53:13 +00:00
2022-12-23 08:18:39 +00:00
postprocess postprocess ( . Xs ( XsM ) , . Ys ( YsM ) , . Xm ( XmM ) , . Ym ( YmM ) , . Zm ( ZmM ) , . Frm ( FrmM ) , . Fmt ( FmtM ) ,
2022-12-30 18:07:44 +00:00
. FmaASticky ( FmaAStickyM ) , . XZero ( XZeroM ) , . YZero ( YZeroM ) , . ZZero ( ZZeroM ) , . XInf ( XInfM ) , . YInf ( YInfM ) , . DivQm ( QmM ) , . FmaSs ( SsM ) ,
2022-12-02 19:11:53 +00:00
. ZInf ( ZInfM ) , . XNaN ( XNaNM ) , . YNaN ( YNaNM ) , . ZNaN ( ZNaNM ) , . XSNaN ( XSNaNM ) , . YSNaN ( YSNaNM ) , . ZSNaN ( ZSNaNM ) , . FmaSm ( SmM ) , . DivQe ( QeM ) , /*.DivDone(DivDoneM), */
2023-01-06 16:35:23 +00:00
. ZSubnorm ( ZSubnormM ) , . FmaAs ( AsM ) , . FmaPs ( PsM ) , . OpCtrl ( OpCtrlM ) , . FmaSCnt ( SCntM ) , . FmaSe ( SeM ) ,
. CvtCe ( CeM ) , . CvtResSubnormUf ( CvtResSubnormUfM ) , . CvtShiftAmt ( CvtShiftAmtM ) , . CvtCs ( CsM ) , . ToInt ( FWriteIntM ) , . DivS ( DivSM ) ,
2022-07-12 01:30:21 +00:00
. CvtLzcIn ( CvtLzcInM ) , . IntZero ( IntZeroM ) , . PostProcSel ( PostProcSelM ) , . PostProcRes ( PostProcResM ) , . PostProcFlg ( PostProcFlgM ) , . FCvtIntRes ( FCvtIntResM ) ) ;
2022-06-13 22:47:51 +00:00
2021-12-20 00:53:41 +00:00
// FPU flag selection - to privileged
2022-06-13 22:47:51 +00:00
mux2 # ( 5 ) FPUFlgMux ( { PreNVM & ~ FResSelM [ 1 ] , 4 'b0 } , PostProcFlgM , ~ FResSelM [ 1 ] & FResSelM [ 0 ] , SetFflagsM ) ;
mux2 # ( `FLEN ) FPUResMux ( PreFpResM , PostProcResM , FResSelM [ 0 ] , FpResM ) ;
2021-12-20 00:53:41 +00:00
// M/W pipe registers
2022-06-13 22:47:51 +00:00
flopenrc # ( `FLEN ) MWRegFp ( clk , reset , FlushW , ~ StallW , FpResM , FpResW ) ;
2022-12-15 01:03:13 +00:00
flopenrc # ( `XLEN ) MWRegIntCvtRes ( clk , reset , FlushW , ~ StallW , FCvtIntResM , FCvtIntResW ) ;
flopenrc # ( `XLEN ) MWRegIntDivRes ( clk , reset , FlushW , ~ StallW , FPIntDivResultM , FPIntDivResultW ) ;
2021-12-20 00:53:41 +00:00
// BEGIN WRITEBACK STAGE
2022-06-13 22:47:51 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// ||| |||
// ||| |||
// ||| ||| |||
// ||| ||||| |||
// ||| ||| ||| |||
// |||||| ||||||
// ||| |||
//////////////////////////////////////////////////////////////////////////////////////////
2021-12-20 00:53:41 +00:00
// select the result to be written to the FP register
2022-06-20 22:53:13 +00:00
mux2 # ( `FLEN ) FPUResultMux ( FpResW , ReadDataW , FResSelW [ 1 ] , FPUResultW ) ;
2022-06-13 22:47:51 +00:00
2021-06-01 19:45:32 +00:00
endmodule // fpu