// exception_mult.sv // Handles the exceptional cases `include "round_modes.sv" module exception_mult ( input logic [31:0] a, b, input logic [31:0] z_calc, input logic ovf, unf, inexact, input logic [2:0] round, output logic [31:0] z, output logic zero_f, inf_f, nan_f, tiny_f, huge_f, inexact_f ); // === ENUM DECLARATION === typedef enum logic [2:0] { ZERO, INF, NORM, MIN_NORM, MAX_NORM } interp_t; // === num_interp FUNCTION === function interp_t num_interp(input logic [31:0] x); automatic logic [7:0] exp = x[30:23]; automatic logic [22:0] mant = x[22:0]; if (exp == 8'd255) return INF; else if (exp == 8'd0) return ZERO; else if (exp == 8'd1 && mant == 0) return MIN_NORM; else if (exp == 8'd254 && mant == 23'h7FFFFF) return MAX_NORM; else return NORM; endfunction // === z_num FUNCTION === function logic [30:0] z_num(input interp_t kind); case (kind) ZERO: return 31'd0; INF: return {8'd255, 23'd0}; MIN_NORM: return {8'd1, 23'd0}; MAX_NORM: return {8'd254, 23'h7FFFFF}; default: return 31'd0; endcase endfunction // === MAIN LOGIC === interp_t a_class, b_class; logic sign; always_comb begin a_class = num_interp(a); b_class = num_interp(b); sign = z_calc[31]; // Default flags {zero_f, inf_f, nan_f, tiny_f, huge_f, inexact_f} = '0; z = z_calc; case ({a_class, b_class}) {ZERO, ZERO}, {ZERO, NORM}, {NORM, ZERO}: begin z = {sign, z_num(ZERO)}; zero_f = 1; end {ZERO, INF}, {INF, ZERO}: begin z = {sign, z_num(INF)}; nan_f = 1; end {INF, INF}, {NORM, INF}, {INF, NORM}: begin z = {sign, z_num(INF)}; inf_f = 1; end default: begin // {NORM, NORM} if (ovf) begin case (round) RND_IEEE_NEAREST_EVEN: z = {sign, z_num(MAX_NORM)}; RND_IEEE_ZERO: z = {sign, z_num(MAX_NORM)}; RND_IEEE_PINF: z = (sign == 0) ? {1'b0, z_num(INF)} : {1'b1, z_num(MAX_NORM)}; RND_IEEE_NINF: z = (sign == 1) ? {1'b1, z_num(INF)} : {1'b0, z_num(MAX_NORM)}; RND_NEAR_UP: z = (sign == 0) ? {1'b1, z_num(INF)} : {1'b0, z_num(MIN_NORM)}; RND_AWAY_ZERO: z = {sign, z_num(MAX_NORM)}; default: z = {sign, z_num(MAX_NORM)}; endcase huge_f = 1; end else if (unf) begin case (round) RND_IEEE_NEAREST_EVEN: z = {sign, z_num(MIN_NORM)}; RND_IEEE_ZERO: z = {sign, z_num(ZERO)}; RND_IEEE_PINF: z = (sign == 0) ? {1'b0, z_num(MIN_NORM)} : {1'b1, z_num(ZERO)}; RND_IEEE_NINF: z = (sign == 1) ? {1'b1, z_num(MIN_NORM)} : {1'b0, z_num(ZERO)}; RND_NEAR_UP: z = (sign == 1) ? {1'b1, z_num(ZERO)} : {1'b0, z_num(MIN_NORM)}; RND_AWAY_ZERO: z = {sign, z_num(MIN_NORM)}; default: z = {sign, z_num(MIN_NORM)}; endcase tiny_f = 1; end inf_f = (z[30:0] == z_num(INF)); zero_f = (z[30:0] == z_num(ZERO)); inexact_f = inexact || ovf || unf; end endcase end endmodule