summaryrefslogtreecommitdiff
path: root/hdl/core.sv
diff options
context:
space:
mode:
Diffstat (limited to 'hdl/core.sv')
-rw-r--r--hdl/core.sv484
1 files changed, 254 insertions, 230 deletions
diff --git a/hdl/core.sv b/hdl/core.sv
index eceea78..43a4a1a 100644
--- a/hdl/core.sv
+++ b/hdl/core.sv
@@ -8,6 +8,9 @@ module core
8 , input bit reset 8 , input bit reset
9 9
10 , input bit switch_cont 10 , input bit switch_cont
11 , input bit switch_stop
12 , input bit switch_sing_step
13 , input bit switch_sing_inst
11 14
12 // verilator lint_off UNDRIVEN 15 // verilator lint_off UNDRIVEN
13 , output bit [ADDR_BITS-1:0] led_pc 16 , output bit [ADDR_BITS-1:0] led_pc
@@ -40,6 +43,7 @@ module core
40 ); 43 );
41 44
42bit run; 45bit run;
46bit switch_cont_observed;
43assign led_run = run; 47assign led_run = run;
44 48
45bit mem_ready; 49bit mem_ready;
@@ -47,6 +51,7 @@ bit mem_valid;
47bit mem_write; 51bit mem_write;
48bit [ADDR_BITS-1:0] mem_address; 52bit [ADDR_BITS-1:0] mem_address;
49bit [DATA_BITS-1:0] mem_write_data; 53bit [DATA_BITS-1:0] mem_write_data;
54assign led_current_address = mem_valid;
50 55
51assign led_df = 0; 56assign led_df = 0;
52assign led_if = 0; 57assign led_if = 0;
@@ -106,7 +111,6 @@ bit [8:0] operand;
106bit [DATA_BITS-1:0] acc; 111bit [DATA_BITS-1:0] acc;
107bit link; 112bit link;
108 113
109assign led_pc = pc;
110assign led_acc = acc; 114assign led_acc = acc;
111assign led_link = link; 115assign led_link = link;
112 116
@@ -147,17 +151,28 @@ assign led_pause = state == MEMWAIT || state == HALT;
147always_ff @(posedge clk) begin 151always_ff @(posedge clk) begin
148 if (reset) begin 152 if (reset) begin
149 run = 0; 153 run = 0;
154 switch_cont_observed = 0;
150 mem_valid = 0; 155 mem_valid = 0;
151 rx_ready = 0; 156 rx_ready = 0;
152 tx_valid = 0; 157 tx_valid = 0;
153 tx_data = 0; 158 tx_data = 0;
154 pc = 'o200; 159 pc = 'o200;
160 led_pc = pc;
155 acc = 0; 161 acc = 0;
156 link = 1; 162 link = 1;
157 kbd_valid = 0; 163 kbd_valid = 0;
158 state = state.first; 164 state = state.first;
159 end else if (run || switch_cont) begin 165 end else begin
160 run = 1; 166 if (switch_cont && !switch_cont_observed) begin
167 run = 1;
168 switch_cont_observed = 1;
169 end
170
171 if (!switch_cont)
172 switch_cont_observed = 0;
173
174 if (switch_stop)
175 run = 0;
161 176
162 if (`lag(tx_ready)) tx_valid = 0; 177 if (`lag(tx_ready)) tx_valid = 0;
163 if (rx_ready && `lag(rx_valid)) begin 178 if (rx_ready && `lag(rx_valid)) begin
@@ -165,259 +180,268 @@ always_ff @(posedge clk) begin
165 kbd_data = {4'b0, 1'b1, `lag(rx_data[6:0])}; 180 kbd_data = {4'b0, 1'b1, `lag(rx_data[6:0])};
166 end 181 end
167 182
168 case (state) 183 if (run) begin
169 FETCH: begin 184 case (state)
170 mem_valid = 1; 185 FETCH: begin
171 mem_address = pc; 186 mem_valid = 1;
172 mem_write = 0; 187 mem_address = pc;
173 if (`lag(mem_ready)) begin 188 mem_write = 0;
174 state = DECODE; 189 if (`lag(mem_ready)) begin
175 page = pc[ADDR_BITS-1:7]; 190 state = DECODE;
176 ++pc; 191 page = pc[ADDR_BITS-1:7];
192 led_pc = pc;
193 ++pc;
194 end
177 end 195 end
178 end
179 196
180 DECODE: begin 197 DECODE: begin
181 mem_valid = 0; 198 mem_valid = 0;
182 mem_write = 0; 199 mem_write = 0;
183 if (`lag(mem_read_valid)) begin 200 if (`lag(mem_read_valid)) begin
184 state = FETCH; 201 state = FETCH;
185 led_memdata = `lag(mem_read_data); 202 led_memdata = `lag(mem_read_data);
186 {opcode, operand} = `lag(mem_read_data); 203 {opcode, operand} = `lag(mem_read_data);
187// $display("%o: decode %o %o", pc-1, opcode, operand); 204 // $display("%o: decode %o %o", pc-1, opcode, operand);
188 // verilator lint_off WIDTH 205 // verilator lint_off WIDTH
189// $display("%o %b %o 0000", 14'(pc-1), link, acc); 206 // $display("%o %b %o 0000", 14'(pc-1), link, acc);
190 // verilator lint_on WIDTH 207 // verilator lint_on WIDTH
191 {i, z, wip} = operand; 208 {i, z, wip} = operand;
192 if (z) 209 if (z)
193 address = {page, wip}; 210 address = {page, wip};
194 else 211 else
195 address = {5'b0, wip}; 212 address = {5'b0, wip};
196 case (opcode) 213 case (opcode)
197 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN; 214 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN;
198 'o3, 'o4: state = i ? INDIRECT : EXEC; 215 'o3, 'o4: state = i ? INDIRECT : EXEC;
199 'o5: begin 216 'o5: begin
200 if (i) begin 217 if (i) begin
201 state = INDIRECT; 218 state = INDIRECT;
202 end else begin 219 end else begin
203 pc = address; 220 pc = address;
204 end
205 end
206 'o7: begin
207 casez (operand)
208 'b0????????: begin
209 automatic bit cla, cll, cma, cml, rar, ral, bsw, iac;
210 {cla, cll, cma, cml, rar, ral, bsw, iac} = operand[7:0];
211 if (cla) acc = 0;
212 if (cll) link = 0;
213 if (cma) acc = ~acc;
214 if (cml) link = ~link;
215 if (iac) {link, acc} += 1;
216 if (rar && !ral) begin
217 {link, acc} = {acc[0], link, acc[11:1]};
218 if (bsw) {link, acc} = {acc[0], link, acc[11:1]};
219 end
220 if (ral && !rar) begin
221 {link, acc} = {acc, link};
222 if (bsw) {link, acc} = {acc, link};
223 end
224 if (bsw && !(rar || ral)) acc = {acc[5:0], acc[11:6]};
225 end
226 'b1????0??0: begin
227 automatic bit cla, sma, sza, snl, osr, hlt;
228 automatic bit skip;
229 {cla, sma, sza, snl, osr, hlt} = {operand[7:4], operand[2:1]};
230 skip = 0;
231 if (sma && acc[11]) skip = 1;
232 if (sza && acc == 0) skip = 1;
233 if (snl && link != 0) skip = 1;
234 if (skip) pc++;
235 if (cla) acc = 0;
236 if (osr) begin
237 $display("%o: unsupported front panel switch test", pc);
238 $finish;
239 end
240 if (hlt) state = HALT;
241 end
242 'b1????1??0: begin
243 automatic bit cla, spa, sna, szl, osr, hlt;
244 automatic bit skip;
245 {cla, spa, sna, szl, osr, hlt} = {operand[7:4], operand[2:1]};
246 skip = 1;
247 if (spa && acc[11]) skip = 0;
248 if (sna && acc == 0) skip = 0;
249 if (szl && link != 0) skip = 0;
250 if (skip) pc++;
251 if (cla) acc = 0;
252 if (osr) begin
253 $display("%o: unsupported front panel switch test", pc);
254 $finish;
255 end
256 if (hlt) state = HALT;
257 end
258 default: begin
259 $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand);
260 $finish;
261 end
262 endcase
263 end
264 'o6: begin
265 case (operand[8:3])
266 'o00: begin
267 case (operand[2:0])
268 'o0, 'o1: ;
269 default: $display("%o: unsupported 600%o op", pc-1, operand[2:0]);
270 endcase
271 end 221 end
272 'o03: begin 222 end
273 case (operand[2:0]) 223 'o7: begin
274 'o1: if (kbd_valid) pc++; 224 casez (operand)
275 'o6: begin 225 'b0????????: begin
276 acc = kbd_data; 226 automatic bit cla, cll, cma, cml, rar, ral, bsw, iac;
277 kbd_valid = 0; 227 {cla, cll, cma, cml, rar, ral, bsw, iac} = operand[7:0];
228 if (cla) acc = 0;
229 if (cll) link = 0;
230 if (cma) acc = ~acc;
231 if (cml) link = ~link;
232 if (iac) {link, acc} += 1;
233 if (rar && !ral) begin
234 {link, acc} = {acc[0], link, acc[11:1]};
235 if (bsw) {link, acc} = {acc[0], link, acc[11:1]};
278 end 236 end
279 default: begin 237 if (ral && !rar) begin
280 $display("%o: unsupported keyboard op %o", pc-1, operand[2:0]); 238 {link, acc} = {acc, link};
281 $finish; 239 if (bsw) {link, acc} = {acc, link};
282 end 240 end
283 endcase 241 if (bsw && !(rar || ral)) acc = {acc[5:0], acc[11:6]};
284 end 242 end
285 'o04: begin 243 'b1????0??0: begin
286 case (operand[2:0]) 244 automatic bit cla, sma, sza, snl, osr, hlt;
287 'o1: if (!tx_valid) pc++; 245 automatic bit skip;
288 'o6: begin 246 {cla, sma, sza, snl, osr, hlt} = {operand[7:4], operand[2:1]};
289 tx_valid = 1; 247 skip = 0;
290 tx_data = {1'b0, acc[6:0]}; 248 if (sma && acc[11]) skip = 1;
249 if (sza && acc == 0) skip = 1;
250 if (snl && link != 0) skip = 1;
251 if (skip) pc++;
252 if (cla) acc = 0;
253 if (osr) begin
254 $display("%o: unsupported front panel switch test", pc);
255 $finish;
291 end 256 end
292 default: begin 257 if (hlt) state = HALT;
293 $display("%o: unsupported tty op %o", pc-1, operand[2:0]); 258 end
259 'b1????1??0: begin
260 automatic bit cla, spa, sna, szl, osr, hlt;
261 automatic bit skip;
262 {cla, spa, sna, szl, osr, hlt} = {operand[7:4], operand[2:1]};
263 skip = 1;
264 if (spa && acc[11]) skip = 0;
265 if (sna && acc == 0) skip = 0;
266 if (szl && link != 0) skip = 0;
267 if (skip) pc++;
268 if (cla) acc = 0;
269 if (osr) begin
270 $display("%o: unsupported front panel switch test", pc);
294 $finish; 271 $finish;
295 end 272 end
296 endcase 273 if (hlt) state = HALT;
297 end 274 end
298 default: begin 275 default: begin
299 $display("%o: unsupported device %o (operation %o)", pc-1, operand[8:3], operand[2:0]); 276 $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand);
277 $finish;
278 end
279 endcase
280 end
281 'o6: begin
282 case (operand[8:3])
283 'o00: begin
284 case (operand[2:0])
285 'o0, 'o1: ;
286 default: $display("%o: unsupported 600%o op", pc-1, operand[2:0]);
287 endcase
288 end
289 'o03: begin
290 case (operand[2:0])
291 'o1: if (kbd_valid) pc++;
292 'o6: begin
293 acc = kbd_data;
294 kbd_valid = 0;
295 end
296 default: begin
297 $display("%o: unsupported keyboard op %o", pc-1, operand[2:0]);
298 $finish;
299 end
300 endcase
301 end
302 'o04: begin
303 case (operand[2:0])
304 'o1: if (!tx_valid) pc++;
305 'o6: begin
306 tx_valid = 1;
307 tx_data = {1'b0, acc[6:0]};
308 end
309 default: begin
310 $display("%o: unsupported tty op %o", pc-1, operand[2:0]);
311 $finish;
312 end
313 endcase
314 end
315 default: begin
316 $display("%o: unsupported device %o (operation %o)", pc-1, operand[8:3], operand[2:0]);
317 end
318 endcase
319 end
320 default: begin
321 $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand);
322 $finish;
323 end
324 endcase
325 end
326 end
327
328 INDIRECT: begin
329 mem_valid = 1;
330 mem_write = 0;
331 mem_address = address;
332 state = `lag(mem_ready) ? INDIRECTED : INDIRECT;
333 end
334
335 INDIRECTED: begin
336 if (`lag(mem_ready)) begin
337 mem_valid = 0;
338 mem_write = 0;
339 end
340 if (`lag(mem_read_valid)) begin
341 if (address[7:3] == 5'b00001) begin
342 led_memdata = `lag(mem_read_data);
343 address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)};
344 address += 1;
345 state = PREINC;
346 end else begin
347 led_memdata = `lag(mem_read_data);
348 address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)};
349 case (opcode)
350 'o0, 'o1, 'o2: state = AGEN;
351 'o3, 'o4: state = EXEC;
352 'o5: begin
353 pc = address;
354 state = FETCH;
300 end 355 end
301 endcase 356 endcase
302 end 357 end
303 default: begin 358 end
304 $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand);
305 $finish;
306 end
307 endcase
308 end 359 end
309 end
310 360
311 INDIRECT: begin 361 PREINC: begin
312 mem_valid = 1; 362 mem_valid = 1;
313 mem_write = 0; 363 mem_write = 1;
314 mem_address = address; 364 mem_write_data = address[DATA_BITS-1:0];
315 state = `lag(mem_ready) ? INDIRECTED : INDIRECT; 365 led_memdata = mem_write_data;
316 end 366 case (opcode)
367 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC;
368 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC;
369 endcase
370 end
317 371
318 INDIRECTED: begin 372 AGEN: begin
319 if (`lag(mem_ready)) begin 373 mem_valid = 1;
320 mem_valid = 0; 374 case (opcode)
321 mem_write = 0; 375 'o0, 'o1, 'o2: mem_write = 0;
376 endcase
377 mem_address = address;
378 state = `lag(mem_ready) ? EXEC : AGEN;
322 end 379 end
323 if (`lag(mem_read_valid)) begin 380
324 if (address[7:3] == 5'b00001) begin 381 EXEC: begin
325 led_memdata = `lag(mem_read_data); 382 automatic bit stall = 0;
326 address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; 383 if (`lag(mem_ready)) begin
327 address += 1; 384 mem_valid = 0;
328 state = PREINC; 385 mem_write = 0;
329 end else begin 386 end else if (mem_valid) begin
330 led_memdata = `lag(mem_read_data); 387 stall = 1;
331 address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; 388 end
389 case (opcode)
390 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1;
391 endcase
392 if (! stall) begin
393 state = FETCH;
332 case (opcode) 394 case (opcode)
333 'o0, 'o1, 'o2: state = AGEN; 395 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end
334 'o3, 'o4: state = EXEC; 396 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end
335 'o5: begin 397 'o2: begin
336 pc = address; 398 mem_valid = 1;
337 state = FETCH; 399 mem_address = address;
400 mem_write = 1;
401 mem_write_data = `lag(mem_read_data) + 1;
402 led_memdata = mem_write_data;
403 if (mem_write_data == 0) ++pc;
404 state = MEMWAIT;
405 end
406 'o3: begin
407 mem_valid = 1;
408 mem_address = address;
409 mem_write = 1;
410 mem_write_data = acc;
411 led_memdata = mem_write_data;
412 acc = 0;
413 state = MEMWAIT;
338 end 414 end
415 'o4: begin
416 mem_valid = 1;
417 mem_address = address;
418 mem_write = 1;
419 mem_write_data = pc[DATA_BITS-1:0];
420 led_memdata = mem_write_data;
421 pc = address + 1;
422 state = MEMWAIT;
423 end
424 'o5: pc = address;
339 endcase 425 endcase
340 end 426 end
341 end 427 end
342 end
343
344 PREINC: begin
345 mem_valid = 1;
346 mem_write = 1;
347 mem_write_data = address[DATA_BITS-1:0];
348 led_memdata = mem_write_data;
349 case (opcode)
350 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC;
351 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC;
352 endcase
353 end
354 428
355 AGEN: begin 429 MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT;
356 mem_valid = 1;
357 case (opcode)
358 'o0, 'o1, 'o2: mem_write = 0;
359 endcase
360 mem_address = address;
361 state = `lag(mem_ready) ? EXEC : AGEN;
362 end
363 430
364 EXEC: begin 431 HALT: begin
365 automatic bit stall = 0; 432 $display("\nhalt state reached");
366 if (`lag(mem_ready)) begin 433 $finish;
367 mem_valid = 0;
368 mem_write = 0;
369 end else if (mem_valid) begin
370 stall = 1;
371 end 434 end
372 case (opcode) 435 endcase
373 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1;
374 endcase
375 if (! stall) begin
376 state = FETCH;
377 case (opcode)
378 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end
379 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end
380 'o2: begin
381 mem_valid = 1;
382 mem_address = address;
383 mem_write = 1;
384 mem_write_data = `lag(mem_read_data) + 1;
385 led_memdata = mem_write_data;
386 if (mem_write_data == 0) ++pc;
387 state = MEMWAIT;
388 end
389 'o3: begin
390 mem_valid = 1;
391 mem_address = address;
392 mem_write = 1;
393 mem_write_data = acc;
394 led_memdata = mem_write_data;
395 acc = 0;
396 state = MEMWAIT;
397 end
398 'o4: begin
399 mem_valid = 1;
400 mem_address = address;
401 mem_write = 1;
402 mem_write_data = pc[DATA_BITS-1:0];
403 led_memdata = mem_write_data;
404 pc = address + 1;
405 state = MEMWAIT;
406 end
407 'o5: pc = address;
408 endcase
409 end
410 end
411 436
412 MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT; 437 if (switch_sing_step)
438 run = 0;
413 439
414 HALT: begin 440 if (state == FETCH && switch_sing_inst)
415 $display("\nhalt state reached"); 441 run = 0;
416 $finish;
417 end
418 endcase
419 442
420 rx_ready = !kbd_valid; 443 rx_ready = !kbd_valid;
444 end
421 end 445 end
422end 446end
423 447