/////////////////////////////////////////// // fdivsqrtfsm.sv // // Written: David_Harris@hmc.edu, me@KatherineParry.com, cturek@hmc.edu // Modified:13 January 2022 // // Purpose: divsqrt state machine for multi-cycle operations // // Documentation: RISC-V System on Chip Design Chapter 13 // // A component of the CORE-V-WALLY configurable RISC-V project. // // Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University // // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // // Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file // except in compliance with the License, or, at your option, the Apache License version 2.0. You // may obtain a copy of the License at // // https://solderpad.org/licenses/SHL-2.1/ // // Unless required by applicable law or agreed to in writing, any work distributed under the // License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// `include "wally-config.vh" module fdivsqrtfsm( input logic clk, reset, input logic XInfE, YInfE, input logic XZeroE, YZeroE, input logic XNaNE, YNaNE, input logic FDivStartE, IDivStartE, input logic XsE, WZeroE, input logic SqrtE, input logic StallM, FlushE, input logic IntDivE, input logic ISpecialCaseE, input logic [`DURLEN-1:0] cycles, output logic IFDivStartE, output logic FDivBusyE, FDivDoneE, output logic SpecialCaseM ); typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; statetype state; logic SpecialCaseE, FSpecialCaseE; logic [`DURLEN-1:0] step; // FDivStartE and IDivStartE come from fctrl, reflecitng the start of floating-point and possibly integer division assign IFDivStartE = (FDivStartE | (IDivStartE & `IDIV_ON_FPU)) & (state == IDLE) & ~StallM; assign FDivDoneE = (state == DONE); assign FDivBusyE = (state == BUSY) | IFDivStartE; // terminate immediately on special cases assign FSpecialCaseE = XZeroE | | XInfE | XNaNE | (XsE&SqrtE) | (YZeroE | YInfE | YNaNE)&~SqrtE; if (`IDIV_ON_FPU) assign SpecialCaseE = IntDivE ? ISpecialCaseE : FSpecialCaseE; else assign SpecialCaseE = FSpecialCaseE; flopenr #(1) SpecialCaseReg(clk, reset, IFDivStartE, SpecialCaseE, SpecialCaseM); // save SpecialCase for checking in fdivsqrtpostproc always_ff @(posedge clk) begin if (reset | FlushE) begin state <= #1 IDLE; end else if (IFDivStartE) begin // IFDivStartE implies stat is IDLE // end else if ((state == IDLE) & IFDivStartE) begin // IFDivStartE implies stat is IDLE step <= cycles; if (SpecialCaseE) state <= #1 DONE; else state <= #1 BUSY; end else if (state == BUSY) begin if (step == 1 | WZeroE) state <= #1 DONE; // finished steps or terminate early on zero residual step <= step - 1; end else if (state == DONE) begin if (StallM) state <= #1 DONE; else state <= #1 IDLE; end end endmodule