aboutsummaryrefslogtreecommitdiff
path: root/tb/alu/alu_logic_tb.sv
diff options
context:
space:
mode:
Diffstat (limited to 'tb/alu/alu_logic_tb.sv')
-rw-r--r--tb/alu/alu_logic_tb.sv134
1 files changed, 134 insertions, 0 deletions
diff --git a/tb/alu/alu_logic_tb.sv b/tb/alu/alu_logic_tb.sv
new file mode 100644
index 0000000..7d70bda
--- /dev/null
+++ b/tb/alu/alu_logic_tb.sv
@@ -0,0 +1,134 @@
+/* Testbench for ALU XOR, OR, AND operations.
+ *
+ * Logical operations are purely combinational per slice — no carry propagation.
+ * carry_o is NOT valid for logical operations and MUST NOT be used by the
+ * caller. It is not checked in this testbench.
+ */
+
+module alu_logic_tb;
+ import montreal_pkg::*;
+
+ logic clk_i;
+ logic rst_ni;
+ fu_op_t alu_op_i;
+ logic [1:0] count_i;
+ slice_t a_i, b_i;
+ slice_t result_o;
+ logic carry_o;
+
+ alu dut (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .alu_op_i (alu_op_i),
+ .count_i (count_i),
+ .a_i (a_i),
+ .b_i (b_i),
+ .result_o (result_o),
+ .carry_o (carry_o)
+ );
+
+ initial clk_i = 0;
+ always #5 clk_i = ~clk_i;
+
+ int pass_count;
+ int fail_count;
+
+ task automatic run_op(
+ input fu_op_t op,
+ input logic [31:0] a,
+ input logic [31:0] b,
+ output logic [31:0] result,
+ output logic final_carry
+ );
+ for (int i = 0; i < 4; i++) begin
+ @(negedge clk_i);
+ alu_op_i = op;
+ count_i = i[1:0];
+ a_i = a[i*8 +: 8];
+ b_i = b[i*8 +: 8];
+
+ #1;
+ result[i*8 +: 8] = result_o;
+ if (i == 3) final_carry = carry_o;
+
+ @(posedge clk_i);
+ end
+ endtask
+
+ task automatic check(
+ input string name,
+ input logic [31:0] a,
+ input logic [31:0] b,
+ input logic [31:0] got,
+ input logic [31:0] expected
+ );
+ if (got === expected) begin
+ $display(" PASS %s: %h op %h = %h", name, a, b, got);
+ pass_count++;
+ end else begin
+ $display(" FAIL %s: %h op %h = %h (expected %h)", name, a, b, got, expected);
+ fail_count++;
+ end
+ endtask
+
+ task automatic test_xor(input logic [31:0] a, input logic [31:0] b);
+ logic [31:0] result;
+ logic final_carry;
+ run_op(XOR, a, b, result, final_carry);
+ check("XOR", a, b, result, a ^ b);
+ endtask
+
+ task automatic test_or(input logic [31:0] a, input logic [31:0] b);
+ logic [31:0] result;
+ logic final_carry;
+ run_op(OR, a, b, result, final_carry);
+ check("OR", a, b, result, a | b);
+ endtask
+
+ task automatic test_and(input logic [31:0] a, input logic [31:0] b);
+ logic [31:0] result;
+ logic final_carry;
+ run_op(AND, a, b, result, final_carry);
+ check("AND", a, b, result, a & b);
+ endtask
+
+ initial begin
+ pass_count = 0;
+ fail_count = 0;
+
+ rst_ni = 0;
+ alu_op_i = XOR;
+ count_i = 0;
+ a_i = 0;
+ b_i = 0;
+ @(posedge clk_i);
+ @(posedge clk_i);
+ rst_ni = 1;
+
+ $display("=== XOR tests ===");
+ test_xor(32'hFFFF_FFFF, 32'hFFFF_FFFF); // all 1s XOR all 1s = 0
+ test_xor(32'hFFFF_FFFF, 32'h0000_0000); // all 1s XOR 0 = all 1s
+ test_xor(32'hAAAA_AAAA, 32'h5555_5555); // alternating bits
+ test_xor(32'h1234_5678, 32'h8765_4321); // mixed
+ test_xor(32'h0000_0000, 32'h0000_0000); // 0 XOR 0 = 0
+
+ $display("\n=== OR tests ===");
+ test_or(32'hFFFF_FFFF, 32'h0000_0000); // all 1s OR 0 = all 1s
+ test_or(32'h0000_0000, 32'h0000_0000); // 0 OR 0 = 0
+ test_or(32'hAAAA_AAAA, 32'h5555_5555); // alternating → all 1s
+ test_or(32'h1234_5678, 32'h8765_4321); // mixed
+ test_or(32'hFFFF_FFFF, 32'hFFFF_FFFF); // all 1s OR all 1s = all 1s
+
+ $display("\n=== AND tests ===");
+ test_and(32'hFFFF_FFFF, 32'hFFFF_FFFF); // all 1s AND all 1s = all 1s
+ test_and(32'hFFFF_FFFF, 32'h0000_0000); // all 1s AND 0 = 0
+ test_and(32'hAAAA_AAAA, 32'h5555_5555); // alternating → 0
+ test_and(32'h1234_5678, 32'h8765_4321); // mixed
+ test_and(32'h0000_0000, 32'h0000_0000); // 0 AND 0 = 0
+
+ $display("\n=== Results: %0d passed, %0d failed ===", pass_count, fail_count);
+
+ $finish;
+ end
+
+endmodule : alu_logic_tb