| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- 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, z_m3;
- reg [K*2-1:0] z_m1a, z_m1b, z_m1z; // Double mantissa
- reg z_m1s, z_m2s;
- reg [M-1:0] a_e0, b_e0; // exponent
- reg [M-1:0] z_e1, z_e2, z_e3;
- reg a_s0, b_s0; // sign
- reg a_s1, b_s1, z_s1, z_s2, z_s3;
- 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_s3, z_e3, z_m3};
- z_m1a = {a_m1, {K{1'b0}}};
- z_m1b = {b_m1, {K{1'b0}}};
- case (greater)
- greater_a: begin
- if (a_s1 == b_s1) {z_m1s, z_m1z} = z_m1a + (z_m1b >> (abs - 1));
- else {z_m1s, z_m1z} = z_m1a - (z_m1b >> (abs - 1));
- end
- greater_b: begin
- if (a_s1 == b_s1) {z_m1s, z_m1z} = z_m1b + (z_m1a >> (abs - 1));
- else {z_m1s, z_m1z} = z_m1b - (z_m1a >> (abs - 1));
- end
- equal_ab: 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;
- // If the signs are different then subtract
- 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
- endcase
- 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 + 1;
- 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 + 1;
- end
- // If the inputs have equal exponent
- else
- begin
- greater <= equal_ab;
- abs <= 0;
- z_e1 <= a_e0 + 1;
- // 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
- case (greater)
- greater_a: z_m2 <= a_m1;
- greater_b: z_m2 <= b_m1;
- endcase
- end
- else
- begin
- z_m2 <= z_m1z[K*2-1:K];
- z_m2s <= z_m1s;
- end
- if(z_m2s) begin
- z_e3 <= z_e2 + 1;
- end else begin
- z_e3 <= z_e2;
- end
- z_m3 <= z_m2;
- z_s3 <= z_s2;
- end // end ~reset
- 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_s1 <= 0;
- z_e1 <= 0;
- z_e2 <= 0;
- z_s2 <= 0;
- z_m2 <= 0;
- z_m2s <= 0;
- z_s3 <= 0;
- z_e3 <= 0;
- z_m3 <= 0;
- greater <= equal_ab;
- abs <= 0;
- end
- end
- endmodule : fp_adder
|