// Copyright © 2019-2023 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // 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 "VX_fpu_define.vh" `ifdef FPU_DSP /// Modified port of rouding module from fpnew Libray /// reference: https://github.com/pulp-platform/fpnew module VX_fpu_rounding #( parameter DAT_WIDTH = 2 // Width of the abolute value, without sign bit ) ( // inputs input wire [DAT_WIDTH-1:0] abs_value_i, // absolute value without sign input wire sign_i, // rounding information input wire [1:0] round_sticky_bits_i, // round and sticky bits {RS} input wire [2:0] rnd_mode_i, input wire effective_subtraction_i, // sign of inputs affects rounding of zeroes // outputs output wire [DAT_WIDTH-1:0] abs_rounded_o, // absolute value without sign output wire sign_o, output wire exact_zero_o // output is an exact zero ); reg round_up; // Rounding decision // Take the rounding decision according to RISC-V spec // RoundMode | Mnemonic | Meaning // :--------:|:--------:|:------- // 000 | RNE | Round to Nearest, ties to Even // 001 | RTZ | Round towards Zero // 010 | RDN | Round Down (towards -\infty) // 011 | RUP | Round Up (towards \infty) // 100 | RMM | Round to Nearest, ties to Max Magnitude // others | | *invalid* always @(*) begin case (rnd_mode_i) `INST_FRM_RNE: // Decide accoring to round/sticky bits case (round_sticky_bits_i) 2'b00, 2'b01: round_up = 1'b0; // < ulp/2 away, round down 2'b10: round_up = abs_value_i[0]; // = ulp/2 away, round towards even result 2'b11: round_up = 1'b1; // > ulp/2 away, round up endcase `INST_FRM_RTZ: round_up = 1'b0; // always round down `INST_FRM_RDN: round_up = (| round_sticky_bits_i) & sign_i; // to 0 if +, away if - `INST_FRM_RUP: round_up = (| round_sticky_bits_i) & ~sign_i; // to 0 if -, away if + `INST_FRM_RMM: round_up = round_sticky_bits_i[1]; // round down if < ulp/2 away, else up default: round_up = 1'bx; // propagate x endcase end // Perform the rounding, exponent change and overflow to inf happens automagically assign abs_rounded_o = abs_value_i + DAT_WIDTH'(round_up); // True zero result is a zero result without dirty round/sticky bits assign exact_zero_o = (abs_value_i == 0) && (round_sticky_bits_i == 0); // In case of effective subtraction (thus signs of addition operands must have differed) and a // true zero result, the result sign is '-' in case of RDN and '+' for other modes. assign sign_o = (exact_zero_o && effective_subtraction_i) ? (rnd_mode_i == `INST_FRM_RDN) : sign_i; endmodule `endif