diff options
| author | vin <git@vineetk.net> | 2025-11-20 12:01:31 -0500 |
|---|---|---|
| committer | vin <git@vineetk.net> | 2025-11-20 12:01:31 -0500 |
| commit | 1c7666facade946e9fd58ce779789e50994ec4a2 (patch) | |
| tree | ae7bd51b4dcf6a7626fd91b6b085a6e7abcba32e /rtl | |
| parent | 46303e07e9bda309cb451aa824680db9bdd19fe8 (diff) | |
add more comprehensive test bench
Diffstat (limited to 'rtl')
| -rw-r--r-- | rtl/tb_lisp_coproc.sv | 348 |
1 files changed, 254 insertions, 94 deletions
diff --git a/rtl/tb_lisp_coproc.sv b/rtl/tb_lisp_coproc.sv index aa721fc..08e3627 100644 --- a/rtl/tb_lisp_coproc.sv +++ b/rtl/tb_lisp_coproc.sv | |||
| @@ -2,52 +2,82 @@ | |||
| 2 | 2 | ||
| 3 | module tb_lisp_coproc; | 3 | module tb_lisp_coproc; |
| 4 | 4 | ||
| 5 | // Signals | 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 | ||
| 6 | reg clk, rst, cs, rw; | 31 | reg clk, rst, cs, rw; |
| 7 | reg [2:0] addr; | 32 | reg [2:0] addr; |
| 8 | reg [7:0] data_in; | 33 | reg [7:0] data_in; |
| 9 | wire [7:0] data_out; | 34 | wire [7:0] data_out; |
| 10 | 35 | ||
| 11 | // Verification Vars | 36 | // Verification Variables |
| 12 | reg [7:0] read_data; | 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; | ||
| 13 | integer i; | 41 | integer i; |
| 14 | 42 | ||
| 15 | // DUT Instance | 43 | // Instantiate DUT |
| 16 | lisp_coproc dut ( | 44 | lisp_coproc dut ( |
| 17 | .clk(clk), .rst(rst), .cs(cs), .rw(rw), | 45 | .clk(clk), .rst(rst), .cs(cs), .rw(rw), |
| 18 | .addr(addr), .data_in(data_in), .data_out(data_out) | 46 | .addr(addr), .data_in(data_in), .data_out(data_out) |
| 19 | ); | 47 | ); |
| 20 | 48 | ||
| 21 | // 100MHz Clock | 49 | // Clock Generation (100MHz) |
| 22 | initial begin | 50 | initial begin |
| 23 | clk = 0; | 51 | clk = 0; |
| 24 | forever #5 clk = ~clk; | 52 | forever #5 clk = ~clk; |
| 25 | end | 53 | end |
| 26 | 54 | ||
| 27 | // --- CPU Bus Tasks --- | 55 | // ======================================================================== |
| 28 | 56 | // 2. HELPER TASKS | |
| 57 | // ======================================================================== | ||
| 58 | |||
| 29 | 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); |
| 30 | begin | 60 | begin |
| 31 | @(posedge clk); | 61 | @(posedge clk); |
| 32 | cs = 1; rw = 0; addr = w_addr; data_in = w_data; | 62 | cs = 1; rw = 0; addr = w_addr; data_in = w_data; |
| 33 | @(posedge clk); | 63 | @(posedge clk); |
| 34 | cs = 0; data_in = 8'h00; // Clear bus | 64 | cs = 0; data_in = 8'h00; |
| 35 | end | 65 | end |
| 36 | endtask | 66 | endtask |
| 37 | 67 | ||
| 38 | task cpu_read(input [2:0] r_addr, output [7:0] r_data); | 68 | // Read with auto-polling for BUSY flag |
| 39 | reg [7:0] stat; | 69 | task cpu_exec_and_read(input [2:0] r_addr, output [7:0] r_data); |
| 40 | begin | 70 | begin |
| 41 | // 1. Poll Status for BUSY=0 | 71 | // Poll Status Bit 0 (BUSY) |
| 42 | do begin | 72 | do begin |
| 43 | @(posedge clk); | 73 | @(posedge clk); |
| 44 | cs = 1; rw = 1; addr = 3'h4; // Status Reg | 74 | cs = 1; rw = 1; addr = 3'h4; // Status |
| 45 | @(posedge clk); | 75 | @(posedge clk); |
| 46 | stat = data_out; | 76 | status_val = data_out; |
| 47 | cs = 0; | 77 | cs = 0; |
| 48 | end while (stat[0] == 1'b1); | 78 | end while (status_val[0] === 1'b1); |
| 49 | 79 | ||
| 50 | // 2. Perform Actual Read | 80 | // Perform Read |
| 51 | @(posedge clk); | 81 | @(posedge clk); |
| 52 | cs = 1; rw = 1; addr = r_addr; | 82 | cs = 1; rw = 1; addr = r_addr; |
| 53 | @(posedge clk); | 83 | @(posedge clk); |
| @@ -55,92 +85,222 @@ module tb_lisp_coproc; | |||
| 55 | cs = 0; | 85 | cs = 0; |
| 56 | end | 86 | end |
| 57 | endtask | 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 | ||
| 58 | 97 | ||
| 59 | // --- Main Test Sequence --- | 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 | |||
| 60 | initial begin | 117 | initial begin |
| 61 | $dumpfile("lisp_coproc.vcd"); | 118 | $dumpfile("lisp_coproc_robust.vcd"); |
| 62 | $dumpvars(0, tb_lisp_coproc); | 119 | $dumpvars(0, tb_lisp_coproc); |
| 63 | 120 | ||
| 64 | // Init | 121 | // --- Initialize --- |
| 65 | rst = 1; cs = 0; rw = 0; addr = 0; data_in = 0; | 122 | rst = 1; cs = 0; rw = 0; addr = 0; data_in = 0; |
| 66 | #20 rst = 0; #20; | 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 ---"); | ||
| 67 | 130 | ||
| 68 | $display("--- Starting Lisp Coprocessor Verification ---"); | 131 | // 1.1 Simple Add: 10 + 15 = 25 |
| 69 | 132 | cpu_write(3'h1, {TAG_NUM, 6'd10}); | |
| 70 | // 1. Reset Test | 133 | cpu_write(3'h2, {TAG_NUM, 6'd15}); |
| 71 | cpu_read(3'h4, read_data); | 134 | cpu_write(3'h0, OP_ADD); |
| 72 | assert_equals(8'h00, read_data, "Reset Status"); | 135 | cpu_exec_and_read(3'h3, read_val); |
| 73 | 136 | check({TAG_NUM, 6'd25}, read_val, "Add 10+15"); | |
| 74 | // 2. ADD Test (5 + 6 = 11) | 137 | check_status(0,0,0,0, "Add Normal Status"); |
| 75 | $display("\n[Test] ADD Operation"); | 138 | |
| 76 | cpu_write(3'h1, 8'h85); // Number(5) | 139 | // 1.2 Zero Check: 0 + 0 = 0 (Should set Zero flag) |
| 77 | cpu_write(3'h2, 8'h86); // Number(6) | 140 | cpu_write(3'h1, {TAG_NUM, 6'd0}); |
| 78 | cpu_write(3'h0, 8'h06); // OPCODE: ADD | 141 | cpu_write(3'h2, {TAG_NUM, 6'd0}); |
| 79 | cpu_read(3'h3, read_data); | 142 | cpu_write(3'h0, OP_ADD); |
| 80 | assert_equals(8'h8B, read_data, "ADD Result (11)"); | 143 | cpu_exec_and_read(3'h3, read_val); |
| 81 | cpu_read(3'h4, read_data); | 144 | check({TAG_NUM, 6'd0}, read_val, "Add 0+0"); |
| 82 | assert_equals(8'h00, read_data, "ADD Status (Clean)"); | 145 | check_status(0,0,0,1, "Add Zero Status"); // Expect Zero=1 |
| 83 | 146 | ||
| 84 | // 3. CONS Test | 147 | // 1.3 Overflow Check: 63 + 1 = 0 (Should set Carry flag) |
| 85 | $display("\n[Test] CONS Operation"); | 148 | // Max 6-bit unsigned is 63. 63+1 wraps to 0. |
| 86 | cpu_write(3'h1, 8'h41); // Atom('T') | 149 | cpu_write(3'h1, {TAG_NUM, 6'd63}); |
| 87 | cpu_write(3'h2, 8'h42); // Atom('B') | 150 | cpu_write(3'h2, {TAG_NUM, 6'd1}); |
| 88 | cpu_write(3'h0, 8'h01); // OPCODE: CONS | 151 | cpu_write(3'h0, OP_ADD); |
| 89 | cpu_read(3'h3, read_data); | 152 | cpu_exec_and_read(3'h3, read_val); |
| 90 | // Expect CONS Tag (11) | Address (0000) -> 0xC0 | 153 | check({TAG_NUM, 6'd0}, read_val, "Add 63+1 (Wrap)"); |
| 91 | assert_equals(8'hC0, read_data, "CONS Pointer"); | 154 | check_status(0,0,1,1, "Add Overflow Status"); // Expect Carry=1, Zero=1 |
| 92 | 155 | ||
| 93 | // Verify Heap Persistence via CAR/CDR | 156 | // -------------------------------------------------------- |
| 94 | cpu_write(3'h1, 8'hC0); // Pointer to just allocated cell | 157 | // SCENARIO 2: Equality (EQ) Logic |
| 95 | cpu_write(3'h0, 8'h02); // OPCODE: CAR | 158 | // -------------------------------------------------------- |
| 96 | cpu_read(3'h3, read_data); | 159 | $display("\n--- Scenario 2: EQ Logic ---"); |
| 97 | assert_equals(8'h41, read_data, "CAR Check"); | 160 | |
| 98 | 161 | // 2.1 Atom Equality (True) | |
| 99 | cpu_write(3'h1, 8'hC0); | 162 | cpu_write(3'h1, VAL_A); |
| 100 | cpu_write(3'h0, 8'h03); // OPCODE: CDR | 163 | cpu_write(3'h2, VAL_A); |
| 101 | cpu_read(3'h3, read_data); | 164 | cpu_write(3'h0, OP_EQ); |
| 102 | assert_equals(8'h42, read_data, "CDR Check"); | 165 | cpu_exec_and_read(3'h3, read_val); |
| 103 | 166 | check(VAL_TRUE, read_val, "EQ(A, A)"); | |
| 104 | // 4. Error Test (Type Error) | 167 | check_status(0,0,0,1, "EQ True Status"); // Zero flag used for equality? Spec says "ZERO (From ADD or EQ op)" |
| 105 | $display("\n[Test] Error Handling (Type)"); | 168 | |
| 106 | cpu_write(3'h1, 8'h85); // Number | 169 | // 2.2 Atom Inequality (False) |
| 107 | cpu_write(3'h0, 8'h02); // OPCODE: CAR (Invalid on Number) | 170 | cpu_write(3'h1, VAL_A); |
| 108 | cpu_read(3'h4, read_data); | 171 | cpu_write(3'h2, VAL_B); |
| 109 | // Bit 2 (ERR_TYPE) should be set -> 0x04 | 172 | cpu_write(3'h0, OP_EQ); |
| 110 | assert_equals(8'h04, read_data, "Error Type Flag"); | 173 | cpu_exec_and_read(3'h3, read_val); |
| 111 | 174 | check(VAL_NIL, read_val, "EQ(A, B)"); | |
| 112 | // 5. Heap Full Test | 175 | check_status(0,0,0,0, "EQ False Status"); |
| 113 | $display("\n[Test] Heap Full Error"); | 176 | |
| 114 | // We used 2 cells (1 CONS). 14 cells remain. | 177 | // 2.3 Mixed Type Equality (Number 10 vs Atom 10) -> Should be NIL (Bits differ in Tag) |
| 115 | // Loop 7 times to fill exactly to 16. | 178 | cpu_write(3'h1, {TAG_NUM, 6'd10}); |
| 116 | for(i=0; i<7; i=i+1) begin | 179 | cpu_write(3'h2, {TAG_ATOM, 6'd10}); |
| 117 | cpu_write(3'h1, 8'h41); | 180 | cpu_write(3'h0, OP_EQ); |
| 118 | cpu_write(3'h2, 8'h42); | 181 | cpu_exec_and_read(3'h3, read_val); |
| 119 | cpu_write(3'h0, 8'h01); // CONS | 182 | check(VAL_NIL, read_val, "EQ(Num, Atom)"); |
| 120 | cpu_read(3'h3, read_data); // Sync | 183 | |
| 121 | end | 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 ---"); | ||
| 122 | 254 | ||
| 123 | // Try 8th CONS -> Should fail | 255 | // Current Alloc Pointer is at 6 (We did 3 CONS ops: 0, 2, 4). |
| 124 | cpu_write(3'h1, 8'hAA); | 256 | // Capacity is 16. Addresses 6, 8, 10, 12, 14 are free. |
| 125 | cpu_write(3'h2, 8'hBB); | 257 | // That is 5 more CONS operations allowed. |
| 126 | cpu_write(3'h0, 8'h01); // CONS | ||
| 127 | 258 | ||
| 128 | cpu_read(3'h4, read_data); | 259 | // Fill 1 (Ptr 6) |
| 129 | // Bit 1 (ERR_HEAP) should be set -> 0x02 | 260 | cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); |
| 130 | assert_equals(8'h02, read_data, "Heap Full Flag"); | 261 | cpu_exec_and_read(3'h3, read_val); // Wait |
| 131 | 262 | ||
| 132 | $display("\n--- All Tests Passed Successfully ---"); | 263 | // Fill 2 (Ptr 8) |
| 133 | $finish; | 264 | cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); |
| 134 | end | 265 | cpu_exec_and_read(3'h3, read_val); |
| 135 | 266 | ||
| 136 | // Helper task for reporting | 267 | // Fill 3 (Ptr 10) |
| 137 | task assert_equals(input [7:0] expected, input [7:0] actual, input string name); | 268 | cpu_write(3'h1, VAL_NIL); cpu_write(3'h2, VAL_NIL); cpu_write(3'h0, OP_CONS); |
| 138 | if (expected !== actual) begin | 269 | cpu_exec_and_read(3'h3, read_val); |
| 139 | $display("ERROR: %s failed. Expected 0x%h, Got 0x%h", name, expected, actual); | 270 | |
| 140 | $finish; | 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; | ||
| 141 | end else begin | 290 | end else begin |
| 142 | $display("PASS: %s", name); | 291 | $display("PASS: Heap Full Detection"); |
| 143 | end | 292 | end |
| 144 | endtask | 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 | ||
| 145 | 305 | ||
| 146 | endmodule | 306 | endmodule |
