2021-07-02 16:53:05 +00:00
|
|
|
|
2022-07-07 23:01:33 +00:00
|
|
|
///////////////////////////////////////////
|
2022-09-20 10:57:57 +00:00
|
|
|
// fcmp.sv
|
2022-07-07 23:01:33 +00:00
|
|
|
//
|
|
|
|
// Written: me@KatherineParry.com
|
|
|
|
// Modified: 7/5/2022
|
|
|
|
//
|
|
|
|
// Purpose: Comparison unit
|
|
|
|
//
|
|
|
|
// A component of the Wally configurable RISC-V project.
|
|
|
|
//
|
2023-01-10 19:35:20 +00:00
|
|
|
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
2022-07-07 23:01:33 +00:00
|
|
|
//
|
2023-01-10 19:35:20 +00:00
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
2022-07-07 23:01:33 +00:00
|
|
|
//
|
2023-01-10 19:35:20 +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-07 23:01:33 +00:00
|
|
|
//
|
2023-01-10 19:35:20 +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-07 23:01:33 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
2022-07-20 02:27:39 +00:00
|
|
|
|
2021-07-02 16:53:05 +00:00
|
|
|
`include "wally-config.vh"
|
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
// OpCtrl values
|
2022-06-13 22:47:51 +00:00
|
|
|
// 110 min
|
2022-01-01 23:50:23 +00:00
|
|
|
// 101 max
|
|
|
|
// 010 equal
|
|
|
|
// 001 less than
|
|
|
|
// 011 less than or equal
|
2021-07-02 16:53:05 +00:00
|
|
|
|
2022-01-01 23:50:23 +00:00
|
|
|
module fcmp (
|
2022-07-20 02:27:39 +00:00
|
|
|
input logic [`FMTBITS-1:0] Fmt, // format of fp number
|
|
|
|
input logic [2:0] OpCtrl, // see above table
|
|
|
|
input logic Xs, Ys, // input signs
|
|
|
|
input logic [`NE-1:0] Xe, Ye, // input exponents
|
|
|
|
input logic [`NF:0] Xm, Ym, // input mantissa
|
|
|
|
input logic XZero, YZero, // is zero
|
|
|
|
input logic XNaN, YNaN, // is NaN
|
|
|
|
input logic XSNaN, YSNaN, // is signaling NaN
|
|
|
|
input logic [`FLEN-1:0] X, Y, // original inputs (before unpacker)
|
|
|
|
output logic CmpNV, // invalid flag
|
|
|
|
output logic [`FLEN-1:0] CmpFpRes, // compare floating-point result
|
|
|
|
output logic [`XLEN-1:0] CmpIntRes // compare integer result
|
2022-01-01 23:50:23 +00:00
|
|
|
);
|
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
logic LTabs, LT, EQ; // is X < or > or = Y
|
|
|
|
logic [`FLEN-1:0] NaNRes; // NaN result
|
|
|
|
logic BothZero; // are both inputs zero
|
|
|
|
logic EitherNaN, EitherSNaN; // are either input a (signaling) NaN
|
2022-03-29 17:11:28 +00:00
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
assign LTabs= {1'b0, Xe, Xm} < {1'b0, Ye, Ym}; // unsigned comparison, treating FP as integers
|
|
|
|
assign LT = (Xs & ~Ys) | (Xs & Ys & ~LTabs & ~EQ) | (~Xs & ~Ys & LTabs); // signed comparison
|
|
|
|
assign EQ = (X == Y);
|
2022-01-01 23:50:23 +00:00
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
assign BothZero = XZero&YZero;
|
|
|
|
assign EitherNaN = XNaN|YNaN;
|
|
|
|
assign EitherSNaN = XSNaN|YSNaN;
|
2022-03-29 17:11:28 +00:00
|
|
|
|
|
|
|
|
2022-01-01 23:50:23 +00:00
|
|
|
// flags
|
|
|
|
// Min/Max - if an input is a signaling NaN set invalid flag
|
|
|
|
// LT/LE - signaling - sets invalid if NaN input
|
|
|
|
// EQ - quiet - sets invalid if signaling NaN input
|
|
|
|
always_comb begin
|
2022-07-20 02:27:39 +00:00
|
|
|
case (OpCtrl[2:0])
|
|
|
|
3'b110: CmpNV = EitherSNaN;//min
|
|
|
|
3'b101: CmpNV = EitherSNaN;//max
|
|
|
|
3'b010: CmpNV = EitherSNaN;//equal
|
|
|
|
3'b001: CmpNV = EitherNaN;//less than
|
|
|
|
3'b011: CmpNV = EitherNaN;//less than or equal
|
|
|
|
default: CmpNV = 1'bx;
|
2022-01-01 23:50:23 +00:00
|
|
|
endcase
|
|
|
|
end
|
2021-07-02 16:53:05 +00:00
|
|
|
|
2022-03-29 17:11:28 +00:00
|
|
|
// fmin/fmax of two NaNs returns a quiet NaN of the appropriate size
|
|
|
|
// for IEEE, return the payload of X
|
|
|
|
// for RISC-V, return the canonical NaN
|
2022-05-20 17:19:50 +00:00
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
// select the NaN result
|
2022-05-20 17:19:50 +00:00
|
|
|
if (`FPSIZES == 1)
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) assign NaNRes = {Xs, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]};
|
2022-05-20 17:19:50 +00:00
|
|
|
else assign NaNRes = {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}};
|
|
|
|
|
|
|
|
else if (`FPSIZES == 2)
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) assign NaNRes = Fmt ? {Xs, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]} : {{`FLEN-`LEN1{1'b1}}, Xs, {`NE1{1'b1}}, 1'b1, Xm[`NF-2:`NF-`NF1]};
|
|
|
|
else assign NaNRes = Fmt ? {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}} : {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, (`NF1-1)'(0)};
|
2022-05-20 17:19:50 +00:00
|
|
|
|
|
|
|
else if (`FPSIZES == 3)
|
|
|
|
always_comb
|
2022-07-20 02:27:39 +00:00
|
|
|
case (Fmt)
|
2022-05-20 17:19:50 +00:00
|
|
|
`FMT:
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) NaNRes = {Xs, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]};
|
2022-05-20 17:19:50 +00:00
|
|
|
else NaNRes = {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}};
|
|
|
|
`FMT1:
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) NaNRes = {{`FLEN-`LEN1{1'b1}}, Xs, {`NE1{1'b1}}, 1'b1, Xm[`NF-2:`NF-`NF1]};
|
2022-05-20 17:19:50 +00:00
|
|
|
else NaNRes = {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, (`NF1-1)'(0)};
|
|
|
|
`FMT2:
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) NaNRes = {{`FLEN-`LEN2{1'b1}}, Xs, {`NE2{1'b1}}, 1'b1, Xm[`NF-2:`NF-`NF2]};
|
2022-05-20 17:19:50 +00:00
|
|
|
else NaNRes = {{`FLEN-`LEN2{1'b1}}, 1'b0, {`NE2{1'b1}}, 1'b1, (`NF2-1)'(0)};
|
2022-06-14 23:58:39 +00:00
|
|
|
default: NaNRes = {`FLEN{1'bx}};
|
2022-05-20 17:19:50 +00:00
|
|
|
endcase
|
|
|
|
|
|
|
|
else if (`FPSIZES == 4)
|
|
|
|
always_comb
|
2022-07-20 02:27:39 +00:00
|
|
|
case (Fmt)
|
2022-05-20 17:19:50 +00:00
|
|
|
2'h3:
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) NaNRes = {Xs, {`NE{1'b1}}, 1'b1, Xm[`NF-2:0]};
|
2022-05-20 17:19:50 +00:00
|
|
|
else NaNRes = {1'b0, {`NE{1'b1}}, 1'b1, {`NF-1{1'b0}}};
|
|
|
|
2'h1:
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) NaNRes = {{`FLEN-`D_LEN{1'b1}}, Xs, {`D_NE{1'b1}}, 1'b1, Xm[`NF-2:`NF-`D_NF]};
|
2022-05-20 17:19:50 +00:00
|
|
|
else NaNRes = {{`FLEN-`D_LEN{1'b1}}, 1'b0, {`D_NE{1'b1}}, 1'b1, (`D_NF-1)'(0)};
|
|
|
|
2'h0:
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) NaNRes = {{`FLEN-`S_LEN{1'b1}}, Xs, {`S_NE{1'b1}}, 1'b1, Xm[`NF-2:`NF-`S_NF]};
|
2022-05-20 17:19:50 +00:00
|
|
|
else NaNRes = {{`FLEN-`S_LEN{1'b1}}, 1'b0, {`S_NE{1'b1}}, 1'b1, (`S_NF-1)'(0)};
|
|
|
|
2'h2:
|
2022-07-20 02:27:39 +00:00
|
|
|
if(`IEEE754) NaNRes = {{`FLEN-`H_LEN{1'b1}}, Xs, {`H_NE{1'b1}}, 1'b1, Xm[`NF-2:`NF-`H_NF]};
|
2022-05-20 17:19:50 +00:00
|
|
|
else NaNRes = {{`FLEN-`H_LEN{1'b1}}, 1'b0, {`H_NE{1'b1}}, 1'b1, (`H_NF-1)'(0)};
|
|
|
|
endcase
|
|
|
|
|
2022-06-13 22:47:51 +00:00
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
// Min/Max
|
|
|
|
// - outputs the min/max of X and Y
|
|
|
|
// - -0 < 0
|
|
|
|
// - if both are NaN return quiet X
|
|
|
|
// - if one is a NaN output the non-NaN
|
|
|
|
always_comb
|
|
|
|
if(OpCtrl[0]) // MAX
|
|
|
|
if(XNaN)
|
|
|
|
if(YNaN) CmpFpRes = NaNRes; // X = NaN Y = NaN
|
|
|
|
else CmpFpRes = Y; // X = NaN Y != NaN
|
|
|
|
else
|
|
|
|
if(YNaN) CmpFpRes = X; // X != NaN Y = NaN
|
|
|
|
else // X,Y != NaN
|
|
|
|
if(LT) CmpFpRes = Y; // X < Y
|
|
|
|
else CmpFpRes = X; // X > Y
|
|
|
|
else // MIN
|
|
|
|
if(XNaN)
|
|
|
|
if(YNaN) CmpFpRes = NaNRes; // X = NaN Y = NaN
|
|
|
|
else CmpFpRes = Y; // X = NaN Y != NaN
|
|
|
|
else
|
|
|
|
if(YNaN) CmpFpRes = X; // X != NaN Y = NaN
|
|
|
|
else // X,Y != NaN
|
|
|
|
if(LT) CmpFpRes = X; // X < Y
|
|
|
|
else CmpFpRes = Y; // X > Y
|
|
|
|
|
|
|
|
// LT/LE/EQ
|
|
|
|
// - -0 = 0
|
|
|
|
// - inf = inf and -inf = -inf
|
|
|
|
// - return 0 if comparison with NaN (unordered)
|
|
|
|
assign CmpIntRes = {(`XLEN-1)'(0), (((EQ|BothZero)&OpCtrl[1])|(LT&OpCtrl[0]&~BothZero))&~EitherNaN};
|
2022-01-01 23:50:23 +00:00
|
|
|
|
|
|
|
endmodule
|