blob: 9e0d25f38feed2b109c2915b2bd4308020f36115 [file] [log] [blame]
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
////////////////////////////////////////////////////////////////////////////////
// Company: IIS @ ETHZ - Federal Institute of Technology //
// //
// Engineers: Lei Li //lile@iis.ee.ethz.ch //
// //
// Additional contributions by: //
// //
// //
// //
// Create Date: 01/03/2018 //
// Design Name: FPU //
// Module Name: preprocess_mvp.sv //
// Project Name: Private FPU //
// Language: SystemVerilog //
// //
// Description: decode and data preparation //
// //
// Revision Date: 12/04/2018 //
// Lei Li //
// To address some requirements by Stefan and add low power //
// control for special cases //
// //
// //
////////////////////////////////////////////////////////////////////////////////
import defs_div_sqrt_mvp::*;
module preprocess_mvp
(
input logic Clk_CI,
input logic Rst_RBI,
input logic Div_start_SI,
input logic Sqrt_start_SI,
input logic Ready_SI,
//Input Operands
input logic [C_OP_FP64-1:0] Operand_a_DI,
input logic [C_OP_FP64-1:0] Operand_b_DI,
input logic [C_RM-1:0] RM_SI, //Rounding Mode
input logic [C_FS-1:0] Format_sel_SI, // Format Selection
// to control
output logic Start_SO,
output logic [C_EXP_FP64:0] Exp_a_DO_norm,
output logic [C_EXP_FP64:0] Exp_b_DO_norm,
output logic [C_MANT_FP64:0] Mant_a_DO_norm,
output logic [C_MANT_FP64:0] Mant_b_DO_norm,
output logic [C_RM-1:0] RM_dly_SO,
output logic Sign_z_DO,
output logic Inf_a_SO,
output logic Inf_b_SO,
output logic Zero_a_SO,
output logic Zero_b_SO,
output logic NaN_a_SO,
output logic NaN_b_SO,
output logic SNaN_SO,
output logic Special_case_SBO,
output logic Special_case_dly_SBO
);
//Hidden Bits
logic Hb_a_D;
logic Hb_b_D;
logic [C_EXP_FP64-1:0] Exp_a_D;
logic [C_EXP_FP64-1:0] Exp_b_D;
logic [C_MANT_FP64-1:0] Mant_a_NonH_D;
logic [C_MANT_FP64-1:0] Mant_b_NonH_D;
logic [C_MANT_FP64:0] Mant_a_D;
logic [C_MANT_FP64:0] Mant_b_D;
/////////////////////////////////////////////////////////////////////////////
// Disassemble operands
/////////////////////////////////////////////////////////////////////////////
logic Sign_a_D,Sign_b_D;
logic Start_S;
always_comb
begin
case(Format_sel_SI)
2'b00:
begin
Sign_a_D = Operand_a_DI[C_OP_FP32-1];
Sign_b_D = Operand_b_DI[C_OP_FP32-1];
Exp_a_D = {3'h0, Operand_a_DI[C_OP_FP32-2:C_MANT_FP32]};
Exp_b_D = {3'h0, Operand_b_DI[C_OP_FP32-2:C_MANT_FP32]};
Mant_a_NonH_D = {Operand_a_DI[C_MANT_FP32-1:0],29'h0};
Mant_b_NonH_D = {Operand_b_DI[C_MANT_FP32-1:0],29'h0};
end
2'b01:
begin
Sign_a_D = Operand_a_DI[C_OP_FP64-1];
Sign_b_D = Operand_b_DI[C_OP_FP64-1];
Exp_a_D = Operand_a_DI[C_OP_FP64-2:C_MANT_FP64];
Exp_b_D = Operand_b_DI[C_OP_FP64-2:C_MANT_FP64];
Mant_a_NonH_D = Operand_a_DI[C_MANT_FP64-1:0];
Mant_b_NonH_D = Operand_b_DI[C_MANT_FP64-1:0];
end
2'b10:
begin
Sign_a_D = Operand_a_DI[C_OP_FP16-1];
Sign_b_D = Operand_b_DI[C_OP_FP16-1];
Exp_a_D = {6'h00, Operand_a_DI[C_OP_FP16-2:C_MANT_FP16]};
Exp_b_D = {6'h00, Operand_b_DI[C_OP_FP16-2:C_MANT_FP16]};
Mant_a_NonH_D = {Operand_a_DI[C_MANT_FP16-1:0],42'h0};
Mant_b_NonH_D = {Operand_b_DI[C_MANT_FP16-1:0],42'h0};
end
2'b11:
begin
Sign_a_D = Operand_a_DI[C_OP_FP16ALT-1];
Sign_b_D = Operand_b_DI[C_OP_FP16ALT-1];
Exp_a_D = {3'h0, Operand_a_DI[C_OP_FP16ALT-2:C_MANT_FP16ALT]};
Exp_b_D = {3'h0, Operand_b_DI[C_OP_FP16ALT-2:C_MANT_FP16ALT]};
Mant_a_NonH_D = {Operand_a_DI[C_MANT_FP16ALT-1:0],45'h0};
Mant_b_NonH_D = {Operand_b_DI[C_MANT_FP16ALT-1:0],45'h0};
end
endcase
end
assign Mant_a_D = {Hb_a_D,Mant_a_NonH_D};
assign Mant_b_D = {Hb_b_D,Mant_b_NonH_D};
assign Hb_a_D = | Exp_a_D; // hidden bit
assign Hb_b_D = | Exp_b_D; // hidden bit
assign Start_S= Div_start_SI | Sqrt_start_SI;
/////////////////////////////////////////////////////////////////////////////
// preliminary checks for infinite/zero/NaN operands //
/////////////////////////////////////////////////////////////////////////////
logic Mant_a_prenorm_zero_S;
logic Mant_b_prenorm_zero_S;
logic Exp_a_prenorm_zero_S;
logic Exp_b_prenorm_zero_S;
assign Exp_a_prenorm_zero_S = ~Hb_a_D;
assign Exp_b_prenorm_zero_S = ~Hb_b_D;
logic Exp_a_prenorm_Inf_NaN_S;
logic Exp_b_prenorm_Inf_NaN_S;
logic Mant_a_prenorm_QNaN_S;
logic Mant_a_prenorm_SNaN_S;
logic Mant_b_prenorm_QNaN_S;
logic Mant_b_prenorm_SNaN_S;
assign Mant_a_prenorm_QNaN_S=Mant_a_NonH_D[C_MANT_FP64-1]&&(~(|Mant_a_NonH_D[C_MANT_FP64-2:0]));
assign Mant_a_prenorm_SNaN_S=(~Mant_a_NonH_D[C_MANT_FP64-1])&&((|Mant_a_NonH_D[C_MANT_FP64-2:0]));
assign Mant_b_prenorm_QNaN_S=Mant_b_NonH_D[C_MANT_FP64-1]&&(~(|Mant_b_NonH_D[C_MANT_FP64-2:0]));
assign Mant_b_prenorm_SNaN_S=(~Mant_b_NonH_D[C_MANT_FP64-1])&&((|Mant_b_NonH_D[C_MANT_FP64-2:0]));
always_comb
begin
case(Format_sel_SI)
2'b00:
begin
Mant_a_prenorm_zero_S=(Operand_a_DI[C_MANT_FP32-1:0] == C_MANT_ZERO_FP32);
Mant_b_prenorm_zero_S=(Operand_b_DI[C_MANT_FP32-1:0] == C_MANT_ZERO_FP32);
Exp_a_prenorm_Inf_NaN_S=(Operand_a_DI[C_OP_FP32-2:C_MANT_FP32] == C_EXP_INF_FP32);
Exp_b_prenorm_Inf_NaN_S=(Operand_b_DI[C_OP_FP32-2:C_MANT_FP32] == C_EXP_INF_FP32);
end
2'b01:
begin
Mant_a_prenorm_zero_S=(Operand_a_DI[C_MANT_FP64-1:0] == C_MANT_ZERO_FP64);
Mant_b_prenorm_zero_S=(Operand_b_DI[C_MANT_FP64-1:0] == C_MANT_ZERO_FP64);
Exp_a_prenorm_Inf_NaN_S=(Operand_a_DI[C_OP_FP64-2:C_MANT_FP64] == C_EXP_INF_FP64);
Exp_b_prenorm_Inf_NaN_S=(Operand_b_DI[C_OP_FP64-2:C_MANT_FP64] == C_EXP_INF_FP64);
end
2'b10:
begin
Mant_a_prenorm_zero_S=(Operand_a_DI[C_MANT_FP16-1:0] == C_MANT_ZERO_FP16);
Mant_b_prenorm_zero_S=(Operand_b_DI[C_MANT_FP16-1:0] == C_MANT_ZERO_FP16);
Exp_a_prenorm_Inf_NaN_S=(Operand_a_DI[C_OP_FP16-2:C_MANT_FP16] == C_EXP_INF_FP16);
Exp_b_prenorm_Inf_NaN_S=(Operand_b_DI[C_OP_FP16-2:C_MANT_FP16] == C_EXP_INF_FP16);
end
2'b11:
begin
Mant_a_prenorm_zero_S=(Operand_a_DI[C_MANT_FP16ALT-1:0] == C_MANT_ZERO_FP16ALT);
Mant_b_prenorm_zero_S=(Operand_b_DI[C_MANT_FP16ALT-1:0] == C_MANT_ZERO_FP16ALT);
Exp_a_prenorm_Inf_NaN_S=(Operand_a_DI[C_OP_FP16ALT-2:C_MANT_FP16ALT] == C_EXP_INF_FP16ALT);
Exp_b_prenorm_Inf_NaN_S=(Operand_b_DI[C_OP_FP16ALT-2:C_MANT_FP16ALT] == C_EXP_INF_FP16ALT);
end
endcase
end
logic Zero_a_SN,Zero_a_SP;
logic Zero_b_SN,Zero_b_SP;
logic Inf_a_SN,Inf_a_SP;
logic Inf_b_SN,Inf_b_SP;
logic NaN_a_SN,NaN_a_SP;
logic NaN_b_SN,NaN_b_SP;
logic SNaN_SN,SNaN_SP;
assign Zero_a_SN = (Start_S&&Ready_SI)?(Exp_a_prenorm_zero_S&&Mant_a_prenorm_zero_S):Zero_a_SP;
assign Zero_b_SN = (Start_S&&Ready_SI)?(Exp_b_prenorm_zero_S&&Mant_b_prenorm_zero_S):Zero_b_SP;
assign Inf_a_SN = (Start_S&&Ready_SI)?(Exp_a_prenorm_Inf_NaN_S&&Mant_a_prenorm_zero_S):Inf_a_SP;
assign Inf_b_SN = (Start_S&&Ready_SI)?(Exp_b_prenorm_Inf_NaN_S&&Mant_b_prenorm_zero_S):Inf_b_SP;
assign NaN_a_SN = (Start_S&&Ready_SI)?(Exp_a_prenorm_Inf_NaN_S&&(~Mant_a_prenorm_zero_S)):NaN_a_SP;
assign NaN_b_SN = (Start_S&&Ready_SI)?(Exp_b_prenorm_Inf_NaN_S&&(~Mant_b_prenorm_zero_S)):NaN_b_SP;
assign SNaN_SN = (Start_S&&Ready_SI) ? ((Mant_a_prenorm_SNaN_S&&NaN_a_SN) | (Mant_b_prenorm_SNaN_S&&NaN_b_SN)) : SNaN_SP;
always_ff @(posedge Clk_CI, negedge Rst_RBI)
begin
if(~Rst_RBI)
begin
Zero_a_SP <='0;
Zero_b_SP <='0;
Inf_a_SP <='0;
Inf_b_SP <='0;
NaN_a_SP <='0;
NaN_b_SP <='0;
SNaN_SP <= '0;
end
else
begin
Inf_a_SP <=Inf_a_SN;
Inf_b_SP <=Inf_b_SN;
Zero_a_SP <=Zero_a_SN;
Zero_b_SP <=Zero_b_SN;
NaN_a_SP <=NaN_a_SN;
NaN_b_SP <=NaN_b_SN;
SNaN_SP <= SNaN_SN;
end
end
/////////////////////////////////////////////////////////////////////////////
// Low power control
/////////////////////////////////////////////////////////////////////////////
assign Special_case_SBO=(~{(Div_start_SI)?(Zero_a_SN | Zero_b_SN | Inf_a_SN | Inf_b_SN | NaN_a_SN | NaN_b_SN): (Zero_a_SN | Inf_a_SN | NaN_a_SN | Sign_a_D) })&&(Start_S&&Ready_SI);
always_ff @(posedge Clk_CI, negedge Rst_RBI)
begin
if(~Rst_RBI)
begin
Special_case_dly_SBO <= '0;
end
else if((Start_S&&Ready_SI))
begin
Special_case_dly_SBO <= Special_case_SBO;
end
else if(Special_case_dly_SBO)
begin
Special_case_dly_SBO <= 1'b1;
end
else
begin
Special_case_dly_SBO <= '0;
end
end
/////////////////////////////////////////////////////////////////////////////
// Delay sign for normalization and round //
/////////////////////////////////////////////////////////////////////////////
logic Sign_z_DN;
logic Sign_z_DP;
always_comb
begin
if(Div_start_SI&&Ready_SI)
Sign_z_DN = Sign_a_D ^ Sign_b_D;
else if(Sqrt_start_SI&&Ready_SI)
Sign_z_DN = Sign_a_D;
else
Sign_z_DN = Sign_z_DP;
end
always_ff @(posedge Clk_CI, negedge Rst_RBI)
begin
if(~Rst_RBI)
begin
Sign_z_DP <= '0;
end
else
begin
Sign_z_DP <= Sign_z_DN;
end
end
logic [C_RM-1:0] RM_DN;
logic [C_RM-1:0] RM_DP;
always_comb
begin
if(Start_S&&Ready_SI)
RM_DN = RM_SI;
else
RM_DN = RM_DP;
end
always_ff @(posedge Clk_CI, negedge Rst_RBI)
begin
if(~Rst_RBI)
begin
RM_DP <= '0;
end
else
begin
RM_DP <= RM_DN;
end
end
assign RM_dly_SO = RM_DP;
logic [5:0] Mant_leadingOne_a, Mant_leadingOne_b;
logic Mant_zero_S_a,Mant_zero_S_b;
lzc #(
.WIDTH ( C_MANT_FP64+1 ),
.MODE ( 1 )
) LOD_Ua (
.in_i ( Mant_a_D ),
.cnt_o ( Mant_leadingOne_a ),
.empty_o ( Mant_zero_S_a )
);
logic [C_MANT_FP64:0] Mant_a_norm_DN,Mant_a_norm_DP;
assign Mant_a_norm_DN = ((Start_S&&Ready_SI))?(Mant_a_D<<(Mant_leadingOne_a)):Mant_a_norm_DP;
always_ff @(posedge Clk_CI, negedge Rst_RBI)
begin
if(~Rst_RBI)
begin
Mant_a_norm_DP <= '0;
end
else
begin
Mant_a_norm_DP<=Mant_a_norm_DN;
end
end
logic [C_EXP_FP64:0] Exp_a_norm_DN,Exp_a_norm_DP;
assign Exp_a_norm_DN = ((Start_S&&Ready_SI))?(Exp_a_D-Mant_leadingOne_a+(|Mant_leadingOne_a)):Exp_a_norm_DP; //Covering the process of denormal numbers
always_ff @(posedge Clk_CI, negedge Rst_RBI)
begin
if(~Rst_RBI)
begin
Exp_a_norm_DP <= '0;
end
else
begin
Exp_a_norm_DP<=Exp_a_norm_DN;
end
end
lzc #(
.WIDTH ( C_MANT_FP64+1 ),
.MODE ( 1 )
) LOD_Ub (
.in_i ( Mant_b_D ),
.cnt_o ( Mant_leadingOne_b ),
.empty_o ( Mant_zero_S_b )
);
logic [C_MANT_FP64:0] Mant_b_norm_DN,Mant_b_norm_DP;
assign Mant_b_norm_DN = ((Start_S&&Ready_SI))?(Mant_b_D<<(Mant_leadingOne_b)):Mant_b_norm_DP;
always_ff @(posedge Clk_CI, negedge Rst_RBI)
begin
if(~Rst_RBI)
begin
Mant_b_norm_DP <= '0;
end
else
begin
Mant_b_norm_DP<=Mant_b_norm_DN;
end
end
logic [C_EXP_FP64:0] Exp_b_norm_DN,Exp_b_norm_DP;
assign Exp_b_norm_DN = ((Start_S&&Ready_SI))?(Exp_b_D-Mant_leadingOne_b+(|Mant_leadingOne_b)):Exp_b_norm_DP; //Covering the process of denormal numbers
always_ff @(posedge Clk_CI, negedge Rst_RBI)
begin
if(~Rst_RBI)
begin
Exp_b_norm_DP <= '0;
end
else
begin
Exp_b_norm_DP<=Exp_b_norm_DN;
end
end
/////////////////////////////////////////////////////////////////////////////
// Output assignments //
/////////////////////////////////////////////////////////////////////////////
assign Start_SO=Start_S;
assign Exp_a_DO_norm=Exp_a_norm_DP;
assign Exp_b_DO_norm=Exp_b_norm_DP;
assign Mant_a_DO_norm=Mant_a_norm_DP;
assign Mant_b_DO_norm=Mant_b_norm_DP;
assign Sign_z_DO=Sign_z_DP;
assign Inf_a_SO=Inf_a_SP;
assign Inf_b_SO=Inf_b_SP;
assign Zero_a_SO=Zero_a_SP;
assign Zero_b_SO=Zero_b_SP;
assign NaN_a_SO=NaN_a_SP;
assign NaN_b_SO=NaN_b_SP;
assign SNaN_SO=SNaN_SP;
endmodule