|
|
@@ -0,0 +1,112 @@
|
|
|
+module floating_add #(parameter N=16, M=4)(a, b, c);
|
|
|
+ input logic [N-1:0] a, b;
|
|
|
+ output logic [N-1:0] c;
|
|
|
+
|
|
|
+ logic flag_a;
|
|
|
+ logic flag_b;
|
|
|
+ logic abs;
|
|
|
+
|
|
|
+ // sign_x = x[N-1]
|
|
|
+ // exponent_x = x[N-2:N-2-M]
|
|
|
+ // mantissa_x = x[N-3-M:0]
|
|
|
+
|
|
|
+ // ASsigning overall sign of the output
|
|
|
+ assign c[N-1] = a[N-1] ^ b[N-1];
|
|
|
+
|
|
|
+ always_comb
|
|
|
+ begin
|
|
|
+ if (a[N-2:N-2-M] > b[N-2:N-2-M])
|
|
|
+ begin
|
|
|
+ // Flags input a as larger and calculates the absolute difference
|
|
|
+ flag_a = 1;
|
|
|
+ flag_b = 0;
|
|
|
+ abs = a[N-2:N-2-M] - b[N-2:N-2-M];
|
|
|
+ // ASsigning overall sign of the output
|
|
|
+ assign c[N-1] = a[N-1];
|
|
|
+ // Sets output to have the same exponent
|
|
|
+ c[N-2:N-2-M] = a[N-2:N-2-M];
|
|
|
+ end
|
|
|
+ else if (b[N-2:N-2-M] > a[N-2:N-2-M])
|
|
|
+ begin
|
|
|
+ // Similarly flags input b as larger and calculates the absolute difference
|
|
|
+ flag_a = 0;
|
|
|
+ flag_b = 1;
|
|
|
+ abs = b[N-2:N-2-M] - a[N-2:N-2-M];
|
|
|
+ // ASsigning overall sign of the output
|
|
|
+ assign c[N-1] = b[N-1];
|
|
|
+ // Sets ouput to have the same exponent
|
|
|
+ c[N-2:N-2-M] = b[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
|
|
|
+ assign c[N-1] = 0;
|
|
|
+ c[N-2:N-2-M] = a[N-2:N-2-M];
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ always_comb
|
|
|
+ begin
|
|
|
+ // Condition for overflow is that it sets the output to the larger input
|
|
|
+ if (abs > 4'b1000)
|
|
|
+ begin
|
|
|
+ if (flag_a & ~flag_b) c = a;
|
|
|
+ else if (~flag_a & flag_b) c = b;
|
|
|
+ else c <= a;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ // Shifts the lower mantissa right based on the absolute difference
|
|
|
+ if (flag_a & ~flag_b)
|
|
|
+ // If the signs of both inputs are the same you add, otherwise you subtract
|
|
|
+ if (a[N-1] == b[N-1])
|
|
|
+ c[N-3-M:0] = a[N-3-M:0] + (b[N-3-M:0] >> abs);
|
|
|
+ else
|
|
|
+ c[N-3-M:0] = a[N-3-M:0] - (b[N-3-M:0] >> abs);
|
|
|
+ else if (~flag_a & flag_b)
|
|
|
+ if (a[N-1] == b[N-1])
|
|
|
+ c[N-3-M:0] = b[N-3-M:0] + (a[N-3-M:0] >> abs);
|
|
|
+ else
|
|
|
+ c[N-3-M:0] = b[N-3-M:0] - (a[N-3-M:0] >> abs);
|
|
|
+ else
|
|
|
+ if (a[N-1] == b[N-1])
|
|
|
+ c[N-3-M:0] = b[N-3-M:0] << 1;
|
|
|
+ else
|
|
|
+ c[N-3-M:0] = 0;
|
|
|
+ end
|
|
|
+ end
|
|
|
+endmodule : floating_add
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+module floating_product #(parameter N=16, M=4)(a, b, c);
|
|
|
+ input logic [N-1:0] a, b;
|
|
|
+ output logic [N-1:0] c;
|
|
|
+
|
|
|
+endmodule : floating_product
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+module floating_add_tb;
|
|
|
+ logic [15:0] a, b, c;
|
|
|
+ floating_add adder1(a, b, c);
|
|
|
+
|
|
|
+ task test_inputs;
|
|
|
+ input [15:0] in_a, in_b, expected_c;
|
|
|
+ assign a = in_a;
|
|
|
+ assign b = in_b;
|
|
|
+ #2ps;
|
|
|
+ if(c == expected_c) $display("PASS: a=%b b=%b c=%b", a,b,c);
|
|
|
+ else $error("FAIL: a=%b b=%b c=%b, expected c=%b", a,b,c,expected_c);
|
|
|
+ #2ps;
|
|
|
+ endtask : test_inputs
|
|
|
+
|
|
|
+ initial begin
|
|
|
+ test_inputs(16'b0, 16'b0_01111_0000000000, 16'b0_01111_0000000000);
|
|
|
+ $finish();
|
|
|
+ end
|
|
|
+endmodule : floating_add_tb
|