2021-07-13 20:59:17 +00:00
|
|
|
//
|
|
|
|
// File name : fpdiv
|
|
|
|
// Title : Floating-Point Divider/Square-Root
|
|
|
|
// project : FPU
|
|
|
|
// Library : fpdiv
|
|
|
|
// Author(s) : James E. Stine, Jr.
|
|
|
|
// Purpose : definition of main unit to floating-point div/sqrt
|
|
|
|
// notes :
|
|
|
|
//
|
|
|
|
// Copyright Oklahoma State University
|
|
|
|
//
|
|
|
|
// Basic Operations
|
|
|
|
//
|
|
|
|
// Step 1: Load operands, set flags, and convert SP to DP
|
|
|
|
// Step 2: Check for special inputs ( +/- Infinity, NaN)
|
|
|
|
// Step 3: Exponent Logic
|
|
|
|
// Step 4: Divide/Sqrt using Goldschmidt
|
|
|
|
// Step 5: Normalize the result.//
|
|
|
|
// Shift left until normalized. Normalized when the value to the
|
|
|
|
// left of the binrary point is 1.
|
|
|
|
// Step 6: Round the result.//
|
|
|
|
// Step 7: Put quotient/remainder onto output.
|
|
|
|
//
|
|
|
|
|
2021-07-14 21:56:49 +00:00
|
|
|
// `timescale 1ps/1ps
|
2021-07-18 18:03:37 +00:00
|
|
|
module fpdiv (
|
2021-07-24 18:59:57 +00:00
|
|
|
input logic clk,
|
|
|
|
input logic reset,
|
|
|
|
input logic start,
|
|
|
|
input logic [63:0] op1, // 1st input operand (A)
|
|
|
|
input logic [63:0] op2, // 2nd input operand (B)
|
|
|
|
input logic [1:0] rm, // Rounding mode - specify values
|
|
|
|
input logic op_type, // Function opcode
|
|
|
|
input logic P, // Result Precision (0 for double, 1 for single)
|
|
|
|
input logic OvEn, // Overflow trap enabled
|
|
|
|
input logic UnEn, // Underflow trap enabled
|
|
|
|
output logic done,
|
|
|
|
output logic FDivBusyE,
|
|
|
|
output logic [63:0] AS_Result, // Result of operation
|
|
|
|
output logic [4:0] Flags); // IEEE exception flags
|
2021-07-13 20:59:17 +00:00
|
|
|
|
|
|
|
|
2021-07-24 18:59:57 +00:00
|
|
|
logic [63:0] Float1;
|
|
|
|
logic [63:0] Float2;
|
2021-07-13 20:59:17 +00:00
|
|
|
|
2021-07-24 18:59:57 +00:00
|
|
|
logic [12:0] exp1, exp2, expF;
|
|
|
|
logic [12:0] exp_diff, bias;
|
|
|
|
logic [13:0] exp_sqrt;
|
|
|
|
logic [12:0] exp_s;
|
|
|
|
logic [12:0] exp_c;
|
2021-07-13 20:59:17 +00:00
|
|
|
|
2021-07-24 18:59:57 +00:00
|
|
|
logic [10:0] exponent;
|
|
|
|
logic [63:0] Result;
|
|
|
|
logic [52:0] mantissaA;
|
|
|
|
logic [52:0] mantissaB;
|
2021-07-13 20:59:17 +00:00
|
|
|
|
2021-07-24 18:59:57 +00:00
|
|
|
logic [2:0] sel_inv;
|
|
|
|
logic Invalid;
|
|
|
|
logic [4:0] FlagsIn;
|
|
|
|
logic signResult;
|
|
|
|
logic convert;
|
|
|
|
logic sub;
|
2021-07-13 20:59:17 +00:00
|
|
|
|
2021-07-24 18:59:57 +00:00
|
|
|
logic [63:0] q1, qm1, qp1, q0, qm0, qp0;
|
|
|
|
logic [63:0] rega_out, regb_out, regc_out, regd_out;
|
|
|
|
logic [127:0] regr_out;
|
|
|
|
logic [2:0] sel_muxa, sel_muxb;
|
|
|
|
logic sel_muxr;
|
|
|
|
logic load_rega, load_regb, load_regc, load_regd, load_regr;
|
2021-07-13 20:59:17 +00:00
|
|
|
|
2021-07-24 18:59:57 +00:00
|
|
|
logic load_regs;
|
|
|
|
logic exp_cout1, exp_cout2;
|
|
|
|
logic exp_odd, open;
|
2021-07-13 20:59:17 +00:00
|
|
|
|
2021-07-24 18:59:57 +00:00
|
|
|
// div/sqrt
|
|
|
|
// fdiv = 0
|
|
|
|
// fsqrt = 1
|
|
|
|
|
2021-07-13 20:59:17 +00:00
|
|
|
// Convert the input operands to their appropriate forms based on
|
|
|
|
// the orignal operands, the op_type , and their precision P.
|
|
|
|
// Single precision inputs are converted to double precision
|
|
|
|
// and the sign of the first operand is set appropratiately based on
|
|
|
|
// if the operation is absolute value or negation.
|
2021-07-24 18:59:57 +00:00
|
|
|
convert_inputs_div conv1 (.op1, .op2, .op_type, .P,
|
|
|
|
// outputs:
|
|
|
|
.Float1, .Float2b(Float2));
|
2021-07-13 20:59:17 +00:00
|
|
|
|
|
|
|
// Test for exceptions and return the "Invalid Operation" and
|
|
|
|
// "Denormalized" Input Flags. The "sel_inv" is used in
|
|
|
|
// the third pipeline stage to select the result. Also, op1_Norm
|
|
|
|
// and op2_Norm are one if op1 and op2 are not zero or denormalized.
|
|
|
|
// sub is one if the effective operation is subtaction.
|
2021-07-24 18:59:57 +00:00
|
|
|
exception_div exc1 (.A(Float1), .B(Float2), .op_type,
|
|
|
|
// output:
|
|
|
|
.Ztype(sel_inv), .Invalid);
|
2021-07-13 20:59:17 +00:00
|
|
|
|
|
|
|
// Determine Sign/Mantissa
|
2021-07-18 18:03:37 +00:00
|
|
|
assign signResult = (Float1[63]^Float2[63]);
|
2021-07-24 18:59:57 +00:00
|
|
|
assign mantissaA = {1'b1, Float1[51:0]};
|
|
|
|
assign mantissaB = {1'b1, Float2[51:0]};
|
2021-07-13 20:59:17 +00:00
|
|
|
// Perform Exponent Subtraction - expA - expB + Bias
|
|
|
|
assign exp1 = {2'b0, Float1[62:52]};
|
|
|
|
assign exp2 = {2'b0, Float2[62:52]};
|
|
|
|
assign bias = {3'h0, 10'h3FF};
|
|
|
|
// Divide exponent
|
2021-07-24 18:59:57 +00:00
|
|
|
assign {exp_cout1, open, exp_diff} = exp1 - exp2 + bias;
|
2021-07-13 20:59:17 +00:00
|
|
|
|
|
|
|
// Sqrt exponent (check if exponent is odd)
|
2021-07-24 18:59:57 +00:00
|
|
|
assign exp_odd = Float1[52] ? 1'b0 : 1'b1;
|
|
|
|
assign {exp_cout2, exp_sqrt} = {1'b0, exp1} + {4'h0, 10'h3ff} + exp_odd;
|
2021-07-13 20:59:17 +00:00
|
|
|
// Choose correct exponent
|
|
|
|
assign expF = op_type ? exp_sqrt[13:1] : exp_diff;
|
|
|
|
|
|
|
|
// Main Goldschmidt/Division Routine
|
2021-07-24 18:59:57 +00:00
|
|
|
divconv goldy (.q1, .qm1, .qp1, .q0, .qm0, .qp0, .rega_out, .regb_out, .regc_out, .regd_out,
|
|
|
|
.regr_out, .d(mantissaB), .n(mantissaA), .sel_muxa, .sel_muxb, .sel_muxr,
|
|
|
|
.reset, .clk, .load_rega, .load_regb, .load_regc, .load_regd,
|
|
|
|
.load_regr, .load_regs, .P, .op_type, .exp_odd);
|
2021-07-13 20:59:17 +00:00
|
|
|
|
|
|
|
// FSM : control divider
|
2021-07-24 18:59:57 +00:00
|
|
|
fsm control (.clk, .reset, .start, .op_type,
|
|
|
|
// outputs:
|
|
|
|
.done, .load_rega, .load_regb, .load_regc, .load_regd,
|
|
|
|
.load_regr, .load_regs, .sel_muxa, .sel_muxb, .sel_muxr,
|
|
|
|
.divBusy(FDivBusyE));
|
2021-07-13 20:59:17 +00:00
|
|
|
|
|
|
|
// Round the mantissa to a 52-bit value, with the leading one
|
|
|
|
// removed. The rounding units also handles special cases and
|
|
|
|
// set the exception flags.
|
2021-07-24 18:59:57 +00:00
|
|
|
rounder_div round1 (.rm, .P, .OvEn, .UnEn, .exp_diff(expF),
|
|
|
|
.sel_inv, .Invalid, .SignR(signResult),
|
|
|
|
.q1, .qm1, .qp1, .q0, .qm0, .qp0, .regr_out,
|
|
|
|
// outputs:
|
|
|
|
.Result, .Flags(FlagsIn));
|
2021-07-13 20:59:17 +00:00
|
|
|
|
|
|
|
// Store the final result and the exception flags in registers.
|
2021-07-24 18:59:57 +00:00
|
|
|
flopenr #(64) rega (clk, reset, done, Result, AS_Result);
|
2021-07-13 20:59:17 +00:00
|
|
|
flopenr #(5) regc (clk, reset, done, FlagsIn, Flags);
|
|
|
|
|
|
|
|
endmodule // fpadd
|
2021-07-18 18:03:37 +00:00
|
|
|
|