OpenFPGA/openfpga_flow/benchmarks/vtr_benchmark/bgm.v

2660 lines
70 KiB
Verilog
Executable File

// DEFINES
`define BITS 32 // Bit width of the operands
`define NumPath 34
module bgm(clock,
reset,
sigma_a,
sigma_b,
sigma_c,
Fn,
dw_x,
dw_y,
dw_z,
dt,
Fn_out
);
// SIGNAL DECLARATIONS
input clock;
input reset;
input [`BITS-1:0] sigma_a;
input [`BITS-1:0] sigma_b;
input [`BITS-1:0] sigma_c;
input [`BITS-1:0] Fn;
input [`BITS-1:0] dw_x;
input [`BITS-1:0] dw_y;
input [`BITS-1:0] dw_z;
input [`BITS-1:0] dt;
output [`BITS-1:0] Fn_out;
wire [`BITS-1:0] x0;
wire [`BITS-1:0] x1;
wire [`BITS-1:0] x2;
wire [`BITS-1:0] x3;
wire [`BITS-1:0] x4;
wire [`BITS-1:0] x5;
wire [`BITS-1:0] x6;
wire [`BITS-1:0] x7;
wire [`BITS-1:0] x8;
wire [`BITS-1:0] x9;
wire [`BITS-1:0] x10;
wire [`BITS-1:0] a0;
wire [`BITS-1:0] a1;
wire [`BITS-1:0] a2;
wire [`BITS-1:0] a3;
wire [`BITS-1:0] a4;
wire [`BITS-1:0] a5;
wire [`BITS-1:0] a6;
wire [`BITS-1:0] a7;
wire [`BITS-1:0] a8;
wire [`BITS-1:0] Fn_out;
wire [`BITS-1:0] Fn_delay_chain;
wire [`BITS-1:0] Fn_delay_chain_delay5;
wire [`BITS-1:0] dw_x_delay;
wire [`BITS-1:0] dw_y_delay;
wire [`BITS-1:0] dw_z_delay;
wire [`BITS-1:0] sigma_a_delay;
wire [`BITS-1:0] sigma_b_delay;
wire [`BITS-1:0] sigma_c_delay;
wire [`BITS-1:0] fifo_out1;
wire [`BITS-1:0] fifo_out2;
wire [`BITS-1:0] fifo_out3;
wire [`BITS-1:0] a4_delay5;
/*
delay44 delay_u1(clock, dw_x, dw_x_delay);
delay44 delay_u2(clock, dw_y, dw_y_delay);
delay44 delay_u3(clock, dw_z, dw_z_delay);
delay44 delay_u4(clock, sigma_a, sigma_a_delay);
delay44 delay_u5(clock, sigma_b, sigma_b_delay);
delay44 delay_u6(clock, sigma_c, sigma_c_delay);
fifo fifo_1(clock, a0, fifo_out1);
fifo fifo_2(clock, a1, fifo_out2);
fifo fifo_3(clock, a2, fifo_out3);
*/
delay5 delay_u1(clock, dw_x, dw_x_delay);
delay5 delay_u2(clock, dw_y, dw_y_delay);
delay5 delay_u3(clock, dw_z, dw_z_delay);
delay5 delay_u4(clock, sigma_a, sigma_a_delay);
delay5 delay_u5(clock, sigma_b, sigma_b_delay);
delay5 delay_u6(clock, sigma_c, sigma_c_delay);
delay5 fifo_1(clock, a0, fifo_out1);
delay5 fifo_2(clock, a1, fifo_out2);
delay5 fifo_3(clock, a2, fifo_out3);
//assign x0 = Fn * sigma_a;
wire [7:0] x0_control;
fpu_mul x0_mul
(
.clk(clock),
.opa(Fn),
.opb(sigma_a),
.out(x0),
.control(x0_control)
);
//assign x1 = Fn * sigma_b;
wire [7:0] x1_control;
fpu_mul x1_mul
(
.clk(clock),
.opa(Fn),
.opb(sigma_b),
.out(x1),
.control(x1_control)
);
//assign x2 = Fn * sigma_c;
wire [7:0] x2_control;
fpu_mul x2_mul
(
.clk(clock),
.opa(Fn),
.opb(sigma_c),
.out(x2),
.control(x2_control)
);
//assign a0 = x0 + fifo_out1;
wire [7:0] a0_control;
fpu_add a0_add
(
.clk(clock),
.opa(x0),
.opb(fifo_out1),
.out(a0),
.control(a0_control)
);
//assign a1 = x1 + fifo_out2;
wire [7:0] a1_control;
fpu_add a1_add
(
.clk(clock),
.opa(x1),
.opb(fifo_out2),
.out(a1),
.control(a1_control)
);
//assign a2 = x2 + fifo_out3;
wire [7:0] a2_control;
fpu_add a2_add
(
.clk(clock),
.opa(x2),
.opb(fifo_out3),
.out(a2),
.control(a2_control)
);
//assign x3 = dw_x_delay * sigma_a_delay;
wire [7:0] x3_control;
fpu_mul x3_mul
(
.clk(clock),
.opa(dw_x_delay),
.opb(sigma_a_delay),
.out(x3),
.control(x3_control)
);
//assign x4 = a0 * sigma_a_delay;
wire [7:0] x4_control;
fpu_mul x4_mul
(
.clk(clock),
.opa(a0),
.opb(sigma_a_delay),
.out(x4),
.control(x4_control)
);
//assign x5 = dw_y_delay * sigma_b_delay;
wire [7:0] x5_control;
fpu_mul x5_mul
(
.clk(clock),
.opa(dw_y_delay),
.opb(sigma_b_delay),
.out(x5),
.control(x5_control)
);
//assign x6 = a1 * sigma_b_delay;
wire [7:0] x6_control;
fpu_mul x6_mul
(
.clk(clock),
.opa(a1),
.opb(sigma_b_delay),
.out(x6),
.control(x6_control)
);
//assign x7 = dw_z_delay * sigma_c_delay;
wire [7:0] x7_control;
fpu_mul x7_mul
(
.clk(clock),
.opa(dw_z_delay),
.opb(sigma_c_delay),
.out(x7),
.control(x7_control)
);
//assign x8 = a2 * sigma_c_delay;
wire [7:0] x8_control;
fpu_mul x8_mul
(
.clk(clock),
.opa(a2),
.opb(sigma_c_delay),
.out(x8),
.control(x8_control)
);
//assign a3 = x3 + x5;
wire [7:0] a3_control;
fpu_add a3_add
(
.clk(clock),
.opa(x3),
.opb(x5),
.out(a3),
.control(a3_control)
);
//assign a4 = a3 + x7;
wire [7:0] a4_control;
fpu_add a4_add
(
.clk(clock),
.opa(a3),
.opb(x7),
.out(a4),
.control(a4_control)
);
//assign a5 = x4 + x6;
wire [7:0] a5_control;
fpu_add a5_add
(
.clk(clock),
.opa(x4),
.opb(x6),
.out(a5),
.control(a5_control)
);
//assign a6 = a5 + x8;
wire [7:0] a6_control;
fpu_add a6_add
(
.clk(clock),
.opa(a5),
.opb(x8),
.out(a6),
.control(a6_control)
);
delay5 delay_a5(clock, a4, a4_delay5);
//assign x9 = dt * a6;
wire [7:0] x9_control;
fpu_mul x9_mul
(
.clk(clock),
.opa(dt),
.opb(a6),
.out(x9),
.control(x9_control)
);
//assign a7 = a4_delay5 + x9;
wire [7:0] a7_control;
fpu_add a7_add
(
.clk(clock),
.opa(a4_delay5),
.opb(x9),
.out(a7),
.control(a7_control)
);
//delay_chain delay_Fn(clock, Fn, Fn_delay_chain);
delay5 delay_Fn(clock, Fn, Fn_delay_chain);
delay5 delay_Fn_delay5(clock, Fn_delay_chain, Fn_delay_chain_delay5);
//assign x10 = a7 * Fn_delay_chain;
wire [7:0] x10_control;
fpu_mul x10_mul
(
.clk(clock),
.opa(a7),
.opb(Fn_delay_chain),
.out(x10),
.control(x10_control)
);
//assign a8 = Fn_delay_chain_delay5 + x10;
wire [7:0] a8_control;
fpu_add a8_add
(
.clk(clock),
.opa(Fn_delay_chain_delay5),
.opb(x10),
.out(a8),
.control(a8_control)
);
assign Fn_out = a8;
endmodule
/*
module fifo(clock, fifo_in, fifo_out);
input clock;
input [`BITS-1:0] fifo_in;
output [`BITS-1:0] fifo_out;
wire [`BITS-1:0] fifo_out;
reg [`BITS-1:0] freg1;
reg [`BITS-1:0] freg2;
reg [`BITS-1:0] freg3;
reg [`BITS-1:0] freg4;
reg [`BITS-1:0] freg5;
reg [`BITS-1:0] freg6;
reg [`BITS-1:0] freg7;
reg [`BITS-1:0] freg8;
reg [`BITS-1:0] freg9;
reg [`BITS-1:0] freg10;
reg [`BITS-1:0] freg11;
reg [`BITS-1:0] freg12;
reg [`BITS-1:0] freg13;
reg [`BITS-1:0] freg14;
reg [`BITS-1:0] freg15;
reg [`BITS-1:0] freg16;
reg [`BITS-1:0] freg17;
reg [`BITS-1:0] freg18;
reg [`BITS-1:0] freg19;
reg [`BITS-1:0] freg20;
reg [`BITS-1:0] freg21;
reg [`BITS-1:0] freg22;
reg [`BITS-1:0] freg23;
reg [`BITS-1:0] freg24;
reg [`BITS-1:0] freg25;
reg [`BITS-1:0] freg26;
reg [`BITS-1:0] freg27;
reg [`BITS-1:0] freg28;
reg [`BITS-1:0] freg29;
reg [`BITS-1:0] freg30;
reg [`BITS-1:0] freg31;
reg [`BITS-1:0] freg32;
reg [`BITS-1:0] freg33;
reg [`BITS-1:0] freg34;
assign fifo_out = freg34;
always @(posedge clock)
begin
freg1 <= fifo_in;
freg2 <= freg1;
freg3 <= freg2;
freg4 <= freg3;
freg5 <= freg4;
freg6 <= freg5;
freg7 <= freg6;
freg8 <= freg7;
freg9 <= freg8;
freg10 <= freg9;
freg11 <= freg10;
freg12 <= freg11;
freg13 <= freg12;
freg14 <= freg13;
freg15 <= freg14;
freg16 <= freg15;
freg17 <= freg16;
freg18 <= freg17;
freg19 <= freg18;
freg20 <= freg19;
freg21 <= freg20;
freg22 <= freg21;
freg23 <= freg22;
freg24 <= freg23;
freg25 <= freg24;
freg26 <= freg25;
freg27 <= freg26;
freg28 <= freg27;
freg29 <= freg28;
freg30 <= freg29;
freg31 <= freg30;
freg32 <= freg31;
freg33 <= freg32;
freg34 <= freg33;
end
endmodule
*/
module delay5 (clock, d5_delay_in, d5_delay_out);
input clock;
input [`BITS-1:0] d5_delay_in;
output [`BITS-1:0] d5_delay_out;
//FIFO delay
reg [`BITS-1:0] d5_reg1;
/*
reg [`BITS-1:0] d5_reg2;
reg [`BITS-1:0] d5_reg3;
reg [`BITS-1:0] d5_reg4;
reg [`BITS-1:0] d5_reg5;
reg [`BITS-1:0] d5_reg6;
*/
assign d5_delay_out = d5_reg1;
always @(posedge clock)
begin
d5_reg1 <= d5_delay_in;
/*
d5_reg2 <= d5_reg1;
d5_reg3 <= d5_reg2;
d5_reg4 <= d5_reg3;
d5_reg5 <= d5_reg4;
d5_reg6 <= d5_reg5;
*/
end
endmodule
/*
module delay44 (clock, delay_in, delay_out);
input clock;
input [`BITS-1:0] delay_in;
output [`BITS-1:0] delay_out;
// wire [`BITS-1:0] delay_out;
//FIFO delay
wire [`BITS-1:0] fifo_out;
//multiplier delay
wire [`BITS-1:0] delay5_dout1;
//adder delay
wire [`BITS-1:0] delay5_dout2;
fifo fifo_delay(clock, delay_in , fifo_out);
delay5 delay_d1(clock, fifo_out, delay5_dout1);
delay5 delay_d2(clock, delay5_dout1, delay5_dout2);
assign delay_out = delay5_dout2;
// always @(posedge clock)
// begin
// fifo_out <= delay_in;
// delay5_dout1 <= fifo_out;
// delay5_dout2 <= delay5_dout1;
// end
endmodule
*/
/*
module delay_chain (clock, delay_in, delay_out);
input clock;
input [`BITS-1:0] delay_in;
output [`BITS-1:0] delay_out;
// wire [`BITS-1:0] delay_out;
wire [`BITS-1:0] delay44_out;
wire [`BITS-1:0] delay5_out1;
wire [`BITS-1:0] delay5_out2;
wire [`BITS-1:0] delay5_out3;
wire [`BITS-1:0] delay5_out4;
delay44 delay_c1(clock, delay_in, delay44_out);
delay5 delay_c2(clock, delay44_out, delay5_out1);
delay5 delay_c3(clock, delay5_out1, delay5_out2);
delay5 delay_c4(clock, delay5_out2, delay5_out3);
delay5 delay_c5(clock, delay5_out3, delay5_out4);
assign delay_out = delay5_out4;
endmodule
*/
module fpu_mul(
clk,
//rmode,
opa, opb, out,
control
/*
inf, snan, qnan, ine, overflow, underflow, zero, div_by_zero
*/
);
input clk;
//input [1:0] rmode;
input [31:0] opa, opb;
output [31:0] out;
output [7:0] control;
/*
output inf, snan, qnan;
output ine;
output overflow, underflow;
output zero;
output div_by_zero;
*/
////////////////////////////////////////////////////////////////////////
//
// Local Wires
//
reg [2:0] fpu_op;
reg zero;
reg [31:0] opa_r, opb_r; // Input operand registers
reg [31:0] out; // Output register
reg div_by_zero; // Divide by zero output register
wire signa, signb; // alias to opX sign
wire sign_fasu; // sign output
wire [26:0] fracta, fractb; // Fraction Outputs from EQU block
wire [7:0] exp_fasu; // Exponent output from EQU block
reg [7:0] exp_r; // Exponent output (registerd)
wire [26:0] fract_out_d; // fraction output
wire co; // carry output
reg [27:0] fract_out_q; // fraction output (registerd)
wire [30:0] out_d; // Intermediate final result output
wire overflow_d, underflow_d;// Overflow/Underflow Indicators
reg overflow, underflow; // Output registers for Overflow & Underflow
reg inf, snan, qnan; // Output Registers for INF, SNAN and QNAN
reg ine; // Output Registers for INE
reg [1:0] rmode_r1, rmode_r2, // Pipeline registers for rounding mode
rmode_r3;
reg [2:0] fpu_op_r1, fpu_op_r2, // Pipeline registers for fp opration
fpu_op_r3;
wire mul_inf, div_inf;
wire mul_00, div_00;
/*
parameter INF = 31'h7f800000;
parameter QNAN = 31'h7fc00001;
parameter SNAN = 31'h7f800001;
*/
wire [1:0] rmode;
assign rmode = 2'b00;
wire [30:0] INF;
assign INF = 31'h7f800000;
wire [30:0] QNAN;
assign QNAN = 31'h7fc00001;
wire [30:0] SNAN;
assign SNAN = 31'h7f800001;
// start output_reg
reg [31:0] out_o1;
reg inf_o1, snan_o1, qnan_o1;
reg ine_o1;
reg overflow_o1, underflow_o1;
reg zero_o1;
reg div_by_zero_o1;
// end output_reg
wire [7:0] contorl;
assign control = {inf, snan, qnan, ine, overflow, underflow, zero, div_by_zero};
////////////////////////////////////////////////////////////////////////
//
// Input Registers
//
always @(posedge clk) begin
fpu_op[2:0] <= 3'b010;
end
always @(posedge clk)
opa_r <= opa;
always @(posedge clk)
opb_r <= opb;
always @(posedge clk)
rmode_r1 <= rmode;
always @(posedge clk)
rmode_r2 <= rmode_r1;
always @(posedge clk)
rmode_r3 <= rmode_r2;
always @(posedge clk)
fpu_op_r1 <= fpu_op;
always @(posedge clk)
fpu_op_r2 <= fpu_op_r1;
always @(posedge clk)
fpu_op_r3 <= fpu_op_r2;
////////////////////////////////////////////////////////////////////////
//
// Exceptions block
//
wire inf_d, ind_d, qnan_d, snan_d, opa_nan, opb_nan;
wire opa_00, opb_00;
wire opa_inf, opb_inf;
wire opa_dn, opb_dn;
except u0( .clk(clk),
.opa(opa_r[30:0]), .opb(opb_r[30:0]),
.inf(inf_d), .ind(ind_d),
.qnan(qnan_d), .snan(snan_d),
.opa_nan(opa_nan), .opb_nan(opb_nan),
.opa_00(opa_00), .opb_00(opb_00),
.opa_inf(opa_inf), .opb_inf(opb_inf),
.opa_dn(opa_dn), .opb_dn(opb_dn)
);
////////////////////////////////////////////////////////////////////////
//
// Pre-Normalize block
// - Adjusts the numbers to equal exponents and sorts them
// - determine result sign
// - determine actual operation to perform (add or sub)
//
wire nan_sign_d, result_zero_sign_d;
reg sign_fasu_r;
wire [7:0] exp_mul;
wire sign_mul;
reg sign_mul_r;
wire [23:0] fracta_mul, fractb_mul;
wire inf_mul;
reg inf_mul_r;
wire [1:0] exp_ovf;
reg [1:0] exp_ovf_r;
wire sign_exe;
reg sign_exe_r;
wire [2:0] underflow_fmul_d;
pre_norm_fmul u2(
.clk(clk),
.fpu_op(fpu_op_r1),
.opa(opa_r), .opb(opb_r),
.fracta(fracta_mul),
.fractb(fractb_mul),
.exp_out(exp_mul), // FMUL exponent output (registered)
.sign(sign_mul), // FMUL sign output (registered)
.sign_exe(sign_exe), // FMUL exception sign output (registered)
.inf(inf_mul), // FMUL inf output (registered)
.exp_ovf(exp_ovf), // FMUL exponnent overflow output (registered)
.underflow(underflow_fmul_d)
);
always @(posedge clk)
sign_mul_r <= sign_mul;
always @(posedge clk)
sign_exe_r <= sign_exe;
always @(posedge clk)
inf_mul_r <= inf_mul;
always @(posedge clk)
exp_ovf_r <= exp_ovf;
////////////////////////////////////////////////////////////////////////
//
// Mul
//
wire [47:0] prod;
mul_r2 u5(.clk(clk), .opa(fracta_mul), .opb(fractb_mul), .prod(prod));
////////////////////////////////////////////////////////////////////////
//
// Normalize Result
//
wire ine_d;
reg [47:0] fract_denorm;
wire [47:0] fract_div;
wire sign_d;
reg sign;
reg [30:0] opa_r1;
reg [47:0] fract_i2f;
reg opas_r1, opas_r2;
wire f2i_out_sign;
always @(posedge clk) // Exponent must be once cycle delayed
exp_r <= exp_mul;
always @(posedge clk)
opa_r1 <= opa_r[30:0];
//always @(fpu_op_r3 or prod)
always @(prod)
fract_denorm = prod;
always @(posedge clk)
opas_r1 <= opa_r[31];
always @(posedge clk)
opas_r2 <= opas_r1;
assign sign_d = sign_mul;
always @(posedge clk)
sign <= (rmode_r2==2'h3) ? !sign_d : sign_d;
wire or_result;
assign or_result = mul_00 | div_00;
post_norm u4(
//.clk(clk), // System Clock
.fpu_op(fpu_op_r3), // Floating Point Operation
.opas(opas_r2), // OPA Sign
.sign(sign), // Sign of the result
.rmode(rmode_r3), // Rounding mode
.fract_in(fract_denorm), // Fraction Input
.exp_in(exp_r), // Exponent Input
.exp_ovf(exp_ovf_r), // Exponent Overflow
.opa_dn(opa_dn), // Operand A Denormalized
.opb_dn(opb_dn), // Operand A Denormalized
.rem_00(1'b0), // Diveide Remainder is zero
.div_opa_ldz(5'b00000), // Divide opa leading zeros count
// .output_zero(mul_00 | div_00), // Force output to Zero
.output_zero(or_result), // Force output to Zero
.out(out_d), // Normalized output (un-registered)
.ine(ine_d), // Result Inexact output (un-registered)
.overflow(overflow_d), // Overflow output (un-registered)
.underflow(underflow_d), // Underflow output (un-registered)
.f2i_out_sign(f2i_out_sign) // F2I Output Sign
);
////////////////////////////////////////////////////////////////////////
//
// FPU Outputs
//
wire [30:0] out_fixed;
wire output_zero_fasu;
wire output_zero_fdiv;
wire output_zero_fmul;
reg inf_mul2;
wire overflow_fasu;
wire overflow_fmul;
wire overflow_fdiv;
wire inf_fmul;
wire sign_mul_final;
wire out_d_00;
wire sign_div_final;
wire ine_mul, ine_mula, ine_div, ine_fasu;
wire underflow_fasu, underflow_fmul, underflow_fdiv;
wire underflow_fmul1;
reg [2:0] underflow_fmul_r;
reg opa_nan_r;
always @(posedge clk)
inf_mul2 <= exp_mul == 8'hff;
// Force pre-set values for non numerical output
assign mul_inf = (fpu_op_r3==3'b010) & (inf_mul_r | inf_mul2) & (rmode_r3==2'h0);
assign div_inf = (fpu_op_r3==3'b011) & (opb_00 | opa_inf);
assign mul_00 = (fpu_op_r3==3'b010) & (opa_00 | opb_00);
assign div_00 = (fpu_op_r3==3'b011) & (opa_00 | opb_inf);
assign out_fixed =
( (qnan_d | snan_d) |
(opa_inf & opb_00)|
(opb_inf & opa_00 )
) ? QNAN : INF;
always @(posedge clk)
out_o1[30:0] <= (mul_inf | div_inf | inf_d | snan_d | qnan_d) ? out_fixed : out_d;
assign out_d_00 = !(|out_d);
assign sign_mul_final = (sign_exe_r & ((opa_00 & opb_inf) | (opb_00 & opa_inf))) ? !sign_mul_r : sign_mul_r;
assign sign_div_final = (sign_exe_r & (opa_inf & opb_inf)) ? !sign_mul_r : sign_mul_r | (opa_00 & opb_00);
always @(posedge clk)
// out_o1[31] <= !(snan_d | qnan_d) ? sign_mul_final : nan_sign_d ;
out_o1[31] <= !(snan_d | qnan_d) & sign_mul_final;
// Exception Outputs
assign ine_mula = ((inf_mul_r | inf_mul2 | opa_inf | opb_inf) & (rmode_r3==2'h1) &
!((opa_inf & opb_00) | (opb_inf & opa_00 )) & fpu_op_r3[1]);
assign ine_mul = (ine_mula | ine_d | inf_fmul | out_d_00 | overflow_d | underflow_d) &
!opa_00 & !opb_00 & !(snan_d | qnan_d | inf_d);
always @(posedge clk)
ine_o1 <= ine_mul;
assign overflow_fmul = !inf_d & (inf_mul_r | inf_mul2 | overflow_d) & !(snan_d | qnan_d);
always @(posedge clk)
overflow_o1 <= overflow_fmul;
always @(posedge clk)
underflow_fmul_r <= underflow_fmul_d;
wire out_d_compare1;
assign out_d_compare1 = (out_d[30:23]==8'b0);
wire out_d_compare2;
assign out_d_compare2 = (out_d[22:0]==23'b0);
/*
assign underflow_fmul1 = underflow_fmul_r[0] |
(underflow_fmul_r[1] & underflow_d ) |
((opa_dn | opb_dn) & out_d_00 & (prod!=0) & sign) |
(underflow_fmul_r[2] & ((out_d[30:23]==8'b0) | (out_d[22:0]==23'b0)));
*/
assign underflow_fmul1 = underflow_fmul_r[0] |
(underflow_fmul_r[1] & underflow_d ) |
((opa_dn | opb_dn) & out_d_00 & (prod!=48'b0) & sign) |
(underflow_fmul_r[2] & (out_d_compare1 | out_d_compare2));
assign underflow_fmul = underflow_fmul1 & !(snan_d | qnan_d | inf_mul_r);
/*
always @(posedge clk)
begin
underflow_o1 <= 1'b0;
snan_o1 <= 1'b0;
qnan_o1 <= 1'b0;
inf_fmul <= 1'b0;
inf_o1 <= 1'b0;
zero_o1 <= 1'b0;
opa_nan_r <= 1'b0;
div_by_zero_o1 <= 1'b0;
end
assign output_zero_fmul = 1'b0;
*/
always @(posedge clk)
underflow_o1 <= underflow_fmul;
always @(posedge clk)
snan_o1 <= snan_d;
// Status Outputs
always @(posedge clk)
qnan_o1 <= ( snan_d | qnan_d |
(((opa_inf & opb_00) | (opb_inf & opa_00 )) & fpu_op_r3==3'b010)
);
assign inf_fmul = (((inf_mul_r | inf_mul2) & (rmode_r3==2'h0)) | opa_inf | opb_inf) &
!((opa_inf & opb_00) | (opb_inf & opa_00 )) &
fpu_op_r3==3'b010;
always @(posedge clk)
/*
inf_o1 <= fpu_op_r3[2] ? 1'b0 :
(!(qnan_d | snan_d) &
( ((&out_d[30:23]) & !(|out_d[22:0]) & !(opb_00 & fpu_op_r3==3'b011)) | inf_fmul)
);
*/
inf_o1 <= !fpu_op_r3[2] & (!(qnan_d | snan_d) &
( ((&out_d[30:23]) & !(|out_d[22:0]) & !(opb_00 & fpu_op_r3==3'b011)) | inf_fmul)
);
assign output_zero_fmul = (out_d_00 | opa_00 | opb_00) &
!(inf_mul_r | inf_mul2 | opa_inf | opb_inf | snan_d | qnan_d) &
!(opa_inf & opb_00) & !(opb_inf & opa_00);
always @(posedge clk)
zero_o1 <= output_zero_fmul;
always @(posedge clk)
opa_nan_r <= (!opa_nan) & (fpu_op_r2==3'b011) ;
always @(posedge clk)
div_by_zero_o1 <= opa_nan_r & !opa_00 & !opa_inf & opb_00;
// output register
always @(posedge clk)
begin
qnan <= qnan_o1;
out <= out_o1;
inf <= inf_o1;
snan <= snan_o1;
//qnan <= qnan_o1;
ine <= ine_o1;
overflow <= overflow_o1;
underflow <= underflow_o1;
zero <= zero_o1;
div_by_zero <= div_by_zero_o1;
end
endmodule
//---------------------------------------------------------------------------------
module except( clk, opa, opb, inf, ind, qnan, snan, opa_nan, opb_nan,
opa_00, opb_00, opa_inf, opb_inf, opa_dn, opb_dn);
input clk;
input [30:0] opa, opb;
output inf, ind, qnan, snan, opa_nan, opb_nan;
output opa_00, opb_00;
output opa_inf, opb_inf;
output opa_dn;
output opb_dn;
////////////////////////////////////////////////////////////////////////
//
// Local Wires and registers
//
wire [7:0] expa, expb; // alias to opX exponent
wire [22:0] fracta, fractb; // alias to opX fraction
reg expa_ff, infa_f_r, qnan_r_a, snan_r_a;
reg expb_ff, infb_f_r, qnan_r_b, snan_r_b;
reg inf, ind, qnan, snan; // Output registers
reg opa_nan, opb_nan;
reg expa_00, expb_00, fracta_00, fractb_00;
reg opa_00, opb_00;
reg opa_inf, opb_inf;
reg opa_dn, opb_dn;
////////////////////////////////////////////////////////////////////////
//
// Aliases
//
assign expa = opa[30:23];
assign expb = opb[30:23];
assign fracta = opa[22:0];
assign fractb = opb[22:0];
////////////////////////////////////////////////////////////////////////
//
// Determine if any of the input operators is a INF or NAN or any other special number
//
always @(posedge clk)
expa_ff <= &expa;
always @(posedge clk)
expb_ff <= &expb;
always @(posedge clk)
infa_f_r <= !(|fracta);
always @(posedge clk)
infb_f_r <= !(|fractb);
always @(posedge clk)
qnan_r_a <= fracta[22];
always @(posedge clk)
snan_r_a <= !fracta[22] & |fracta[21:0];
always @(posedge clk)
qnan_r_b <= fractb[22];
always @(posedge clk)
snan_r_b <= !fractb[22] & |fractb[21:0];
always @(posedge clk)
ind <= (expa_ff & infa_f_r) & (expb_ff & infb_f_r);
always @(posedge clk)
inf <= (expa_ff & infa_f_r) | (expb_ff & infb_f_r);
always @(posedge clk)
qnan <= (expa_ff & qnan_r_a) | (expb_ff & qnan_r_b);
always @(posedge clk)
snan <= (expa_ff & snan_r_a) | (expb_ff & snan_r_b);
always @(posedge clk)
opa_nan <= &expa & (|fracta[22:0]);
always @(posedge clk)
opb_nan <= &expb & (|fractb[22:0]);
always @(posedge clk)
opa_inf <= (expa_ff & infa_f_r);
always @(posedge clk)
opb_inf <= (expb_ff & infb_f_r);
always @(posedge clk)
expa_00 <= !(|expa);
always @(posedge clk)
expb_00 <= !(|expb);
always @(posedge clk)
fracta_00 <= !(|fracta);
always @(posedge clk)
fractb_00 <= !(|fractb);
always @(posedge clk)
opa_00 <= expa_00 & fracta_00;
always @(posedge clk)
opb_00 <= expb_00 & fractb_00;
always @(posedge clk)
opa_dn <= expa_00;
always @(posedge clk)
opb_dn <= expb_00;
endmodule
//---------------------------------------------------------------------------------
module pre_norm_fmul(clk, fpu_op, opa, opb, fracta, fractb, exp_out, sign,
sign_exe, inf, exp_ovf, underflow);
input clk;
input [2:0] fpu_op;
input [31:0] opa, opb;
output [23:0] fracta, fractb;
output [7:0] exp_out;
output sign, sign_exe;
output inf;
output [1:0] exp_ovf;
output [2:0] underflow;
////////////////////////////////////////////////////////////////////////
//
// Local Wires and registers
//
reg [7:0] exp_out;
wire signa, signb;
reg sign, sign_d;
reg sign_exe;
reg inf;
wire [1:0] exp_ovf_d;
reg [1:0] exp_ovf;
wire [7:0] expa, expb;
wire [7:0] exp_tmp1, exp_tmp2;
wire co1, co2;
wire expa_dn, expb_dn;
wire [7:0] exp_out_a;
wire opa_00, opb_00, fracta_00, fractb_00;
wire [7:0] exp_tmp3, exp_tmp4, exp_tmp5;
wire [2:0] underflow_d;
reg [2:0] underflow;
wire op_div;
wire [7:0] exp_out_mul, exp_out_div;
assign op_div = (fpu_op == 3'b011);
////////////////////////////////////////////////////////////////////////
//
// Aliases
//
assign signa = opa[31];
assign signb = opb[31];
assign expa = opa[30:23];
assign expb = opb[30:23];
////////////////////////////////////////////////////////////////////////
//
// Calculate Exponenet
//
assign expa_dn = !(|expa);
assign expb_dn = !(|expb);
assign opa_00 = !(|opa[30:0]);
assign opb_00 = !(|opb[30:0]);
assign fracta_00 = !(|opa[22:0]);
assign fractb_00 = !(|opb[22:0]);
assign fracta[22:0] = opa[22:0];
assign fractb[22:0] = opb[22:0];
assign fracta[23:23] = !expa_dn;
assign fractb[23:23] = !expb_dn;
//assign fracta = {!expa_dn,opa[22:0]}; // Recover hidden bit
//assign fractb = {!expb_dn,opb[22:0]}; // Recover hidden bit
assign {co1,exp_tmp1} = op_div ? ({1'b0,expa[7:0]} - {1'b0,expb[7:0]}) : ({1'b0,expa[7:0]} + {1'b0,expb[7:0]});
assign {co2,exp_tmp2} = op_div ? ({co1,exp_tmp1} + 9'h07f) : ({co1,exp_tmp1} - 9'h07f);
assign exp_tmp3 = exp_tmp2 + 8'h01;
assign exp_tmp4 = 8'h7f - exp_tmp1;
assign exp_tmp5 = op_div ? (exp_tmp4+8'h01) : (exp_tmp4-8'h01);
always@(posedge clk)
exp_out <= op_div ? exp_out_div : exp_out_mul;
assign exp_out_div = (expa_dn | expb_dn) ? (co2 ? exp_tmp5 : exp_tmp3 ) : co2 ? exp_tmp4 : exp_tmp2;
assign exp_out_mul = exp_ovf_d[1] ? exp_out_a : (expa_dn | expb_dn) ? exp_tmp3 : exp_tmp2;
assign exp_out_a = (expa_dn | expb_dn) ? exp_tmp5 : exp_tmp4;
assign exp_ovf_d[0] = op_div ? (expa[7] & !expb[7]) : (co2 & expa[7] & expb[7]);
assign exp_ovf_d[1] = op_div ? co2 : ((!expa[7] & !expb[7] & exp_tmp2[7]) | co2);
always @(posedge clk)
exp_ovf <= exp_ovf_d;
assign underflow_d[0] = (exp_tmp1 < 8'h7f) & !co1 & !(opa_00 | opb_00 | expa_dn | expb_dn);
assign underflow_d[1] = ((expa[7] | expb[7]) & !opa_00 & !opb_00) |
(expa_dn & !fracta_00) | (expb_dn & !fractb_00);
assign underflow_d[2] = !opa_00 & !opb_00 & (exp_tmp1 == 8'h7f);
always @(posedge clk)
underflow <= underflow_d;
always @(posedge clk)
inf <= op_div ? (expb_dn & !expa[7]) : ({co1,exp_tmp1} > 9'h17e) ;
////////////////////////////////////////////////////////////////////////
//
// Determine sign for the output
//
// sign: 0=Posetive Number; 1=Negative Number
always @(signa or signb)
case({signa, signb}) // synopsys full_case parallel_case
2'b00: sign_d = 0;
2'b01: sign_d = 1;
2'b10: sign_d = 1;
2'b11: sign_d = 0;
endcase
always @(posedge clk)
sign <= sign_d;
always @(posedge clk)
sign_exe <= signa & signb;
endmodule
//----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
//
// Multiply
//
module mul_r2(clk, opa, opb, prod);
input clk;
input [23:0] opa, opb;
output [47:0] prod;
reg [47:0] prod1, prod;
always @(posedge clk)
prod1 <= opa * opb;
always @(posedge clk)
prod <= prod1;
endmodule
//----------------------------------------------------------------------------
module post_norm( fpu_op, opas, sign, rmode, fract_in, exp_in, exp_ovf,
opa_dn, opb_dn, rem_00, div_opa_ldz, output_zero, out,
ine, overflow, underflow, f2i_out_sign);
input [2:0] fpu_op;
input opas;
input sign;
input [1:0] rmode;
input [47:0] fract_in;
input [7:0] exp_in;
input [1:0] exp_ovf;
input opa_dn, opb_dn;
input rem_00;
input [4:0] div_opa_ldz;
input output_zero;
output [30:0] out;
output ine;
output overflow, underflow;
output f2i_out_sign;
////////////////////////////////////////////////////////////////////////
//
// Local Wires and registers
//
wire [22:0] fract_out;
wire [7:0] exp_out;
wire [30:0] out;
wire exp_out1_co, overflow, underflow;
wire [22:0] fract_out_final;
reg [22:0] fract_out_rnd;
wire [8:0] exp_next_mi;
wire dn;
wire exp_rnd_adj;
wire [7:0] exp_out_final;
reg [7:0] exp_out_rnd;
wire op_dn;
wire op_mul;
wire op_div;
wire op_i2f;
wire op_f2i;
//reg [5:0] fi_ldz;
wire [5:0] fi_ldz;
wire g, r, s;
wire round, round2, round2a, round2_fasu, round2_fmul;
wire [7:0] exp_out_rnd0, exp_out_rnd1, exp_out_rnd2, exp_out_rnd2a;
wire [22:0] fract_out_rnd0, fract_out_rnd1, fract_out_rnd2, fract_out_rnd2a;
wire exp_rnd_adj0, exp_rnd_adj2a;
wire r_sign;
wire ovf0, ovf1;
wire [23:0] fract_out_pl1;
wire [7:0] exp_out_pl1, exp_out_mi1;
wire exp_out_00, exp_out_fe, exp_out_ff, exp_in_00, exp_in_ff;
wire exp_out_final_ff, fract_out_7fffff;
wire [24:0] fract_trunc;
wire [7:0] exp_out1;
wire grs_sel;
wire fract_out_00, fract_in_00;
wire shft_co;
wire [8:0] exp_in_pl1, exp_in_mi1;
wire [47:0] fract_in_shftr;
wire [47:0] fract_in_shftl;
// for block shifter
wire [47:0] fract_in_shftr_1;
wire [47:0] fract_in_shftl_1;
// end for block shifter
wire [7:0] exp_div;
wire [7:0] shft2;
wire [7:0] exp_out1_mi1;
wire div_dn;
wire div_nr;
wire grs_sel_div;
wire div_inf;
wire [6:0] fi_ldz_2a;
wire [7:0] fi_ldz_2;
wire [7:0] div_shft1, div_shft2, div_shft3, div_shft4;
wire div_shft1_co;
wire [8:0] div_exp1;
wire [7:0] div_exp2, div_exp3;
wire left_right, lr_mul, lr_div;
wire [7:0] shift_right, shftr_mul, shftr_div;
wire [7:0] shift_left, shftl_mul, shftl_div;
wire [7:0] fasu_shift;
wire [7:0] exp_fix_div;
wire [7:0] exp_fix_diva, exp_fix_divb;
wire [5:0] fi_ldz_mi1;
wire [5:0] fi_ldz_mi22;
wire exp_zero;
wire [6:0] ldz_all;
wire [7:0] ldz_dif;
wire [8:0] div_scht1a;
wire [7:0] f2i_shft;
wire [55:0] exp_f2i_1;
wire f2i_zero, f2i_max;
wire [7:0] f2i_emin;
wire [7:0] conv_shft;
wire [7:0] exp_i2f, exp_f2i, conv_exp;
wire round2_f2i;
assign op_mul = fpu_op[2:0]==3'b010;
assign op_div = fpu_op[2:0]==3'b011;
assign op_i2f = fpu_op[2:0]==3'b100;
assign op_f2i = fpu_op[2:0]==3'b101;
assign op_dn = opa_dn | opb_dn;
pri_encoder u6(
.fract_in (fract_in),
.fi_ldz (fi_ldz)
);
// ---------------------------------------------------------------------
// Normalize
wire exp_in_80;
wire rmode_00, rmode_01, rmode_10, rmode_11;
// Misc common signals
assign exp_in_ff = &exp_in;
assign exp_in_00 = !(|exp_in);
assign exp_in_80 = exp_in[7] & !(|exp_in[6:0]);
assign exp_out_ff = &exp_out;
assign exp_out_00 = !(|exp_out);
assign exp_out_fe = &exp_out[7:1] & !exp_out[0];
assign exp_out_final_ff = &exp_out_final;
assign fract_out_7fffff = &fract_out;
assign fract_out_00 = !(|fract_out);
assign fract_in_00 = !(|fract_in);
assign rmode_00 = (rmode==2'b00);
assign rmode_01 = (rmode==2'b01);
assign rmode_10 = (rmode==2'b10);
assign rmode_11 = (rmode==2'b11);
// Fasu Output will be denormalized ...
assign dn = !op_mul & !op_div & (exp_in_00 | (exp_next_mi[8] & !fract_in[47]) );
// ---------------------------------------------------------------------
// Fraction Normalization
wire[7:0] f2i_emax;
assign f2i_emax = 8'h9d;
//parameter f2i_emax = 8'h9d;
// Incremented fraction for rounding
assign fract_out_pl1 = {1'b0, fract_out} + 24'h000001;
// Special Signals for f2i
assign f2i_emin = rmode_00 ? 8'h7e : 8'h7f;
assign f2i_zero = (!opas & (exp_in<f2i_emin)) | (opas & (exp_in>f2i_emax)) | (opas & (exp_in<f2i_emin) & (fract_in_00 | !rmode_11));
assign f2i_max = (!opas & (exp_in>f2i_emax)) | (opas & (exp_in<f2i_emin) & !fract_in_00 & rmode_11);
// Calculate various shifting options
assign {shft_co,shftr_mul} = (!exp_ovf[1] & exp_in_00) ? {1'b0, exp_out} : exp_in_mi1 ;
assign {div_shft1_co, div_shft1} = exp_in_00 ? {1'b0, div_opa_ldz} : div_scht1a;
assign div_scht1a = {1'b0, exp_in}-{4'b0, div_opa_ldz}; // 9 bits - includes carry out
assign div_shft2 = exp_in+8'h02;
assign div_shft3 = {3'b0, div_opa_ldz}+exp_in;
assign div_shft4 = {3'b0, div_opa_ldz}-exp_in;
assign div_dn = op_dn & div_shft1_co;
assign div_nr = op_dn & exp_ovf[1] & !(|fract_in[46:23]) & (div_shft3>8'h16);
assign f2i_shft = exp_in-8'h7d;
// Select shifting direction
assign left_right = op_div ? lr_div : op_mul ? lr_mul :1'b1;
assign lr_div = (op_dn & !exp_ovf[1] & exp_ovf[0]) ? 1'b1 :
(op_dn & exp_ovf[1]) ? 1'b0 :
(op_dn & div_shft1_co) ? 1'b0 :
(op_dn & exp_out_00) ? 1'b1 :
(!op_dn & exp_out_00 & !exp_ovf[1]) ? 1'b1 :
exp_ovf[1] ? 1'b0 :
1'b1;
assign lr_mul = (shft_co | (!exp_ovf[1] & exp_in_00) |
(!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00) )) ? 1'b1 :
( exp_ovf[1] | exp_in_00 ) ? 1'b0 :
1'b1;
// Select Left and Right shift value
assign fasu_shift = (dn | exp_out_00) ? (exp_in_00 ? 8'h02 : exp_in_pl1[7:0]) : {2'h0, fi_ldz};
assign shift_right = op_div ? shftr_div : shftr_mul;
assign conv_shft = op_f2i ? f2i_shft : {2'h0, fi_ldz};
assign shift_left = op_div ? shftl_div : op_mul ? shftl_mul : (op_f2i | op_i2f) ? conv_shft : fasu_shift;
assign shftl_mul = (shft_co |
(!exp_ovf[1] & exp_in_00) |
(!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00))) ? exp_in_pl1[7:0] : {2'h0, fi_ldz};
assign shftl_div = ( op_dn & exp_out_00 & !(!exp_ovf[1] & exp_ovf[0])) ? div_shft1[7:0] :
(!op_dn & exp_out_00 & !exp_ovf[1]) ? exp_in[7:0] :
{2'h0, fi_ldz};
assign shftr_div = (op_dn & exp_ovf[1]) ? div_shft3 :
(op_dn & div_shft1_co) ? div_shft4 : div_shft2;
// Do the actual shifting
//assign fract_in_shftr = (|shift_right[7:6]) ? 0 : fract_in>>shift_right[5:0];
//assign fract_in_shftl = (|shift_left[7:6] | (f2i_zero & op_f2i)) ? 0 : fract_in<<shift_left[5:0];
b_right_shifter u1(
.shift_in (fract_in),
.shift_value (shift_right[5:0]),
.shift_out (fract_in_shftr_1)
);
assign fract_in_shftr = (|shift_right[7:6]) ? 48'b0 : fract_in_shftr_1; // fract_in>>shift_right[5:0];
b_left_shifter u7(
.shift_in (fract_in),
.shift_value (shift_left[5:0]),
.shift_out (fract_in_shftl_1)
);
assign fract_in_shftl = (|shift_left[7:6] | (f2i_zero & op_f2i)) ? 48'b0 : fract_in_shftl_1; // fract_in<<shift_left[5:0];
// Chose final fraction output
assign {fract_out,fract_trunc} = left_right ? fract_in_shftl : fract_in_shftr;
// ---------------------------------------------------------------------
// Exponent Normalization
assign fi_ldz_mi1 = fi_ldz - 6'h01;
assign fi_ldz_mi22 = fi_ldz - 6'd22;
assign exp_out_pl1 = exp_out + 8'h01;
assign exp_out_mi1 = exp_out - 8'h01;
assign exp_in_pl1 = {1'b0, exp_in} + 9'd1; // 9 bits - includes carry out
assign exp_in_mi1 = {1'b0, exp_in} - 9'd1; // 9 bits - includes carry out
assign exp_out1_mi1 = exp_out1 - 8'h01;
assign exp_next_mi = exp_in_pl1 - {3'b0, fi_ldz_mi1}; // 9 bits - includes carry out
assign exp_fix_diva = exp_in - {2'b0, fi_ldz_mi22};
assign exp_fix_divb = exp_in - {2'b0, fi_ldz_mi1};
//assign exp_zero = (exp_ovf[1] & !exp_ovf[0] & op_mul & (!exp_rnd_adj2a | !rmode[1])) | (op_mul & exp_out1_co);
assign exp_zero = (exp_ovf[1] & !exp_ovf[0] & op_mul ) | (op_mul & exp_out1_co);
assign {exp_out1_co, exp_out1} = fract_in[47] ? exp_in_pl1 : exp_next_mi;
assign f2i_out_sign = !opas ? ((exp_in<f2i_emin) ? 1'b0 : (exp_in>f2i_emax) ? 1'b0 : opas) :
((exp_in<f2i_emin) ? 1'b0 : (exp_in>f2i_emax) ? 1'b1 : opas);
assign exp_i2f = fract_in_00 ? (opas ? 8'h9e : 8'h00) : (8'h9e-{2'b0, fi_ldz});
//assign exp_f2i_1 = {{8{fract_in[47]}}, fract_in }<<f2i_shft;
b_left_shifter_new u3(
.shift_in ({{8{fract_in[47]}}, fract_in }),
.shift_value (f2i_shft[5:0]),
.shift_out (exp_f2i_1)
);
assign exp_f2i = f2i_zero ? 8'h00 : f2i_max ? 8'hff : exp_f2i_1[55:48];
assign conv_exp = op_f2i ? exp_f2i : exp_i2f;
assign exp_out = op_div ? exp_div : (op_f2i | op_i2f) ? conv_exp : exp_zero ? 8'h0 : dn ? {6'h0, fract_in[47:46]} : exp_out1;
assign ldz_all = {2'b0, div_opa_ldz} + {1'b0, fi_ldz};
assign ldz_dif = fi_ldz_2 - {3'b0, div_opa_ldz};
assign fi_ldz_2a = 7'd23 - {1'b0,fi_ldz};
assign fi_ldz_2 = {fi_ldz_2a[6], fi_ldz_2a[6:0]};
assign div_exp1 = exp_in_mi1 + {1'b0, fi_ldz_2}; // 9 bits - includes carry out
assign div_exp2 = exp_in_pl1[7:0] - {1'b0, ldz_all};
assign div_exp3 = exp_in + ldz_dif;
assign exp_div =(opa_dn & opb_dn)? div_exp3 : opb_dn? div_exp1[7:0] :
(opa_dn & !( (exp_in[4:0]<div_opa_ldz) | (div_exp2>8'hfe) )) ? div_exp2 :
(opa_dn | (exp_in_00 & !exp_ovf[1]) ) ? 8'h00 :
exp_out1_mi1;
assign div_inf = opb_dn & !opa_dn & (div_exp1[7:0] < 8'h7f);
// ---------------------------------------------------------------------
// Round
// Extract rounding (GRS) bits
assign grs_sel_div = op_div & (exp_ovf[1] | div_dn | exp_out1_co | exp_out_00);
assign g = grs_sel_div ? fract_out[0] : fract_out[0];
assign r = grs_sel_div ? (fract_trunc[24] & !div_nr) : fract_trunc[24];
assign s = grs_sel_div ? |fract_trunc[24:0] : (|fract_trunc[23:0] | (fract_trunc[24] & op_div));
// Round to nearest even
assign round = (g & r) | (r & s) ;
assign {exp_rnd_adj0, fract_out_rnd0} = round ? fract_out_pl1 : {1'b0, fract_out};
assign exp_out_rnd0 = exp_rnd_adj0 ? exp_out_pl1 : exp_out;
assign ovf0 = exp_out_final_ff & !rmode_01 & !op_f2i;
// round to zero
assign fract_out_rnd1 = (exp_out_ff & !op_div & !dn & !op_f2i) ? 23'h7fffff : fract_out;
assign exp_fix_div = (fi_ldz>6'd22) ? exp_fix_diva : exp_fix_divb;
assign exp_out_rnd1 = (g & r & s & exp_in_ff) ? (op_div ? exp_fix_div : exp_next_mi[7:0]) : (exp_out_ff & !op_f2i) ? exp_in : exp_out;
assign ovf1 = exp_out_ff & !dn;
// round to +inf (UP) and -inf (DOWN)
assign r_sign = sign;
assign round2a = !exp_out_fe | !fract_out_7fffff | (exp_out_fe & fract_out_7fffff);
assign round2_fasu = ((r | s) & !r_sign) & (!exp_out[7] | (exp_out[7] & round2a));
assign round2_fmul = !r_sign &
(
(exp_ovf[1] & !fract_in_00 &
( ((!exp_out1_co | op_dn) & (r | s | (!rem_00 & op_div) )) | fract_out_00 | (!op_dn & !op_div))
) |
(
(r | s | (!rem_00 & op_div)) & (
(!exp_ovf[1] & (exp_in_80 | !exp_ovf[0])) | op_div |
( exp_ovf[1] & !exp_ovf[0] & exp_out1_co)
)
)
);
//assign round2_f2i = rmode_10 & (( |fract_in[23:0] & !opas & (exp_in<8'h80 )) | (|fract_trunc));
wire temp_fract_in;
assign temp_fract_in = |fract_in[23:0];
assign round2_f2i = rmode_10 & (( temp_fract_in & !opas & (exp_in<8'h80 )) | (|fract_trunc));
assign round2 = (op_mul | op_div) ? round2_fmul : op_f2i ? round2_f2i : round2_fasu;
assign {exp_rnd_adj2a, fract_out_rnd2a} = round2 ? fract_out_pl1 : {1'b0, fract_out};
assign exp_out_rnd2a = exp_rnd_adj2a ? ((exp_ovf[1] & op_mul) ? exp_out_mi1 : exp_out_pl1) : exp_out;
assign fract_out_rnd2 = (r_sign & exp_out_ff & !op_div & !dn & !op_f2i) ? 23'h7fffff : fract_out_rnd2a;
assign exp_out_rnd2 = (r_sign & exp_out_ff & !op_f2i) ? 8'hfe : exp_out_rnd2a;
// Choose rounding mode
always @(rmode or exp_out_rnd0 or exp_out_rnd1 or exp_out_rnd2)
case(rmode) // synopsys full_case parallel_case
2'b00: exp_out_rnd = exp_out_rnd0;
2'b01: exp_out_rnd = exp_out_rnd1;
2'b10: exp_out_rnd = exp_out_rnd2;
2'b11: exp_out_rnd = exp_out_rnd2;
endcase
always @(rmode or fract_out_rnd0 or fract_out_rnd1 or fract_out_rnd2)
case (rmode) // synopsys full_case parallel_case
2'b00: fract_out_rnd = fract_out_rnd0;
2'b01: fract_out_rnd = fract_out_rnd1;
2'b10: fract_out_rnd = fract_out_rnd2;
2'b11: fract_out_rnd = fract_out_rnd2;
endcase
// ---------------------------------------------------------------------
// Final Output Mux
// Fix Output for denormalized and special numbers
wire max_num, inf_out;
assign max_num = ( !rmode_00 & (op_mul | op_div ) & (
( exp_ovf[1] & exp_ovf[0]) |
(!exp_ovf[1] & !exp_ovf[0] & exp_in_ff & (fi_ldz_2<8'd24) & (exp_out!=8'hfe) )
)
) |
( op_div & (
( rmode_01 & ( div_inf |
(exp_out_ff & !exp_ovf[1] ) |
(exp_ovf[1] & exp_ovf[0] )
)
) |
( rmode[1] & !exp_ovf[1] & (
( exp_ovf[0] & exp_in_ff & r_sign & fract_in[47]
) |
( r_sign & (
(fract_in[47] & div_inf) |
(exp_in[7] & !exp_out_rnd[7] & !exp_in_80 & exp_out!=8'h7f ) |
(exp_in[7] & exp_out_rnd[7] & r_sign & exp_out_ff & op_dn &
div_exp1>9'h0fe )
)
) |
( exp_in_00 & r_sign & (
div_inf |
(r_sign & exp_out_ff & fi_ldz_2<8'h18)
)
)
)
)
)
);
assign inf_out = (rmode[1] & (op_mul | op_div) & !r_sign & ( (exp_in_ff & !op_div) |
(exp_ovf[1] & exp_ovf[0] & (exp_in_00 | exp_in[7]) )
)
) | (div_inf & op_div & (
rmode_00 |
(rmode[1] & !exp_in_ff & !exp_ovf[1] & !exp_ovf[0] & !r_sign ) |
(rmode[1] & !exp_ovf[1] & exp_ovf[0] & exp_in_00 & !r_sign)
)
) | (op_div & rmode[1] & exp_in_ff & op_dn & !r_sign & (fi_ldz_2 < 8'd24) & (exp_out_rnd!=8'hfe) );
assign fract_out_final = (inf_out | ovf0 | output_zero ) ? 23'h000000 :
(max_num | (f2i_max & op_f2i) ) ? 23'h7fffff :
fract_out_rnd;
assign exp_out_final = ((op_div & exp_ovf[1] & !exp_ovf[0]) | output_zero ) ? 8'h00 :
((op_div & exp_ovf[1] & exp_ovf[0] & rmode_00) | inf_out | (f2i_max & op_f2i) ) ? 8'hff :
max_num ? 8'hfe :
exp_out_rnd;
// ---------------------------------------------------------------------
// Pack Result
assign out = {exp_out_final, fract_out_final};
// ---------------------------------------------------------------------
// Exceptions
wire underflow_fmul;
wire overflow_fdiv;
wire undeflow_div;
wire z;
assign z = shft_co | ( exp_ovf[1] | exp_in_00) |
(!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00));
assign underflow_fmul = ( (|fract_trunc) & z & !exp_in_ff ) |
(fract_out_00 & !fract_in_00 & exp_ovf[1]);
assign undeflow_div = !(exp_ovf[1] & exp_ovf[0] & rmode_00) & !inf_out & !max_num & exp_out_final!=8'hff & (
((|fract_trunc) & !opb_dn & (
( op_dn & !exp_ovf[1] & exp_ovf[0]) |
( op_dn & exp_ovf[1]) |
( op_dn & div_shft1_co) |
exp_out_00 |
exp_ovf[1]
)
) |
( exp_ovf[1] & !exp_ovf[0] & (
( op_dn & exp_in>8'h16 & fi_ldz<6'd23) |
( op_dn & exp_in<8'd23 & fi_ldz<6'd23 & !rem_00) |
( !op_dn & (exp_in[7]==exp_div[7]) & !rem_00) |
( !op_dn & exp_in_00 & (exp_div[7:1]==7'h7f) ) |
( !op_dn & exp_in<8'h7f & exp_in>8'h20 )
)
) |
(!exp_ovf[1] & !exp_ovf[0] & (
( op_dn & fi_ldz<6'd23 & exp_out_00) |
( exp_in_00 & !rem_00) |
( !op_dn & ldz_all<7'd23 & exp_in==8'h01 & exp_out_00 & !rem_00)
)
)
);
assign underflow = op_div ? undeflow_div : op_mul ? underflow_fmul : (!fract_in[47] & exp_out1_co) & !dn;
assign overflow_fdiv = inf_out |
(!rmode_00 & max_num) |
(exp_in[7] & op_dn & exp_out_ff) |
(exp_ovf[0] & (exp_ovf[1] | exp_out_ff) );
assign overflow = op_div ? overflow_fdiv : (ovf0 | ovf1);
wire f2i_ine;
assign f2i_ine = (f2i_zero & !fract_in_00 & !opas) |
(|fract_trunc) |
(f2i_zero & (exp_in<8'h80) & opas & !fract_in_00) |
(f2i_max & rmode_11 & (exp_in<8'h80));
assign ine = op_f2i ? f2i_ine :
op_i2f ? (|fract_trunc) :
((r & !dn) | (s & !dn) | max_num | (op_div & !rem_00));
endmodule
//-------------------------------------------------------------------------------------
module pri_encoder ( fract_in, fi_ldz );
input [47:0] fract_in;
output [5:0] fi_ldz;
reg [5:0] fi_ldz_r0;
assign fi_ldz = fi_ldz_r0;
always @(fract_in)
begin
if (fract_in[47:47] == 1'b1)
fi_ldz_r0 = 6'd1;
else if (fract_in[47:46] == 2'b01)
fi_ldz_r0 = 6'd2;
else if (fract_in[47:45] == 3'b001)
fi_ldz_r0 = 6'd3;
else if (fract_in[47:44] == 4'b0001)
fi_ldz_r0 = 6'd4;
else if (fract_in[47:43] == 5'b00001)
fi_ldz_r0 = 6'd5;
else if (fract_in[47:42] == 6'b000001)
fi_ldz_r0 = 6'd6;
else if (fract_in[47:41] == 7'b0000001)
fi_ldz_r0 = 6'd7;
else if (fract_in[47:40] == 8'b00000001)
fi_ldz_r0 = 6'd8;
else if (fract_in[47:39] == 9'b000000001)
fi_ldz_r0 = 6'd9;
else if (fract_in[47:38] == 10'b0000000001)
fi_ldz_r0 = 6'd10;
else if (fract_in[47:37] == 11'b00000000001)
fi_ldz_r0 = 6'd11;
else if (fract_in[47:36] == 12'b000000000001)
fi_ldz_r0 = 6'd12;
else if (fract_in[47:35] == 13'b0000000000001)
fi_ldz_r0 = 6'd13;
else if (fract_in[47:34] == 14'b00000000000001)
fi_ldz_r0 = 6'd14;
else if (fract_in[47:33] == 15'b000000000000001)
fi_ldz_r0 = 6'd15;
else if (fract_in[47:32] == 16'b0000000000000001)
fi_ldz_r0 = 6'd16;
else if (fract_in[47:31] == 17'b00000000000000001)
fi_ldz_r0 = 6'd17;
else if (fract_in[47:30] == 18'b000000000000000001)
fi_ldz_r0 = 6'd18;
else if (fract_in[47:29] == 19'b0000000000000000001)
fi_ldz_r0 = 6'd19;
else if (fract_in[47:28] == 20'b00000000000000000001)
fi_ldz_r0 = 6'd20;
else if (fract_in[47:27] == 21'b000000000000000000001)
fi_ldz_r0 = 6'd21;
else if (fract_in[47:26] == 22'b0000000000000000000001)
fi_ldz_r0 = 6'd22;
else if (fract_in[47:25] == 23'b00000000000000000000001)
fi_ldz_r0 = 6'd23;
else if (fract_in[47:24] == 24'b000000000000000000000001)
fi_ldz_r0 = 6'd24;
else if (fract_in[47:23] == 25'b0000000000000000000000001)
fi_ldz_r0 = 6'd25;
else if (fract_in[47:22] == 26'b00000000000000000000000001)
fi_ldz_r0 = 6'd26;
else if (fract_in[47:21] == 27'b000000000000000000000000001)
fi_ldz_r0 = 6'd27;
else if (fract_in[47:20] == 28'b0000000000000000000000000001)
fi_ldz_r0 = 6'd28;
else if (fract_in[47:19] == 29'b00000000000000000000000000001)
fi_ldz_r0 = 6'd29;
else if (fract_in[47:18] == 30'b000000000000000000000000000001)
fi_ldz_r0 = 6'd30;
else if (fract_in[47:17] == 31'b0000000000000000000000000000001)
fi_ldz_r0 = 6'd31;
else if (fract_in[47:16] == 32'b00000000000000000000000000000001)
fi_ldz_r0 = 6'd32;
else if (fract_in[47:15] == 33'b000000000000000000000000000000001)
fi_ldz_r0 = 6'd33;
else if (fract_in[47:14] == 34'b0000000000000000000000000000000001)
fi_ldz_r0 = 6'd34;
else if (fract_in[47:13] == 35'b00000000000000000000000000000000001)
fi_ldz_r0 = 6'd35;
else if (fract_in[47:12] == 36'b000000000000000000000000000000000001)
fi_ldz_r0 = 6'd36;
else if (fract_in[47:11] == 37'b0000000000000000000000000000000000001)
fi_ldz_r0 = 6'd37;
else if (fract_in[47:10] == 38'b00000000000000000000000000000000000001)
fi_ldz_r0 = 6'd38;
else if (fract_in[47:9] == 39'b000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd39;
else if (fract_in[47:8] == 40'b0000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd40;
else if (fract_in[47:7] == 41'b00000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd41;
else if (fract_in[47:6] == 42'b000000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd42;
else if (fract_in[47:5] == 43'b0000000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd43;
else if (fract_in[47:4] == 44'b00000000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd44;
else if (fract_in[47:3] == 45'b000000000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd45;
else if (fract_in[47:2] == 46'b0000000000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd46;
else if (fract_in[47:1] == 47'b00000000000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd47;
else if (fract_in[47:0] == 48'b000000000000000000000000000000000000000000000001)
fi_ldz_r0 = 6'd48;
else if (fract_in[47:0] == 48'b000000000000000000000000000000000000000000000000)
fi_ldz_r0 = 6'd48;
end
endmodule
module b_right_shifter (
shift_in,
shift_value,
shift_out
);
input [47:0] shift_in;
input [5:0] shift_value;
output [47:0] shift_out;
reg [47:0] shift_out;
always @(shift_value)
begin
case (shift_value)
6'b000000: shift_out = shift_in;
6'b000001: shift_out = shift_in >> 1;
6'b000010: shift_out = shift_in >> 2;
6'b000011: shift_out = shift_in >> 3;
6'b000100: shift_out = shift_in >> 4;
6'b000101: shift_out = shift_in >> 5;
6'b000110: shift_out = shift_in >> 6;
6'b000111: shift_out = shift_in >> 7;
6'b001000: shift_out = shift_in >> 8;
6'b001001: shift_out = shift_in >> 9;
6'b001010: shift_out = shift_in >> 10;
6'b001011: shift_out = shift_in >> 11;
6'b001100: shift_out = shift_in >> 12;
6'b001101: shift_out = shift_in >> 13;
6'b001110: shift_out = shift_in >> 14;
6'b001111: shift_out = shift_in >> 15;
6'b010000: shift_out = shift_in >> 16;
6'b010001: shift_out = shift_in >> 17;
6'b010010: shift_out = shift_in >> 18;
6'b010011: shift_out = shift_in >> 19;
6'b010100: shift_out = shift_in >> 20;
6'b010101: shift_out = shift_in >> 21;
6'b010110: shift_out = shift_in >> 22;
6'b010111: shift_out = shift_in >> 23;
6'b011000: shift_out = shift_in >> 24;
6'b011001: shift_out = shift_in >> 25;
6'b011010: shift_out = shift_in >> 26;
6'b011011: shift_out = shift_in >> 27;
6'b011100: shift_out = shift_in >> 28;
6'b011101: shift_out = shift_in >> 29;
6'b011110: shift_out = shift_in >> 30;
6'b011111: shift_out = shift_in >> 31;
6'b100000: shift_out = shift_in >> 32;
6'b100001: shift_out = shift_in >> 33;
6'b100010: shift_out = shift_in >> 34;
6'b100011: shift_out = shift_in >> 35;
6'b100100: shift_out = shift_in >> 36;
6'b100101: shift_out = shift_in >> 37;
6'b100110: shift_out = shift_in >> 38;
6'b100111: shift_out = shift_in >> 39;
6'b101000: shift_out = shift_in >> 40;
6'b101001: shift_out = shift_in >> 41;
6'b101010: shift_out = shift_in >> 42;
6'b101011: shift_out = shift_in >> 43;
6'b101100: shift_out = shift_in >> 44;
6'b101101: shift_out = shift_in >> 45;
6'b101110: shift_out = shift_in >> 46;
6'b101111: shift_out = shift_in >> 47;
6'b110000: shift_out = shift_in >> 48;
endcase
end
//assign shift_out = shift_in >> shift_value;
endmodule
module b_left_shifter (
shift_in,
shift_value,
shift_out
);
input [47:0] shift_in;
input [5:0] shift_value;
output [47:0] shift_out;
reg [47:0] shift_out;
always @(shift_value)
begin
case (shift_value)
6'b000000: shift_out = shift_in;
6'b000001: shift_out = shift_in << 1;
6'b000010: shift_out = shift_in << 2;
6'b000011: shift_out = shift_in << 3;
6'b000100: shift_out = shift_in << 4;
6'b000101: shift_out = shift_in << 5;
6'b000110: shift_out = shift_in << 6;
6'b000111: shift_out = shift_in << 7;
6'b001000: shift_out = shift_in << 8;
6'b001001: shift_out = shift_in << 9;
6'b001010: shift_out = shift_in << 10;
6'b001011: shift_out = shift_in << 11;
6'b001100: shift_out = shift_in << 12;
6'b001101: shift_out = shift_in << 13;
6'b001110: shift_out = shift_in << 14;
6'b001111: shift_out = shift_in << 15;
6'b010000: shift_out = shift_in << 16;
6'b010001: shift_out = shift_in << 17;
6'b010010: shift_out = shift_in << 18;
6'b010011: shift_out = shift_in << 19;
6'b010100: shift_out = shift_in << 20;
6'b010101: shift_out = shift_in << 21;
6'b010110: shift_out = shift_in << 22;
6'b010111: shift_out = shift_in << 23;
6'b011000: shift_out = shift_in << 24;
6'b011001: shift_out = shift_in << 25;
6'b011010: shift_out = shift_in << 26;
6'b011011: shift_out = shift_in << 27;
6'b011100: shift_out = shift_in << 28;
6'b011101: shift_out = shift_in << 29;
6'b011110: shift_out = shift_in << 30;
6'b011111: shift_out = shift_in << 31;
6'b100000: shift_out = shift_in << 32;
6'b100001: shift_out = shift_in << 33;
6'b100010: shift_out = shift_in << 34;
6'b100011: shift_out = shift_in << 35;
6'b100100: shift_out = shift_in << 36;
6'b100101: shift_out = shift_in << 37;
6'b100110: shift_out = shift_in << 38;
6'b100111: shift_out = shift_in << 39;
6'b101000: shift_out = shift_in << 40;
6'b101001: shift_out = shift_in << 41;
6'b101010: shift_out = shift_in << 42;
6'b101011: shift_out = shift_in << 43;
6'b101100: shift_out = shift_in << 44;
6'b101101: shift_out = shift_in << 45;
6'b101110: shift_out = shift_in << 46;
6'b101111: shift_out = shift_in << 47;
6'b110000: shift_out = shift_in << 48;
endcase
end
endmodule
module b_left_shifter_new (
shift_in,
shift_value,
shift_out
);
input [55:0] shift_in;
input [5:0] shift_value;
output [55:0] shift_out;
reg [55:0] shift_out;
always @(shift_value)
begin
case (shift_value)
6'b000000: shift_out = shift_in;
6'b000001: shift_out = shift_in << 1;
6'b000010: shift_out = shift_in << 2;
6'b000011: shift_out = shift_in << 3;
6'b000100: shift_out = shift_in << 4;
6'b000101: shift_out = shift_in << 5;
6'b000110: shift_out = shift_in << 6;
6'b000111: shift_out = shift_in << 7;
6'b001000: shift_out = shift_in << 8;
6'b001001: shift_out = shift_in << 9;
6'b001010: shift_out = shift_in << 10;
6'b001011: shift_out = shift_in << 11;
6'b001100: shift_out = shift_in << 12;
6'b001101: shift_out = shift_in << 13;
6'b001110: shift_out = shift_in << 14;
6'b001111: shift_out = shift_in << 15;
6'b010000: shift_out = shift_in << 16;
6'b010001: shift_out = shift_in << 17;
6'b010010: shift_out = shift_in << 18;
6'b010011: shift_out = shift_in << 19;
6'b010100: shift_out = shift_in << 20;
6'b010101: shift_out = shift_in << 21;
6'b010110: shift_out = shift_in << 22;
6'b010111: shift_out = shift_in << 23;
6'b011000: shift_out = shift_in << 24;
6'b011001: shift_out = shift_in << 25;
6'b011010: shift_out = shift_in << 26;
6'b011011: shift_out = shift_in << 27;
6'b011100: shift_out = shift_in << 28;
6'b011101: shift_out = shift_in << 29;
6'b011110: shift_out = shift_in << 30;
6'b011111: shift_out = shift_in << 31;
6'b100000: shift_out = shift_in << 32;
6'b100001: shift_out = shift_in << 33;
6'b100010: shift_out = shift_in << 34;
6'b100011: shift_out = shift_in << 35;
6'b100100: shift_out = shift_in << 36;
6'b100101: shift_out = shift_in << 37;
6'b100110: shift_out = shift_in << 38;
6'b100111: shift_out = shift_in << 39;
6'b101000: shift_out = shift_in << 40;
6'b101001: shift_out = shift_in << 41;
6'b101010: shift_out = shift_in << 42;
6'b101011: shift_out = shift_in << 43;
6'b101100: shift_out = shift_in << 44;
6'b101101: shift_out = shift_in << 45;
6'b101110: shift_out = shift_in << 46;
6'b101111: shift_out = shift_in << 47;
6'b110000: shift_out = shift_in << 48;
6'b110001: shift_out = shift_in << 49;
6'b110010: shift_out = shift_in << 50;
6'b110011: shift_out = shift_in << 51;
6'b110100: shift_out = shift_in << 52;
6'b110101: shift_out = shift_in << 53;
6'b110110: shift_out = shift_in << 54;
6'b110111: shift_out = shift_in << 55;
6'b111000: shift_out = shift_in << 56;
endcase
end
endmodule
module fpu_add( clk,
//rmode,
opa, opb, out,
control
//inf, snan, qnan, ine, overflow, underflow, zero, div_by_zero
);
input clk;
//input [1:0] rmode;
//input [2:0] fpu_op;
input [31:0] opa, opb;
output [31:0] out;
/*
output inf, snan, qnan;
output ine;
output overflow, underflow;
output zero;
output div_by_zero;
*/
output [7:0] control;
/*
parameter INF = 31'h7f800000;
parameter QNAN = 31'h7fc00001;
parameter SNAN = 31'h7f800001;
*/
wire [30:0] INF;
assign INF = 31'h7f800000;
wire [30:0] QNAN;
assign QNAN = 31'h7fc00001;
wire [30:0] SNAN;
assign SNAN = 31'h7f800001;
////////////////////////////////////////////////////////////////////////
//
// Local Wires
//
reg [2:0] fpu_op;
reg zero;
reg [31:0] opa_r, opb_r; // Input operand registers
reg [31:0] out; // Output register
reg div_by_zero; // Divide by zero output register
// wire signa, signb; // alias to opX sign
wire sign_fasu; // sign output
wire [26:0] fracta, fractb; // Fraction Outputs from EQU block
wire [7:0] exp_fasu; // Exponent output from EQU block
reg [7:0] exp_r; // Exponent output (registerd)
wire [26:0] fract_out_d; // fraction output
// wire co; // carry output
reg [27:0] fract_out_q; // fraction output (registerd)
wire [30:0] out_d; // Intermediate final result output
wire overflow_d, underflow_d;// Overflow/Underflow Indicators
reg overflow, underflow; // Output registers for Overflow & Underflow
reg inf, snan, qnan; // Output Registers for INF, SNAN and QNAN
reg ine; // Output Registers for INE
reg [1:0] rmode_r1, rmode_r2, // Pipeline registers for rounding mode
rmode_r3;
reg [2:0] fpu_op_r1, fpu_op_r2, // Pipeline registers for fp opration
fpu_op_r3;
// wire mul_inf, div_inf;
// wire mul_00, div_00;
// start output_reg
reg [31:0] out_o1;
reg inf_o1, snan_o1, qnan_o1;
reg ine_o1;
reg overflow_o1, underflow_o1;
reg zero_o1;
reg div_by_zero_o1;
// end output_reg
wire [7:0] contorl;
assign control = {inf, snan, qnan, ine, overflow, underflow, zero, div_by_zero};
wire [1:0] rmode;
assign rmode= 2'b00;
always@(posedge clk)
begin
fpu_op[2:0] <= 3'b000;
end
////////////////////////////////////////////////////////////////////////
//
// Input Registers
//
always @(posedge clk)
opa_r <= opa;
always @(posedge clk)
opb_r <= opb;
always @(posedge clk)
rmode_r1 <= rmode;
always @(posedge clk)
rmode_r2 <= rmode_r1;
always @(posedge clk)
rmode_r3 <= rmode_r2;
always @(posedge clk)
fpu_op_r1 <= fpu_op;
always @(posedge clk)
fpu_op_r2 <= fpu_op_r1;
always @(posedge clk)
fpu_op_r3 <= fpu_op_r2;
////////////////////////////////////////////////////////////////////////
//
// Exceptions block
//
wire inf_d, ind_d, qnan_d, snan_d, opa_nan, opb_nan;
wire opa_00, opb_00;
wire opa_inf, opb_inf;
wire opa_dn, opb_dn;
except u0( .clk(clk),
.opa(opa_r), .opb(opb_r),
.inf(inf_d), .ind(ind_d),
.qnan(qnan_d), .snan(snan_d),
.opa_nan(opa_nan), .opb_nan(opb_nan),
.opa_00(opa_00), .opb_00(opb_00),
.opa_inf(opa_inf), .opb_inf(opb_inf),
.opa_dn(opa_dn), .opb_dn(opb_dn)
);
////////////////////////////////////////////////////////////////////////
//
// Pre-Normalize block
// - Adjusts the numbers to equal exponents and sorts them
// - determine result sign
// - determine actual operation to perform (add or sub)
//
wire nan_sign_d, result_zero_sign_d;
reg sign_fasu_r;
wire fasu_op;
wire add_input;
assign add_input=!fpu_op_r1[0];
pre_norm u1(.clk(clk), // System Clock
.rmode(rmode_r2), // Roundin Mode
// .add(!fpu_op_r1[0]), // Add/Sub Input
.add(add_input),
.opa(opa_r), .opb(opb_r), // Registered OP Inputs
.opa_nan(opa_nan), // OpA is a NAN indicator
.opb_nan(opb_nan), // OpB is a NAN indicator
.fracta_out(fracta), // Equalized and sorted fraction
.fractb_out(fractb), // outputs (Registered)
.exp_dn_out(exp_fasu), // Selected exponent output (registered);
.sign(sign_fasu), // Encoded output Sign (registered)
.nan_sign(nan_sign_d), // Output Sign for NANs (registered)
.result_zero_sign(result_zero_sign_d), // Output Sign for zero result (registered)
.fasu_op(fasu_op) // Actual fasu operation output (registered)
);
always @(posedge clk)
sign_fasu_r <= sign_fasu;
wire co_d;
////////////////////////////////////////////////////////////////////////
//
// Add/Sub
//
add_sub27 u3(
.add(fasu_op), // Add/Sub
.opa(fracta), // Fraction A input
.opb(fractb), // Fraction B Input
.sum(fract_out_d), // SUM output
.co(co_d) ); // Carry Output
always @(posedge clk)
fract_out_q <= {co_d, fract_out_d};
////////////////////////////////////////////////////////////////////////
//
// Normalize Result
//
wire ine_d;
//reg [47:0] fract_denorm;
wire [47:0] fract_denorm;
wire sign_d;
reg sign;
reg [30:0] opa_r1;
reg [47:0] fract_i2f;
reg opas_r1, opas_r2;
wire f2i_out_sign;
always @(posedge clk) // Exponent must be once cycle delayed
exp_r <= exp_fasu;
always @(posedge clk)
opa_r1 <= opa_r[30:0];
//always @(fpu_op_r3 or fract_out_q)
assign fract_denorm = {fract_out_q, 20'h0};
always @(posedge clk)
opas_r1 <= opa_r[31];
always @(posedge clk)
opas_r2 <= opas_r1;
assign sign_d = sign_fasu;
always @(posedge clk)
sign <= (rmode_r2==2'h3) ? !sign_d : sign_d;
post_norm u4(
//.clk(clk), // System Clock
.fpu_op(fpu_op_r3), // Floating Point Operation
.opas(opas_r2), // OPA Sign
.sign(sign), // Sign of the result
.rmode(rmode_r3), // Rounding mode
.fract_in(fract_denorm), // Fraction Input
.exp_in(exp_r), // Exponent Input
.exp_ovf(2'b00), // Exponent Overflow
.opa_dn(opa_dn), // Operand A Denormalized
.opb_dn(opb_dn), // Operand A Denormalized
.rem_00(1'b0), // Diveide Remainder is zero
.div_opa_ldz(5'b00000), // Divide opa leading zeros count
.output_zero(1'b0), // Force output to Zero
.out(out_d), // Normalized output (un-registered)
.ine(ine_d), // Result Inexact output (un-registered)
.overflow(overflow_d), // Overflow output (un-registered)
.underflow(underflow_d), // Underflow output (un-registered)
.f2i_out_sign(f2i_out_sign) // F2I Output Sign
);
////////////////////////////////////////////////////////////////////////
//
// FPU Outputs
//
reg fasu_op_r1, fasu_op_r2;
wire [30:0] out_fixed;
wire output_zero_fasu;
wire overflow_fasu;
wire out_d_00;
wire ine_fasu;
wire underflow_fasu;
reg opa_nan_r;
always @(posedge clk)
fasu_op_r1 <= fasu_op;
always @(posedge clk)
fasu_op_r2 <= fasu_op_r1;
// Force pre-set values for non numerical output
assign out_fixed = ( (qnan_d | snan_d) |
(ind_d & !fasu_op_r2) ) ? QNAN : INF;
always @(posedge clk)
out_o1[30:0] <= (inf_d | snan_d | qnan_d) ? out_fixed : out_d;
assign out_d_00 = !(|out_d);
always @(posedge clk)
out_o1[31] <= (snan_d | qnan_d | ind_d) ? nan_sign_d :
output_zero_fasu ? result_zero_sign_d :
sign_fasu_r;
assign ine_fasu = (ine_d | overflow_d | underflow_d) & !(snan_d | qnan_d | inf_d);
always @(posedge clk)
ine_o1 <= ine_fasu ;
assign overflow_fasu = overflow_d & !(snan_d | qnan_d | inf_d);
always @(posedge clk)
overflow_o1 <= overflow_fasu ;
assign underflow_fasu = underflow_d & !(inf_d | snan_d | qnan_d);
always @(posedge clk)
underflow_o1 <= underflow_fasu ;
always @(posedge clk)
snan_o1 <= snan_d;
// Status Outputs
always @(posedge clk)
qnan_o1 <= ( snan_d | qnan_d | (ind_d & !fasu_op_r2) );
always @(posedge clk)
inf_o1 <= (!(qnan_d | snan_d) & (( (&out_d[30:23]) & !(|out_d[22:0] ) ) | (inf_d & !(ind_d & !fasu_op_r2) & !fpu_op_r3[1]) ));
assign output_zero_fasu = out_d_00 & !(inf_d | snan_d | qnan_d);
always @(posedge clk)
zero_o1 <= output_zero_fasu ;
always @(posedge clk)
opa_nan_r <= !opa_nan & fpu_op_r2==3'b011;
always @(posedge clk)
div_by_zero_o1 <= 1'b0;
// output register
always @(posedge clk)
begin
qnan <= qnan_o1;
out <= out_o1;
inf <= inf_o1;
snan <= snan_o1;
//qnan <= qnan_o1;
ine <= ine_o1;
overflow <= overflow_o1;
underflow <= underflow_o1;
zero <= zero_o1;
div_by_zero <= div_by_zero_o1;
end
endmodule
//---------------------------------------------------------------------------------
module pre_norm(clk, rmode, add, opa, opb, opa_nan, opb_nan, fracta_out,
fractb_out, exp_dn_out, sign, nan_sign, result_zero_sign,
fasu_op);
input clk;
input [1:0] rmode;
input add;
input [31:0] opa, opb;
input opa_nan, opb_nan;
output [26:0] fracta_out, fractb_out;
output [7:0] exp_dn_out;
output sign;
output nan_sign, result_zero_sign;
output fasu_op; // Operation Output
////////////////////////////////////////////////////////////////////////
//
// Local Wires and registers
//
wire signa, signb; // alias to opX sign
wire [7:0] expa, expb; // alias to opX exponent
wire [22:0] fracta, fractb; // alias to opX fraction
wire expa_lt_expb; // expa is larger than expb indicator
wire fractb_lt_fracta; // fractb is larger than fracta indicator
reg [7:0] exp_dn_out; // de normalized exponent output
wire [7:0] exp_small, exp_large;
wire [7:0] exp_diff; // Numeric difference of the two exponents
wire [22:0] adj_op; // Fraction adjustment: input
wire [26:0] adj_op_tmp;
wire [26:0] adj_op_out; // Fraction adjustment: output
wire [26:0] fracta_n, fractb_n; // Fraction selection after normalizing
wire [26:0] fracta_s, fractb_s; // Fraction Sorting out
reg [26:0] fracta_out, fractb_out; // Fraction Output
reg sign, sign_d; // Sign Output
reg add_d; // operation (add/sub)
reg fasu_op; // operation (add/sub) register
wire expa_dn, expb_dn;
reg sticky;
reg result_zero_sign;
reg add_r, signa_r, signb_r;
wire [4:0] exp_diff_sft;
wire exp_lt_27;
wire op_dn;
wire [26:0] adj_op_out_sft;
reg fracta_lt_fractb, fracta_eq_fractb;
wire nan_sign1;
reg nan_sign;
////////////////////////////////////////////////////////////////////////
//
// Aliases
//
assign signa = opa[31];
assign signb = opb[31];
assign expa = opa[30:23];
assign expb = opb[30:23];
assign fracta = opa[22:0];
assign fractb = opb[22:0];
////////////////////////////////////////////////////////////////////////
//
// Pre-Normalize exponents (and fractions)
//
assign expa_lt_expb = expa > expb; // expa is larger than expb
// ---------------------------------------------------------------------
// Normalize
assign expa_dn = !(|expa); // opa denormalized
assign expb_dn = !(|expb); // opb denormalized
// ---------------------------------------------------------------------
// Calculate the difference between the smaller and larger exponent
wire [7:0] exp_diff1, exp_diff1a, exp_diff2;
assign exp_small = expa_lt_expb ? expb : expa;
assign exp_large = expa_lt_expb ? expa : expb;
assign exp_diff1 = exp_large - exp_small;
assign exp_diff1a = exp_diff1-8'h01;
assign exp_diff2 = (expa_dn | expb_dn) ? exp_diff1a : exp_diff1;
assign exp_diff = (expa_dn & expb_dn) ? 8'h0 : exp_diff2;
always @(posedge clk) // If numbers are equal we should return zero
exp_dn_out <= (!add_d & expa==expb & fracta==fractb) ? 8'h0 : exp_large;
// ---------------------------------------------------------------------
// Adjust the smaller fraction
assign op_dn = expa_lt_expb ? expb_dn : expa_dn;
assign adj_op = expa_lt_expb ? fractb : fracta;
wire temp1;
assign temp1 = ~op_dn;
//assign adj_op_tmp[26:0] = {~op_dn, adj_op, 3'b000}; // recover hidden bit (op_dn)
assign adj_op_tmp[26:0] = {temp1, adj_op, 3'b000}; // recover hidden bit (op_dn)
// adj_op_out is 27 bits wide, so can only be shifted 27 bits to the right
assign exp_lt_27 = exp_diff > 8'd27;
assign exp_diff_sft = exp_lt_27 ? 5'd27 : exp_diff[4:0];
//assign adj_op_out_sft = adj_op_tmp >> exp_diff_sft;
b_right_shifter_new u7(
.shift_in(adj_op_tmp),
.shift_value(exp_diff_sft),
.shift_out(adj_op_out_sft)
);
wire temp2;
assign temp2 = adj_op_out_sft[0] | sticky;
//assign adj_op_out[26:0] = {adj_op_out_sft[26:1], adj_op_out_sft[0] | sticky };
assign adj_op_out[26:0] = {adj_op_out_sft[26:1], temp2 };
// ---------------------------------------------------------------------
// Get truncated portion (sticky bit)
always @(exp_diff_sft or adj_op_tmp)
case(exp_diff_sft) // synopsys full_case parallel_case
5'd00: sticky = 1'h0;
5'd01: sticky = adj_op_tmp[0];
5'd02: sticky = |adj_op_tmp[01:0];
5'd03: sticky = |adj_op_tmp[02:0];
5'd04: sticky = |adj_op_tmp[03:0];
5'd05: sticky = |adj_op_tmp[04:0];
5'd06: sticky = |adj_op_tmp[05:0];
5'd07: sticky = |adj_op_tmp[06:0];
5'd08: sticky = |adj_op_tmp[07:0];
5'd09: sticky = |adj_op_tmp[08:0];
5'd10: sticky = |adj_op_tmp[09:0];
5'd11: sticky = |adj_op_tmp[10:0];
5'd12: sticky = |adj_op_tmp[11:0];
5'd13: sticky = |adj_op_tmp[12:0];
5'd14: sticky = |adj_op_tmp[13:0];
5'd15: sticky = |adj_op_tmp[14:0];
5'd16: sticky = |adj_op_tmp[15:0];
5'd17: sticky = |adj_op_tmp[16:0];
5'd18: sticky = |adj_op_tmp[17:0];
5'd19: sticky = |adj_op_tmp[18:0];
5'd20: sticky = |adj_op_tmp[19:0];
5'd21: sticky = |adj_op_tmp[20:0];
5'd22: sticky = |adj_op_tmp[21:0];
5'd23: sticky = |adj_op_tmp[22:0];
5'd24: sticky = |adj_op_tmp[23:0];
5'd25: sticky = |adj_op_tmp[24:0];
5'd26: sticky = |adj_op_tmp[25:0];
5'd27: sticky = |adj_op_tmp[26:0];
endcase
// ---------------------------------------------------------------------
// Select operands for add/sub (recover hidden bit)
assign fracta_n = expa_lt_expb ? {~expa_dn, fracta, 3'b0} : adj_op_out;
assign fractb_n = expa_lt_expb ? adj_op_out : {~expb_dn, fractb, 3'b0};
// ---------------------------------------------------------------------
// Sort operands (for sub only)
assign fractb_lt_fracta = fractb_n > fracta_n; // fractb is larger than fracta
assign fracta_s = fractb_lt_fracta ? fractb_n : fracta_n;
assign fractb_s = fractb_lt_fracta ? fracta_n : fractb_n;
always @(posedge clk)
fracta_out <= fracta_s;
always @(posedge clk)
fractb_out <= fractb_s;
// ---------------------------------------------------------------------
// Determine sign for the output
// sign: 0=Positive Number; 1=Negative Number
always @(signa or signb or add or fractb_lt_fracta)
case({signa, signb, add}) // synopsys full_case parallel_case
// Add
3'b001: sign_d = 0;
3'b011: sign_d = fractb_lt_fracta;
3'b101: sign_d = !fractb_lt_fracta;
3'b111: sign_d = 1;
// Sub
3'b000: sign_d = fractb_lt_fracta;
3'b010: sign_d = 0;
3'b100: sign_d = 1;
3'b110: sign_d = !fractb_lt_fracta;
endcase
always @(posedge clk)
sign <= sign_d;
// Fix sign for ZERO result
always @(posedge clk)
signa_r <= signa;
always @(posedge clk)
signb_r <= signb;
always @(posedge clk)
add_r <= add;
always @(posedge clk)
result_zero_sign <= ( add_r & signa_r & signb_r) |
(!add_r & signa_r & !signb_r) |
( add_r & (signa_r | signb_r) & (rmode==3)) |
(!add_r & (signa_r == signb_r) & (rmode==3));
// Fix sign for NAN result
always @(posedge clk)
fracta_lt_fractb <= fracta < fractb;
always @(posedge clk)
fracta_eq_fractb <= fracta == fractb;
assign nan_sign1 = fracta_eq_fractb ? (signa_r & signb_r) : fracta_lt_fractb ? signb_r : signa_r;
always @(posedge clk)
nan_sign <= (opa_nan & opb_nan) ? nan_sign1 : opb_nan ? signb_r : signa_r;
////////////////////////////////////////////////////////////////////////
//
// Decode Add/Sub operation
//
// add: 1=Add; 0=Subtract
always @(signa or signb or add)
case({signa, signb, add}) // synopsys full_case parallel_case
// Add
3'b001: add_d = 1;
3'b011: add_d = 0;
3'b101: add_d = 0;
3'b111: add_d = 1;
// Sub
3'b000: add_d = 0;
3'b010: add_d = 1;
3'b100: add_d = 1;
3'b110: add_d = 0;
endcase
always @(posedge clk)
fasu_op <= add_d;
endmodule
module b_right_shifter_new (
shift_in,
shift_value,
shift_out
);
input [26:0] shift_in;
input [4:0] shift_value;
output [26:0] shift_out;
reg [26:0] shift_out;
always @(shift_value)
begin
case (shift_value)
5'b00000: shift_out = shift_in;
5'b00001: shift_out = shift_in >> 1;
5'b00010: shift_out = shift_in >> 2;
5'b00011: shift_out = shift_in >> 3;
5'b00100: shift_out = shift_in >> 4;
5'b00101: shift_out = shift_in >> 5;
5'b00110: shift_out = shift_in >> 6;
5'b00111: shift_out = shift_in >> 7;
5'b01000: shift_out = shift_in >> 8;
5'b01001: shift_out = shift_in >> 9;
5'b01010: shift_out = shift_in >> 10;
5'b01011: shift_out = shift_in >> 11;
5'b01100: shift_out = shift_in >> 12;
5'b01101: shift_out = shift_in >> 13;
5'b01110: shift_out = shift_in >> 14;
5'b01111: shift_out = shift_in >> 15;
5'b10000: shift_out = shift_in >> 16;
5'b10001: shift_out = shift_in >> 17;
5'b10010: shift_out = shift_in >> 18;
5'b10011: shift_out = shift_in >> 19;
5'b10100: shift_out = shift_in >> 20;
5'b10101: shift_out = shift_in >> 21;
5'b10110: shift_out = shift_in >> 22;
5'b10111: shift_out = shift_in >> 23;
5'b11000: shift_out = shift_in >> 24;
5'b11001: shift_out = shift_in >> 25;
5'b11010: shift_out = shift_in >> 26;
5'b11011: shift_out = shift_in >> 27;
endcase
end
endmodule
//----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
//
// Add/Sub
//
module add_sub27(add, opa, opb, sum, co);
input add;
input [26:0] opa, opb;
output [26:0] sum;
output co;
assign {co, sum} = add ? ({1'b0, opa} + {1'b0, opb}) : ({1'b0, opa} - {1'b0, opb});
endmodule