|
@@ -0,0 +1,113 @@
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// Check if x0 > x1
|
|
|
|
|
+module fpu32_gt(x0, x1, y);
|
|
|
|
|
+ input logic [31:0] x0;
|
|
|
|
|
+ input logic [31:0] x1;
|
|
|
|
|
+ output logic y;
|
|
|
|
|
+
|
|
|
|
|
+ wire s_x0, s_x1;
|
|
|
|
|
+ wire [7:0] e_x0, e_x1;
|
|
|
|
|
+ wire [22:0] m_x0, m_x1;
|
|
|
|
|
+
|
|
|
|
|
+ assign s_x0 = x0[31];
|
|
|
|
|
+ assign e_x0 = x0[30:23];
|
|
|
|
|
+ assign m_x0 = x0[22:0];
|
|
|
|
|
+
|
|
|
|
|
+ assign s_x1 = x1[31];
|
|
|
|
|
+ assign e_x1 = x1[30:23];
|
|
|
|
|
+ assign m_x1 = x1[22:0];
|
|
|
|
|
+
|
|
|
|
|
+ wire comp;
|
|
|
|
|
+ assign comp = s_x0 ^ ((e_x0 > e_x1) | (e_x0 == e_x1 & m_x0 > m_x1));
|
|
|
|
|
+ assign y = (~s_x0 & s_x1) | (~(s_x0 ^ s_x1) & comp);
|
|
|
|
|
+endmodule : fpu32_gt
|
|
|
|
|
+
|
|
|
|
|
+// Check if x0 >= x1
|
|
|
|
|
+module fpu32_ge(x0, x1, y);
|
|
|
|
|
+ input logic [31:0] x0;
|
|
|
|
|
+ input logic [31:0] x1;
|
|
|
|
|
+ output logic y;
|
|
|
|
|
+
|
|
|
|
|
+ wire y0;
|
|
|
|
|
+ fpu32_gt gt0(x0, x1, y0);
|
|
|
|
|
+ assign y = y0 | (x0 == x1);
|
|
|
|
|
+endmodule : fpu32_ge
|
|
|
|
|
+
|
|
|
|
|
+// Check if x0 < x1
|
|
|
|
|
+module fpu32_lt(x0, x1, y);
|
|
|
|
|
+ input logic [31:0] x0;
|
|
|
|
|
+ input logic [31:0] x1;
|
|
|
|
|
+ output logic y;
|
|
|
|
|
+
|
|
|
|
|
+ wire y0;
|
|
|
|
|
+ fpu32_ge ge0(x0, x1, y0);
|
|
|
|
|
+ assign y = ~y0;
|
|
|
|
|
+endmodule : fpu32_lt
|
|
|
|
|
+
|
|
|
|
|
+// Check if x0 <= x1
|
|
|
|
|
+module fpu32_le(x0, x1, y);
|
|
|
|
|
+ input logic [31:0] x0;
|
|
|
|
|
+ input logic [31:0] x1;
|
|
|
|
|
+ output logic y;
|
|
|
|
|
+
|
|
|
|
|
+ wire y0;
|
|
|
|
|
+ fpu32_gt gt0(x0, x1, y0);
|
|
|
|
|
+ assign y = ~y0;
|
|
|
|
|
+endmodule : fpu32_le
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+module fpu32_compare_tb();
|
|
|
|
|
+ logic [31:0] x0;
|
|
|
|
|
+ logic [31:0] x1;
|
|
|
|
|
+
|
|
|
|
|
+ reg [31:0] test_mem [9999:0][3:0];
|
|
|
|
|
+ initial $readmemh("scripts/fp32_test.hex", test_mem);
|
|
|
|
|
+ reg [4:0] test_mem_cmp [9999:0];
|
|
|
|
|
+ initial $readmemb("scripts/fp32_test_comp.hex", test_mem_cmp);
|
|
|
|
|
+
|
|
|
|
|
+ wire y_gt, y_lt, y_ge, y_le, y_eq;
|
|
|
|
|
+ logic exp_gt, exp_lt, exp_ge, exp_le, exp_eq;
|
|
|
|
|
+ fpu32_gt gt0(x0, x1, y_gt);
|
|
|
|
|
+ fpu32_lt lt0(x0, x1, y_lt);
|
|
|
|
|
+ fpu32_ge ge0(x0, x1, y_ge);
|
|
|
|
|
+ fpu32_le le0(x0, x1, y_le);
|
|
|
|
|
+ assign y_eq = x0 == x1;
|
|
|
|
|
+
|
|
|
|
|
+ static int num_err = 0;
|
|
|
|
|
+ static int num_tests = $size(test_mem) * 5;
|
|
|
|
|
+
|
|
|
|
|
+ task test_val;
|
|
|
|
|
+ input int i;
|
|
|
|
|
+ input val, exp;
|
|
|
|
|
+ input string name;
|
|
|
|
|
+ if(val != exp) begin
|
|
|
|
|
+ if(num_err < 20) begin
|
|
|
|
|
+ $display("FAIL %d at %s: 0x%H, 0x%H => %b, expected %b", i, name, x0, x1, val, exp);
|
|
|
|
|
+ end
|
|
|
|
|
+ num_err++;
|
|
|
|
|
+ end
|
|
|
|
|
+ endtask : test_val
|
|
|
|
|
+
|
|
|
|
|
+ initial begin
|
|
|
|
|
+ for (int i=0; i < $size(test_mem); i++) begin
|
|
|
|
|
+ x0 = test_mem[i][0];
|
|
|
|
|
+ x1 = test_mem[i][1];
|
|
|
|
|
+ exp_gt = test_mem_cmp[i][4];
|
|
|
|
|
+ exp_lt = test_mem_cmp[i][3];
|
|
|
|
|
+ exp_ge = test_mem_cmp[i][2];
|
|
|
|
|
+ exp_le = test_mem_cmp[i][1];
|
|
|
|
|
+ exp_eq = test_mem_cmp[i][0];
|
|
|
|
|
+ #1;
|
|
|
|
|
+ test_val(i, y_gt, exp_gt, "GT");
|
|
|
|
|
+ test_val(i, y_lt, exp_lt, "LT");
|
|
|
|
|
+ test_val(i, y_ge, exp_ge, "GE");
|
|
|
|
|
+ test_val(i, y_le, exp_le, "LE");
|
|
|
|
|
+ test_val(i, y_eq, exp_eq, "EQ");
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ $display("Passed %d of %d tests", num_tests-num_err, num_tests);
|
|
|
|
|
+ $finish();
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+endmodule : fpu32_compare_tb
|