// 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_inf2i_emax)) | (opas & (exp_inf2i_emax)) | (opas & (exp_in8'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_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<f2i_emax) ? 1'b0 : opas) : ((exp_inf2i_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 }<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