2022-07-07 23:01:33 +00:00
///////////////////////////////////////////
2022-08-29 11:04:05 +00:00
// fdivsqrtfsm.sv
2022-07-07 23:01:33 +00:00
//
2022-09-19 21:26:32 +00:00
// Written: David_Harris@hmc.edu, me@KatherineParry.com, cturek@hmc.edu
2022-07-07 23:01:33 +00:00
// Modified:13 January 2022
//
// Purpose: Combined Divide and Square Root Floating Point and Integer Unit
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// 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:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
`include " wally-config.vh "
2022-08-29 11:04:05 +00:00
module fdivsqrtfsm (
2022-07-07 23:01:33 +00:00
input logic clk ,
input logic reset ,
2022-09-17 16:55:34 +00:00
input logic [ `FMTBITS - 1 : 0 ] FmtE ,
2022-07-07 23:01:33 +00:00
input logic XInfE , YInfE ,
input logic XZeroE , YZeroE ,
input logic XNaNE , YNaNE ,
2022-11-16 18:00:07 +00:00
input logic FDivStartE , IDivStartE ,
2022-07-22 22:02:04 +00:00
input logic XsE ,
input logic SqrtE ,
2022-07-15 20:16:59 +00:00
input logic StallE ,
input logic StallM ,
2022-12-02 19:11:53 +00:00
input logic TrapM ,
2022-11-11 00:23:25 +00:00
input logic WZero ,
input logic MDUE ,
input logic [ `DIVBLEN : 0 ] n ,
2022-11-16 18:00:07 +00:00
output logic DivStartE ,
2022-12-02 19:11:53 +00:00
// output logic DivDone,
output logic FDivBusyE , FDivDoneE ,
2022-09-21 11:55:43 +00:00
output logic SpecialCaseM
2022-08-23 17:14:54 +00:00
) ;
2022-07-07 23:01:33 +00:00
typedef enum logic [ 1 : 0 ] { IDLE , BUSY , DONE } statetype ;
statetype state ;
2022-07-12 01:30:21 +00:00
logic [ `DURLEN - 1 : 0 ] step ;
2022-09-17 12:58:59 +00:00
logic [ `DURLEN - 1 : 0 ] cycles ;
2022-09-21 11:55:43 +00:00
logic SpecialCaseE ;
2022-09-07 13:32:07 +00:00
2022-11-16 18:00:07 +00:00
// *** start logic is presently in fctl. Make it look more like integer division start logic
// DivStartE comes from fctrl, reflecitng the start of floating-point and possibly integer division
2022-11-16 18:13:27 +00:00
assign DivStartE = ( FDivStartE | IDivStartE ) & ( state = = IDLE ) & ~ StallM ;
2022-12-02 19:11:53 +00:00
assign FDivDoneE = ( state = = DONE ) ;
// assign DivDone = (state == DONE) | (WZero & (state == BUSY)); // *** used in postprocess.sv and round.sv. This doesn't seem proper. They break when removed.
//assign FDivBusyE = (state == BUSY & ~DivDone); // *** want to add | DivStartE but it creates comb loop
assign FDivBusyE = ( state = = BUSY ) | DivStartE ;
2022-11-16 18:00:07 +00:00
// Divider control signals from MDU
//assign DivBusyE = (state == BUSY) | DivStartE;
2022-08-29 11:29:58 +00:00
// terminate immediately on special cases
2022-09-21 11:55:43 +00:00
assign SpecialCaseE = XZeroE | ( YZeroE & ~ SqrtE ) | XInfE | YInfE | XNaNE | YNaNE | ( XsE & SqrtE ) ;
2022-09-21 12:02:08 +00:00
flopenr # ( 1 ) SpecialCaseReg ( clk , reset , ~ StallM , SpecialCaseE , SpecialCaseM ) ; // save SpecialCase for checking in fdivsqrtpostproc
2022-08-29 11:29:58 +00:00
2022-09-17 16:55:34 +00:00
// DIVN = `NF+3
// NS = NF + 1
// N = NS or NS+2 for div/sqrt.
/* verilator lint_off WIDTH */
logic [ `DURLEN + 1 : 0 ] Nf , fbits ; // number of fractional bits
if ( `FPSIZES = = 1 )
assign Nf = `NF ;
else if ( `FPSIZES = = 2 )
always_comb
case ( FmtE )
1 'b0 : Nf = `NF1 ;
1 'b1 : Nf = `NF ;
endcase
else if ( `FPSIZES = = 3 )
always_comb
case ( FmtE )
`FMT : Nf = `NF ;
`FMT1 : Nf = `NF1 ;
`FMT2 : Nf = `NF2 ;
endcase
else if ( `FPSIZES = = 4 )
always_comb
case ( FmtE )
`S_FMT : Nf = `S_NF ;
`D_FMT : Nf = `D_NF ;
`H_FMT : Nf = `H_NF ;
`Q_FMT : Nf = `Q_NF ;
endcase
always_comb begin
if ( SqrtE ) fbits = Nf + 2 + 2 ; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2
else fbits = Nf + 2 + `LOGR ; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs
2022-11-11 00:23:25 +00:00
cycles = MDUE ? n : ( fbits + ( `LOGR * `DIVCOPIES ) - 1 ) / ( `LOGR * `DIVCOPIES ) ;
2022-09-17 16:55:34 +00:00
end
/* verilator lint_on WIDTH */
2022-09-17 12:58:59 +00:00
2022-12-02 19:11:53 +00:00
always_ff @ ( posedge clk ) begin
if ( reset | TrapM ) begin
state < = # 1 IDLE ;
end else if ( DivStartE ) begin
step < = cycles ;
if ( SpecialCaseE ) state < = # 1 DONE ;
else state < = # 1 BUSY ;
end else if ( state = = BUSY ) begin
if ( step = = 1 ) state < = # 1 DONE ;
step < = step - 1 ;
end else if ( ( state = = DONE ) | ( WZero & ( state = = BUSY ) ) ) begin
if ( StallM ) state < = # 1 DONE ;
else state < = # 1 IDLE ;
end
end
/ *
2022-07-07 23:01:33 +00:00
always_ff @ ( posedge clk ) begin
if ( reset ) begin
state < = # 1 IDLE ;
2022-09-29 23:30:25 +00:00
end else if ( DivStartE & ~ StallE ) begin
step < = cycles ;
2022-09-17 16:55:34 +00:00
// $display("Setting Nf = %d fbits %d cycles = %d FmtE %d FPSIZES = %d Q_NF = %d num = %d denom = %d\n", Nf, fbits, cycles, FmtE, `FPSIZES, `Q_NF,
// (fbits +(`LOGR*`DIVCOPIES)-1), (`LOGR*`DIVCOPIES));
2022-09-21 11:55:43 +00:00
if ( SpecialCaseE ) state < = # 1 DONE ;
2022-08-29 11:29:58 +00:00
else state < = # 1 BUSY ;
2022-08-29 19:01:09 +00:00
end else if ( DivDone ) begin
if ( StallM ) state < = # 1 DONE ;
else state < = # 1 IDLE ;
2022-07-07 23:01:33 +00:00
end else if ( state = = BUSY ) begin
2022-08-31 17:54:50 +00:00
if ( step = = 1 ) begin
2022-07-07 23:01:33 +00:00
state < = # 1 DONE ;
end
step < = step - 1 ;
end
end
2022-12-02 19:11:53 +00:00
*/
2022-09-07 13:27:01 +00:00
2022-07-07 23:01:33 +00:00
endmodule