summaryrefslogtreecommitdiff
path: root/vlsi/tb_chip_core.v
diff options
context:
space:
mode:
Diffstat (limited to 'vlsi/tb_chip_core.v')
-rw-r--r--vlsi/tb_chip_core.v306
1 files changed, 306 insertions, 0 deletions
diff --git a/vlsi/tb_chip_core.v b/vlsi/tb_chip_core.v
new file mode 100644
index 0000000..66fa212
--- /dev/null
+++ b/vlsi/tb_chip_core.v
@@ -0,0 +1,306 @@
1`timescale 1ns/1ps
2
3module tb_chip_core;
4
5 // ========================================================================
6 // 1. CONFIGURATION & CONSTANTS
7 // ========================================================================
8
9 // Opcodes
10 localparam [7:0] OP_CONS = 8'h01;
11 localparam [7:0] OP_CAR = 8'h02;
12 localparam [7:0] OP_CDR = 8'h03;
13 localparam [7:0] OP_ATOM = 8'h04;
14 localparam [7:0] OP_EQ = 8'h05;
15 localparam [7:0] OP_ADD = 8'h06;
16
17 // Tags
18 localparam [1:0] TAG_NIL = 2'b00;
19 localparam [1:0] TAG_ATOM = 2'b01;
20 localparam [1:0] TAG_NUM = 2'b10;
21 localparam [1:0] TAG_CONS = 2'b11;
22
23 // Standard Values for Testing
24 localparam [7:0] VAL_NIL = {TAG_NIL, 6'h00};
25 localparam [7:0] VAL_TRUE = {TAG_ATOM, 6'h01}; // 'T'
26 localparam [7:0] VAL_A = {TAG_ATOM, 6'h0A};
27 localparam [7:0] VAL_B = {TAG_ATOM, 6'h0B};
28 localparam [7:0] VAL_C = {TAG_ATOM, 6'h0C};
29
30 // Testbench Signals
31 reg clk, rst, cs, rw;
32 reg [2:0] addr;
33 reg [7:0] data_in;
34 wire [7:0] data_out;
35
36 // Verification Variables
37 reg [7:0] read_val;
38 reg [7:0] status_val;
39 reg [7:0] ptr_node3, ptr_node2, ptr_node1;
40 integer errors = 0;
41 integer i;
42
43 // Instantiate DUT
44 chip_core dut (
45 .clk(clk), .rst(rst), .cs(cs), .rw(rw),
46 .addr(addr), .data_in(data_in), .data_out(data_out)
47 );
48
49 // Clock Generation (100MHz)
50 initial begin
51 clk = 0;
52 forever #5 clk = ~clk;
53 end
54
55 // ========================================================================
56 // 2. HELPER TASKS
57 // ========================================================================
58
59 task cpu_write(input [2:0] w_addr, input [7:0] w_data);
60 begin
61 @(posedge clk);
62 cs = 1; rw = 0; addr = w_addr; data_in = w_data;
63 @(posedge clk);
64 cs = 0; data_in = 8'h00;
65 end
66 endtask
67
68 // Read with auto-polling for BUSY flag
69 task cpu_exec_and_read(input [2:0] r_addr, output [7:0] r_data);
70 begin
71 // Poll Status Bit 0 (BUSY)
72 do begin
73 @(posedge clk);
74 cs = 1; rw = 1; addr = 3'h4; // Status
75 @(posedge clk);
76 status_val = data_out;
77 cs = 0;
78 end while (status_val[0] === 1'b1);
79
80 // Perform Read
81 @(posedge clk);
82 cs = 1; rw = 1; addr = r_addr;
83 @(posedge clk);
84 r_data = data_out;
85 cs = 0;
86 end
87 endtask
88
89 task check(input [7:0] expected, input [7:0] actual, input string name);
90 if (expected !== actual) begin
91 $display("FAIL: %s | Exp: 0x%h, Got: 0x%h", name, expected, actual);
92 errors = errors + 1;
93 end else begin
94 $display("PASS: %s", name);
95 end
96 endtask
97
98 task check_status(input bit exp_heap, input bit exp_type, input bit exp_carry, input bit exp_zero, input string name);
99 // Status Reg: [7:5]Rsrv, [4]Zero, [3]Carry, [2]Type, [1]Heap, [0]Busy
100 reg [7:0] expected_mask;
101 expected_mask = {3'b000, exp_zero, exp_carry, exp_type, exp_heap, 1'b0};
102
103 cpu_exec_and_read(3'h4, status_val);
104 // Mask out the busy bit for comparison as it should be 0 now
105 if ((status_val & 8'hFE) !== expected_mask) begin
106 $display("FAIL: %s (Status) | Exp: %b, Got: %b", name, expected_mask, status_val);
107 errors = errors + 1;
108 end else begin
109 $display("PASS: %s (Status)", name);
110 end
111 endtask
112
113 // ========================================================================
114 // 3. MAIN TEST SCENARIOS
115 // ========================================================================
116
117 initial begin
118 $dumpfile("chip_core_robust.vcd");
119 $dumpvars(0, tb_chip_core);
120
121 // --- Initialize ---
122 rst = 1; cs = 0; rw = 0; addr = 0; data_in = 0;
123 #20 rst = 0; #20;
124 $display("\n=== STARTING ROBUST VERIFICATION ===\n");
125
126 // --------------------------------------------------------
127 // SCENARIO 1: ALU Boundary & Overflow
128 // --------------------------------------------------------
129 $display("--- Scenario 1: ALU Mathematics ---");
130
131 // 1.1 Simple Add: 10 + 15 = 25
132 cpu_write(3'h1, {TAG_NUM, 6'd10});
133 cpu_write(3'h2, {TAG_NUM, 6'd15});
134 cpu_write(3'h0, OP_ADD);
135 cpu_exec_and_read(3'h3, read_val);
136 check({TAG_NUM, 6'd25}, read_val, "Add 10+15");
137 check_status(0,0,0,0, "Add Normal Status");
138
139 // 1.2 Zero Check: 0 + 0 = 0 (Should set Zero flag)
140 cpu_write(3'h1, {TAG_NUM, 6'd0});
141 cpu_write(3'h2, {TAG_NUM, 6'd0});
142 cpu_write(3'h0, OP_ADD);
143 cpu_exec_and_read(3'h3, read_val);
144 check({TAG_NUM, 6'd0}, read_val, "Add 0+0");
145 check_status(0,0,0,1, "Add Zero Status"); // Expect Zero=1
146
147 // 1.3 Overflow Check: 63 + 1 = 0 (Should set Carry flag)
148 // Max 6-bit unsigned is 63. 63+1 wraps to 0.
149 cpu_write(3'h1, {TAG_NUM, 6'd63});
150 cpu_write(3'h2, {TAG_NUM, 6'd1});
151 cpu_write(3'h0, OP_ADD);
152 cpu_exec_and_read(3'h3, read_val);
153 check({TAG_NUM, 6'd0}, read_val, "Add 63+1 (Wrap)");
154 check_status(0,0,1,1, "Add Overflow Status"); // Expect Carry=1, Zero=1
155
156 // --------------------------------------------------------
157 // SCENARIO 2: Equality (EQ) Logic
158 // --------------------------------------------------------
159 $display("\n--- Scenario 2: EQ Logic ---");
160
161 // 2.1 Atom Equality (True)
162 cpu_write(3'h1, VAL_A);
163 cpu_write(3'h2, VAL_A);
164 cpu_write(3'h0, OP_EQ);
165 cpu_exec_and_read(3'h3, read_val);
166 check(VAL_TRUE, read_val, "EQ(A, A)");
167 check_status(0,0,0,1, "EQ True Status"); // Zero flag used for equality? Spec says "ZERO (From ADD or EQ op)"
168
169 // 2.2 Atom Inequality (False)
170 cpu_write(3'h1, VAL_A);
171 cpu_write(3'h2, VAL_B);
172 cpu_write(3'h0, OP_EQ);
173 cpu_exec_and_read(3'h3, read_val);
174 check(VAL_NIL, read_val, "EQ(A, B)");
175 check_status(0,0,0,0, "EQ False Status");
176
177 // 2.3 Mixed Type Equality (Number 10 vs Atom 10) -> Should be NIL (Bits differ in Tag)
178 cpu_write(3'h1, {TAG_NUM, 6'd10});
179 cpu_write(3'h2, {TAG_ATOM, 6'd10});
180 cpu_write(3'h0, OP_EQ);
181 cpu_exec_and_read(3'h3, read_val);
182 check(VAL_NIL, read_val, "EQ(Num, Atom)");
183
184 // --------------------------------------------------------
185 // SCENARIO 3: Linked List Construction (Chain Verification)
186 // --------------------------------------------------------
187 $display("\n--- Scenario 3: Linked List (A B C) ---");
188 // Goal: Construct (A . (B . (C . NIL)))
189 // Steps:
190 // 1. Node3 = CONS(C, NIL)
191 // 2. Node2 = CONS(B, Node3)
192 // 3. Node1 = CONS(A, Node2)
193
194 // Step 1: Node 3
195 cpu_write(3'h1, VAL_C);
196 cpu_write(3'h2, VAL_NIL);
197 cpu_write(3'h0, OP_CONS);
198 cpu_exec_and_read(3'h3, ptr_node3);
199 check({TAG_CONS, 2'b00, 4'h0}, ptr_node3, "Alloc Node 3 (Ptr=0)");
200
201 // Step 2: Node 2
202 cpu_write(3'h1, VAL_B);
203 cpu_write(3'h2, ptr_node3);
204 cpu_write(3'h0, OP_CONS);
205 cpu_exec_and_read(3'h3, ptr_node2);
206 check({TAG_CONS, 2'b00, 4'h2}, ptr_node2, "Alloc Node 2 (Ptr=2)");
207
208 // Step 3: Node 1
209 cpu_write(3'h1, VAL_A);
210 cpu_write(3'h2, ptr_node2);
211 cpu_write(3'h0, OP_CONS);
212 cpu_exec_and_read(3'h3, ptr_node1);
213 check({TAG_CONS, 2'b00, 4'h4}, ptr_node1, "Alloc Node 1 (Ptr=4)");
214
215 // Step 4: Traverse! CAR(CDR(ptr_node1)) should be B
216
217 // CDR(Node1) -> Should get Node2 Ptr
218 cpu_write(3'h1, ptr_node1);
219 cpu_write(3'h0, OP_CDR);
220 cpu_exec_and_read(3'h3, read_val);
221 check(ptr_node2, read_val, "Traverse: CDR(Node1)");
222
223 // CAR(Result) -> Should get B
224 cpu_write(3'h1, read_val);
225 cpu_write(3'h0, OP_CAR);
226 cpu_exec_and_read(3'h3, read_val);
227 check(VAL_B, read_val, "Traverse: CAR(Node2)");
228
229 // --------------------------------------------------------
230 // SCENARIO 4: Error Type Matrix
231 // --------------------------------------------------------
232 $display("\n--- Scenario 4: Type Safety ---");
233
234 // 4.1 CAR on ATOM (Fail)
235 cpu_write(3'h1, VAL_A);
236 cpu_write(3'h0, OP_CAR);
237 check_status(0,1,0,0, "Err: CAR on Atom"); // Expect ErrType=1
238
239 // 4.2 CDR on NUMBER (Fail)
240 cpu_write(3'h1, {TAG_NUM, 6'd5});
241 cpu_write(3'h0, OP_CDR);
242 check_status(0,1,0,0, "Err: CDR on Number");
243
244 // 4.3 ADD on CONS (Fail)
245 cpu_write(3'h1, {TAG_NUM, 6'd5});
246 cpu_write(3'h2, ptr_node1);
247 cpu_write(3'h0, OP_ADD);
248 check_status(0,1,0,0, "Err: ADD on CONS");
249
250 // --------------------------------------------------------
251 // SCENARIO 5: Heap Full Boundary
252 // --------------------------------------------------------
253 $display("\n--- Scenario 5: Heap Full Boundary ---");
254
255 // Current Alloc Pointer is at 6 (We did 3 CONS ops: 0, 2, 4).
256 // Capacity is 16. Addresses 6, 8, 10, 12, 14 are free.
257 // That is 5 more CONS operations allowed.
258
259 // Fill 1 (Ptr 6)
260 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
261 cpu_exec_and_read(3'h3, read_val); // Wait
262
263 // Fill 2 (Ptr 8)
264 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
265 cpu_exec_and_read(3'h3, read_val);
266
267 // Fill 3 (Ptr 10)
268 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
269 cpu_exec_and_read(3'h3, read_val);
270
271 // Fill 4 (Ptr 12)
272 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
273 cpu_exec_and_read(3'h3, read_val);
274
275 // Fill 5 (Ptr 14) - THE LAST VALID ONE
276 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
277 cpu_exec_and_read(3'h3, read_val);
278 check({TAG_CONS, 2'b00, 4'hE}, read_val, "Last Valid Alloc (Ptr=14)");
279 check_status(0,0,0,0, "Status at Capacity");
280
281 // ATTEMPT OVERFLOW
282 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
283
284 // Check Status
285 cpu_exec_and_read(3'h4, status_val);
286 // Expect ErrHeap=1
287 if (status_val[1] !== 1'b1) begin
288 $display("FAIL: Heap Full Detection | Got Status: %b", status_val);
289 errors = errors + 1;
290 end else begin
291 $display("PASS: Heap Full Detection");
292 end
293
294 // --------------------------------------------------------
295 // RESULT SUMMARY
296 // --------------------------------------------------------
297 $display("\n==================================");
298 if (errors == 0)
299 $display(" SUCCESS: All Tests Passed");
300 else
301 $display(" FAILURE: %0d Errors Found", errors);
302 $display("==================================");
303 $finish;
304 end
305
306endmodule