blob: 3e9b993721012d00894dd8b1dd77b5a315707963 [file] [log] [blame]
module fpu_norm (
Mant_in_DI,
Exp_in_DI,
Sign_in_DI,
RM_SI,
OP_SI,
Mant_res_DO,
Exp_res_DO,
Rounded_SO,
Exp_OF_SO,
Exp_UF_SO
);
parameter C_RM = 2;
parameter C_RM_NEAREST = 2'h0;
parameter C_RM_TRUNC = 2'h1;
parameter C_RM_PLUSINF = 2'h2;
parameter C_RM_MINUSINF = 2'h3;
parameter C_PC = 5;
parameter C_OP = 32;
parameter C_MANT = 23;
parameter C_EXP = 8;
parameter C_BIAS = 127;
parameter C_HALF_BIAS = 63;
parameter C_LEADONE_WIDTH = 7;
parameter C_MANT_PRENORM = C_MANT+1;
parameter C_EXP_ZERO = 8'h00;
parameter C_EXP_ONE = 8'h01;
parameter C_EXP_INF = 8'hff;
parameter C_MANT_ZERO = 23'h0;
parameter C_MANT_NAN = 23'h400000;
parameter C_CMD = 4;
parameter C_FPU_ADD_CMD = 4'h0;
parameter C_FPU_SUB_CMD = 4'h1;
parameter C_FPU_MUL_CMD = 4'h2;
parameter C_FPU_DIV_CMD = 4'h3;
parameter C_FPU_I2F_CMD = 4'h4;
parameter C_FPU_F2I_CMD = 4'h5;
parameter C_FPU_SQRT_CMD = 4'h6;
parameter C_FPU_NOP_CMD = 4'h7;
parameter C_FPU_FMADD_CMD = 4'h8;
parameter C_FPU_FMSUB_CMD = 4'h9;
parameter C_FPU_FNMADD_CMD = 4'hA;
parameter C_FPU_FNMSUB_CMD = 4'hB;
parameter C_RM_NEAREST_MAX = 3'h4;
parameter C_EXP_PRENORM = C_EXP+2;
parameter C_MANT_ADDIN = C_MANT+4;
parameter C_MANT_ADDOUT = C_MANT+5;
parameter C_MANT_SHIFTIN = C_MANT+3;
parameter C_MANT_SHIFTED = C_MANT+4;
parameter C_MANT_INT = C_OP-1;
parameter C_INF = 32'h7fffffff;
parameter C_MINF = 32'h80000000;
parameter C_EXP_SHIFT = C_EXP_PRENORM;
parameter C_SHIFT_BIAS = 9'd127;
parameter C_UNKNOWN = 8'd157;
parameter C_PADMANT = 16'b0;
parameter C_MANT_NoHB_ZERO = 23'h0;
parameter C_MANT_PRENORM_IND = 6;
parameter F_QNAN =32'h7FC00000;
input wire [C_MANT_PRENORM - 1:0] Mant_in_DI;
input wire signed [C_EXP_PRENORM - 1:0] Exp_in_DI;
input wire Sign_in_DI;
input wire [C_RM - 1:0] RM_SI;
input wire [C_CMD - 1:0] OP_SI;
output wire [C_MANT:0] Mant_res_DO;
output wire [C_EXP - 1:0] Exp_res_DO;
output wire Rounded_SO;
output reg Exp_OF_SO;
output reg Exp_UF_SO;
wire [C_MANT_PRENORM_IND - 1:0] Mant_leadingOne_D;
wire Mant_zero_S;
reg [C_MANT + 4:0] Mant_norm_D;
wire signed [C_EXP_PRENORM - 1:0] Exp_norm_D;
wire signed [C_EXP_PRENORM - 1:0] Mant_shAmt_D;
wire signed [C_EXP_PRENORM:0] Mant_shAmt2_D;
wire [C_EXP - 1:0] Exp_final_D;
wire signed [C_EXP_PRENORM - 1:0] Exp_rounded_D;
reg Mant_sticky_D;
wire Denormal_S;
wire Mant_renorm_S;
fpu_ff #(.LEN(C_MANT_PRENORM)) LOD(
.in_i(Mant_in_DI),
.first_one_o(Mant_leadingOne_D),
.no_ones_o(Mant_zero_S)
);
wire Denormals_shift_add_D;
wire Denormals_exp_add_D;
assign Denormals_shift_add_D = (~Mant_zero_S & (Exp_in_DI == C_EXP_ZERO)) & ((OP_SI != C_FPU_MUL_CMD) | (~Mant_in_DI[C_MANT_PRENORM - 1] & ~Mant_in_DI[C_MANT_PRENORM - 2]));
assign Denormals_exp_add_D = (Mant_in_DI[C_MANT_PRENORM - 2] & (Exp_in_DI == C_EXP_ZERO)) & ((OP_SI == C_FPU_ADD_CMD) | (OP_SI == C_FPU_SUB_CMD));
assign Denormal_S = (C_EXP_PRENORM'($signed(Mant_leadingOne_D)) >= Exp_in_DI) || Mant_zero_S;
assign Mant_shAmt_D = (Denormal_S ? Exp_in_DI + Denormals_shift_add_D : Mant_leadingOne_D);
assign Mant_shAmt2_D = {Mant_shAmt_D[C_EXP_PRENORM - 1], Mant_shAmt_D} + (C_MANT + 5);
function automatic [(((C_MANT_PRENORM + C_MANT) + 4) >= 0 ? (C_MANT_PRENORM + C_MANT) + 5 : 1 - ((C_MANT_PRENORM + C_MANT) + 4)) - 1:0] sv2v_cast_F3481;
input reg [(((C_MANT_PRENORM + C_MANT) + 4) >= 0 ? (C_MANT_PRENORM + C_MANT) + 5 : 1 - ((C_MANT_PRENORM + C_MANT) + 4)) - 1:0] inp;
sv2v_cast_F3481 = inp;
endfunction
always @(*) begin : sv2v_autoblock_1
reg [(C_MANT_PRENORM + C_MANT) + 4:0] temp;
temp = sv2v_cast_F3481(Mant_in_DI) << Mant_shAmt2_D;
Mant_norm_D = temp[(C_MANT_PRENORM + C_MANT) + 4:C_MANT_PRENORM];
end
always @(*) begin
Mant_sticky_D = 1'b0;
if (Mant_shAmt2_D <= 0)
Mant_sticky_D = |Mant_in_DI;
else if (Mant_shAmt2_D <= C_MANT_PRENORM)
Mant_sticky_D = |(Mant_in_DI << Mant_shAmt2_D);
end
assign Exp_norm_D = ((Exp_in_DI - C_EXP_PRENORM'($signed(Mant_leadingOne_D))) + 1) + Denormals_exp_add_D;
assign Exp_rounded_D = Exp_norm_D + Mant_renorm_S;
assign Exp_final_D = Exp_rounded_D[C_EXP - 1:0];
always @(*) begin
Exp_OF_SO = 1'b0;
Exp_UF_SO = 1'b0;
if (Exp_rounded_D >= $signed({2'b00, C_EXP_INF}))
Exp_OF_SO = 1'b1;
else if (Exp_rounded_D <= $signed({2'b00, C_EXP_ZERO}))
Exp_UF_SO = 1'b1;
end
wire [C_MANT:0] Mant_upper_D;
wire [3:0] Mant_lower_D;
wire [C_MANT + 1:0] Mant_upperRounded_D;
reg Mant_roundUp_S;
wire Mant_rounded_S;
assign Mant_lower_D = Mant_norm_D[3:0];
assign Mant_upper_D = Mant_norm_D[C_MANT + 4:4];
assign Mant_rounded_S = |Mant_lower_D | Mant_sticky_D;
always @(*) begin
Mant_roundUp_S = 1'b0;
case (RM_SI)
C_RM_NEAREST: Mant_roundUp_S = Mant_lower_D[3] && ((|Mant_lower_D[2:0] | Mant_sticky_D) || Mant_upper_D[0]);
C_RM_TRUNC: Mant_roundUp_S = 0;
C_RM_PLUSINF: Mant_roundUp_S = Mant_rounded_S & ~Sign_in_DI;
C_RM_MINUSINF: Mant_roundUp_S = Mant_rounded_S & Sign_in_DI;
default: Mant_roundUp_S = 0;
endcase
end
assign Mant_upperRounded_D = Mant_upper_D + Mant_roundUp_S;
assign Mant_renorm_S = Mant_upperRounded_D[C_MANT + 1];
assign Mant_res_DO = Mant_upperRounded_D >> (Mant_renorm_S & ~Denormal_S);
assign Exp_res_DO = Exp_final_D;
assign Rounded_SO = Mant_rounded_S;
endmodule