summaryrefslogtreecommitdiff
path: root/rtl/tb_lisp_coproc.sv
blob: 6c39aa4c9ab7d7ee383a48edf4c819c79f360335 (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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
`timescale 1ns/1ps

module tb_lisp_coproc;

    // Testbench signals
    reg        clk;
    reg        rst;
    reg        cs;
    reg        rw;      // 0=Write, 1=Read
    reg [2:0]  addr;
    reg [7:0]  data_in;
    wire [7:0] data_out;
    
    // Test variables
    reg [7:0]  read_data;
    integer i; 
    
    // Instantiate the DUT
    lisp_coproc dut (
        .clk(clk),
        .rst(rst),
        .cs(cs),
        .rw(rw),
        .addr(addr),
        .data_in(data_in),
        .data_out(data_out)
    );
    
    // Clock generation
    initial begin
        clk = 0;
        forever #5 clk = ~clk;
    end
    
    // CPU Write Task
    task cpu_write;
        input [2:0] addr_in;
        input [7:0] data_in_in;
        begin
            @(posedge clk);
            cs = 1'b1;
            rw = 1'b0;  // Write
            addr = addr_in;
            data_in = data_in_in;
            @(posedge clk);
            cs = 1'b0;
        end
    endtask
    
    // CPU Read Task
    task cpu_read;
        input [2:0] addr_in;
        output [7:0] data_out_out;
        reg [7:0] status;
        begin
            // Poll until not busy
            do begin
                @(posedge clk);
                cs = 1'b1;
                rw = 1'b1;  // Read
                addr = 3'h4;  // Status register
                @(posedge clk);
                status = data_out;
                cs = 1'b0;
            end while (status[0]);  // Check BUSY bit
            
            // Read the requested address
            @(posedge clk);
            cs = 1'b1;
            rw = 1'b1;  // Read
            addr = addr_in;
            @(posedge clk);
            data_out_out = data_out;
            cs = 1'b0;
        end
    endtask
    
    // Test Sequence
    initial begin
        // Initialize signals
        rst = 1'b1;
        cs = 1'b0;
        rw = 1'b0;
        addr = 3'h0;
        data_in = 8'h00;
        
        // Apply reset
        #20;
        rst = 1'b0;
        #20;
        
        // Test 1: Reset Test
        $display("Test 1: Reset Test");
        cpu_read(3'h4, read_data);  // Read STATUS
        $display("STATUS after reset: 0x%02h (expected: 0x00)", read_data);
        if (read_data != 8'h00) $display("ERROR: Reset test failed");
        
        // Test 2: ADD Test
        $display("\nTest 2: ADD Test");
        cpu_write(3'h1, 8'h85);  // ARG1 = NUMBER(5)
        cpu_write(3'h2, 8'h86);  // ARG2 = NUMBER(6)
        cpu_write(3'h0, 8'h06);  // OPCODE = ADD
        
        cpu_read(3'h3, read_data);  // Read RESULT
        $display("ADD Result: 0x%02h (expected: 0x8B, NUMBER(11))", read_data);
        if (read_data != 8'h8B) $display("ERROR: ADD test failed");
        
        cpu_read(3'h4, read_data);  // Read STATUS
        $display("STATUS after ADD: 0x%02h (expected: 0x00, ZERO=0)", read_data);
        if (read_data != 8'h00) $display("ERROR: ADD status test failed");
        
        // Test 3: CONS Test
        $display("\nTest 3: CONS Test");
        cpu_write(3'h1, 8'h41);  // ARG1 = ATOM('T')
        cpu_write(3'h2, 8'h42);  // ARG2 = ATOM('B')
        cpu_write(3'h0, 8'h01);  // OPCODE = CONS
        
        cpu_read(3'h3, read_data);  // Read RESULT
        $display("CONS Result: 0x%02h (expected: 0xC0, CONS(0))", read_data);
        if (read_data != 8'hC0) $display("ERROR: CONS test failed");
        
        // Test CAR and CDR
        cpu_write(3'h1, read_data);  // Use the CONS result as ARG1
        cpu_write(3'h0, 8'h02);      // OPCODE = CAR
        
        cpu_read(3'h3, read_data);   // Read RESULT
        $display("CAR Result: 0x%02h (expected: 0x41, ATOM('T'))", read_data);
        if (read_data != 8'h41) $display("ERROR: CAR test failed");
        
        cpu_write(3'h1, 8'hC0);      // ARG1 = CONS(0)
        cpu_write(3'h0, 8'h03);      // OPCODE = CDR
        
        cpu_read(3'h3, read_data);   // Read RESULT
        $display("CDR Result: 0x%02h (expected: 0x42, ATOM('B'))", read_data);
        if (read_data != 8'h42) $display("ERROR: CDR test failed");
        
        // Test 4: Error Test (CAR on a Number)
        $display("\nTest 4: Error Test (CAR on a Number)");
        cpu_write(3'h1, 8'h85);  // ARG1 = NUMBER(5)
        cpu_write(3'h0, 8'h02);  // OPCODE = CAR
        
        cpu_read(3'h4, read_data);  // Read STATUS
        $display("STATUS after CAR on Number: 0x%02h (expected: 0x04, ERR_TYPE=1)", read_data);
        if (read_data != 8'h04) $display("ERROR: Error test failed");
        
        // Test 5: Heap Full Test
        $display("\nTest 5: Heap Full Test");
        // Fill the heap with CONS operations
        // Since bump_alloc is now 2, we have used 2 cells. 
        // 16 cells total. 14 left. 7 more CONS possible.
        for (i = 0; i < 7; i = i + 1) begin 
            cpu_write(3'h1, 8'h41);  
            cpu_write(3'h2, 8'h42);  
            cpu_write(3'h0, 8'h01);  
            cpu_read(3'h3, read_data); 
        end
        
        // One more CONS should cause heap full error
        cpu_write(3'h1, 8'h41); 
        cpu_write(3'h2, 8'h42); 
        cpu_write(3'h0, 8'h01); 
        
        cpu_read(3'h4, read_data);  // Read STATUS
        $display("STATUS after Heap Full: 0x%02h (expected: 0x02, ERR_HEAP_FULL=1)", read_data);
        if (read_data != 8'h02) $display("ERROR: Heap Full test failed");
        
        $display("\nAll tests completed.");
        $finish;
    end

endmodule