summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile65
-rw-r--r--config.json6
-rw-r--r--rtl/lisp_coproc.sv453
-rw-r--r--rtl/tb_lisp_coproc.sv611
-rw-r--r--vlsi/tb_chip_core.v4
6 files changed, 631 insertions, 510 deletions
diff --git a/.gitignore b/.gitignore
index 82b46f9..d2ccc6d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@ rtl/lisp_coproc_sim
2*.vcd 2*.vcd
3*~ 3*~
4#* 4#*
5runs/
6obj_dir/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8b7bf3a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,65 @@
1# ==============================================================================
2# CONFIGURATION
3# ==============================================================================
4PROJECT_NAME = lisp_coproc
5CONFIG_FILE = config.json
6
7# Tool Paths
8LIBRELANE = librelane
9VERILATOR = verilator
10
11# PDK Paths (Standard Volare location)
12PDK_ROOT ?= $(HOME)/.ciel/ciel/sky130/versions/0fe599b2afb6708d281543108caf8310912f54af/
13PDK = sky130A
14LIB_VERILOG = $(PDK_ROOT)/$(PDK)/libs.ref/sky130_fd_sc_hd/verilog/sky130_fd_sc_hd.v
15PRIM_VERILOG = $(PDK_ROOT)/$(PDK)/libs.ref/sky130_fd_sc_hd/verilog/primitives.v
16
17# Simulation Flags
18VERILATOR_FLAGS = --binary -j 0 --timing --trace --top-module tb_$(PROJECT_NAME) \
19 -Wno-fatal -Wno-style -Wno-lint
20
21# ==============================================================================
22# TARGETS
23# ==============================================================================
24.PHONY: all rtl harden gls clean
25
26# 1. Default: Run the full pipeline (RTL -> GDS -> Check)
27all: rtl harden gls
28
29# 2. RTL Verification: Runs your Golden SystemVerilog Testbench
30rtl:
31 @echo "\n=== [1/3] Running RTL Verification ==="
32 $(VERILATOR) $(VERILATOR_FLAGS) \
33 -DGL_SIM=0 \
34 rtl/tb_$(PROJECT_NAME).sv rtl/$(PROJECT_NAME).sv
35 ./obj_dir/Vtb_$(PROJECT_NAME)
36 @echo ">>> RTL Verification Passed <<<"
37
38# 3. Hardening: Runs LibreLane (Synthesis, Place & Route)
39# Note: Uses --run-tag to create a predictable folder name for the GLS step
40harden:
41 @echo "\n=== [2/3] Running LibreLane Hardening ==="
42 $(LIBRELANE) --flow Classic \
43 --run-tag automated_run \
44 --overwrite \
45 $(CONFIG_FILE)
46 @echo ">>> Hardening Complete <<<"
47
48# 4. Gate-Level Simulation (GLS): Verifies the final GDSII netlist
49# Finds the netlist generated by the 'harden' step
50GL_NETLIST = runs/automated_run/final/nl/$(PROJECT_NAME).nl.v
51
52gls:
53 @echo "\n=== [3/3] Running Gate-Level Simulation (GLS) ==="
54 $(VERILATOR) $(VERILATOR_FLAGS) \
55 -DGL_SIM=1 -DFUNCTIONAL -DUNIT_DELAY=\#1 \
56 -I$(PDK_ROOT)/$(PDK)/libs.ref/sky130_fd_sc_hd/verilog \
57 rtl/tb_$(PROJECT_NAME).sv \
58 $(GL_NETLIST) \
59 $(LIB_VERILOG) $(PRIM_VERILOG)
60 ./obj_dir/Vtb_$(PROJECT_NAME)
61 @echo ">>> GLS Verification Passed <<<"
62
63# Clean up build artifacts
64clean:
65 rm -rf obj_dir runs/automated_run $(PROJECT_NAME).vcd
diff --git a/config.json b/config.json
new file mode 100644
index 0000000..0f2e115
--- /dev/null
+++ b/config.json
@@ -0,0 +1,6 @@
1{
2 "DESIGN_NAME": "lisp_coproc",
3 "VERILOG_FILES": ["dir::rtl/lisp_coproc.sv"],
4 "CLOCK_PERIOD": 100,
5 "CLOCK_PORT": "clk"
6}
diff --git a/rtl/lisp_coproc.sv b/rtl/lisp_coproc.sv
index 6bd8574..7d1c8a8 100644
--- a/rtl/lisp_coproc.sv
+++ b/rtl/lisp_coproc.sv
@@ -1,220 +1,251 @@
1`timescale 1ns/1ps // be consistent with testbench
2
3module lisp_coproc ( 1module lisp_coproc (
4 input wire clk, 2 input wire clk,
5 input wire rst, 3 input wire rst,
6 input wire cs, 4 input wire cs,
7 input wire rw, // 0=Write, 1=Read 5 input wire rw, // 0=Write, 1=Read
8 input wire [2:0] addr, 6 input wire [2:0] addr,
9 input wire [7:0] data_in, 7 input wire [7:0] data_in,
10 output reg [7:0] data_out 8 output reg [7:0] data_out
11); 9 );
12
13 // ========================================================================
14 // 1. DATAPATH Signals & Storage
15 // ========================================================================
16
17 // Registers
18 reg [7:0] opcode_reg, arg1_reg, arg2_reg, result_reg;
19 reg [7:0] heap [0:15];
20
21 // Bump Allocator: Uniform 4-bit register (0-15)
22 reg [3:0] bump_alloc;
23
24 // Heap Status: Sticky bit to track if we have wrapped around (Full)
25 reg heap_filled;
26
27 // Internal Flags (Transient for current OP)
28 reg flag_err_heap, flag_err_type, flag_carry, flag_zero;
29
30 // ALU Signals
31 wire [5:0] alu_val_a = arg1_reg[5:0];
32 wire [5:0] alu_val_b = arg2_reg[5:0];
33 wire [6:0] alu_sum = alu_val_a + alu_val_b;
34 wire alu_eq = (arg1_reg == arg2_reg);
35
36 // Type Checkers
37 wire is_cons_a = (arg1_reg[7:6] == 2'b11);
38 wire is_num_a = (arg1_reg[7:6] == 2'b10);
39 wire is_num_b = (arg2_reg[7:6] == 2'b10);
40
41 // Allocation Logic (Datapath Adder)
42 // We use a 5-bit wire to capture the carry out.
43 // If bump_alloc is 14 (1110) + 2 = 16 (10000).
44 // alloc_sum[4] (Carry) is 1. alloc_sum[3:0] is 0000.
45 wire [4:0] alloc_sum = {1'b0, bump_alloc} + 5'd2;
46 wire alloc_carry = alloc_sum[4];
47
48 // ========================================================================
49 // 2. FSM CONTROLLER
50 // ========================================================================
51
52 parameter [4:0] RESET = 5'b00001;
53 parameter [4:0] IDLE = 5'b00010;
54 parameter [4:0] DECODE = 5'b00100;
55 parameter [4:0] EXECUTE = 5'b01000;
56 parameter [4:0] WRITEBACK = 5'b10000;
57
58 reg [4:0] state, next_state;
59
60 always @(posedge clk or posedge rst) begin
61 if (rst) state <= RESET;
62 else state <= next_state;
63 end
64
65 always @(*) begin
66 next_state = state;
67 case (state)
68 RESET: next_state = IDLE;
69 IDLE: if (cs && !rw && addr == 3'h0) next_state = DECODE;
70 DECODE: next_state = EXECUTE;
71 EXECUTE: next_state = WRITEBACK;
72 WRITEBACK: next_state = IDLE;
73 default: next_state = IDLE;
74 endcase
75 end
76
77 // ========================================================================
78 // 3. SEQUENTIAL LOGIC
79 // ========================================================================
80
81 integer i;
82 always @(posedge clk or posedge rst) begin
83 if (rst) begin
84 opcode_reg <= 8'h00;
85 arg1_reg <= 8'h00;
86 arg2_reg <= 8'h00;
87 result_reg <= 8'h00;
88 bump_alloc <= 4'h0;
89 heap_filled <= 1'b0;
90
91 flag_err_heap <= 1'b0;
92 flag_err_type <= 1'b0;
93 flag_carry <= 1'b0;
94 flag_zero <= 1'b0;
95
96 for (i=0; i<16; i=i+1) heap[i] <= 8'h00;
97
98 end else begin
99
100 // --- MMIO Writes ---
101 if (cs && !rw) begin
102 case (addr)
103 3'h0: opcode_reg <= data_in;
104 3'h1: arg1_reg <= data_in;
105 3'h2: arg2_reg <= data_in;
106 3'h3: result_reg <= data_in;
107 default: ;
108 endcase
109 end
110
111 // --- State Actions ---
112 case (state)
113 RESET: begin
114 bump_alloc <= 4'h0;
115 heap_filled <= 1'b0;
116 end
117 10
118 IDLE: begin 11 // ========================================================================
119 if (cs && !rw && addr == 3'h0) begin 12 // 1. DATAPATH Signals & Storage
120 flag_err_heap <= 1'b0; 13 // ========================================================================
121 flag_err_type <= 1'b0; 14
122 flag_carry <= 1'b0; 15 // Registers
123 flag_zero <= 1'b0; 16 reg [7:0] opcode_reg, arg1_reg, arg2_reg, result_reg;
124 end 17 reg [7:0] heap [0:15];
125 end 18
19 // Bump Allocator: Uniform 4-bit register (0-15)
20 reg [3:0] bump_alloc;
21
22 // Heap Status: Sticky bit to track if we have wrapped around (Full)
23 reg heap_filled;
24
25 // Internal Flags (Transient for current OP)
26 reg flag_err_heap, flag_err_type, flag_carry, flag_zero;
27
28 // ALU Signals
29 wire [5:0] alu_val_a = arg1_reg[5:0];
30 wire [5:0] alu_val_b = arg2_reg[5:0];
31 wire [6:0] alu_sum = alu_val_a + alu_val_b;
32 wire alu_eq = (arg1_reg == arg2_reg);
33
34 // Type Checkers
35 wire is_cons_a = (arg1_reg[7:6] == 2'b11);
36 wire is_num_a = (arg1_reg[7:6] == 2'b10);
37 wire is_num_b = (arg2_reg[7:6] == 2'b10);
38
39 // Allocation Logic (Datapath Adder)
40 // We use a 5-bit wire to capture the carry out.
41 // If bump_alloc is 14 (1110) + 2 = 16 (10000).
42 // alloc_sum[4] (Carry) is 1. alloc_sum[3:0] is 0000.
43 wire [4:0] alloc_sum = {1'b0, bump_alloc} + 5'd2;
44 wire alloc_carry = alloc_sum[4];
126 45
127 EXECUTE: begin 46 // ========================================================================
128 case (opcode_reg) 47 // 2. FSM CONTROLLER (Safe Binary Encoding)
129 8'h01: begin // CONS 48 // ========================================================================
130 if (heap_filled) begin 49
131 // If sticky flag is set, we are full. Error. 50 // Explicit 3-bit encoding avoids optimization ambiguity
132 flag_err_heap <= 1'b1; 51 localparam [2:0] RESET = 3'd0;
133 end else begin 52 localparam [2:0] IDLE = 3'd1;
134 // Perform allocation 53 localparam [2:0] DECODE = 3'd2;
135 heap[bump_alloc] <= arg1_reg; 54 localparam [2:0] EXECUTE = 3'd3;
136 heap[bump_alloc + 1] <= arg2_reg; 55 localparam [2:0] WRITEBACK = 3'd4;
137
138 // Update pointer (wraps automatically due to 4-bit)
139 bump_alloc <= alloc_sum[3:0];
140
141 // If we generated a carry (14->16), mark heap as filled
142 if (alloc_carry) heap_filled <= 1'b1;
143 end
144 end
145 8'h02: begin // CAR
146 if (!is_cons_a) flag_err_type <= 1'b1;
147 end
148 8'h03: begin // CDR
149 if (!is_cons_a) flag_err_type <= 1'b1;
150 end
151 8'h05: begin // EQ
152 if (alu_eq) flag_zero <= 1'b1;
153 end
154 8'h06: begin // ADD
155 if (!is_num_a || !is_num_b) begin
156 flag_err_type <= 1'b1;
157 end else begin
158 if (alu_sum[6]) flag_carry <= 1'b1;
159 if (alu_sum[5:0] == 6'd0) flag_zero <= 1'b1;
160 end
161 end
162 default: ;
163 endcase
164 end
165 56
166 WRITEBACK: begin 57 reg [2:0] state, next_state;
167 case (opcode_reg) 58 reg busy_bit;
168 8'h01: begin // CONS 59
169 if (!flag_err_heap) 60 // Sequential Logic
170 // Math trick: If bump_alloc wrapped to 0, 61 always @(posedge clk or posedge rst) begin
171 // 0 - 2 = 14 (1110 in 2's comp), which is the correct pointer. 62 if (rst) state <= RESET;
172 result_reg <= {2'b11, 2'b00, bump_alloc - 4'd2}; 63 else state <= next_state;
173 end 64 end
174 8'h02: begin // CAR 65
175 if (!flag_err_type) result_reg <= heap[arg1_reg[3:0]]; 66 // Combinational Next-State Logic
176 end 67 always @(*) begin
177 8'h03: begin // CDR 68 // 1. Default assignments to prevent latches
178 if (!flag_err_type) result_reg <= heap[arg1_reg[3:0] + 1]; 69 next_state = IDLE; // Default to IDLE (Safe recovery)
179 end 70 busy_bit = 1'b1; // Default to BUSY
180 8'h04: begin // ATOM 71
181 result_reg <= is_cons_a ? 8'h00 : 8'h41; 72 case (state)
182 end 73 RESET: begin
183 8'h05: begin // EQ 74 next_state = IDLE;
184 result_reg <= alu_eq ? 8'h41 : 8'h00; 75 busy_bit = 1'b1;
185 end 76 end
186 8'h06: begin // ADD 77
187 if (!flag_err_type) result_reg <= {2'b10, alu_sum[5:0]}; 78 IDLE: begin
188 end 79 busy_bit = 1'b0; // Not Busy
189 default: ; 80 // Transition Logic
190 endcase 81 if (cs && !rw && addr == 3'h0)
191 end 82 next_state = DECODE;
192 default: ; 83 else
193 endcase 84 next_state = IDLE;
85 end
86
87 DECODE: begin
88 next_state = EXECUTE;
89 busy_bit = 1'b1;
90 end
91
92 EXECUTE: begin
93 next_state = WRITEBACK;
94 busy_bit = 1'b1;
95 end
96
97 WRITEBACK: begin
98 next_state = IDLE;
99 busy_bit = 1'b1;
100 end
101
102 default: begin
103 next_state = IDLE;
104 busy_bit = 1'b1;
194 end 105 end
195 end 106 endcase
196 107 end
197 // ======================================================================== 108
198 // 4. OUTPUT LOGIC 109 // ========================================================================
199 // ======================================================================== 110 // 3. SEQUENTIAL LOGIC
200 111 // ========================================================================
201 wire busy_bit = (state != IDLE); 112
202 // Note: bit 1 is the transient error flag, not the internal sticky state 113 integer i;
203 wire [7:0] current_status = {3'b000, flag_zero, flag_carry, flag_err_type, flag_err_heap, busy_bit}; 114 always @(posedge clk or posedge rst) begin
204 115 if (rst) begin
205 always @(*) begin 116 opcode_reg <= 8'h00;
206 if (cs && rw) begin 117 arg1_reg <= 8'h00;
118 arg2_reg <= 8'h00;
119 result_reg <= 8'h00;
120 bump_alloc <= 4'h0;
121 heap_filled <= 1'b0;
122
123 flag_err_heap <= 1'b0;
124 flag_err_type <= 1'b0;
125 flag_carry <= 1'b0;
126 flag_zero <= 1'b0;
127
128 for (i=0; i<16; i=i+1) heap[i] <= 8'h00;
129
130 end else begin
131
132 // --- MMIO Writes ---
133 if (cs && !rw) begin
207 case (addr) 134 case (addr)
208 3'h0: data_out = opcode_reg; 135 3'h0: opcode_reg <= data_in;
209 3'h1: data_out = arg1_reg; 136 3'h1: arg1_reg <= data_in;
210 3'h2: data_out = arg2_reg; 137 3'h2: arg2_reg <= data_in;
211 3'h3: data_out = result_reg; 138 3'h3: result_reg <= data_in;
212 3'h4: data_out = current_status; 139 default: ;
213 default: data_out = 8'h00;
214 endcase 140 endcase
215 end else begin 141 end
216 data_out = 8'hZZ; 142
217 end 143 // --- State Actions ---
218 end 144 case (state)
145 RESET: begin
146 bump_alloc <= 4'h0;
147 heap_filled <= 1'b0;
148 end
149
150 IDLE: begin
151 if (cs && !rw && addr == 3'h0) begin
152 flag_err_heap <= 1'b0;
153 flag_err_type <= 1'b0;
154 flag_carry <= 1'b0;
155 flag_zero <= 1'b0;
156 end
157 end
158
159 EXECUTE: begin
160 case (opcode_reg)
161 8'h01: begin // CONS
162 if (heap_filled) begin
163 // If sticky flag is set, we are full. Error.
164 flag_err_heap <= 1'b1;
165 end else begin
166 // Perform allocation
167 heap[bump_alloc] <= arg1_reg;
168 heap[(bump_alloc + 1) % 16] <= arg2_reg;
169
170 // Update pointer (wraps automatically due to 4-bit)
171 bump_alloc <= alloc_sum[3:0];
172
173 // If we generated a carry (14->16), mark heap as filled
174 if (alloc_carry) heap_filled <= 1'b1;
175 end
176 end
177 8'h02: begin // CAR
178 if (!is_cons_a) flag_err_type <= 1'b1;
179 end
180 8'h03: begin // CDR
181 if (!is_cons_a) flag_err_type <= 1'b1;
182 end
183 8'h05: begin // EQ
184 if (alu_eq) flag_zero <= 1'b1;
185 end
186 8'h06: begin // ADD
187 if (!is_num_a || !is_num_b) begin
188 flag_err_type <= 1'b1;
189 end else begin
190 if (alu_sum[6]) flag_carry <= 1'b1;
191 if (alu_sum[5:0] == 6'd0) flag_zero <= 1'b1;
192 end
193 end
194 default: ;
195 endcase
196 end
197
198 WRITEBACK: begin
199 case (opcode_reg)
200 8'h01: begin // CONS
201 if (!flag_err_heap)
202 // Math trick: If bump_alloc wrapped to 0,
203 // 0 - 2 = 14 (1110 in 2's comp), which is the correct pointer.
204 result_reg <= {2'b11, 2'b00, bump_alloc - 4'd2};
205 end
206 8'h02: begin // CAR
207 if (!flag_err_type) result_reg <= heap[arg1_reg[3:0]];
208 end
209 8'h03: begin // CDR
210 if (!flag_err_type) result_reg <= heap[arg1_reg[3:0] + 1];
211 end
212 8'h04: begin // ATOM
213 result_reg <= is_cons_a ? 8'h00 : 8'h41;
214 end
215 8'h05: begin // EQ
216 result_reg <= alu_eq ? 8'h41 : 8'h00;
217 end
218 8'h06: begin // ADD
219 if (!flag_err_type) result_reg <= {2'b10, alu_sum[5:0]};
220 end
221 default: ;
222 endcase
223 end
224 default: ;
225 endcase
226 end
227 end
228
229 // ========================================================================
230 // 4. OUTPUT LOGIC
231 // ========================================================================
232
233 // Status Register: [7:5]Rsrv, [4]Zero, [3]Carry, [2]Type, [1]Heap, [0]Busy
234 wire [7:0] current_status = {3'b000, flag_zero, flag_carry, flag_err_type, flag_err_heap, busy_bit};
235
236 always @(*) begin
237 if (cs && rw) begin
238 case (addr)
239 3'h0: data_out = opcode_reg;
240 3'h1: data_out = arg1_reg;
241 3'h2: data_out = arg2_reg;
242 3'h3: data_out = result_reg;
243 3'h4: data_out = current_status;
244 default: data_out = 8'h00;
245 endcase
246 end else begin
247 data_out = 8'h00; // Drive 0 instead of Z to satisfy internal logic checks
248 end
249 end
219 250
220endmodule 251endmodule
diff --git a/rtl/tb_lisp_coproc.sv b/rtl/tb_lisp_coproc.sv
index 08e3627..4e7b28d 100644
--- a/rtl/tb_lisp_coproc.sv
+++ b/rtl/tb_lisp_coproc.sv
@@ -2,305 +2,322 @@
2 2
3module tb_lisp_coproc; 3module tb_lisp_coproc;
4 4
5 // ======================================================================== 5 // ========================================================================
6 // 1. CONFIGURATION & CONSTANTS 6 // 1. CONFIGURATION & CONSTANTS
7 // ======================================================================== 7 // ========================================================================
8 8
9 // Opcodes 9 // Opcodes
10 localparam [7:0] OP_CONS = 8'h01; 10 localparam [7:0] OP_CONS = 8'h01;
11 localparam [7:0] OP_CAR = 8'h02; 11 localparam [7:0] OP_CAR = 8'h02;
12 localparam [7:0] OP_CDR = 8'h03; 12 localparam [7:0] OP_CDR = 8'h03;
13 localparam [7:0] OP_ATOM = 8'h04; 13 localparam [7:0] OP_ATOM = 8'h04;
14 localparam [7:0] OP_EQ = 8'h05; 14 localparam [7:0] OP_EQ = 8'h05;
15 localparam [7:0] OP_ADD = 8'h06; 15 localparam [7:0] OP_ADD = 8'h06;
16 16
17 // Tags 17 // Tags
18 localparam [1:0] TAG_NIL = 2'b00; 18 localparam [1:0] TAG_NIL = 2'b00;
19 localparam [1:0] TAG_ATOM = 2'b01; 19 localparam [1:0] TAG_ATOM = 2'b01;
20 localparam [1:0] TAG_NUM = 2'b10; 20 localparam [1:0] TAG_NUM = 2'b10;
21 localparam [1:0] TAG_CONS = 2'b11; 21 localparam [1:0] TAG_CONS = 2'b11;
22 22
23 // Standard Values for Testing 23 // Standard Values for Testing
24 localparam [7:0] VAL_NIL = {TAG_NIL, 6'h00}; 24 localparam [7:0] VAL_NIL = {TAG_NIL, 6'h00};
25 localparam [7:0] VAL_TRUE = {TAG_ATOM, 6'h01}; // 'T' 25 localparam [7:0] VAL_TRUE = {TAG_ATOM, 6'h01}; // 'T'
26 localparam [7:0] VAL_A = {TAG_ATOM, 6'h0A}; 26 localparam [7:0] VAL_A = {TAG_ATOM, 6'h0A};
27 localparam [7:0] VAL_B = {TAG_ATOM, 6'h0B}; 27 localparam [7:0] VAL_B = {TAG_ATOM, 6'h0B};
28 localparam [7:0] VAL_C = {TAG_ATOM, 6'h0C}; 28 localparam [7:0] VAL_C = {TAG_ATOM, 6'h0C};
29 29
30 // Testbench Signals 30 // Testbench Signals
31 reg clk, rst, cs, rw; 31 reg clk, rst, cs, rw;
32 reg [2:0] addr; 32 reg [2:0] addr;
33 reg [7:0] data_in; 33 reg [7:0] data_in;
34 wire [7:0] data_out; 34 wire [7:0] data_out;
35 35
36 // Verification Variables 36 // Verification Variables
37 reg [7:0] read_val; 37 reg [7:0] read_val;
38 reg [7:0] status_val; 38 reg [7:0] status_val;
39 reg [7:0] ptr_node3, ptr_node2, ptr_node1; 39 reg [7:0] ptr_node3, ptr_node2, ptr_node1;
40 integer errors = 0; 40 integer errors = 0;
41 integer i; 41 integer i;
42 42
43 // Instantiate DUT 43 // Instantiate DUT
44 lisp_coproc dut ( 44 lisp_coproc dut (
45 .clk(clk), .rst(rst), .cs(cs), .rw(rw), 45 .clk(clk), .rst(rst), .cs(cs), .rw(rw),
46 .addr(addr), .data_in(data_in), .data_out(data_out) 46 .addr(addr), .data_in(data_in), .data_out(data_out)
47 ); 47 );
48 48
49 // Clock Generation (100MHz) 49 // Clock Generation (10MHz)
50 initial begin 50 initial begin
51 clk = 0; 51 clk = 0;
52 forever #5 clk = ~clk; 52 forever #50 clk = ~clk;
53 end 53 end
54 54
55 // ======================================================================== 55 // ========================================================================
56 // 2. HELPER TASKS 56 // 2. HELPER TASKS
57 // ======================================================================== 57 // ========================================================================
58 58
59 task cpu_write(input [2:0] w_addr, input [7:0] w_data); 59 task cpu_write(input [2:0] w_addr, input [7:0] w_data);
60 begin 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 integer timeout;
71 begin
72 timeout = 0;
73 // Poll Status Bit 0 (BUSY)
74 do begin
61 @(posedge clk); 75 @(posedge clk);
62 cs = 1; rw = 0; addr = w_addr; data_in = w_data; 76 cs = 1; rw = 1; addr = 3'h4; // Status
63 @(posedge clk); 77 @(posedge clk);
64 cs = 0; data_in = 8'h00; 78 status_val = data_out;
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; 79 cs = 0;
86 end 80
87 endtask 81 // Panic button: Break if stuck for 100 cycles
88 82 timeout = timeout + 1;
89 task check(input [7:0] expected, input [7:0] actual, input string name); 83 if (timeout > 100) begin
90 if (expected !== actual) begin 84 $display("ERROR: Timed out polling BUSY bit! Status: %b", status_val);
91 $display("FAIL: %s | Exp: 0x%h, Got: 0x%h", name, expected, actual); 85 break;
92 errors = errors + 1; 86 end
93 end else begin 87 end while (status_val[0] === 1'b1);
94 $display("PASS: %s", name); 88
95 end 89 // Perform Read
96 endtask 90 @(posedge clk);
97 91 cs = 1;
98 task check_status(input bit exp_heap, input bit exp_type, input bit exp_carry, input bit exp_zero, input string name); 92 rw = 1; addr = r_addr;
99 // Status Reg: [7:5]Rsrv, [4]Zero, [3]Carry, [2]Type, [1]Heap, [0]Busy 93 @(posedge clk);
100 reg [7:0] expected_mask; 94 r_data = data_out;
101 expected_mask = {3'b000, exp_zero, exp_carry, exp_type, exp_heap, 1'b0}; 95 cs = 0;
102 96 end
103 cpu_exec_and_read(3'h4, status_val); 97 endtask
104 // Mask out the busy bit for comparison as it should be 0 now 98
105 if ((status_val & 8'hFE) !== expected_mask) begin 99 task check(input [7:0] expected, input [7:0] actual, input string name);
106 $display("FAIL: %s (Status) | Exp: %b, Got: %b", name, expected_mask, status_val); 100 if (expected !== actual) begin
107 errors = errors + 1; 101 $display("FAIL: %s | Exp: 0x%h, Got: 0x%h", name, expected, actual);
108 end else begin 102 errors = errors + 1;
109 $display("PASS: %s (Status)", name); 103 end else begin
110 end 104 $display("PASS: %s", name);
111 endtask 105 end
112 106 endtask
113 // ======================================================================== 107
114 // 3. MAIN TEST SCENARIOS 108 task check_status(input bit exp_heap, input bit exp_type, input bit exp_carry, input bit exp_zero, input string name);
115 // ======================================================================== 109 // Status Reg: [7:5]Rsrv, [4]Zero, [3]Carry, [2]Type, [1]Heap, [0]Busy
116 110 reg [7:0] expected_mask;
117 initial begin 111 expected_mask = {3'b000, exp_zero, exp_carry, exp_type, exp_heap, 1'b0};
118 $dumpfile("lisp_coproc_robust.vcd"); 112
119 $dumpvars(0, tb_lisp_coproc); 113 cpu_exec_and_read(3'h4, status_val);
120 114 // Mask out the busy bit for comparison as it should be 0 now
121 // --- Initialize --- 115 if ((status_val & 8'hFE) !== expected_mask) begin
122 rst = 1; cs = 0; rw = 0; addr = 0; data_in = 0; 116 $display("FAIL: %s (Status) | Exp: %b, Got: %b", name, expected_mask, status_val);
123 #20 rst = 0; #20; 117 errors = errors + 1;
124 $display("\n=== STARTING ROBUST VERIFICATION ===\n"); 118 end else begin
125 119 $display("PASS: %s (Status)", name);
126 // -------------------------------------------------------- 120 end
127 // SCENARIO 1: ALU Boundary & Overflow 121 endtask
128 // -------------------------------------------------------- 122
129 $display("--- Scenario 1: ALU Mathematics ---"); 123 // ========================================================================
130 124 // 3. MAIN TEST SCENARIOS
131 // 1.1 Simple Add: 10 + 15 = 25 125 // ========================================================================
132 cpu_write(3'h1, {TAG_NUM, 6'd10}); 126
133 cpu_write(3'h2, {TAG_NUM, 6'd15}); 127 initial begin
134 cpu_write(3'h0, OP_ADD); 128 $dumpfile("lisp_coproc.vcd");
135 cpu_exec_and_read(3'h3, read_val); 129 $dumpvars(0, tb_lisp_coproc);
136 check({TAG_NUM, 6'd25}, read_val, "Add 10+15"); 130
137 check_status(0,0,0,0, "Add Normal Status"); 131 // --- Initialize ---
138 132 clk = 0;
139 // 1.2 Zero Check: 0 + 0 = 0 (Should set Zero flag) 133 cs = 0; rw = 0; addr = 0; data_in = 0;
140 cpu_write(3'h1, {TAG_NUM, 6'd0}); 134
141 cpu_write(3'h2, {TAG_NUM, 6'd0}); 135 // --- AGGRESSIVE RESET SEQUENCE ---
142 cpu_write(3'h0, OP_ADD); 136 rst = 1; // Assert Reset
143 cpu_exec_and_read(3'h3, read_val); 137 #500; // Hold for 50 cycles (allows X propagation to clear)
144 check({TAG_NUM, 6'd0}, read_val, "Add 0+0"); 138 rst = 0; // Release Reset
145 check_status(0,0,0,1, "Add Zero Status"); // Expect Zero=1 139 #100; // Wait for logic to settle into IDLE
146 140
147 // 1.3 Overflow Check: 63 + 1 = 0 (Should set Carry flag) 141 $display("\n=== STARTING VERIFICATION ===\n");
148 // Max 6-bit unsigned is 63. 63+1 wraps to 0. 142
149 cpu_write(3'h1, {TAG_NUM, 6'd63}); 143 // --------------------------------------------------------
150 cpu_write(3'h2, {TAG_NUM, 6'd1}); 144 // SCENARIO 1: ALU Boundary & Overflow
151 cpu_write(3'h0, OP_ADD); 145 // --------------------------------------------------------
152 cpu_exec_and_read(3'h3, read_val); 146 $display("--- Scenario 1: ALU Mathematics ---");
153 check({TAG_NUM, 6'd0}, read_val, "Add 63+1 (Wrap)"); 147
154 check_status(0,0,1,1, "Add Overflow Status"); // Expect Carry=1, Zero=1 148 // 1.1 Simple Add: 10 + 15 = 25
155 149 cpu_write(3'h1, {TAG_NUM, 6'd10});
156 // -------------------------------------------------------- 150 cpu_write(3'h2, {TAG_NUM, 6'd15});
157 // SCENARIO 2: Equality (EQ) Logic 151 cpu_write(3'h0, OP_ADD);
158 // -------------------------------------------------------- 152 cpu_exec_and_read(3'h3, read_val);
159 $display("\n--- Scenario 2: EQ Logic ---"); 153 check({TAG_NUM, 6'd25}, read_val, "Add 10+15");
160 154 check_status(0,0,0,0, "Add Normal Status");
161 // 2.1 Atom Equality (True) 155
162 cpu_write(3'h1, VAL_A); 156 // 1.2 Zero Check: 0 + 0 = 0 (Should set Zero flag)
163 cpu_write(3'h2, VAL_A); 157 cpu_write(3'h1, {TAG_NUM, 6'd0});
164 cpu_write(3'h0, OP_EQ); 158 cpu_write(3'h2, {TAG_NUM, 6'd0});
165 cpu_exec_and_read(3'h3, read_val); 159 cpu_write(3'h0, OP_ADD);
166 check(VAL_TRUE, read_val, "EQ(A, A)"); 160 cpu_exec_and_read(3'h3, read_val);
167 check_status(0,0,0,1, "EQ True Status"); // Zero flag used for equality? Spec says "ZERO (From ADD or EQ op)" 161 check({TAG_NUM, 6'd0}, read_val, "Add 0+0");
168 162 check_status(0,0,0,1, "Add Zero Status"); // Expect Zero=1
169 // 2.2 Atom Inequality (False) 163
170 cpu_write(3'h1, VAL_A); 164 // 1.3 Overflow Check: 63 + 1 = 0 (Should set Carry flag)
171 cpu_write(3'h2, VAL_B); 165 // Max 6-bit unsigned is 63. 63+1 wraps to 0.
172 cpu_write(3'h0, OP_EQ); 166 cpu_write(3'h1, {TAG_NUM, 6'd63});
173 cpu_exec_and_read(3'h3, read_val); 167 cpu_write(3'h2, {TAG_NUM, 6'd1});
174 check(VAL_NIL, read_val, "EQ(A, B)"); 168 cpu_write(3'h0, OP_ADD);
175 check_status(0,0,0,0, "EQ False Status"); 169 cpu_exec_and_read(3'h3, read_val);
176 170 check({TAG_NUM, 6'd0}, read_val, "Add 63+1 (Wrap)");
177 // 2.3 Mixed Type Equality (Number 10 vs Atom 10) -> Should be NIL (Bits differ in Tag) 171 check_status(0,0,1,1, "Add Overflow Status"); // Expect Carry=1, Zero=1
178 cpu_write(3'h1, {TAG_NUM, 6'd10}); 172
179 cpu_write(3'h2, {TAG_ATOM, 6'd10}); 173 // --------------------------------------------------------
180 cpu_write(3'h0, OP_EQ); 174 // SCENARIO 2: Equality (EQ) Logic
181 cpu_exec_and_read(3'h3, read_val); 175 // --------------------------------------------------------
182 check(VAL_NIL, read_val, "EQ(Num, Atom)"); 176 $display("\n--- Scenario 2: EQ Logic ---");
183 177
184 // -------------------------------------------------------- 178 // 2.1 Atom Equality (True)
185 // SCENARIO 3: Linked List Construction (Chain Verification) 179 cpu_write(3'h1, VAL_A);
186 // -------------------------------------------------------- 180 cpu_write(3'h2, VAL_A);
187 $display("\n--- Scenario 3: Linked List (A B C) ---"); 181 cpu_write(3'h0, OP_EQ);
188 // Goal: Construct (A . (B . (C . NIL))) 182 cpu_exec_and_read(3'h3, read_val);
189 // Steps: 183 check(VAL_TRUE, read_val, "EQ(A, A)");
190 // 1. Node3 = CONS(C, NIL) 184 check_status(0,0,0,1, "EQ True Status"); // Zero flag used for equality? Spec says "ZERO (From ADD or EQ op)"
191 // 2. Node2 = CONS(B, Node3) 185
192 // 3. Node1 = CONS(A, Node2) 186 // 2.2 Atom Inequality (False)
193 187 cpu_write(3'h1, VAL_A);
194 // Step 1: Node 3 188 cpu_write(3'h2, VAL_B);
195 cpu_write(3'h1, VAL_C); 189 cpu_write(3'h0, OP_EQ);
196 cpu_write(3'h2, VAL_NIL); 190 cpu_exec_and_read(3'h3, read_val);
197 cpu_write(3'h0, OP_CONS); 191 check(VAL_NIL, read_val, "EQ(A, B)");
198 cpu_exec_and_read(3'h3, ptr_node3); 192 check_status(0,0,0,0, "EQ False Status");
199 check({TAG_CONS, 2'b00, 4'h0}, ptr_node3, "Alloc Node 3 (Ptr=0)"); 193
200 194 // 2.3 Mixed Type Equality (Number 10 vs Atom 10) -> Should be NIL (Bits differ in Tag)
201 // Step 2: Node 2 195 cpu_write(3'h1, {TAG_NUM, 6'd10});
202 cpu_write(3'h1, VAL_B); 196 cpu_write(3'h2, {TAG_ATOM, 6'd10});
203 cpu_write(3'h2, ptr_node3); 197 cpu_write(3'h0, OP_EQ);
204 cpu_write(3'h0, OP_CONS); 198 cpu_exec_and_read(3'h3, read_val);
205 cpu_exec_and_read(3'h3, ptr_node2); 199 check(VAL_NIL, read_val, "EQ(Num, Atom)");
206 check({TAG_CONS, 2'b00, 4'h2}, ptr_node2, "Alloc Node 2 (Ptr=2)"); 200
207 201 // --------------------------------------------------------
208 // Step 3: Node 1 202 // SCENARIO 3: Linked List Construction (Chain Verification)
209 cpu_write(3'h1, VAL_A); 203 // --------------------------------------------------------
210 cpu_write(3'h2, ptr_node2); 204 $display("\n--- Scenario 3: Linked List (A B C) ---");
211 cpu_write(3'h0, OP_CONS); 205 // Goal: Construct (A . (B . (C . NIL)))
212 cpu_exec_and_read(3'h3, ptr_node1); 206 // Steps:
213 check({TAG_CONS, 2'b00, 4'h4}, ptr_node1, "Alloc Node 1 (Ptr=4)"); 207 // 1. Node3 = CONS(C, NIL)
214 208 // 2. Node2 = CONS(B, Node3)
215 // Step 4: Traverse! CAR(CDR(ptr_node1)) should be B 209 // 3. Node1 = CONS(A, Node2)
216 210
217 // CDR(Node1) -> Should get Node2 Ptr 211 // Step 1: Node 3
218 cpu_write(3'h1, ptr_node1); 212 cpu_write(3'h1, VAL_C);
219 cpu_write(3'h0, OP_CDR); 213 cpu_write(3'h2, VAL_NIL);
220 cpu_exec_and_read(3'h3, read_val); 214 cpu_write(3'h0, OP_CONS);
221 check(ptr_node2, read_val, "Traverse: CDR(Node1)"); 215 cpu_exec_and_read(3'h3, ptr_node3);
222 216 check({TAG_CONS, 2'b00, 4'h0}, ptr_node3, "Alloc Node 3 (Ptr=0)");
223 // CAR(Result) -> Should get B 217
224 cpu_write(3'h1, read_val); 218 // Step 2: Node 2
225 cpu_write(3'h0, OP_CAR); 219 cpu_write(3'h1, VAL_B);
226 cpu_exec_and_read(3'h3, read_val); 220 cpu_write(3'h2, ptr_node3);
227 check(VAL_B, read_val, "Traverse: CAR(Node2)"); 221 cpu_write(3'h0, OP_CONS);
228 222 cpu_exec_and_read(3'h3, ptr_node2);
229 // -------------------------------------------------------- 223 check({TAG_CONS, 2'b00, 4'h2}, ptr_node2, "Alloc Node 2 (Ptr=2)");
230 // SCENARIO 4: Error Type Matrix 224
231 // -------------------------------------------------------- 225 // Step 3: Node 1
232 $display("\n--- Scenario 4: Type Safety ---"); 226 cpu_write(3'h1, VAL_A);
233 227 cpu_write(3'h2, ptr_node2);
234 // 4.1 CAR on ATOM (Fail) 228 cpu_write(3'h0, OP_CONS);
235 cpu_write(3'h1, VAL_A); 229 cpu_exec_and_read(3'h3, ptr_node1);
236 cpu_write(3'h0, OP_CAR); 230 check({TAG_CONS, 2'b00, 4'h4}, ptr_node1, "Alloc Node 1 (Ptr=4)");
237 check_status(0,1,0,0, "Err: CAR on Atom"); // Expect ErrType=1 231
238 232 // Step 4: Traverse! CAR(CDR(ptr_node1)) should be B
239 // 4.2 CDR on NUMBER (Fail) 233
240 cpu_write(3'h1, {TAG_NUM, 6'd5}); 234 // CDR(Node1) -> Should get Node2 Ptr
241 cpu_write(3'h0, OP_CDR); 235 cpu_write(3'h1, ptr_node1);
242 check_status(0,1,0,0, "Err: CDR on Number"); 236 cpu_write(3'h0, OP_CDR);
243 237 cpu_exec_and_read(3'h3, read_val);
244 // 4.3 ADD on CONS (Fail) 238 check(ptr_node2, read_val, "Traverse: CDR(Node1)");
245 cpu_write(3'h1, {TAG_NUM, 6'd5}); 239
246 cpu_write(3'h2, ptr_node1); 240 // CAR(Result) -> Should get B
247 cpu_write(3'h0, OP_ADD); 241 cpu_write(3'h1, read_val);
248 check_status(0,1,0,0, "Err: ADD on CONS"); 242 cpu_write(3'h0, OP_CAR);
249 243 cpu_exec_and_read(3'h3, read_val);
250 // -------------------------------------------------------- 244 check(VAL_B, read_val, "Traverse: CAR(Node2)");
251 // SCENARIO 5: Heap Full Boundary 245
252 // -------------------------------------------------------- 246 // --------------------------------------------------------
253 $display("\n--- Scenario 5: Heap Full Boundary ---"); 247 // SCENARIO 4: Error Type Matrix
254 248 // --------------------------------------------------------
255 // Current Alloc Pointer is at 6 (We did 3 CONS ops: 0, 2, 4). 249 $display("\n--- Scenario 4: Type Safety ---");
256 // Capacity is 16. Addresses 6, 8, 10, 12, 14 are free. 250
257 // That is 5 more CONS operations allowed. 251 // 4.1 CAR on ATOM (Fail)
258 252 cpu_write(3'h1, VAL_A);
259 // Fill 1 (Ptr 6) 253 cpu_write(3'h0, OP_CAR);
260 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); 254 check_status(0,1,0,0, "Err: CAR on Atom"); // Expect ErrType=1
261 cpu_exec_and_read(3'h3, read_val); // Wait 255
262 256 // 4.2 CDR on NUMBER (Fail)
263 // Fill 2 (Ptr 8) 257 cpu_write(3'h1, {TAG_NUM, 6'd5});
264 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); 258 cpu_write(3'h0, OP_CDR);
265 cpu_exec_and_read(3'h3, read_val); 259 check_status(0,1,0,0, "Err: CDR on Number");
266 260
267 // Fill 3 (Ptr 10) 261 // 4.3 ADD on CONS (Fail)
268 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); 262 cpu_write(3'h1, {TAG_NUM, 6'd5});
269 cpu_exec_and_read(3'h3, read_val); 263 cpu_write(3'h2, ptr_node1);
270 264 cpu_write(3'h0, OP_ADD);
271 // Fill 4 (Ptr 12) 265 check_status(0,1,0,0, "Err: ADD on CONS");
272 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); 266
273 cpu_exec_and_read(3'h3, read_val); 267 // --------------------------------------------------------
274 268 // SCENARIO 5: Heap Full Boundary
275 // Fill 5 (Ptr 14) - THE LAST VALID ONE 269 // --------------------------------------------------------
276 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); 270 $display("\n--- Scenario 5: Heap Full Boundary ---");
277 cpu_exec_and_read(3'h3, read_val); 271
278 check({TAG_CONS, 2'b00, 4'hE}, read_val, "Last Valid Alloc (Ptr=14)"); 272 // Current Alloc Pointer is at 6 (We did 3 CONS ops: 0, 2, 4).
279 check_status(0,0,0,0, "Status at Capacity"); 273 // Capacity is 16. Addresses 6, 8, 10, 12, 14 are free.
280 274 // That is 5 more CONS operations allowed.
281 // ATTEMPT OVERFLOW 275
282 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); 276 // Fill 1 (Ptr 6)
283 277 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
284 // Check Status 278 cpu_exec_and_read(3'h3, read_val); // Wait
285 cpu_exec_and_read(3'h4, status_val); 279
286 // Expect ErrHeap=1 280 // Fill 2 (Ptr 8)
287 if (status_val[1] !== 1'b1) begin 281 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
288 $display("FAIL: Heap Full Detection | Got Status: %b", status_val); 282 cpu_exec_and_read(3'h3, read_val);
289 errors = errors + 1; 283
290 end else begin 284 // Fill 3 (Ptr 10)
291 $display("PASS: Heap Full Detection"); 285 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
292 end 286 cpu_exec_and_read(3'h3, read_val);
293 287
294 // -------------------------------------------------------- 288 // Fill 4 (Ptr 12)
295 // RESULT SUMMARY 289 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
296 // -------------------------------------------------------- 290 cpu_exec_and_read(3'h3, read_val);
297 $display("\n=================================="); 291
298 if (errors == 0) 292 // Fill 5 (Ptr 14) - THE LAST VALID ONE
299 $display(" SUCCESS: All Tests Passed"); 293 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
300 else 294 cpu_exec_and_read(3'h3, read_val);
301 $display(" FAILURE: %0d Errors Found", errors); 295 check({TAG_CONS, 2'b00, 4'hE}, read_val, "Last Valid Alloc (Ptr=14)");
302 $display("=================================="); 296 check_status(0,0,0,0, "Status at Capacity");
303 $finish; 297
304 end 298 // ATTEMPT OVERFLOW
299 cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS);
300
301 // Check Status
302 cpu_exec_and_read(3'h4, status_val);
303 // Expect ErrHeap=1
304 if (status_val[1] !== 1'b1) begin
305 $display("FAIL: Heap Full Detection | Got Status: %b", status_val);
306 errors = errors + 1;
307 end else begin
308 $display("PASS: Heap Full Detection");
309 end
310
311 // --------------------------------------------------------
312 // RESULT SUMMARY
313 // --------------------------------------------------------
314 $display("\n==================================");
315 if (errors == 0)
316 $display(" SUCCESS: All Tests Passed");
317 else
318 $display(" FAILURE: %0d Errors Found", errors);
319 $display("==================================");
320 $finish;
321 end
305 322
306endmodule 323endmodule
diff --git a/vlsi/tb_chip_core.v b/vlsi/tb_chip_core.v
index 66fa212..b4a8925 100644
--- a/vlsi/tb_chip_core.v
+++ b/vlsi/tb_chip_core.v
@@ -115,13 +115,13 @@ module tb_chip_core;
115 // ======================================================================== 115 // ========================================================================
116 116
117 initial begin 117 initial begin
118 $dumpfile("chip_core_robust.vcd"); 118 $dumpfile("chip_core.vcd");
119 $dumpvars(0, tb_chip_core); 119 $dumpvars(0, tb_chip_core);
120 120
121 // --- Initialize --- 121 // --- Initialize ---
122 rst = 1; cs = 0; rw = 0; addr = 0; data_in = 0; 122 rst = 1; cs = 0; rw = 0; addr = 0; data_in = 0;
123 #20 rst = 0; #20; 123 #20 rst = 0; #20;
124 $display("\n=== STARTING ROBUST VERIFICATION ===\n"); 124 $display("\n=== STARTING VERIFICATION ===\n");
125 125
126 // -------------------------------------------------------- 126 // --------------------------------------------------------
127 // SCENARIO 1: ALU Boundary & Overflow 127 // SCENARIO 1: ALU Boundary & Overflow