summaryrefslogtreecommitdiff
path: root/hdl
diff options
context:
space:
mode:
authorJulian Blake Kongslie2022-02-27 17:21:05 -0800
committerJulian Blake Kongslie2022-02-27 17:21:05 -0800
commit0553c4839c06011bd044f69b4913e5c793fdd2ec (patch)
treed11e69863532621fe1fa55cc7e8aa2a8cfa3b727 /hdl
downloadmultipdp8-0553c4839c06011bd044f69b4913e5c793fdd2ec.tar.xz
Initial commit.
Diffstat (limited to '')
-rw-r--r--hdl/command_parser.sv109
-rw-r--r--hdl/core.sv856
-rw-r--r--hdl/defs.svh58
-rw-r--r--hdl/echo_arbiter.sv64
-rw-r--r--hdl/front_panel.sv211
-rw-r--r--hdl/pll.sv126
-rw-r--r--hdl/ram_controller.sv240
-rw-r--r--hdl/result_printer.sv71
-rw-r--r--hdl/top.sv298
9 files changed, 2033 insertions, 0 deletions
diff --git a/hdl/command_parser.sv b/hdl/command_parser.sv
new file mode 100644
index 0000000..5c49db9
--- /dev/null
+++ b/hdl/command_parser.sv
@@ -0,0 +1,109 @@
1`include "defs.svh"
2
3module command_parser
4 #( TAG = 0
5 ) ( input bit clock
6 , input bit reset
7
8 , output bit uart_ready
9 , input bit uart_valid
10 , input uart_byte_t uart_data
11
12 , input bit echo_ready
13 , output bit echo_valid
14 , output uart_byte_t echo_data
15
16 , input bit command_ready
17 , output bit command_valid
18 , output ram_command_t command_data
19 );
20
21 bit input_byte_valid;
22 uart_byte_t input_byte;
23
24 (* syn_encoding = "one-hot" *) enum int unsigned
25 { READ_ADDRESS_OR_COMMAND
26 , READ_DATA
27 } state;
28
29 always @(posedge clock) begin
30 if (reset) begin
31 uart_ready = 0;
32 command_valid = 0;
33 input_byte_valid = 0;
34 input_byte = 0;
35 state = state.first;
36 end else begin
37 if (echo_ready) echo_valid = 0;
38 if (command_ready && command_valid) begin
39 command_valid = 0;
40 command_data.address = 0;
41 command_data.write = 0;
42 for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) begin
43 command_data.data[i] = 0;
44 command_data.mask[i] = ~0;
45 end
46 command_data.tag = TAG;
47 end
48 if (uart_ready && uart_valid) begin
49 echo_valid = 1;
50 echo_data = uart_data;
51 input_byte_valid = 1;
52 input_byte = uart_data;
53 end
54
55 if (!command_valid && input_byte_valid) begin
56 case (state)
57
58 READ_ADDRESS_OR_COMMAND: begin
59 if (input_byte >= "0" && input_byte <= "9") begin
60 command_data.address = command_data.address << 4;
61 command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "0";
62 end else if (input_byte >= "a" && input_byte <= "f") begin
63 command_data.address = command_data.address << 4;
64 command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "a" + 10;
65 end else if (input_byte >= "A" && input_byte <= "F") begin
66 command_data.address = command_data.address << 4;
67 command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "A" + 10;
68 end else if (input_byte == "?") begin
69 command_valid = 1;
70 command_data.write = 0;
71 command_data.data = 0;
72 end else if (input_byte == "=") begin
73 command_data.write = 1;
74 command_data.data = 0;
75 state = READ_DATA;
76 end else begin
77 command_data.address = 0;
78 command_data.write = 0;
79 command_data.data = 0;
80 end
81 end
82
83 READ_DATA: begin
84 automatic bit [$bits(command_data.data)-1:0] flat_data = command_data.data;
85 flat_data = flat_data << 4;
86 if (input_byte >= "0" && input_byte <= "9") begin
87 flat_data[3:0] = input_byte - "0";
88 command_data.data = flat_data;
89 end else if (input_byte >= "a" && input_byte <= "f") begin
90 flat_data[3:0] = input_byte - "a" + 10;
91 command_data.data = flat_data;
92 end else if (input_byte >= "A" && input_byte <= "F") begin
93 flat_data[3:0] = input_byte - "A" + 10;
94 command_data.data = flat_data;
95 end else begin
96 command_valid = 1;
97 state = state.first;
98 end
99 end
100
101 endcase
102 input_byte_valid = 0;
103 end
104
105 uart_ready = !echo_valid && !input_byte_valid;
106 end
107 end
108
109endmodule
diff --git a/hdl/core.sv b/hdl/core.sv
new file mode 100644
index 0000000..17b753d
--- /dev/null
+++ b/hdl/core.sv
@@ -0,0 +1,856 @@
1`ifdef SYNTHESIS
2`define lag(x) x
3`else
4`define lag(x) $past(x)
5`endif
6
7module mem
8 ( input bit clk
9 , input bit reset
10
11 , output bit ready
12 , input bit valid
13 , input bit write
14 , input bit [ADDR_BITS-1:0] address
15 , input bit [DATA_BITS-1:0] write_data
16
17 , output bit read_valid
18 , output bit [DATA_BITS-1:0] read_data
19 );
20
21parameter ADDR_BITS;
22parameter DATA_BITS;
23parameter INIT_FILE;
24
25bit [DATA_BITS-1:0] storage [0:(1<<ADDR_BITS)-1];
26initial $readmemh(INIT_FILE, storage);
27
28always_ff @(posedge clk) begin
29 if (reset) begin
30 ready = 0;
31 read_valid = 0;
32 end else begin
33 read_valid = 0;
34 if (ready && `lag(valid)) begin
35 if (`lag(write)) begin
36 storage[`lag(address)] = `lag(write_data);
37 end else begin
38 read_valid = 1;
39 read_data = storage[`lag(address)];
40 end
41 end
42 ready = 1;
43 end
44end
45
46endmodule
47
48module core
49 #( ADDR_BITS = 15
50 , DATA_BITS = 12
51 )
52 ( input bit clk
53 , input bit reset
54
55 , input bit [2:0] switch_df
56 , input bit [2:0] switch_if
57 , input bit [ADDR_BITS-3-1:0] switch_sr
58 , input bit switch_start
59 , input bit switch_load_add
60 , input bit switch_dep
61 , input bit switch_exam
62 , input bit switch_cont
63 , input bit switch_stop
64 , input bit switch_sing_step
65 , input bit switch_sing_inst
66
67 // verilator lint_off UNDRIVEN
68 , output bit [ADDR_BITS-3-1:0] led_pc
69 , output bit [ADDR_BITS-3-1:0] led_memaddr
70 , output bit [DATA_BITS-1:0] led_memdata
71 , output bit [DATA_BITS-1:0] led_acc
72 , output bit [DATA_BITS-1:0] led_mq
73 , output bit led_and
74 , output bit led_tad
75 , output bit led_isz
76 , output bit led_dca
77 , output bit led_jms
78 , output bit led_jmp
79 , output bit led_iot
80 , output bit led_opr
81 , output bit led_fetch
82 , output bit led_execute
83 , output bit led_defer
84 , output bit led_word_count
85 , output bit led_current_address
86 , output bit led_break
87 , output bit led_ion
88 , output bit led_pause
89 , output bit led_run
90 , output bit [4:0] led_step_counter
91 , output bit [2:0] led_df
92 , output bit [2:0] led_if
93 , output bit led_link
94 // verilator lint_on UNDRIVEN
95 );
96
97`ifndef SYNTHESIS
98integer pctrace;
99initial pctrace = $fopen("trace.pcs", "w");
100
101integer eventtrace;
102initial eventtrace = $fopen("trace.events", "r");
103
104// Event trace file format: lines of the form
105// instruction-count skip interrupt
106// Events are triggered before the corresponding instruction
107// Skip opcodes:
108// 0 Do not override skip behaviour of this instruction
109// 1 Force this instruction to "not skip"
110// 2 Force this instruction to "skip"
111// Interrupt opcodes:
112// 0 Do not force an interrupt this instruction
113// 1 Force an interrupt this instruction
114// The first instruction has instruction count 1
115
116integer unsigned nextevent = ~0;
117integer force_skip = 0;
118bit force_interrupt = 0;
119initial if (eventtrace != 0) $fscanf(eventtrace, "%d %d %d", nextevent, force_skip, force_interrupt);
120initial $display("nextevent=%d force_skip=%d force_interrupt=%d", nextevent, force_skip, force_interrupt);
121`endif
122
123bit run;
124bit int_enable;
125bit int_delay;
126bit int_request;
127
128bit switch_start_observed;
129bit switch_load_add_observed;
130bit switch_dep_observed;
131bit switch_exam_observed;
132bit switch_cont_observed;
133
134assign led_run = run;
135assign led_ion = int_enable;
136
137bit mem_ready;
138bit mem_valid;
139bit mem_write;
140bit [ADDR_BITS-1:0] mem_address;
141bit [DATA_BITS-1:0] mem_write_data;
142assign led_current_address = mem_valid;
143
144assign led_memaddr = mem_address[ADDR_BITS-3-1:0];
145
146bit mem_read_valid;
147bit [DATA_BITS-1:0] mem_read_data;
148
149mem
150 #( .ADDR_BITS(ADDR_BITS)
151 , .DATA_BITS(DATA_BITS)
152// , .INIT_FILE("mem/focal69.loaded.hex")
153 , .INIT_FILE("build/mem/hello.hex")
154 )
155 memory
156 ( .clk(clk)
157 , .reset(reset)
158
159 , .ready(mem_ready)
160 , .valid(mem_valid)
161 , .address(mem_address)
162 , .write(mem_write)
163 , .write_data(mem_write_data)
164
165 , .read_valid(mem_read_valid)
166 , .read_data(mem_read_data)
167 );
168
169bit rx_ready;
170bit rx_valid;
171bit [7:0] rx_data;
172
173bit tx_ready;
174bit tx_valid;
175bit [7:0] tx_data;
176
177alt_jtag_atlantic
178 #( .INSTANCE_ID(1)
179 , .LOG2_RXFIFO_DEPTH(6)
180 , .LOG2_TXFIFO_DEPTH(6)
181 , .SLD_AUTO_INSTANCE_INDEX("NO")
182 ) uart
183 ( .clk(clk)
184 , .rst_n(!reset)
185
186 , .r_dat(tx_data)
187 , .r_val(tx_valid)
188 , .r_ena(tx_ready)
189
190 , .t_dat(rx_data)
191 , .t_dav(rx_data)
192 , .t_ena(rx_valid)
193 );
194
195bit [ADDR_BITS-3-1:7] page;
196
197bit [2:0] data_field;
198bit [2:0] data_field_saved;
199bit [2:0] inst_field;
200bit [2:0] inst_field_buffer;
201bit [2:0] inst_field_saved;
202bit [ADDR_BITS-3-1:0] pc;
203bit [ADDR_BITS-3-1:0] next_pc;
204assign led_pc = pc;
205bit [2:0] opcode;
206bit [8:0] operand;
207bit [DATA_BITS-1:0] acc;
208bit link;
209
210assign led_df = data_field;
211assign led_if = inst_field;
212
213assign led_acc = acc;
214assign led_link = link;
215
216assign led_and = opcode == 0;
217assign led_tad = opcode == 1;
218assign led_isz = opcode == 2;
219assign led_dca = opcode == 3;
220assign led_jms = opcode == 4;
221assign led_jmp = opcode == 5;
222assign led_iot = opcode == 6;
223assign led_opr = opcode == 7;
224
225bit tti_int_enable;
226bit tti_valid;
227bit [DATA_BITS-1:0] tti_data;
228
229bit [15:0] tto_delay;
230bit tto_int_enable;
231bit tto_flag;
232bit tto_flag_old;
233
234bit i;
235bit z;
236bit [6:0] wip;
237bit [ADDR_BITS-1:0] address;
238
239bit can_skip;
240bit skip;
241bit injected_instruction;
242
243`ifndef SYNTHESIS
244integer unsigned instcount = 1;
245`endif
246
247assign int_request = 0
248 || (tti_int_enable && tti_valid)
249 || (tto_int_enable && tto_flag && !tto_flag_old)
250 ;
251
252enum
253 { FETCH
254 , DECODE
255 , INDIRECT
256 , INDIRECTED
257 , PREINC
258 , AGEN
259 , EXEC
260 , MEMWAIT
261 , HALT
262 , DEPOSIT
263 , RETIRE
264 } state;
265
266assign led_fetch = state == FETCH;
267assign led_execute = state == DECODE || state == AGEN || state == EXEC;
268assign led_defer = state == INDIRECT || state == INDIRECTED || state == PREINC;
269assign led_pause = state == MEMWAIT || state == HALT;
270
271always_ff @(posedge clk) begin
272 if (reset) begin
273`ifdef SYNTHESIS
274 run = 0;
275`else
276 run = 1;
277`endif
278 int_enable = 0;
279 int_delay = 0;
280 switch_start_observed = 0;
281 switch_load_add_observed = 0;
282 switch_dep_observed = 0;
283 switch_exam_observed = 0;
284 switch_cont_observed = 0;
285 mem_valid = 0;
286 rx_ready = 0;
287 tx_valid = 0;
288 tto_delay = 0;
289 tto_flag = 1;
290 tto_flag_old = 1;
291 tx_data = 0;
292 data_field = 0;
293 data_field_saved = 0;
294 inst_field = 0;
295 inst_field_buffer = 0;
296 inst_field_saved = 0;
297 pc = 'o200;
298 acc = 0;
299 link = 1;
300 tti_int_enable = 1;
301 tto_int_enable = 1;
302 tti_valid = 0;
303 state = state.first;
304 end else begin
305 if (switch_start && !switch_start_observed) begin
306 switch_start_observed = 1;
307 run = 1;
308 int_enable = 0;
309 int_delay = 0;
310 mem_valid = 0;
311 acc = 0;
312 link = 1;
313 state = state.first;
314 end
315
316 if (!switch_start)
317 switch_start_observed = 0;
318
319 if (switch_load_add && !switch_load_add_observed) begin
320 switch_load_add_observed = 1;
321 data_field = switch_df;
322 inst_field = switch_if;
323 inst_field_buffer = switch_if;
324 pc = switch_sr;
325 end
326
327 if (!switch_load_add)
328 switch_load_add_observed = 0;
329
330`ifdef HISTORIC_SWITCH_BEHAVIOUR
331 if (switch_dep)
332 switch_dep_observed = 1;
333
334 if (!switch_dep && switch_dep_observed) begin
335`else
336 if (switch_dep && !switch_dep_observed) begin
337 switch_dep_observed = 1;
338`endif
339 state = DEPOSIT;
340 mem_valid = 1;
341 mem_address = {inst_field, pc};
342 mem_write = 1;
343 mem_write_data = switch_sr;
344 led_memdata = mem_write_data;
345 run = 1;
346 end
347
348 if (!switch_dep)
349 switch_dep_observed = 0;
350
351 if (switch_exam && !switch_exam_observed) begin
352 if (!run) begin
353 switch_exam_observed = 1;
354 state = FETCH;
355 run = 1;
356 end
357 end
358
359 if (!switch_exam)
360 switch_exam_observed = 0;
361
362 if (switch_cont && !switch_cont_observed) begin
363 switch_cont_observed = 1;
364 run = 1;
365 end
366
367 if (!switch_cont)
368 switch_cont_observed = 0;
369
370 if (switch_stop)
371 run = 0;
372
373 if (`lag(tx_ready)) begin
374 if (tx_valid)
375 tto_flag = 1;
376 tx_valid = 0;
377 end
378 if (tto_delay == 1)
379 tx_valid = 1;
380 if (tto_delay != 0)
381 --tto_delay;
382 if (rx_ready && `lag(rx_valid)) begin
383 tti_valid = 1;
384 tti_data = {4'b0, 1'b1, `lag(rx_data[6:0])};
385 if (tti_data[6:0] == 7'h0a)
386 tti_data[6:0] = 7'h0d;
387 else if (tti_data[6:0] == 7'h1b)
388 tti_data[6:0] = 7'h03;
389 end
390
391 if (run) begin
392 case (state)
393 FETCH: begin
394 can_skip = 0;
395 skip = 0;
396 injected_instruction = 0;
397 mem_valid = 1;
398 mem_address = {inst_field, pc};
399 mem_write = 0;
400 if (`lag(mem_ready)) begin
401 state = DECODE;
402 page = pc[ADDR_BITS-3-1:7];
403 next_pc = pc + 1;
404 end
405 end
406
407 DECODE: begin
408 automatic bit go;
409 go = 0;
410 mem_valid = 0;
411 mem_write = 0;
412`ifdef SYNTHESIS
413 if (!switch_exam_observed && (int_enable && int_request)) begin
414`else
415 if (!switch_exam_observed && ((nextevent == ~0 && int_enable && int_request) || (instcount == nextevent && force_interrupt))) begin
416 if (! int_enable)
417 $display("ERROR: forced interrupt at a point where architecturally interrupts are disabled");
418`endif
419 $display("taking interrupt at instcount=%d", instcount);
420 int_enable = 0;
421 int_delay = 0;
422 data_field_saved = data_field;
423 inst_field_saved = inst_field;
424 data_field = 0;
425 inst_field = 0;
426 inst_field_buffer = 0;
427 tto_flag_old = tto_flag;
428 opcode = 'o4;
429 operand = 'o000;
430 next_pc = pc;
431 injected_instruction = 1;
432 go = 1;
433 end else if (`lag(mem_read_valid)) begin
434 state = RETIRE;
435 led_memdata = `lag(mem_read_data);
436 {opcode, operand} = `lag(mem_read_data);
437 if (switch_exam_observed) begin
438 run = 0;
439 end else begin
440 go = 1;
441 end
442 end
443 if (go) begin
444 int_enable = int_delay;
445 {i, z, wip} = operand;
446 if (z)
447 address = {inst_field, page, wip};
448 else
449 address = {inst_field, 5'b0, wip};
450 $display("%d %o: %o%o", instcount, pc, opcode, operand);
451 case (opcode)
452 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN;
453 'o3, 'o4: state = i ? INDIRECT : EXEC;
454 'o5: begin
455 if (i) begin
456 state = INDIRECT;
457 end else begin
458 next_pc = address[ADDR_BITS-3-1:0];
459 inst_field = inst_field_buffer;
460 end
461 end
462 'o7: begin
463 casez (operand)
464 'b0????????: begin
465 automatic bit cla, cll, cma, cml, rar, ral, bsw, iac;
466 {cla, cll, cma, cml, rar, ral, bsw, iac} = operand[7:0];
467 if (cla) acc = 0;
468 if (cll) link = 0;
469 if (cma) acc = ~acc;
470 if (cml) link = ~link;
471 if (iac) {link, acc} += 1;
472 if (rar && !ral) begin
473 {link, acc} = {acc[0], link, acc[11:1]};
474 if (bsw) {link, acc} = {acc[0], link, acc[11:1]};
475 end
476 if (ral && !rar) begin
477 {link, acc} = {acc, link};
478 if (bsw) {link, acc} = {acc, link};
479 end
480 if (bsw && !(rar || ral)) acc = {acc[5:0], acc[11:6]};
481 end
482 'b1????0??0: begin
483 automatic bit cla, sma, sza, snl, osr, hlt;
484 can_skip = 1;
485 {cla, sma, sza, snl, osr, hlt} = {operand[7:4], operand[2:1]};
486 if (sma && acc[11]) skip = 1;
487 if (sza && acc == 0) skip = 1;
488 if (snl && link != 0) skip = 1;
489 if (cla) acc = 0;
490 if (osr) begin
491 $display("%o: unsupported front panel switch test", pc);
492 $finish;
493 end
494 if (hlt) state = HALT;
495 end
496 'b1????1??0: begin
497 automatic bit cla, spa, sna, szl, osr, hlt;
498 can_skip = 1;
499 skip = 1;
500 {cla, spa, sna, szl, osr, hlt} = {operand[7:4], operand[2:1]};
501 if (spa && acc[11]) skip = 0;
502 if (sna && acc == 0) skip = 0;
503 if (szl && link != 0) skip = 0;
504 if (cla) acc = 0;
505 if (osr) begin
506 $display("%o: unsupported front panel switch test", pc);
507 $finish;
508 end
509 if (hlt) state = HALT;
510 end
511 default: begin
512 $display("%o: decoded unknown opcode %o %o", pc, opcode, operand);
513 $finish;
514 end
515 endcase
516 end
517 'o6: begin
518 case (operand[8:6])
519 'o0: begin
520 case (operand[5:3])
521 'o0: begin
522 case (operand[2:0])
523 'o0: begin
524 can_skip = 1;
525 if (int_enable)
526 skip = 1;
527 int_enable = 0;
528 int_delay = 0;
529 end
530 'o1: int_delay = 1;
531 'o2: begin
532 int_enable = 0;
533 int_delay = 0;
534 end
535 'o3: begin
536 can_skip = 1;
537 if (int_request)
538 skip = 1;
539 end
540 'o4: acc = {link, 1'b0/*gt*/, int_request, 1'b0/*ii*/, int_enable, 1'b0/*u*/, 3'b0/*if*/, 3'b0/*df*/};
541 'o5: begin
542 link = acc[11];
543 if (acc[7]) begin
544 int_delay = 1;
545 end else begin
546 int_enable = 0;
547 int_delay = 0;
548 end
549 end
550 'o7: begin
551 int_enable = 0;
552 int_delay = 0;
553 acc = 0;
554 link = 1;
555 tx_valid = 0;
556 tto_flag = 1;
557 tto_flag_old = 1;
558 tti_valid = 0;
559 end
560 default: $display("%o: unsupported 600%o op", pc, operand[2:0]);
561 endcase
562 end
563 'o3: begin
564 case (operand[2:0])
565 'o0: tti_valid = 0;
566 'o1: begin
567 can_skip = 1;
568 if (tti_valid) skip = 1;
569 end
570 'o2: begin
571 acc = 0;
572 tti_valid = 0;
573 end
574 'o4: begin
575 acc |= tti_data;
576 end
577 'o5: begin
578 tti_int_enable = acc[0];
579 end
580 'o6: begin
581 acc = tti_data;
582 tti_valid = 0;
583 end
584 default: begin
585 $display("%o: unsupported keyboard op %o", pc, operand[2:0]);
586 $finish;
587 end
588 endcase
589 end
590 'o4: begin
591 case (operand[2:0])
592 'o0: begin
593 tto_flag = 1;
594 tto_flag_old = 1;
595 end
596 'o1: begin
597 can_skip = 1;
598 if (tto_flag) skip = 1;
599 end
600 'o2: begin
601 tto_flag = 0;
602 tto_flag_old = 0;
603 end
604 'o4: begin
605 tto_delay = 100;
606 $display("[%o] write %o", pc, acc[6:0]);
607 tx_data = {1'b0, acc[6:0]};
608 if (tx_data == 'h8d)
609 tx_data = 'h8a;
610 end
611 'o5: begin
612 can_skip = 1;
613 if (tto_flag || tti_valid) skip = 1;
614 end
615 'o6: begin
616 tto_delay =100;
617 tto_flag = 0;
618 tto_flag_old = 0;
619 $display("[%o] write %o", pc, acc[6:0]);
620 tx_data = {1'b0, acc[6:0]};
621 if (tx_data == 'h8d)
622 tx_data = 'h8a;
623 end
624 default: begin
625 $display("%o: unsupported tty op %o", pc, operand[2:0]);
626 $finish;
627 end
628 endcase
629 end
630 default: begin
631 $display("%o: unsupported device %o (operation %o)", pc, operand[8:3], operand[2:0]);
632 can_skip = 1;
633 end
634 endcase
635 end
636 'o2: begin
637 if (operand[0])
638 data_field = operand[5:3];
639 if (operand[1])
640 inst_field_buffer = operand[5:3];
641 if (operand[2]) begin
642 if (operand[3] && operand[4])
643 acc = acc | {6'b0, inst_field_saved, data_field_saved};
644 else if (operand[3])
645 acc = acc | {6'b0, data_field, 3'b0};
646 else if (operand[4])
647 acc = acc | {6'b0, inst_field, 3'b0};
648 if (operand[5]) begin
649 data_field = data_field_saved;
650 inst_field_buffer = inst_field_saved;
651 end
652 end
653 end
654 default: begin
655 $display("%o: unsupported device %o (operation %o)", pc, operand[8:3], operand[2:0]);
656 can_skip = 1;
657 end
658 endcase
659 end
660 default: begin
661 $display("%o: decoded unknown opcode %o %o", pc, opcode, operand);
662 $finish;
663 end
664 endcase
665 end
666 end
667
668 INDIRECT: begin
669 mem_valid = 1;
670 mem_write = 0;
671 mem_address = address;
672 state = `lag(mem_ready) ? INDIRECTED : INDIRECT;
673 end
674
675 INDIRECTED: begin
676 if (`lag(mem_ready)) begin
677 mem_valid = 0;
678 mem_write = 0;
679 end
680 if (`lag(mem_read_valid)) begin
681 if (opcode != 'o5 && address[7:3] == 5'b00001) begin
682 led_memdata = `lag(mem_read_data);
683 address = {3'b0, `lag(mem_read_data)};
684 address += 1;
685 address[ADDR_BITS-1:ADDR_BITS-3] = data_field;
686 state = PREINC;
687 end else begin
688 led_memdata = `lag(mem_read_data);
689 address = {data_field, `lag(mem_read_data)};
690 case (opcode)
691 'o0, 'o1, 'o2: state = AGEN;
692 'o3, 'o4: state = EXEC;
693 'o5: begin
694 next_pc = address[ADDR_BITS-3-1:0];
695 $display("indirect jump to %o", next_pc);
696 inst_field = inst_field_buffer;
697 state = RETIRE;
698 end
699 endcase
700 end
701 end
702 end
703
704 PREINC: begin
705 mem_valid = 1;
706 mem_write = 1;
707 mem_write_data = address[DATA_BITS-1:0];
708 led_memdata = mem_write_data;
709 $display("preinc [%o] <- %o", mem_address, mem_write_data);
710 case (opcode)
711 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC;
712 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC;
713 endcase
714 end
715
716 AGEN: begin
717 mem_valid = 1;
718 case (opcode)
719 'o0, 'o1, 'o2: mem_write = 0;
720 endcase
721 mem_address = address;
722 state = `lag(mem_ready) ? EXEC : AGEN;
723 end
724
725 EXEC: begin
726 automatic bit stall = 0;
727 if (`lag(mem_ready)) begin
728 mem_valid = 0;
729 mem_write = 0;
730 end else if (mem_valid) begin
731 stall = 1;
732 end
733 case (opcode)
734 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1;
735 endcase
736 if (! stall) begin
737 state = RETIRE;
738 case (opcode)
739 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end
740 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end
741 'o2: begin
742 mem_valid = 1;
743 mem_address = address;
744 mem_write = 1;
745 mem_write_data = `lag(mem_read_data) + 1;
746 led_memdata = mem_write_data;
747 $display("store [%o] <- %o", mem_address, mem_write_data);
748 can_skip = 1;
749 if (mem_write_data == 0) skip = 1;
750 state = MEMWAIT;
751 end
752 'o3: begin
753 mem_valid = 1;
754 mem_address = address;
755 mem_write = 1;
756 mem_write_data = acc;
757 led_memdata = mem_write_data;
758 $display("store [%o] <- %o", mem_address, mem_write_data);
759 acc = 0;
760 state = MEMWAIT;
761 end
762 'o4: begin
763 mem_valid = 1;
764 mem_address = address;
765 mem_write = 1;
766 mem_write_data = next_pc[DATA_BITS-1:0];
767 led_memdata = mem_write_data;
768 $display("store [%o] <- %o", mem_address, mem_write_data);
769 next_pc = address[ADDR_BITS-3-1:0] + 1;
770 inst_field = inst_field_buffer;
771 state = MEMWAIT;
772 end
773 'o5: begin
774 next_pc = address[ADDR_BITS-3-1:0];
775 inst_field = inst_field_buffer;
776 end
777 endcase
778 end
779 end
780
781 MEMWAIT: state = `lag(mem_ready) ? RETIRE : MEMWAIT;
782
783 HALT: begin
784 run = 0;
785 $display("\nhalt state reached");
786 $finish;
787 end
788
789 DEPOSIT: begin
790 if (`lag(mem_ready)) begin
791 state = FETCH; // Not a retired instruction; go directly to decode
792 page = pc[ADDR_BITS-3-1:7];
793 ++pc; // Not a skip; normal part of panel deposit (because we are skipping RETIRE)
794 run = 0;
795 end
796 end
797 endcase
798
799 if (state == RETIRE) begin
800`ifndef SYNTHESIS
801 if (!injected_instruction) begin
802 $display("retiring pc=%o%o", inst_field, pc);
803 $fdisplay(pctrace, "%o%o", inst_field, pc);
804 end
805`endif
806
807 state = FETCH;
808 pc = next_pc;
809
810 if (can_skip) begin
811`ifndef SYNTHESIS
812 if (instcount == nextevent) begin
813 $display("checking instcount=%d force_skip=%d against inferred skip=%d", instcount, force_skip, skip);
814 if (force_skip == 1)
815 skip = 0;
816 else if (force_skip == 2)
817 skip = 1;
818 end
819`endif
820 if (skip) begin
821 $display("skip at instcount=%d pc=%o", instcount, pc);
822 ++pc;
823 end
824 end
825`ifndef SYNTHESIS
826 else if (instcount == nextevent && force_skip != 0) begin
827 $display("Error: forced skip at impossible boundary instcount=%d nextpc=%o", instcount, pc);
828 $finish;
829 end
830`endif
831
832`ifndef SYNTHESIS
833 if (instcount == nextevent) begin
834 nextevent = ~0;
835 if (eventtrace != 0) $fscanf(eventtrace, "%d %d %d", nextevent, force_skip, force_interrupt);
836 $display("nextevent=%d force_skip=%d force_interrupt=%d", nextevent, force_skip, force_interrupt);
837 end
838 if (!injected_instruction) begin
839 ++instcount;
840 if (instcount >= 26000) $finish;
841 end
842`endif
843 end
844
845 if (switch_sing_step)
846 run = 0;
847
848 if (state == FETCH && switch_sing_inst)
849 run = 0;
850
851 rx_ready = !tti_valid;
852 end
853 end
854end
855
856endmodule
diff --git a/hdl/defs.svh b/hdl/defs.svh
new file mode 100644
index 0000000..ea8dbc1
--- /dev/null
+++ b/hdl/defs.svh
@@ -0,0 +1,58 @@
1`define RAM_ADDRESS_BITS 23
2`define RAM_BYTE_BITS 8
3`define RAM_WORD_BYTES 2
4`define RAM_LINE_WORDS 1
5
6`define PDP_ADDRESS_BITS 15
7
8`define UART_BYTE_BITS 8
9
10`define TAG_BITS 1
11
12typedef bit [`RAM_ADDRESS_BITS-1:0] ram_word_address_t;
13typedef bit [`RAM_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] ram_line_address_t;
14typedef bit [`RAM_BYTE_BITS-1:0] ram_byte_t;
15typedef ram_byte_t [`RAM_WORD_BYTES-1:0] ram_word_t;
16typedef ram_word_t [`RAM_LINE_WORDS-1:0] ram_line_t;
17typedef bit [$clog2(`RAM_WORD_BYTES):0] ram_word_mask_t;
18typedef ram_word_mask_t [`RAM_LINE_WORDS-1:0] ram_line_mask_t;
19
20typedef bit [$clog2(`RAM_WORD_BYTES+1):0] ram_byte_count_t;
21typedef bit [$clog2(`RAM_LINE_WORDS+1):0] ram_word_count_t;
22
23typedef bit [`RAM_ADDRESS_BITS-1:`PDP_ADDRESS_BITS] ram_pdp_address_space_t;
24
25typedef bit [`PDP_ADDRESS_BITS-1:0] pdp_word_address_t;
26typedef bit [`PDP_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] pdp_line_address_t;
27
28typedef bit [`TAG_BITS-1:0] tag_t;
29
30typedef bit [`UART_BYTE_BITS-1:0] uart_byte_t;
31
32typedef struct {
33 ram_line_address_t address;
34 bit write;
35 ram_line_t data;
36 ram_line_mask_t mask;
37 tag_t tag;
38} ram_command_t;
39
40typedef struct {
41 ram_line_address_t address;
42 ram_line_t data;
43 tag_t tag;
44} ram_read_response_t;
45
46typedef struct {
47 pdp_line_address_t address;
48 bit write;
49 ram_line_t data;
50 ram_line_mask_t mask;
51 tag_t tag;
52} pdp_command_t;
53
54typedef struct {
55 pdp_line_address_t address;
56 ram_line_t data;
57 tag_t tag;
58} pdp_read_response_t;
diff --git a/hdl/echo_arbiter.sv b/hdl/echo_arbiter.sv
new file mode 100644
index 0000000..1c27e31
--- /dev/null
+++ b/hdl/echo_arbiter.sv
@@ -0,0 +1,64 @@
1`include "defs.svh"
2
3module echo_arbiter
4 ( input bit clock
5 , input bit reset
6
7 , output bit in0_ready
8 , input bit in0_valid
9 , input uart_byte_t in0_data
10
11 , output bit in1_ready
12 , input bit in1_valid
13 , input uart_byte_t in1_data
14
15 , input bit out_ready
16 , output bit out_valid
17 , output uart_byte_t out_data
18 );
19
20 bit in0_hold_valid;
21 uart_byte_t in0_hold;
22
23 bit in1_hold_valid;
24 uart_byte_t in1_hold;
25
26 always @(posedge clock) begin
27 if (reset) begin
28 in0_ready = 0;
29 in1_ready = 0;
30 out_valid = 0;
31 out_data = 0;
32 in0_hold_valid = 0;
33 in0_hold = 0;
34 in1_hold_valid = 0;
35 in1_hold = 0;
36 end else begin
37 if (out_ready) out_valid = 0;
38 if (in0_ready && in0_valid) begin
39 in0_hold_valid = 1;
40 in0_hold = in0_data;
41 end
42 if (in1_ready && in1_valid) begin
43 in1_hold_valid = 1;
44 in1_hold = in1_data;
45 end
46
47 if (!out_valid) begin
48 if (in0_hold_valid) begin
49 out_valid = 1;
50 out_data = in0_hold;
51 in0_hold_valid = 0;
52 end else if (in1_hold_valid) begin
53 out_valid = 1;
54 out_data = in1_hold;
55 in1_hold_valid = 0;
56 end
57 end
58
59 in0_ready = !in0_hold_valid;
60 in1_ready = !in1_hold_valid;
61 end
62 end
63
64endmodule
diff --git a/hdl/front_panel.sv b/hdl/front_panel.sv
new file mode 100644
index 0000000..52b4bdb
--- /dev/null
+++ b/hdl/front_panel.sv
@@ -0,0 +1,211 @@
1module front_panel
2 #( DEBOUNCE_MAX = 100
3 )
4 ( input bit clk
5 , input bit reset
6
7 , input bit [8:1][12:1] led
8 , output bit [3:1][12:1] switch
9
10 , inout wire [10:1] gpioa
11 , inout wire [28:13] gpiob
12 , inout wire [40:31] gpioc
13 );
14
15localparam DEBOUNCE_BITS = $clog2(DEBOUNCE_MAX+1);
16
17enum
18 { LED_ROW1
19 , DEAD_ROW2
20 , LED_ROW2
21 , DEAD_ROW3
22 , LED_ROW3
23 , DEAD_ROW4
24 , LED_ROW4
25 , DEAD_ROW5
26 , LED_ROW5
27 , DEAD_ROW6
28 , LED_ROW6
29 , DEAD_ROW7
30 , LED_ROW7
31 , DEAD_ROW8
32 , LED_ROW8
33 , DEAD_ROW9
34 , SWITCH_PREP
35 , SWITCH_ROW1
36 , SWITCH_ROW2
37 , SWITCH_ROW3
38 } state;
39
40bit [3:1][12:1] switch_raw;
41bit [DEBOUNCE_BITS-1:0] switch_debounce;
42
43`define LEDROW1 gpioc[38]
44`define LEDROW2 gpioc[40]
45`define LEDROW3 gpiob[15]
46`define LEDROW4 gpiob[16]
47`define LEDROW5 gpiob[18]
48`define LEDROW6 gpiob[22]
49`define LEDROW7 gpioc[37]
50`define LEDROW8 gpiob[13]
51
52`define SWROW1 gpioc[36]
53`define SWROW2 gpioa[1]
54`define SWROW3 gpioa[2]
55
56`define COL1 gpioa[8]
57`define COL2 gpioa[10]
58`define COL3 gpioa[7]
59`define COL4 gpiob[27]
60`define COL5 gpioc[31]
61`define COL6 gpiob[26]
62`define COL7 gpiob[24]
63`define COL8 gpiob[21]
64`define COL9 gpiob[19]
65`define COL10 gpiob[23]
66`define COL11 gpioc[32]
67`define COL12 gpioc[33]
68
69`define DO_LEDS
70`define DO_SWITCHES
71
72always_ff @(posedge clk) begin
73 // LED rows (active high)
74 `LEDROW1 = 1'b0;
75 `LEDROW2 = 1'b0;
76 `LEDROW3 = 1'b0;
77 `LEDROW4 = 1'b0;
78 `LEDROW5 = 1'b0;
79 `LEDROW6 = 1'b0;
80 `LEDROW7 = 1'b0;
81 `LEDROW8 = 1'b0;
82
83 // Switch rows (active low)
84 `SWROW1 = 1'b1;
85 `SWROW2 = 1'b1;
86 `SWROW3 = 1'b1;
87
88 if (reset) begin
89 switch = 0;
90 switch_raw = 0;
91 switch_debounce = 0;
92 state = state.first;
93 end else begin
94 automatic bit [3:1][12:1] new_switch = switch_raw;
95
96 case (state)
97`ifdef DO_LEDS
98`define LED_ROW(n) \
99 LED_ROW``n: begin \
100 `LEDROW``n = 1'b1; \
101 `COL1 = ~led[n][1]; \
102 `COL2 = ~led[n][2]; \
103 `COL3 = ~led[n][3]; \
104 `COL4 = ~led[n][4]; \
105 `COL5 = ~led[n][5]; \
106 `COL6 = ~led[n][6]; \
107 `COL7 = ~led[n][7]; \
108 `COL8 = ~led[n][8]; \
109 `COL9 = ~led[n][9]; \
110 `COL10 = ~led[n][10]; \
111 `COL11 = ~led[n][11]; \
112 `COL12 = ~led[n][12]; \
113 end
114
115 `LED_ROW(1)
116 `LED_ROW(2)
117 `LED_ROW(3)
118 `LED_ROW(4)
119 `LED_ROW(5)
120 `LED_ROW(6)
121 `LED_ROW(7)
122 `LED_ROW(8)
123`endif
124
125`ifdef DO_SWITCHES
126 SWITCH_PREP: begin
127 `SWROW1 = 1'b0;
128
129 `COL1 = 1'bZ;
130 `COL2 = 1'bZ;
131 `COL3 = 1'bZ;
132 `COL4 = 1'bZ;
133 `COL5 = 1'bZ;
134 `COL6 = 1'bZ;
135 `COL7 = 1'bZ;
136 `COL8 = 1'bZ;
137 `COL9 = 1'bZ;
138 `COL10 = 1'bZ;
139 `COL11 = 1'bZ;
140 `COL12 = 1'bZ;
141 end
142
143 SWITCH_ROW1: begin
144 `SWROW2 = 1'b0;
145
146 new_switch[1][1] = ~`COL1;
147 new_switch[1][2] = ~`COL2;
148 new_switch[1][3] = ~`COL3;
149 new_switch[1][4] = ~`COL4;
150 new_switch[1][5] = ~`COL5;
151 new_switch[1][6] = ~`COL6;
152 new_switch[1][7] = ~`COL7;
153 new_switch[1][8] = ~`COL8;
154 new_switch[1][9] = ~`COL9;
155 new_switch[1][10] = ~`COL10;
156 new_switch[1][11] = ~`COL11;
157 new_switch[1][12] = ~`COL12;
158 end
159
160 SWITCH_ROW2: begin
161 `SWROW3 = 1'b0;
162
163 new_switch[2][1] = ~`COL1;
164 new_switch[2][2] = ~`COL2;
165 new_switch[2][3] = ~`COL3;
166 new_switch[2][4] = ~`COL4;
167 new_switch[2][5] = ~`COL5;
168 new_switch[2][6] = ~`COL6;
169 new_switch[2][7] = ~`COL7;
170 new_switch[2][8] = ~`COL8;
171 new_switch[2][9] = ~`COL9;
172 new_switch[2][10] = ~`COL10;
173 new_switch[2][11] = ~`COL11;
174 new_switch[2][12] = ~`COL12;
175 end
176
177 SWITCH_ROW3: begin
178 new_switch[3][1] = ~`COL1;
179 new_switch[3][2] = ~`COL2;
180 new_switch[3][3] = ~`COL3;
181 new_switch[3][4] = ~`COL4;
182 new_switch[3][5] = ~`COL5;
183 new_switch[3][6] = ~`COL6;
184 new_switch[3][7] = ~`COL7;
185 new_switch[3][8] = ~`COL8;
186 new_switch[3][9] = ~`COL9;
187 new_switch[3][10] = ~`COL10;
188 new_switch[3][11] = ~`COL11;
189 new_switch[3][12] = ~`COL12;
190 end
191`endif
192 endcase
193
194 if (state == state.last)
195 state = state.first;
196 else
197 state = state.next;
198
199 if (new_switch == switch_raw) begin
200 if (switch_debounce == 0)
201 switch = switch_raw;
202 else
203 --switch_debounce;
204 end else begin
205 switch_raw = new_switch;
206 switch_debounce = DEBOUNCE_MAX;
207 end
208 end
209end
210
211endmodule
diff --git a/hdl/pll.sv b/hdl/pll.sv
new file mode 100644
index 0000000..d348b7c
--- /dev/null
+++ b/hdl/pll.sv
@@ -0,0 +1,126 @@
1module pll
2 #( MULTIPLY_BY = 1
3 , DIVIDE_BY = 1
4 , NATIVE_PERIOD_PICOSECONDS = 20_000
5 )
6 ( input bit native_clk
7 , input bit reset_n
8
9 , output bit target_clk
10 , output bit reset
11 );
12
13enum
14 { NOT_LOCKED
15 , RESET_CYCLE
16 , READY
17 } state = state.first;
18
19bit locked;
20
21`ifndef SYNTHESIS
22
23assign target_clk = native_clk;
24assign locked = 1;
25
26`else
27
28altpll
29 #( .clk0_divide_by(DIVIDE_BY)
30 , .clk0_multiply_by(MULTIPLY_BY)
31 , .inclk0_input_frequency(NATIVE_PERIOD_PICOSECONDS)
32 , .intended_device_family("Cyclone 10 LP")
33 , .operation_mode("NORMAL")
34 , .port_activeclock("PORT_UNUSED")
35 , .port_areset("PORT_USED")
36 , .port_clkbad0("PORT_UNUSED")
37 , .port_clkbad1("PORT_UNUSED")
38 , .port_clkloss("PORT_UNUSED")
39 , .port_clkswitch("PORT_UNUSED")
40 , .port_configupdate("PORT_UNUSED")
41 , .port_fbin("PORT_UNUSED")
42 , .port_inclk0("PORT_USED")
43 , .port_inclk1("PORT_UNUSED")
44 , .port_locked("PORT_USED")
45 , .port_pfdena("PORT_UNUSED")
46 , .port_phasecounterselect("PORT_UNUSED")
47 , .port_phasedone("PORT_UNUSED")
48 , .port_phasestep("PORT_UNUSED")
49 , .port_phaseupdown("PORT_UNUSED")
50 , .port_pllena("PORT_UNUSED")
51 , .port_scanaclr("PORT_UNUSED")
52 , .port_scanclk("PORT_UNUSED")
53 , .port_scanclkena("PORT_UNUSED")
54 , .port_scandata("PORT_UNUSED")
55 , .port_scandataout("PORT_UNUSED")
56 , .port_scandone("PORT_UNUSED")
57 , .port_scanread("PORT_UNUSED")
58 , .port_scanwrite("PORT_UNUSED")
59 , .port_clk0("PORT_USED")
60 , .port_clk1("PORT_UNUSED")
61 , .port_clk2("PORT_UNUSED")
62 , .port_clk3("PORT_UNUSED")
63 , .port_clk4("PORT_UNUSED")
64 , .port_clk5("PORT_UNUSED")
65 , .port_clkena0("PORT_UNUSED")
66 , .port_clkena1("PORT_UNUSED")
67 , .port_clkena2("PORT_UNUSED")
68 , .port_clkena3("PORT_UNUSED")
69 , .port_clkena4("PORT_UNUSED")
70 , .port_clkena5("PORT_UNUSED")
71 , .port_extclk0("PORT_UNUSED")
72 , .port_extclk1("PORT_UNUSED")
73 , .port_extclk2("PORT_UNUSED")
74 , .port_extclk3("PORT_UNUSED")
75 , .self_reset_on_loss_lock("ON")
76 , .width_clock(5)
77 ) pll
78 ( .areset(!reset_n)
79 , .inclk(native_clk)
80 , .clk(target_clk)
81 , .locked(locked)
82 , .activeclock()
83 , .clkbad()
84 , .clkena({6{1'b1}})
85 , .clkloss()
86 , .clkswitch(1'b0)
87 , .configupdate(1'b0)
88 , .extclkena({4{1'b1}})
89 , .fbin(1'b1)
90 , .fbmimicbidir()
91 , .fbout()
92 , .fref()
93 , .icdrclk()
94 , .pfdena(1'b1)
95 , .phasecounterselect({4{1'b1}})
96 , .phasedone()
97 , .phasestep(1'b1)
98 , .phaseupdown(1'b1)
99 , .pllena(1'b1)
100 , .scanaclr(1'b0)
101 , .scanclk(1'b0)
102 , .scanclkena(1'b1)
103 , .scandata(1'b0)
104 , .scandataout()
105 , .scandone()
106 , .scanread(1'b0)
107 , .scanwrite(1'b0)
108 , .sclkout0()
109 , .sclkout1()
110 , .vcooverrange()
111 , .vcounderrange()
112 );
113
114`endif
115
116always_ff @(posedge target_clk) begin
117 if (!reset_n || !locked) begin
118 state = state.first;
119 end else if (state != state.last) begin
120 state = state.next;
121 end
122
123 reset = !(state == state.last);
124end
125
126endmodule
diff --git a/hdl/ram_controller.sv b/hdl/ram_controller.sv
new file mode 100644
index 0000000..6eeb46d
--- /dev/null
+++ b/hdl/ram_controller.sv
@@ -0,0 +1,240 @@
1`include "defs.svh"
2
3module ram_controller
4 ( input bit clock
5 , input bit reset
6
7 , output bit command_ready
8 , input bit command_valid
9 , input ram_command_t command_data
10
11 , input bit result_ready
12 , output bit result_valid
13 , output ram_read_response_t result_data
14
15 , output bit ram_resetn
16 , output bit ram_csn
17 , output bit ram_clkp
18 , output bit ram_clkn
19 , output bit ram_rwds_oe
20 , input bit ram_rwds_in
21 , output bit ram_rwds_out
22 , output bit ram_data_oe
23 , input bit [7:0] ram_data_in
24 , output bit [7:0] ram_data_out
25 );
26
27 assign ram_clkn = !ram_clkp;
28
29 bit valid;
30 ram_command_t command;
31 ram_word_address_t base_address;
32
33 bit slow;
34 ram_word_count_t word_count;
35
36 (* syn_encoding = "one-hot" *) enum int unsigned
37 { CHIP_SELECT
38
39 , SEND_COMMAND_1
40 , SEND_COMMAND_2
41 , SEND_COMMAND_3
42 , SEND_COMMAND_4
43 , SEND_COMMAND_5
44 , SEND_COMMAND_6
45
46 , LAT2_12
47 , LAT2_11
48 , LAT2_10
49 , LAT2_9
50 , LAT2_8
51 , LAT2_7
52 , LAT2_6
53 , LAT2_5
54 , LAT2_4
55 , LAT2_3
56 , LAT2_2
57 , LAT2_1
58
59 /* Latency blocks are 6 cycle, but you start counting after the upper
60 * column address is sent (SEND_COMMAND_4) so we reduce the
61 * lowest-latency block by one full cycle (two states).
62 , LAT1_12
63 , LAT1_11
64 */
65 , LAT1_10
66 , LAT1_9
67 , LAT1_8
68 , LAT1_7
69 , LAT1_6
70 , LAT1_5
71 , LAT1_4
72 , LAT1_3
73 , LAT1_2
74 , LAT1_1
75
76 , DATA_1
77 , DATA_2
78 } state;
79
80 (* syn_encoding = "compact" *) enum bit
81 { SETUP_OUTPUTS
82 , TOGGLE_CLOCK
83 } half_state;
84
85 bit [2:0] reset_counter;
86
87 bit prev_rwds;
88
89 always @(posedge clock) begin
90 if (reset || reset_counter != 0) begin
91 command_ready = 0;
92 result_valid = 0;
93 ram_resetn = 0;
94 ram_csn = 1;
95 ram_clkp = 0;
96 ram_rwds_oe = 0;
97 ram_rwds_out = 0;
98 ram_data_oe = 0;
99 ram_data_out = 0;
100 base_address = 0;
101 slow = 0;
102 word_count = `RAM_LINE_WORDS;
103 state = state.first;
104 half_state = half_state.first;
105 if (reset)
106 reset_counter = 5; // Spec wants >= 100ns of reset
107 else
108 reset_counter = reset_counter - 1;
109 end else begin
110 ram_resetn = 1;
111
112 if (result_ready) result_valid = 0;
113 if (command_ready && command_valid) begin
114 valid = 1;
115 command = command_data;
116 base_address = 0;
117 base_address[`RAM_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] = command.address;
118 word_count = `RAM_LINE_WORDS;
119 state = state.first;
120 end
121
122 if (!valid) begin
123 ram_rwds_oe = 0;
124 ram_data_oe = 0;
125 ram_csn = 1;
126 ram_clkp = 0;
127 end else if (half_state == TOGGLE_CLOCK) begin
128 half_state = half_state.next;
129 if (state != CHIP_SELECT && state != SEND_COMMAND_1)
130 ram_clkp = !ram_clkp;
131 end else if (half_state == SETUP_OUTPUTS) begin
132 automatic bit stall = 0;
133 half_state = half_state.next;
134 ram_rwds_oe = 0;
135 ram_data_oe = 0;
136 case (state)
137
138 CHIP_SELECT: begin
139 ram_clkp = 0; // Overriding clock to guarantee that we're starting the command with the correct clock polarity
140 ram_csn = 0;
141 end
142
143 SEND_COMMAND_1: begin
144 ram_data_oe = 1;
145 ram_data_out = {!command.write, 1'b0, 1'b1, 5'b0}; // R/W#, ADDRSPACE, BURST, RESERVED
146 end
147
148 SEND_COMMAND_2: begin
149 ram_data_oe = 1;
150 ram_data_out = {4'b0, base_address[22:19]}; // RESERVED, ROW
151 end
152
153 SEND_COMMAND_3: begin
154 ram_data_oe = 1;
155 ram_data_out = {base_address[18:11]}; // ROW
156 end
157
158 SEND_COMMAND_4: begin
159 ram_data_oe = 1;
160 ram_data_out = {base_address[10:9], base_address[8:3]}; // ROW, UPPERCOL
161 // This is the cycle immediately before the latency countdown *really* begins.
162 // So we capture RWDS now in order to know how many latency blocks are required.
163 slow = ram_rwds_in;
164 end
165
166 SEND_COMMAND_5: begin
167 ram_data_oe = 1;
168 ram_data_out = {8'b0}; // RESERVED
169 end
170
171 SEND_COMMAND_6: begin
172 ram_data_oe = 1;
173 ram_data_out = {5'b0, base_address[2:0]}; // RESERVED, LOWERCOL
174 // If we're not in "slow" mode then skip the LAT2 latency
175 // block. Note that the state=state.next will still happen
176 // below, taking us to the first state in the LAT1 block.
177 if (!slow) state = LAT2_1;
178 end
179
180 // Nothing happens on any of the LAT_* states except for
181 // cycling the clock and advancing state.
182
183 DATA_1: begin
184 if (command.write) begin
185 ram_rwds_oe = 1;
186 ram_rwds_out = !command.mask[word_count - 1][0];
187 ram_data_oe = 1;
188 ram_data_out = command.data[word_count - 1][0];
189 end else if (prev_rwds != ram_rwds_in) begin
190 command.data[word_count - 1][0] = ram_data_in;
191 end else begin
192 stall = 1;
193 end
194 end
195
196 DATA_2: begin
197 if (command.write) begin
198 ram_rwds_oe = 1;
199 ram_rwds_out = !command.mask[word_count - 1][1];
200 ram_data_oe = 1;
201 ram_data_out = command.data[word_count - 1][1];
202 word_count = word_count - 1;
203 if (word_count != 0) begin
204 stall = 1;
205 state = DATA_1;
206 end
207 end else if (prev_rwds != ram_rwds_in) begin
208 command.data[word_count - 1][1] = ram_data_in;
209 word_count = word_count - 1;
210 if (word_count != 0) begin
211 stall = 1;
212 state = DATA_1;
213 end
214 end else begin
215 stall = 1;
216 end
217 end
218
219 endcase
220 if (!stall) begin
221 state = state.next;
222 if (state == state.first) begin
223 valid = 0;
224 if (!command.write) begin
225 // We know that this is safe because we don't accept commands unless we have result bandwidth
226 result_valid = 1;
227 result_data.address = command.address;
228 result_data.data = command.data;
229 result_data.tag = command.tag;
230 end
231 end
232 end
233 end
234
235 prev_rwds = ram_rwds_in;
236 command_ready = !valid && !result_valid;
237 end
238 end
239
240endmodule
diff --git a/hdl/result_printer.sv b/hdl/result_printer.sv
new file mode 100644
index 0000000..3041e6e
--- /dev/null
+++ b/hdl/result_printer.sv
@@ -0,0 +1,71 @@
1`include "defs.svh"
2
3module result_printer
4 #( TAG = 0
5 ) ( input bit clock
6 , input bit reset
7
8 , output bit result_ready
9 , input bit result_valid
10 , input ram_read_response_t result_data
11
12 , input bit echo_ready
13 , output bit echo_valid
14 , output uart_byte_t echo_data
15 );
16
17 ram_read_response_t hold;
18 ram_byte_count_t byte_count;
19 ram_word_count_t word_count;
20
21 (* syn_encoding = "one-hot" *) enum int unsigned
22 { HIGH_NIBBLE
23 , LOW_NIBBLE
24 } state;
25
26 always @(posedge clock) begin
27 if (reset) begin
28 result_ready = 0;
29 echo_valid = 0;
30 echo_data = 0;
31 byte_count = 0;
32 word_count = 0;
33 state = state.first;
34 end else begin
35 if (echo_ready) echo_valid = 0;
36 if (result_ready && result_valid) begin
37 hold = result_data;
38 if (hold.tag == TAG) begin
39 byte_count = `RAM_WORD_BYTES;
40 word_count = `RAM_LINE_WORDS;
41 state = state.first;
42 end
43 end
44
45 if (word_count != 0 && !echo_valid) begin
46 automatic ram_word_t w = hold.data[word_count-1];
47 automatic ram_byte_t b = w[byte_count-1];
48 echo_valid = 1;
49 case (state)
50 HIGH_NIBBLE: echo_data = b[7:4];
51 LOW_NIBBLE: echo_data = b[3:0];
52 endcase
53 if (echo_data < 10)
54 echo_data = echo_data + "0";
55 else
56 echo_data = echo_data + "A" - 10;
57 state = state.next;
58 if (state == state.first) begin
59 byte_count = byte_count - 1;
60 if (byte_count == 0) begin
61 byte_count = `RAM_WORD_BYTES;
62 word_count = word_count - 1;
63 end
64 end
65 end
66
67 result_ready = word_count == 0;
68 end
69 end
70
71endmodule
diff --git a/hdl/top.sv b/hdl/top.sv
new file mode 100644
index 0000000..7ec57b7
--- /dev/null
+++ b/hdl/top.sv
@@ -0,0 +1,298 @@
1`include "defs.svh"
2
3module top
4 ( input bit clock
5 , input bit resetn
6
7 , inout wire [10:1] gpioa
8 , inout wire [28:13] gpiob
9 , inout wire [40:31] gpioc
10
11 , output bit ram_resetn
12 , output bit ram_csn
13 , output bit ram_clkp
14 , output bit ram_clkn
15 , inout bit ram_rwds
16 , inout bit [7:0] ram_data
17 );
18
19 bit internal_clock;
20 bit internal_reset;
21 pll
22 #( .MULTIPLY_BY(1)
23 , .DIVIDE_BY(1)
24 ) fastpll
25 ( .native_clk(clock)
26 , .reset_n(resetn)
27 , .target_clk(internal_clock)
28 , .reset(internal_reset)
29 );
30
31 bit ram_rx_ready;
32 bit ram_rx_valid;
33 uart_byte_t ram_rx_data;
34
35 bit ram_tx_ready;
36 bit ram_tx_valid;
37 uart_byte_t ram_tx_data;
38
39 bit ram_echo_in0_ready;
40 bit ram_echo_in0_valid;
41 uart_byte_t ram_echo_in0_data;
42
43 bit ram_echo_in1_ready;
44 bit ram_echo_in1_valid;
45 uart_byte_t ram_echo_in1_data;
46
47 bit command_ready;
48 bit command_valid;
49 ram_command_t command_data;
50
51 bit result_ready;
52 bit result_valid;
53 ram_read_response_t result_data;
54
55 bit ram_rwds_oe;
56 bit ram_rwds_out;
57 assign ram_rwds = ram_rwds_oe ? ram_rwds_out : 1'bZ;
58
59 bit ram_data_oe;
60 bit [7:0] ram_data_out;
61 assign ram_data = ram_data_oe ? ram_data_out : 8'bZ;
62
63 alt_jtag_atlantic
64 #( .INSTANCE_ID(0)
65 , .LOG2_RXFIFO_DEPTH(6)
66 , .LOG2_TXFIFO_DEPTH(6)
67 , .SLD_AUTO_INSTANCE_INDEX("NO")
68 ) ram_jtag
69 ( .clk(internal_clock)
70 , .rst_n(!internal_reset)
71
72 , .r_dat(ram_tx_data)
73 , .r_val(ram_tx_valid)
74 , .r_ena(ram_tx_ready)
75
76 , .t_dat(ram_rx_data)
77 , .t_dav(ram_rx_ready)
78 , .t_ena(ram_rx_valid)
79 );
80
81 echo_arbiter arb
82 ( .clock(internal_clock)
83 , .reset(internal_reset)
84
85 , .in0_ready(ram_echo_in0_ready)
86 , .in0_valid(ram_echo_in0_valid)
87 , .in0_data(ram_echo_in0_data)
88
89 , .in1_ready(ram_echo_in1_ready)
90 , .in1_valid(ram_echo_in1_valid)
91 , .in1_data(ram_echo_in1_data)
92
93 , .out_ready(ram_tx_ready)
94 , .out_valid(ram_tx_valid)
95 , .out_data(ram_tx_data)
96 );
97
98 command_parser
99 #( .TAG(0)
100 ) parser
101 ( .clock(internal_clock)
102 , .reset(internal_reset)
103
104 , .uart_ready(ram_rx_ready)
105 , .uart_valid(ram_rx_valid)
106 , .uart_data(ram_rx_data)
107
108 , .echo_ready(ram_echo_in0_ready)
109 , .echo_valid(ram_echo_in0_valid)
110 , .echo_data(ram_echo_in0_data)
111
112 , .command_ready(command_ready)
113 , .command_valid(command_valid)
114 , .command_data(command_data)
115 );
116
117 ram_controller ram
118 ( .clock(internal_clock)
119 , .reset(internal_reset)
120
121 , .command_ready(command_ready)
122 , .command_valid(command_valid)
123 , .command_data(command_data)
124
125 , .result_ready(result_ready)
126 , .result_valid(result_valid)
127 , .result_data(result_data)
128
129 , .ram_resetn(ram_resetn)
130 , .ram_csn(ram_csn)
131 , .ram_clkp(ram_clkp)
132 , .ram_clkn(ram_clkn)
133 , .ram_rwds_oe(ram_rwds_oe)
134 , .ram_rwds_in(ram_rwds)
135 , .ram_rwds_out(ram_rwds_out)
136 , .ram_data_oe(ram_data_oe)
137 , .ram_data_in(ram_data)
138 , .ram_data_out(ram_data_out)
139 );
140
141 result_printer
142 #( .TAG(0)
143 ) print
144 ( .clock(internal_clock)
145 , .reset(internal_reset)
146
147 , .result_ready(result_ready)
148 , .result_valid(result_valid)
149 , .result_data(result_data)
150
151 , .echo_ready(ram_echo_in1_ready)
152 , .echo_valid(ram_echo_in1_valid)
153 , .echo_data(ram_echo_in1_data)
154 );
155
156 bit slow_clock;
157 bit slow_reset;
158 pll
159 #( .MULTIPLY_BY(1)
160 , .DIVIDE_BY(500)
161 ) slowpll
162 ( .native_clk(clock)
163 , .reset_n(resetn)
164 , .target_clk(slow_clock)
165 , .reset(slow_reset)
166 );
167
168 bit [8:1][12:1] led;
169 bit [3:1][12:1] switch;
170
171 front_panel panel
172 ( .clk(slow_clock)
173 , .reset(slow_reset)
174
175 , .led(led)
176 , .switch(switch)
177
178 , .gpioa(gpioa)
179 , .gpiob(gpiob)
180 , .gpioc(gpioc)
181 );
182
183 bit [2:0] switch_df;
184 bit [2:0] switch_if;
185 bit [11:0] switch_sr;
186 bit switch_start;
187 bit switch_load_add;
188 bit switch_dep;
189 bit switch_exam;
190 bit switch_cont;
191 bit switch_stop;
192 bit switch_sing_step;
193 bit switch_sing_inst;
194
195 // Note that we are reversing the order here on a number of aggregates because
196 // the panel model gives us LEDs and switches in schematic-order, which is the
197 // opposite of the bit order
198 assign switch_df = {switch[2][1], switch[2][2], switch[2][3]};
199 assign switch_if = {switch[2][4], switch[2][5], switch[2][6]};
200 assign switch_sr = {switch[1][1], switch[1][2], switch[1][3], switch[1][4], switch[1][5], switch[1][6], switch[1][7], switch[1][8], switch[1][9], switch[1][10], switch[1][11], switch[1][12]};
201 assign switch_start = switch[3][1];
202 assign switch_load_add = switch[3][2];
203 assign switch_dep = switch[3][3];
204 assign switch_exam = switch[3][4];
205 assign switch_cont = switch[3][5];
206 assign switch_stop = switch[3][6];
207 `ifdef HISTORIC_SWITCH_BEHAVIOUR
208 assign switch_sing_step = !switch[3][7];
209 assign switch_sing_inst = !switch[3][8];
210 `else
211 assign switch_sing_step = switch[3][7];
212 assign switch_sing_inst = switch[3][8];
213 `endif
214
215 bit [11:0] led_pc;
216 bit [11:0] led_memaddr;
217 bit [11:0] led_memdata;
218 bit [11:0] led_acc;
219 bit [11:0] led_mq;
220 bit led_and;
221 bit led_tad;
222 bit led_isz;
223 bit led_dca;
224 bit led_jms;
225 bit led_jmp;
226 bit led_iot;
227 bit led_opr;
228 bit led_fetch;
229 bit led_execute;
230 bit led_defer;
231 bit led_word_count;
232 bit led_current_address;
233 bit led_break;
234 bit led_ion;
235 bit led_pause;
236 bit led_run;
237 bit [4:0] led_step_counter;
238 bit [2:0] led_df;
239 bit [2:0] led_if;
240 bit led_link;
241
242 // Note that we are reversing the order here on a number of aggregates because
243 // the panel model gives us LEDs and switches in schematic-order, which is the
244 // opposite of the bit order
245 assign led[1] = {led_pc[0], led_pc[1], led_pc[2], led_pc[3], led_pc[4], led_pc[5], led_pc[6], led_pc[7], led_pc[8], led_pc[9], led_pc[10], led_pc[11]};
246 assign led[2] = {led_memaddr[0], led_memaddr[1], led_memaddr[2], led_memaddr[3], led_memaddr[4], led_memaddr[5], led_memaddr[6], led_memaddr[7], led_memaddr[8], led_memaddr[9], led_memaddr[10], led_memaddr[11]};
247 assign led[3] = {led_memdata[0], led_memdata[1], led_memdata[2], led_memdata[3], led_memdata[4], led_memdata[5], led_memdata[6], led_memdata[7], led_memdata[8], led_memdata[9], led_memdata[10], led_memdata[11]};
248 assign led[4] = {led_acc[0], led_acc[1], led_acc[2], led_acc[3], led_acc[4], led_acc[5], led_acc[6], led_acc[7], led_acc[8], led_acc[9], led_acc[10], led_acc[11]};
249 assign led[5] = {led_mq[0], led_mq[1], led_mq[2], led_mq[3], led_mq[4], led_mq[5], led_mq[6], led_mq[7], led_mq[8], led_mq[9], led_mq[10], led_mq[11]};
250 assign led[6] = {led_word_count, led_defer, led_execute, led_fetch, led_opr, led_iot, led_jmp, led_jms, led_dca, led_isz, led_tad, led_and};
251 assign led[7] = {2'b0, led_step_counter[4], led_step_counter[3], led_step_counter[2], led_step_counter[1], led_step_counter[0], led_run, led_pause, led_ion, led_break, led_current_address};
252 assign led[8] = {5'b0, led_link, led_if[0], led_if[1], led_if[2], led_df[0], led_df[1], led_df[2]};
253
254 core cpu
255 ( .clk(internal_clock)
256 , .reset(internal_reset)
257
258 , .switch_df(switch_df)
259 , .switch_if(switch_if)
260 , .switch_sr(switch_sr)
261 , .switch_start(switch_start)
262 , .switch_load_add(switch_load_add)
263 , .switch_dep(switch_dep)
264 , .switch_exam(switch_exam)
265 , .switch_cont(switch_cont)
266 , .switch_stop(switch_stop)
267 , .switch_sing_step(switch_sing_step)
268 , .switch_sing_inst(switch_sing_inst)
269
270 , .led_pc(led_pc)
271 , .led_memaddr(led_memaddr)
272 , .led_memdata(led_memdata)
273 , .led_acc(led_acc)
274 , .led_mq(led_mq)
275 , .led_and(led_and)
276 , .led_tad(led_tad)
277 , .led_isz(led_isz)
278 , .led_dca(led_dca)
279 , .led_jms(led_jms)
280 , .led_jmp(led_jmp)
281 , .led_iot(led_iot)
282 , .led_opr(led_opr)
283 , .led_fetch(led_fetch)
284 , .led_execute(led_execute)
285 , .led_defer(led_defer)
286 , .led_word_count(led_word_count)
287 , .led_current_address(led_current_address)
288 , .led_break(led_break)
289 , .led_ion(led_ion)
290 , .led_pause(led_pause)
291 , .led_run(led_run)
292 , .led_step_counter(led_step_counter)
293 , .led_df(led_df)
294 , .led_if(led_if)
295 , .led_link(led_link)
296 );
297
298endmodule