| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- module floating_add #(parameter N=16, M=4)(input_1, input_2, sum, diff);
- input logic [N-1:0] input_1, input_2;
- output logic [N-1:0] sum;
- output logic [M:0] diff;
- logic flag_a;
- logic flag_b;
- logic [M:0] abs;
- logic [N-3-M:0] res;
-
- // sign_x = x[N-1]
- // exponent_x = x[N-2:N-2-M]
- // mantissa_x = x[N-3-M:0]
-
- always_comb
- begin
- if (input_1[N-2:N-2-M] > input_2[N-2:N-2-M]) // If input 1 has the bigger exponent
- begin
- // Flags input a as larger and calculates the absolute difference
- flag_a = 1;
- flag_b = 0;
- abs = input_1[N-2:N-2-M] - input_2[N-2:N-2-M];
- // ASsigning overall sign of the output
- sum[N-1] = input_1[N-1];
- // Sets output to have the same exponent
- sum[N-2:N-2-M] = input_1[N-2:N-2-M];
- end
- else if (input_2[N-2:N-2-M] > input_1[N-2:N-2-M]) // If input 2 has the bigger exponent
- begin
- // Similarly flags input b as larger and calculates the absolute difference
- flag_a = 0;
- flag_b = 1;
- abs = input_2[N-2:N-2-M] - input_1[N-2:N-2-M];
- // ASsigning overall sign of the output
- sum[N-1] = input_2[N-1];
- // Sets ouput to have the same exponent
- sum[N-2:N-2-M] = input_2[N-2:N-2-M];
- end
- else
- begin
- // THe condition that both inputs have the same exponent
- flag_a = 1;
- flag_b = 1;
- abs = 0;
- // ASsigning overall sign of the output based on size of the mantissa
- if (input_1[N-3-M:0] >= input_2[N-3-M:0]) sum[N-1] = input_1[N-1];
- else sum[N-1] = input_2[N-1];
- sum[N-2:N-2-M] = input_1[N-2:N-2-M];
- end
- diff = abs;
- end
- //Second pipeline stage 1
- pipe pipe1(.clk(clk), .reset(reset), .D(Q0), .Q(Q1));
- always_comb
- begin
- // Condition for overflow is that it sets the output to the larger input
- if (abs > 9) // Because size of mantissa is 10 bits and shifting by 10 would give 0
- begin
- if (flag_a & ~flag_b) sum = input_1; // input 1 is larger and is translated to output
- else if (~flag_a & flag_b) sum = input_2; // input 2 is larger and is translated to output
- else // exponents are the same
- begin
- if (input_1[N-3-M:0] >= input_2[N-3-M:0]) sum = input_1;// input 1 has the bigger mantissa
- else sum = input_2; // input 2 has the bigger mantissa
- end
- end
- else
- begin
- // Shifts the smaller input's mantissa to the right based on abs
- if (flag_a & ~flag_b)// If input 1 has the larger exponent
- begin
- // If the signs of both inputs are the same you add, otherwise you subtract
- if (input_1[N-1] == input_2[N-1])
- begin
- res = input_1[N-3-M:0] + (input_2[N-3-M:0] >> abs-1); // Sum the mantissa
- sum[N-3-M:0] = res;
- end
- else
- begin
- res = input_1[N-3-M:0] - (input_2[N-3-M:0] >> abs-1); // Subtract the mantissas
- sum[N-3-M:0] = res;
- end
- end
- else if (~flag_a & flag_b)
- begin
- // If the signs of both inputs are the same you add, otherwise you subtract
- if (input_1[N-1] == input_2[N-1])
- begin
- res = (input_1[N-3-M:0] >> abs-1) + input_2[N-3-M:0]; // Sum the mantissa
- sum[N-3-M:0] = res;
- end
- else
- begin
- res = input_2[N-3-M:0] - (input_1[N-3-M:0] >> abs-1); // Subtract the mantissas
- sum[N-3-M:0] = res;
- end
- end
- else
- begin
- if (input_1[N-1] == input_2[N-1]) // If exponents and signs equal
- begin
- res = input_1[N-3-M:0] + input_2[N-3-M:0]; // Sum the mantissa
- sum[N-3-M:0] = res;
- end
- else // In this case it will be a subtraction
- begin
- if (input_1[N-3-M:0] > input_2[N-3-M:0]) // Which has the larger mantissa
- begin
- res = input_1[N-3-M:0] - input_2[N-3-M:0]; // Subtract the mantissa
- sum[N-3-M:0] = res;
- end
- else if (input_1[N-3-M:0] < input_2[N-3-M:0])
- begin
- res = input_2[N-3-M:0] - input_1[N-3-M:0]; // Subtract the mantissa
- sum[N-3-M:0] = res;
- end
- else res = 0; // Both the exponent and the mantissa are equal so subtraction leads to 0
- sum[N-3-M:0] = res;
- end
- end
- end
- end
- endmodule : floating_add
- module floating_product #(parameter N=16, M=4)(input_1, input_2, product);
- input logic [N-1:0] input_1, input_2;
- output logic [N-1:0] product;
- // sign_x = x[N-1]
- // exponent_x = x[N-2:N-2-M]
- // mantissa_x = x[N-3-M:0]
- logic [N-2:N-2-M] sum;
- logic [2*(N-3-M):0] mult;
- // We have assigned an {M+1} bit exponent so we must have a 2^{M} offset
- assign sum = input_1[N-2:N-2-M] + input_2[N-2:N-2-M];
- assign product[N-2:N-2-M] = sum - (1'b1 << M) + 2;
- always_comb
- begin
- // Setting the mantissa of the output
- mult = input_1[N-3-M:0] * input_2[N-3-M:0];
- if (mult[N-3-M]) product[N-3-M:0] = mult[2*(N-3-M):2*(N-3-M)-9];
- else product[N-3-M:0] = mult[2*(N-3-M):2*(N-3-M)-9] << 1;
- product[N-1] = input_1[N-1] ^ input_2[N-1];
- end
- endmodule : floating_product
- module pipe #(parameter N=16)(clk, reset, Q, D);
- input logic clk, reset;
- input logic [N-1:0] D;
- output reg [N-1:0] Q;
- reg [N-1:0] in_pipe;
-
- always @(posedge clk or negedge reset)
- begin
- if(reset) in_pipe = 0;
- else in_pipe = D;
- end
-
- always @(posedge clk or negedge reset)
- begin
- if(reset) Q = 0;
- else Q = in_pipe;
- end
- endmodule : pipe
- module floating_tb;
- reg reset, clk;
- logic [15:0] input_a, input_b, result_add, result_mult;
- logic [4:0] diff;
- floating_add adder1(.input_1(input_a), .input_2(input_b), .sum(result_add), .diff(diff));
- floating_product multiplier1(.input_1(input_a), .input_2(input_b), .product(result_mult));
- reg [15:0] test_mem [29:0][3:0];
- initial $readmemh("../../scripts/fp16_test.hex", test_mem);
- initial begin
- static int num_err = 0;
- static int num_tests = $size(test_mem) * 2;
- for (int i=0; i < $size(test_mem); i++) begin
- input_a = test_mem[i][0];
- input_b = test_mem[i][1];
- #10;
- if(result_add != test_mem[i][2]) begin
- if(num_err < 20)
- $display("FAIL ADD: %H + %H = %H, expected %H", input_a, input_b, result_add, test_mem[i][2]);
- num_err = num_err + 1;
- end
- if(result_mult != test_mem[i][3]) begin
- if(num_err < 20)
- $display("FAIL MULTIPLY: %H + %H = %H, expected %H", input_a, input_b, result_mult, test_mem[i][3]);
- num_err = num_err + 1;
- end
- end
- $display("Passed %d of %d tests", num_tests-num_err, num_tests);
- $finish();
- end
- endmodule : floating_tb
- module floating32_tb;
- reg reset, clk;
- logic [31:0] input_a, input_b, result_add, result_mult;
- floating_add#(.N(32), .M(8)) add0(
- .input_1(input_a), .input_2(input_b), .sum(result_add), .diff()
- );
- floating_product#(.N(32), .M(8)) mult0(
- .input_1(input_a), .input_2(input_b), .product(result_mult)
- );
- reg [31:0] test_mem [29:0][3:0];
- initial $readmemh("scripts/fp32_test.hex", test_mem);
- initial begin
- static int num_err = 0;
- static int num_tests = $size(test_mem) * 2;
- for (int i=0; i < $size(test_mem); i++) begin
- input_a = test_mem[i][0];
- input_b = test_mem[i][1];
- #10;
- if(result_add != test_mem[i][2]) begin
- if(num_err < 20)
- $display("FAIL ADD: %H + %H = %H, expected %H", input_a, input_b, result_add, test_mem[i][2]);
- num_err = num_err + 1;
- end
- if(result_mult != test_mem[i][3]) begin
- if(num_err < 20)
- $display("FAIL MULTIPLY: %H + %H = %H, expected %H", input_a, input_b, result_mult, test_mem[i][3]);
- num_err = num_err + 1;
- end
- end
- $display("Passed %d of %d tests", num_tests-num_err, num_tests);
- $finish();
- end
- endmodule : floating32_tb
|