aboutsummaryrefslogtreecommitdiffstats
path: root/atk16_fpga/alu_tb.v
blob: 7569e2d9c4e3c5e227e4b89b54a7379cc92588bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
`default_nettype none
`define DUMPSTR(x) `"x.vcd`"

`define PLUS  3'd0
`define MINUS 3'd1
`define AND   3'd2
`define OR    3'd3
`define XOR   3'd4
`define SHL   3'd5
`define SHR   3'd6
`define SAR   3'd7

`define TESTCASE(ma, msel, mb, mexpected, mflags) \
    sel      <= `msel; \
    a        <= ma; \
    b        <= mb; \
    #5 if (result != $unsigned(mexpected) || flags !== mflags) begin \
        failed <= 1; \
        $write("\033[0;31m[FAIL]\033[0m "); \
        $display("%d msel %0d = %0d, flags %04b", a, b, result, flags); \
        $display("_             expected result %0d", $unsigned(mexpected)); \
        $display("_             expected flags  %04b", mflags); \
    end \
    else begin \
        $write("\033[0;32m[PASS]\033[0m "); \
        $display("%d msel %0d = %0d, flags %04b", a, b, result, flags); \
    end

`timescale 10 ns / 100 ps
module alu_tb();

    reg  [2:0]  sel;
    reg  [15:0] a, b;
    wire [15:0] result;
    wire [3:0]  flags;

    alu dut (
        .sel(sel),
        .a(a),
        .b(b),
        .result(result),
        .flags(flags)
    );

    reg failed;
    initial begin
        failed <= 0;
        $dumpfile(`DUMPSTR(`VCD_OUTPUT));
        $dumpvars(0, alu_tb);

        `TESTCASE(10, PLUS, 20, 30, 4'b0000)
        `TESTCASE(-1, PLUS, 1, 0, 4'b1001)
        `TESTCASE(16'h7fff, PLUS, 16'h7fff, 16'hfffe, 4'b0110)
        `TESTCASE(30, MINUS, 30, 0, 4'b0001)
        `TESTCASE(30, MINUS, 40, -16'd10, 4'b1010)
        `TESTCASE(16'h7fff, MINUS, 16'h7fff, 0, 4'b0001)
        `TESTCASE(16'h8000, MINUS, 16'h1, 16'h7fff, 4'b0100)
        `TESTCASE(3'b110, AND, 3'b101, 3'b100, 4'b0000)
        `TESTCASE(3'b110, OR, 3'b101, 3'b111, 4'b0000)
        `TESTCASE(3'b110, XOR, 3'b101, 3'b011, 4'b0000)
        `TESTCASE(16'b110, SHL, 16'd3, 16'b110000, 4'b0000)
        `TESTCASE(16'b1100_0000_0000_0000, SHR, 16'd3, 16'b0001_1000_0000_0000, 4'b0000)
        `TESTCASE(16'b1100_0000_0000_0000, SAR, 16'd3, 16'b1111_1000_0000_0000, 4'b0010)

        #5
        if (failed) begin
            $display("🛑 \033[0;31mTest suite failed\033[0m");
            $fatal(1);
        end else
            $display("✅ \033[0;32mTest suite passed\033[0m");
        $finish;
    end
endmodule