blob: 129663b14ee25fa5ccf7b7d5b41a776e031ee157 [file] [log] [blame]
//Created by : Ali Raza Zaidi
// This is the top most leevel module of FPU
//This is designed as per the latest architechtural updates, dissucssed with MERL's RTL team heads
/*`include "F_F_T_I.v"
`include "F_I_T_F.v"
`include "F_M.v"
`include "F_Comp.v"
`include "F_S.v"
`include "F_Cl.v"
`include "F_IV.v"
`include "FMA_S_Top_Single_Cycle.v"
`include "LZD_comb.v"
`include "LZD_mux.v"*/
module FPU_Top (Operand_A_w,Operand_B_w,Operand_C_w, clk,rst_l, frm_w, sfpu_op_w,vfpu_op_w,fpu_sel_w,FPU_resultant, S_Flags, Exception_flag, interupt_Pin,FPU_Result_rd,Operand_Int_w);
parameter std= 31;
parameter man = 22;
parameter exp = 7;
parameter Bias = 127 /*8'b01111111*/;
parameter lzd = 4;
//inputs
input [std:0] Operand_A_w,Operand_B_w,Operand_C_w;
input clk,rst_l;
input [2:0] frm_w;
input [23:0] sfpu_op_w;
input [2:0] fpu_sel_w;
input [27:0] vfpu_op_w;
input [31:0] Operand_Int_w;
//output
output [std:0] FPU_resultant;
output [4:0] S_Flags;
output Exception_flag;
output interupt_Pin;
output [31:0]FPU_Result_rd;
//interim register
reg [std:0] FPU_resultant_reg;
reg[31:0] FPU_Result_rd_reg;
reg [4:0] S_Flags_reg;
reg [std:0] Operand_A,Operand_B,Operand_C;
reg [2:0] frm;
reg [23:0] sfpu_op;
reg [2:0] fpu_sel;
reg [27:0] vfpu_op;
reg [31:0] Operand_Int;
always @(posedge clk)
begin
if(rst_l == 1'b0)
begin
Operand_A <= {(std+1){1'b0}};
Operand_B <= {(std+1){1'b0}};
Operand_C <= {(std+1){1'b0}};
frm <= 3'b000;
sfpu_op <= 24'h000000;
fpu_sel <= 3'b000;
vfpu_op <= 28'h0000000;
Operand_Int <= 32'h00000000;
end
else
begin
Operand_A <= Operand_A_w;
Operand_B <= Operand_B_w;
Operand_C <= Operand_C_w;
frm <= frm_w;
sfpu_op <= sfpu_op_w;
fpu_sel <= fpu_sel_w;
vfpu_op <= vfpu_op_w;
Operand_Int <= Operand_Int_w;
end
end
//assigment of interim register on outptu ports
assign FPU_resultant = (rst_l) ? FPU_resultant_reg:{std+1{1'b0}};
assign S_Flags = (rst_l) ? S_Flags_reg:5'b00000 ;
assign FPU_Result_rd = (rst_l) ? FPU_Result_rd_reg : 32'h00000000;
/*opcode ctivation signals
sfpu[0] = Fadd
sfpu[1] = Fsubb
sfpu[2] = Fmul
sfpu[3] = Fdiv
sfpu[4] = Fsqrt
sfpu[5] = Fmin
sfpu[6] = Fmax
sfpu[7] = Fmvx
sfpu[8] = Fmvf
sfpu[9] = feq
sfpu[10] = flt
sfpu[11] = fle
sfpu[12] = Fmadd
sfpu[13] = Fmsubb
sfpu[14] = FCVT.W.P
sfpu[15] = FCVT.P.W
sfpu[16] = Fnmsubb
sfpu[17] = Fnmadd
sfpu[18] = fsgnj
sfpu[19] = fsgnjn
sfpu[20] = fsgnjx
sfpu[21] = fclass
sfpu[22] = unsign
sfpu[23] = sign
*/
/* CSR flag registers adrsses
CSR[4] = NV
CSR[3] = DZ
CSR[2] = OF
CSR[1] = UF
CSR[0] = NX
*/
//Module instantiation for input vlaidation stage of the FPU
wire [std:0] output_interim_input_validation_temp_storage;
wire output_interim_input_validation_exception_flag_Fadd,output_interim_input_validation_exception_flag_Fsub,output_interim_input_validation_exception_flag_Fmul ,output_interim_input_validation_exception_flag_Fdiv, output_interim_input_validation_exception_flag_Fsqrt, output_interim_input_validation_exception_flag_Fcomp, output_interim_input_validation_exception_flag_Fmadd, output_interim_input_validation_exception_flag_Fmsub;
wire Exception_flag_interim ;
wire output_interim_input_validation_Divide_By_Zero;
wire output_interim_input_validation_invalid_flag;
FPU_Input_Validation input_Validation (
.INPUT_VALIDATION_input_ieee_A(Operand_A),
.INPUT_VALIDATION_input_ieee_B(Operand_B),
.INPUT_VALIDATION_input_ieee_C(Operand_C),
.INPUT_VALIDATION_input_opcode(sfpu_op),
.INPUT_VALIDATION_Output_temp_storage (output_interim_input_validation_temp_storage),
.INPUT_VALIDATION_Output_exception_flag_Fadd (output_interim_input_validation_exception_flag_Fadd),
.INPUT_VALIDATION_Output_exception_flag_Fsub (output_interim_input_validation_exception_flag_Fsub),
.INPUT_VALIDATION_Output_exception_flag_Fmul (output_interim_input_validation_exception_flag_Fmul),
.INPUT_VALIDATION_Output_exception_flag_Fdiv (output_interim_input_validation_exception_flag_Fdiv),
.INPUT_VALIDATION_Output_exception_flag_Fsqrt (output_interim_input_validation_exception_flag_Fsqrt),
.INPUT_VALIDATION_Output_exception_flag_Fcomp (output_interim_input_validation_exception_flag_Fcomp),
.INPUT_VALIDATION_Output_exception_flag_Fmadd (output_interim_input_validation_exception_flag_Fmadd),
.INPUT_VALIDATION_Output_exception_flag_Fmsub (output_interim_input_validation_exception_flag_Fmsub),
.INPUT_VALIDATION_Output_Flag_DZ (output_interim_input_validation_Divide_By_Zero),
.INPUT_VALIDATION_Output_invalid_flag (output_interim_input_validation_invalid_flag),
.interupt_Pin(interupt_Pin),
.rst_l(rst_l)
);
assign Exception_flag_interim = output_interim_input_validation_exception_flag_Fadd | output_interim_input_validation_exception_flag_Fsub | output_interim_input_validation_exception_flag_Fmul | output_interim_input_validation_exception_flag_Fdiv | output_interim_input_validation_exception_flag_Fsqrt | output_interim_input_validation_exception_flag_Fcomp | output_interim_input_validation_exception_flag_Fmadd |output_interim_input_validation_exception_flag_Fmsub ;
assign Exception_flag = Exception_flag_interim ;
defparam input_Validation.std=std;
defparam input_Validation.man=man;
defparam input_Validation.exp=exp;
defparam input_Validation.bias=Bias;
//module instantiation for Fmove instruction
wire [std:0] output_interim_Fmove;
FPU_move Floating_move (
.rst_l(rst_l),
.opcode({(sfpu_op[8]),(sfpu_op[7] | vfpu_op[4])}),
.Move_Input_IEEE(Operand_A),
.Move_Output_IEEE(output_interim_Fmove)
);
defparam Floating_move.Std = std;
//module instantiation of FPU_sign injection instructions
wire [std:0] output_interim_FPU_sign;
FPU_sign Floating_sign_injection (
.rst_l(rst_l),
.op({(sfpu_op[20] | vfpu_op[24]),(sfpu_op[19] | vfpu_op[23]),(sfpu_op[18] | vfpu_op[22])}),
.IEEE_A(Operand_A),
.IEEE_B(Operand_B),
.IEEE_out(output_interim_FPU_sign)
);
defparam Floating_sign_injection.Std=std;
defparam Floating_sign_injection.Man=man;
defparam Floating_sign_injection.Exp=exp;
//module instatiation of Float to int instrution
wire [31:0] output_interim_FLOAT_to_Int;
wire output_interim_Invalid_Flag_Float_To_Int;
wire output_interim_Inexact_Flag_Float_To_Int;
FPU_Float_to_Int Floating_Float2Int(
.FLOAT_TO_INT_input_float(Operand_A),
.FLOAT_TO_INT_input_rm(frm),
.FLOAT_TO_INT_input_opcode_FI (sfpu_op[14] | vfpu_op[18]),
.FLOAT_TO_INT_input_opcode_unsigned(sfpu_op[22] | vfpu_op[26]),
.FLOAT_TO_INT_input_opcode_signed(sfpu_op[23] | vfpu_op[27]),
.FLOAT_TO_INT_output_int(output_interim_FLOAT_to_Int),
.FLOAT_TO_INT_output_invalid_flag(output_interim_Invalid_Flag_Float_To_Int),
.FLOAT_TO_INT_output_inexact_flag(output_interim_Inexact_Flag_Float_To_Int),
.rst_l(rst_l)
);
defparam Floating_Float2Int.std=std;
defparam Floating_Float2Int.man=man;
defparam Floating_Float2Int.exp=exp;
defparam Floating_Float2Int.bias=Bias;
//module instantiation of In to FLoat istruction
wire [std:0] output_interim_Int_to_Float;
wire output_interim_Invalid_Flag_Int_To_Float;
wire output_interim_Inexact_Flag_Int_To_Float;
FPU_Int_to_Float floating_Int2Float (
.INT_TO_FLOAT_input_int(Operand_Int),
.INT_TO_FLOAT_input_rm(frm),
.INT_TO_FLOAT_input_opcode_IF (sfpu_op[15] | vfpu_op[19]),
.INT_TO_FLOAT_input_opcode_signed (sfpu_op[23] | vfpu_op[27]),
.INT_TO_FLOAT_input_opcode_unsigned (sfpu_op[22] | vfpu_op[26]),
.INT_TO_FLOAT_output_float(output_interim_Int_to_Float),
.INT_TO_FLOAT_output_invalid_flag(output_interim_Invalid_Flag_Int_To_Float),
.INT_TO_FLOAT_output_inexact_flag (output_interim_Inexact_Flag_Int_To_Float),
.rst_l(rst_l)
);
defparam floating_Int2Float.std=std;
defparam floating_Int2Float.man=man;
defparam floating_Int2Float.exp=exp;
defparam floating_Int2Float.bias=Bias;
//module instatniation of comparision instructions
wire [31:0] output_interim_Comparison;
wire [7:0] input_Opcode_Fcomp;
wire [std:0] output_interim_Fmax_Fmin;
assign input_Opcode_Fcomp = {(sfpu_op[6] | vfpu_op[3]),(sfpu_op[5] | vfpu_op[2]),vfpu_op[10],vfpu_op[9],(sfpu_op[11] | vfpu_op[6]),(sfpu_op[10] | vfpu_op[7]),vfpu_op[8],(sfpu_op[9] | vfpu_op[5])};
FPU_Comparison Floating_Comparison (
.rst_l(rst_l),
.opcode(input_Opcode_Fcomp),
.Comparator_Input_IEEE_A(Operand_A),
.Comparator_Input_IEEE_B(Operand_B),
.Comparator_Output_IEEE(output_interim_Comparison),
.Min_Max_Output_IEEE(output_interim_Fmax_Fmin)
);
defparam Floating_Comparison.Std=std;
defparam Floating_Comparison.Man=man;
defparam Floating_Comparison.Exp=exp;
//module instantiation for FCLASS instruction
wire [31:0] output_interim_Fclass;
FPU_Fclass Floating_Classify (
.rst_l (rst_l),
.Classification_Output (output_interim_Fclass),
.Classification_Input (Operand_A),
.opcode (sfpu_op[21] | vfpu_op[25])
);
defparam Floating_Classify.Std=std;
defparam Floating_Classify.Man=man;
// module instantiation for Fmadd/fmsub/fnmadd/fnmsub/fadd/fsub/fmul instruction
wire [std:0] output_interim_FMADD,output_interim_Fmul;
wire [2:0] output_interim_S_Flags_Fmul, output_interim_S_Flags_Fmadd;
wire output_FMADD_interim_ready_Flagg;
FPU_FMADD_SUBB_Top Floating_FMADD (
.FMADD_SUBB_input_IEEE_A(Operand_A),
.FMADD_SUBB_input_IEEE_B(Operand_B),
.FMADD_SUBB_input_IEEE_C(Operand_C),
.FMADD_SUBB_input_opcode( { (sfpu_op[16] | vfpu_op[20]),(sfpu_op[17] | vfpu_op[21]),(sfpu_op[13] | vfpu_op[14]),(sfpu_op[12] | vfpu_op[13]),(sfpu_op[2] | vfpu_op[12]),(sfpu_op[1] | vfpu_op[1]),(sfpu_op[0] | vfpu_op[0])} ),
.rst_l(rst_l),
.FMADD_SUBB_input_Frm(frm),
.FMADD_SUBB_output_IEEE_FMADD (output_interim_FMADD),
.FMADD_SUBB_output_S_Flags_FMADD(output_interim_S_Flags_Fmadd),
.FMADD_SUBB_output_IEEE_FMUL(output_interim_Fmul),
.FMADD_SUBB_output_S_Flags_FMUL(output_interim_S_Flags_Fmul)
);
defparam Floating_FMADD.std=std;
defparam Floating_FMADD.man=man;
defparam Floating_FMADD.exp=exp;
defparam Floating_FMADD.bias=Bias;
defparam Floating_FMADD.lzd=lzd;
//block for declartion of register output port
// THis port is anmed as FPU_reusltant_reg and would be assigned a 0 on reset of the FPU however the asssignent to this would be controlled by the opcode bits if the rsrt condition is not true.
always @ (posedge clk)
begin
if (~rst_l)
begin
FPU_resultant_reg <= {(std+1){1'b0}};
FPU_Result_rd_reg <= 32'h00000000;
S_Flags_reg <= 5'b00000;
end
else if (Exception_flag_interim)
begin
FPU_resultant_reg <= output_interim_input_validation_temp_storage;
FPU_Result_rd_reg <= (std==15) ? {16'h0000,output_interim_input_validation_temp_storage[15:0]} : output_interim_input_validation_temp_storage;
S_Flags_reg <= { output_interim_input_validation_invalid_flag , output_interim_input_validation_Divide_By_Zero , 3'b000 } ;
end
else if (rst_l & (~Exception_flag_interim) )
begin
if ( sfpu_op[0] | sfpu_op[1] | sfpu_op[12] | sfpu_op[13] | sfpu_op[16] | sfpu_op[17] | vfpu_op[0] | vfpu_op[1] | vfpu_op[13] | vfpu_op[14] | vfpu_op[20] | vfpu_op[21]) //output selection for FMADD FMSUB FNMADD FNMSUBB FADD FSUB
begin
FPU_resultant_reg <= output_interim_FMADD;
FPU_Result_rd_reg <= 32'h00000000;
S_Flags_reg <= {2'b00,output_interim_S_Flags_Fmadd};
end
else if (sfpu_op[2] | vfpu_op[12]) //output selection for FMUL
begin
FPU_resultant_reg <= output_interim_Fmul;
FPU_Result_rd_reg <= 32'h00000000;
S_Flags_reg <= {2'b00,output_interim_S_Flags_Fmul};
end
else if (sfpu_op[15] | vfpu_op[19]) //otuput selection for Int to float intruction FCVT.S.W
begin
FPU_resultant_reg <= output_interim_Int_to_Float;
FPU_Result_rd_reg <= 32'h00000000;
S_Flags_reg <= {(output_interim_Invalid_Flag_Int_To_Float),3'b000,(output_interim_Inexact_Flag_Int_To_Float)};
end
else if (sfpu_op[18] | sfpu_op[19] | sfpu_op[20] | vfpu_op[22] | vfpu_op[23] |vfpu_op[24]) //output selection for sign injection instructions
begin
FPU_resultant_reg <= output_interim_FPU_sign;
FPU_Result_rd_reg <= 32'h00000000;
S_Flags_reg <= 5'b00000;
end
else if (sfpu_op[7] | sfpu_op[8] | vfpu_op[4]) //output selection for move instruction, FMOVE
begin
FPU_resultant_reg <= output_interim_Fmove;
FPU_Result_rd_reg <= (std==15) ? {16'h0000,output_interim_Fmove[15:0]} : output_interim_Fmove;
S_Flags_reg <= 5'b00000;
end
else if (sfpu_op[14] | vfpu_op[18]) //output selection logic for Float to int instruction FCVT.W.S
begin
FPU_resultant_reg <= {(std+1){1'b0}};
FPU_Result_rd_reg <= output_interim_FLOAT_to_Int;
S_Flags_reg <= {output_interim_Invalid_Flag_Float_To_Int,3'b000,output_interim_Inexact_Flag_Float_To_Int};
end
else if (sfpu_op[9] | sfpu_op[10] | sfpu_op[11] | (|vfpu_op[10:5])) //output selection for comparision instructions
begin
FPU_resultant_reg <= {(std+1){1'b0}};
FPU_Result_rd_reg <= output_interim_Comparison;
S_Flags_reg <= 5'b00000;
end
else if (sfpu_op[6] | sfpu_op[5] | vfpu_op[2] | vfpu_op[3]) // otuput sleection for Fmin,Max
begin
FPU_resultant_reg <= output_interim_Fmax_Fmin;
FPU_Result_rd_reg <= 32'h00000000;
S_Flags_reg <= 5'b00000;
end
else if (sfpu_op[21] | vfpu_op[25]) //output slection for Fclass instructions
begin
FPU_resultant_reg <= {(std+1){1'b0}};
FPU_Result_rd_reg <= output_interim_Fclass;
S_Flags_reg <= 5'b00000;
end
else
begin
FPU_resultant_reg <= {(std+1){1'b0}};
FPU_Result_rd_reg <= 32'h00000000;
S_Flags_reg <= 5'b00000;
end
end
end //end
endmodule