aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMyDariell <Dari3llsugiaman@gmail.com>2026-06-22 19:52:30 -0700
committerWarrick Lo <wlo@warricklo.net>2026-06-22 19:52:30 -0700
commit4381dbcfccee329aed76158ea62a62a9b221bdd8 (patch)
treefdee59e96b08e464ac17f56a995b64f9ffceec77
parentImplement ADD and SUB operations in sliced ALU (diff)
downloadmontreal-4381dbcfccee329aed76158ea62a62a9b221bdd8.tar.xz
montreal-4381dbcfccee329aed76158ea62a62a9b221bdd8.zip
Implement XOR, OR, AND logical operations in sliced ALU
Signed-off-by: MyDariell <Dari3llsugiaman@gmail.com>
Diffstat (limited to '')
-rw-r--r--rtl/alu.sv15
-rw-r--r--tb/alu/alu_logic_tb.sv151
2 files changed, 163 insertions, 3 deletions
diff --git a/rtl/alu.sv b/rtl/alu.sv
index 8805bf9..30645c1 100644
--- a/rtl/alu.sv
+++ b/rtl/alu.sv
@@ -54,11 +54,20 @@ module alu
result_o = adder_result[SLICE_WIDTH-1:0];
end
/* XOR. */
- 3'b100: begin end
+ 3'b100: begin
+ result_o = a_i ^ b_i;
+ carry_d = 0;
+ end
/* OR. */
- 3'b110: begin end
+ 3'b110: begin
+ result_o = a_i | b_i;
+ carry_d = 0;
+ end
/* AND. */
- 3'b111: begin end
+ 3'b111: begin
+ result_o = a_i & b_i;
+ carry_d = 0;
+ end
default: begin end
endcase
end : alu_core
diff --git a/tb/alu/alu_logic_tb.sv b/tb/alu/alu_logic_tb.sv
new file mode 100644
index 0000000..6533132
--- /dev/null
+++ b/tb/alu/alu_logic_tb.sv
@@ -0,0 +1,151 @@
+/* Testbench for ALU XOR, OR, AND operations.
+ *
+ * Logical operations are purely combinational per slice — no carry propagation.
+ * carry_o MUST be 0 on every slice for all logical operations.
+ */
+
+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 check_carry(
+ input string name,
+ input logic [31:0] a,
+ input logic [31:0] b,
+ input logic got
+ );
+ if (got === 1'b0) begin
+ $display(" PASS %s carry: %h op %h -> carry_o = 0", name, a, b);
+ pass_count++;
+ end else begin
+ $display(" FAIL %s carry: %h op %h -> carry_o = %b (expected 0)", name, a, b, got);
+ 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);
+ check_carry("XOR", a, b, final_carry);
+ 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);
+ check_carry("OR", a, b, final_carry);
+ 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);
+ check_carry("AND", a, b, final_carry);
+ 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