cvw/src/fpu/fdivsqrt/fdivsqrtiter.sv

141 lines
5.3 KiB
Systemverilog
Raw Normal View History

2022-07-15 21:42:45 +00:00
///////////////////////////////////////////
2022-08-29 11:04:05 +00:00
// fdivsqrtiter.sv
2022-07-15 21:42:45 +00:00
//
// Written: David_Harris@hmc.edu, me@KatherineParry.com, cturek@hmc.edu
// Modified:13 January 2022
//
2023-01-12 12:35:44 +00:00
// Purpose: k stages of divsqrt logic, plus registers
2022-07-15 21:42:45 +00:00
//
2023-01-12 12:35:44 +00:00
// Documentation: RISC-V System on Chip Design Chapter 13
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
2022-07-15 21:42:45 +00:00
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
2022-07-15 21:42:45 +00:00
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
2022-07-15 21:42:45 +00:00
//
// 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
2022-07-15 21:42:45 +00:00
//
// 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.
2022-07-15 21:42:45 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
2022-08-29 11:04:05 +00:00
module fdivsqrtiter(
2022-07-15 21:42:45 +00:00
input logic clk,
2022-12-02 19:30:49 +00:00
input logic IFDivStartE,
2022-11-16 18:13:27 +00:00
input logic FDivBusyE,
input logic SqrtE,
2022-09-14 17:26:56 +00:00
input logic [`DIVb+3:0] X,
input logic [`DIVb-1:0] DPreproc,
output logic [`DIVb-1:0] D,
output logic [`DIVb:0] FirstU, FirstUM,
output logic [`DIVb+1:0] FirstC,
output logic Firstun,
output logic [`DIVb+3:0] FirstWS, FirstWC
2022-07-15 21:42:45 +00:00
);
/* verilator lint_off UNOPTFLAT */
logic [`DIVb+3:0] WSNext[`DIVCOPIES-1:0]; // Q4.b
logic [`DIVb+3:0] WCNext[`DIVCOPIES-1:0]; // Q4.b
logic [`DIVb+3:0] WS[`DIVCOPIES:0]; // Q4.b
logic [`DIVb+3:0] WC[`DIVCOPIES:0]; // Q4.b
logic [`DIVb:0] U[`DIVCOPIES:0]; // U1.b
logic [`DIVb:0] UM[`DIVCOPIES:0]; // U1.b
logic [`DIVb:0] UNext[`DIVCOPIES-1:0]; // U1.b
logic [`DIVb:0] UMNext[`DIVCOPIES-1:0]; // U1.b
logic [`DIVb+1:0] C[`DIVCOPIES:0]; // Q2.b
logic [`DIVb+1:0] initC; // Q2.b
logic [`DIVCOPIES-1:0] un;
2022-09-07 18:36:35 +00:00
logic [`DIVb+3:0] WSN, WCN; // Q4.b
logic [`DIVb+3:0] DBar, D2, DBar2; // Q4.b
logic [`DIVb+1:0] NextC;
logic [`DIVb:0] UMux, UMMux;
logic [`DIVb:0] initU, initUM;
/* verilator lint_on UNOPTFLAT */
2022-07-15 21:42:45 +00:00
// Top Muxes and Registers
// When start is asserted, the inputs are loaded into the divider.
// Otherwise, the divisor is retained and the residual and result
// are fed back for the next iteration.
2022-10-09 10:37:27 +00:00
// Residual WS/SC registers/initializaiton mux
2022-12-02 19:30:49 +00:00
mux2 #(`DIVb+4) wsmux(WS[`DIVCOPIES], X, IFDivStartE, WSN);
mux2 #(`DIVb+4) wcmux(WC[`DIVCOPIES], '0, IFDivStartE, WCN);
flopen #(`DIVb+4) wsreg(clk, FDivBusyE, WSN, WS[0]);
flopen #(`DIVb+4) wcreg(clk, FDivBusyE, WCN, WC[0]);
2022-10-09 10:37:27 +00:00
// UOTFC Result U and UM registers/initialization mux
2022-12-30 23:13:52 +00:00
// Initialize U to 1.0 and UM to 0 for square root; U to 0 and UM to -1 otherwise
assign initU = {SqrtE, {(`DIVb){1'b0}}};
assign initUM = {~SqrtE, {(`DIVb){1'b0}}};
mux2 #(`DIVb+1) Umux(UNext[`DIVCOPIES-1], initU, IFDivStartE, UMux);
mux2 #(`DIVb+1) UMmux(UMNext[`DIVCOPIES-1], initUM, IFDivStartE, UMMux);
flopen #(`DIVb+1) UReg(clk, IFDivStartE|FDivBusyE, UMux, U[0]);
flopen #(`DIVb+1) UMReg(clk, IFDivStartE|FDivBusyE, UMMux, UM[0]);
2022-10-09 10:37:27 +00:00
// C register/initialization mux
// Initialize C to -1 for sqrt and -R for division
2022-10-09 10:37:27 +00:00
logic [1:0] initCUpper;
if(`RADIX == 4) begin
mux2 #(2) cuppermux4(2'b00, 2'b11, SqrtE, initCUpper);
end else begin
mux2 #(2) cuppermux2(2'b10, 2'b11, SqrtE, initCUpper);
end
assign initC = {initCUpper, {`DIVb{1'b0}}};
mux2 #(`DIVb+2) cmux(C[`DIVCOPIES], initC, IFDivStartE, NextC);
2022-12-23 08:18:39 +00:00
flopen #(`DIVb+2) creg(clk, IFDivStartE|FDivBusyE, NextC, C[0]);
2022-07-15 21:42:45 +00:00
2022-10-09 10:37:27 +00:00
// Divisior register
flopen #(`DIVb) dreg(clk, IFDivStartE, DPreproc, D);
2022-10-09 10:37:27 +00:00
2022-07-15 21:42:45 +00:00
// Divisor Selections
2022-07-22 22:02:04 +00:00
// - choose the negitive version of what's being selected
// - D is a 0.b mantissa
assign DBar = {3'b111, 1'b0, ~D};
2022-07-15 21:42:45 +00:00
if(`RADIX == 4) begin : d2
assign DBar2 = {2'b11, 1'b0, ~D, 1'b1};
assign D2 = {2'b0, 1'b1, D, 1'b0};
2022-07-15 21:42:45 +00:00
end
2022-10-09 10:37:27 +00:00
// k=DIVCOPIES of the recurrence logic
2022-07-15 21:42:45 +00:00
genvar i;
generate
for(i=0; $unsigned(i)<`DIVCOPIES; i++) begin : iterations
if (`RADIX == 2) begin: stage
fdivsqrtstage2 fdivsqrtstage(.D, .DBar, .SqrtE,
.WS(WS[i]), .WC(WC[i]), .WSNext(WSNext[i]), .WCNext(WCNext[i]),
.C(C[i]), .U(U[i]), .UM(UM[i]), .CNext(C[i+1]), .UNext(UNext[i]), .UMNext(UMNext[i]), .un(un[i]));
end else begin: stage
2022-09-01 23:57:57 +00:00
logic j1;
2022-09-16 02:15:48 +00:00
assign j1 = (i == 0 & ~C[0][`DIVb-1]);
fdivsqrtstage4 fdivsqrtstage(.D, .DBar, .D2, .DBar2, .SqrtE, .j1,
.WS(WS[i]), .WC(WC[i]), .WSNext(WSNext[i]), .WCNext(WCNext[i]),
.C(C[i]), .U(U[i]), .UM(UM[i]), .CNext(C[i+1]), .UNext(UNext[i]), .UMNext(UMNext[i]), .un(un[i]));
end
assign WS[i+1] = WSNext[i];
assign WC[i+1] = WCNext[i];
2022-10-09 10:37:27 +00:00
assign U[i+1] = UNext[i];
assign UM[i+1] = UMNext[i];
2022-07-15 21:42:45 +00:00
end
endgenerate
2022-10-09 10:37:27 +00:00
// Send values from start of cycle for postprocessing
2022-07-15 21:42:45 +00:00
assign FirstWS = WS[0];
assign FirstWC = WC[0];
assign FirstU = U[0];
2022-09-19 07:43:27 +00:00
assign FirstUM = UM[0];
assign FirstC = C[0];
assign Firstun = un[0];
2022-07-15 21:42:45 +00:00
endmodule