typedef enum logic [1:0]{ greater_a, greater_b, equal_ab } grater_state; module fp_adder#(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset); localparam K=N-M-1; // Size of mantissa input reg [N-1:0] input_a, input_b; input logic clk, reset; output reg [N-1:0] output_z; reg [K-1:0] a_m0, b_m0; // mantissa reg [K-1:0] a_m1, b_m1, z_m2; reg [K*2-1:0] z_m1a, z_m1b, z_m1z; // Double mantissa reg z_m1s; reg [M-1:0] a_e0, b_e0; // exponent reg [M-1:0] z_e1, z_e2; reg a_s0, b_s0; // sign reg a_s1, b_s1, z_s1, z_s2; grater_state greater; // 01 for a, 10 for b, 11 for both and 00 for neither reg [M:0] abs; // For the absolute difference between exponents always_comb begin output_z = {z_s2, z_e2, z_m2}; z_m1a = {a_m1, {K{1'b0}}}; z_m1b = {b_m1, {K{1'b0}}}; // If a has the bigger exponent if (greater == greater_a) begin // If the signs are the same then add if (a_s1 == b_s1) {z_m1s, z_m1z} = z_m1a+(z_m1b >> abs - 2); // If they are different then subtract else {z_m1s, z_m1z} = z_m1a-(z_m1b >> abs - 2); end // If b has the bigger exponent else if (greater == greater_b) begin // If the signs are the same then add if (a_s1 == b_s1) {z_m1s, z_m1z} = z_m1b+(z_m1a >> abs - 2); // If they are different then subtract else {z_m1s, z_m1z} = z_m1b-(z_m1a >> abs - 2); end // If the exponents are equal else begin // If the signs are the same then add if (a_s1 == b_s1) {z_m1s, z_m1z} = (z_m1a + z_m1b) >> 1; // If the signs are different then subtract else begin // First checking which has the bigger mantissa if (a_m1 > b_m1) {z_m1s, z_m1z} = z_m1a-z_m1b; else if (b_m1 > a_m1) {z_m1s, z_m1z} = z_m1b-z_m1a; // If the mantissa are the same as well then the result should be 0 else {z_m1s, z_m1z} = 0; end end end always_ff @(posedge clk) begin if (~reset) begin // Unpacking the inputs a_m0 <= input_a[K-1:0]; a_e0 <= input_a[N-2:K]; a_s0 <= input_a[N-1]; b_m0 <= input_b[K-1:0]; b_e0 <= input_b[N-2:K]; b_s0 <= input_b[N-1]; // Second stage a_m1 <= a_m0; a_s1 <= a_s0; b_m1 <= b_m0; b_s1 <= b_s0; z_e2 <= z_e1; z_s2 <= z_s1; // If input_a has the bigger exponent then flag it with greater and find the absolute difference if (a_e0 > b_e0) begin greater <= greater_a; abs <= a_e0-b_e0; z_s1 <= a_s0; z_e1 <= a_e0; end // If input_a has the bigger exponent then flag it with greater and find the absolute difference else if (b_e0 > a_e0) begin greater <= greater_b; abs <= b_e0-a_e0; z_s1 <= b_s0; z_e1 <= b_e0; end // If the inputs have equal exponent else begin greater <= equal_ab; abs <= -1; z_e1 <= a_e0; // Assigning the overall sign based on the difference between the mantissa if (a_m0 > b_m0) z_s1 <= a_s0; else if (b_m0 > a_m0) z_s1 <= b_s0; else z_s1 <= 0; end // Condition for overflow is that it sets the output to the larger input if (abs > K) // Shifting by N-1-M would give 0 begin z_m2 <= (greater == greater_a) ? a_m1 : b_m1; // Input a is larger and is translated to the output // if (greater == greater_a) z_m0 <= a_m1; // Input b is larger and is translated to the output // else if (greater == greater_b) z_m0 <= b_m1; // Shouldn't happen as abs should be 0 for this to occur // else begin // if (a_m1 >= b_m1) z_m0 <= a_m1; // Equal exponents but a has the larger mantissa // else if (b_m1 > a_m1) z_m0 <= b_m1; // Equal exponents but b has the larger mantissa // end end else begin z_m2 <= z_m1z[K*2-1:K]; end end else begin a_m0 <= 0; a_e0 <= 0; a_s0 <= 0; b_m0 <= 0; b_e0 <= 0; b_s0 <= 0; a_m1 <= 0; b_m1 <= 0; z_e2 <= 0; z_s2 <= 0; z_s1 <= 0; z_e1 <= 0; z_s2 <= 0; z_e2 <= 0; z_m2 <= 0; greater <= equal_ab; abs <= 0; end end endmodule : fp_adder