summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Blake Kongslie2022-03-20 17:27:02 -0700
committerJulian Blake Kongslie2022-03-20 17:27:02 -0700
commit4a878b3d2924e74eb311b34df8b7c4091e6700bb (patch)
tree84ce7dd5fcd89ae7d24f34d1b6e0ed9bbb35e57f
parentSupport loading RIMs and multi-word lines via the UART loader. (diff)
downloadmultipdp8-4a878b3d2924e74eb311b34df8b7c4091e6700bb.tar.xz
Cleanup of PDP-8 core to support arbitrated memory protocol.
No support yet for multiple words per line; otherwise complete.
Diffstat (limited to '')
-rw-r--r--hdl/core.sv299
1 files changed, 109 insertions, 190 deletions
diff --git a/hdl/core.sv b/hdl/core.sv
index 8bbea98..7fdd20a 100644
--- a/hdl/core.sv
+++ b/hdl/core.sv
@@ -1,80 +1,20 @@
1`include "defs.svh" 1`include "defs.svh"
2 2
3`ifdef SYNTHESIS
4`define lag(x) x
5`else
6`define lag(x) $past(x)
7`endif
8
9`define DATA_BITS 12 3`define DATA_BITS 12
10 4
11module mem 5module core
6 #( JTAG_INSTANCE = 1
7 )
12 ( input bit clk 8 ( input bit clk
13 , input bit reset 9 , input bit reset
14 10
15 , output bit command_ready 11 , input bit mem_command_ready
16 , input bit command_valid 12 , output bit mem_command_valid
17 , input pdp_command_t command_data 13 , output pdp_command_t mem_command
18
19 , input bit read_ready
20 , output bit read_valid
21 , output pdp_read_response_t read_data
22 );
23
24parameter INIT_FILE;
25 14
26bit hold_valid; 15 , output bit mem_read_ready
27pdp_command_t hold; 16 , input bit mem_read_valid
28 17 , input pdp_read_response_t mem_read
29bit [`DATA_BITS-1:0] storage [0:(1 << `PDP_ADDRESS_BITS)-1];
30initial $readmemh(INIT_FILE, storage);
31
32always_ff @(posedge clk) begin
33 if (reset) begin
34 command_ready = 0;
35 read_valid = 0;
36 hold_valid = 0;
37 end else begin
38 if (read_ready) read_valid = 0;
39
40 if (command_ready && command_valid) begin
41 hold_valid = 1;
42 hold = command_data;
43 end
44
45 if (hold_valid && hold.write) begin
46// for (int i = 0; i < `RAM_LINE_WORDS; ++i) begin
47 if (hold.mask[0]) begin
48 automatic pdp_word_address_t addr = 0;
49 addr[`PDP_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] = hold.address;
50// if (`RAM_LINE_WORDS != 1)
51// addr[$clog2(`RAM_LINE_WORDS)-1:0] = i;
52 storage[addr] = hold.data[/*i*/0];
53 end
54// end
55 hold_valid = 0;
56 end else if (hold_valid && !read_valid) begin
57 read_valid = 1;
58 read_data.address = hold.address;
59 /*for (int i = 0; i < `RAM_LINE_WORDS; ++i)*/ begin
60 automatic pdp_word_address_t addr = 0;
61 addr[`PDP_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] = hold.address;
62// if (`RAM_LINE_WORDS != 1)
63// addr[$clog2(`RAM_LINE_WORDS)-1:0] = i;
64 read_data.data[/*i*/0] = storage[addr];
65 end
66 hold_valid = 0;
67 end
68
69 command_ready = !hold_valid;
70 end
71end
72
73endmodule
74
75module core
76 ( input bit clk
77 , input bit reset
78 18
79 , input bit [2:0] switch_df 19 , input bit [2:0] switch_df
80 , input bit [2:0] switch_if 20 , input bit [2:0] switch_if
@@ -158,41 +98,14 @@ bit switch_cont_observed;
158assign led_run = run; 98assign led_run = run;
159assign led_ion = int_enable; 99assign led_ion = int_enable;
160 100
161bit mem_ready; 101assign led_current_address = mem_command_valid;
162bit mem_valid;
163bit mem_write;
164bit [`PDP_ADDRESS_BITS-1:0] mem_address;
165bit [`DATA_BITS-1:0] mem_write_data;
166assign led_current_address = mem_valid;
167
168assign led_memaddr = mem_address[`PDP_ADDRESS_BITS-3-1:0];
169 102
170bit mem_read_valid; 103assign led_memaddr = mem_command.address[`PDP_ADDRESS_BITS-3-1:0];
171bit [`DATA_BITS-1:0] mem_read_data;
172 104
173pdp_command_t mem_command;
174pdp_read_response_t mem_response;
175
176assign mem_command.address = mem_address;
177assign mem_command.write = mem_write;
178assign mem_command.data = mem_write_data;
179assign mem_command.mask = ~0; 105assign mem_command.mask = ~0;
180assign mem_read_data = mem_response.data;
181
182mem
183 #( .INIT_FILE("mem/focal69.loaded.hex")
184 ) memory
185 ( .clk(clk)
186 , .reset(reset)
187 106
188 , .command_ready(mem_ready) 107bit mem_hold_valid;
189 , .command_valid(mem_valid) 108pdp_read_response_t mem_hold;
190 , .command_data(mem_command)
191
192 , .read_ready(1)
193 , .read_valid(mem_read_valid)
194 , .read_data(mem_response)
195 );
196 109
197bit rx_ready; 110bit rx_ready;
198bit rx_valid; 111bit rx_valid;
@@ -203,7 +116,7 @@ bit tx_valid;
203bit [7:0] tx_data; 116bit [7:0] tx_data;
204 117
205alt_jtag_atlantic 118alt_jtag_atlantic
206 #( .INSTANCE_ID(1) 119 #( .INSTANCE_ID(JTAG_INSTANCE)
207 , .LOG2_RXFIFO_DEPTH(10) 120 , .LOG2_RXFIFO_DEPTH(10)
208 , .LOG2_TXFIFO_DEPTH(10) 121 , .LOG2_TXFIFO_DEPTH(10)
209 , .SLD_AUTO_INSTANCE_INDEX("NO") 122 , .SLD_AUTO_INSTANCE_INDEX("NO")
@@ -285,7 +198,6 @@ enum
285 , PREINC 198 , PREINC
286 , AGEN 199 , AGEN
287 , EXEC 200 , EXEC
288 , MEMWAIT
289 , HALT 201 , HALT
290 , DEPOSIT 202 , DEPOSIT
291 , RETIRE 203 , RETIRE
@@ -294,7 +206,7 @@ enum
294assign led_fetch = state == FETCH; 206assign led_fetch = state == FETCH;
295assign led_execute = state == DECODE || state == AGEN || state == EXEC; 207assign led_execute = state == DECODE || state == AGEN || state == EXEC;
296assign led_defer = state == INDIRECT || state == INDIRECTED || state == PREINC; 208assign led_defer = state == INDIRECT || state == INDIRECTED || state == PREINC;
297assign led_pause = state == MEMWAIT || state == HALT; 209assign led_pause = state == HALT;
298 210
299always_ff @(posedge clk) begin 211always_ff @(posedge clk) begin
300 if (reset) begin 212 if (reset) begin
@@ -310,7 +222,8 @@ always_ff @(posedge clk) begin
310 switch_dep_observed = 0; 222 switch_dep_observed = 0;
311 switch_exam_observed = 0; 223 switch_exam_observed = 0;
312 switch_cont_observed = 0; 224 switch_cont_observed = 0;
313 mem_valid = 0; 225 mem_command_valid = 0;
226 mem_hold_valid = 0;
314 rx_ready = 0; 227 rx_ready = 0;
315 tx_valid = 0; 228 tx_valid = 0;
316 tto_delay = 0; 229 tto_delay = 0;
@@ -330,12 +243,25 @@ always_ff @(posedge clk) begin
330 tti_valid = 0; 243 tti_valid = 0;
331 state = state.first; 244 state = state.first;
332 end else begin 245 end else begin
246 if (mem_command_ready && mem_command_valid) begin
247 mem_command_valid = 0;
248 end
249
250 if (mem_read_ready && mem_read_valid) begin
251 if (mem_read.address == mem_command.address) begin
252 mem_hold_valid = 1;
253 mem_hold = mem_read;
254 mem_hold.data &= 'hfff;
255 led_memdata = mem_hold.data;
256 end
257 end
258
333 if (switch_start && !switch_start_observed) begin 259 if (switch_start && !switch_start_observed) begin
334 switch_start_observed = 1; 260 switch_start_observed = 1;
335 run = 1; 261 run = 1;
336 int_enable = 0; 262 int_enable = 0;
337 int_delay = 0; 263 int_delay = 0;
338 mem_valid = 0; 264 mem_command_valid = 0;
339 acc = 0; 265 acc = 0;
340 link = 1; 266 link = 1;
341 state = state.first; 267 state = state.first;
@@ -365,11 +291,11 @@ always_ff @(posedge clk) begin
365 switch_dep_observed = 1; 291 switch_dep_observed = 1;
366`endif 292`endif
367 state = DEPOSIT; 293 state = DEPOSIT;
368 mem_valid = 1; 294 mem_command_valid = 1;
369 mem_address = {inst_field, pc}; 295 mem_command.address = {inst_field, pc};
370 mem_write = 1; 296 mem_command.write = 1;
371 mem_write_data = switch_sr; 297 mem_command.data = switch_sr;
372 led_memdata = mem_write_data; 298 led_memdata = mem_command.data;
373 run = 1; 299 run = 1;
374 end 300 end
375 301
@@ -398,7 +324,7 @@ always_ff @(posedge clk) begin
398 if (switch_stop) 324 if (switch_stop)
399 run = 0; 325 run = 0;
400 326
401 if (`lag(tx_ready)) begin 327 if (tx_ready) begin
402 if (tx_valid) 328 if (tx_valid)
403 tto_flag = 1; 329 tto_flag = 1;
404 tx_valid = 0; 330 tx_valid = 0;
@@ -407,9 +333,9 @@ always_ff @(posedge clk) begin
407 tx_valid = 1; 333 tx_valid = 1;
408 if (tto_delay != 0) 334 if (tto_delay != 0)
409 --tto_delay; 335 --tto_delay;
410 if (rx_ready && `lag(rx_valid)) begin 336 if (rx_ready && rx_valid) begin
411 tti_valid = 1; 337 tti_valid = 1;
412 tti_data = {4'b0, 1'b1, `lag(rx_data[6:0])}; 338 tti_data = {4'b0, 1'b1, rx_data[6:0]};
413 if (tti_data[6:0] == 7'h0a) 339 if (tti_data[6:0] == 7'h0a)
414 tti_data[6:0] = 7'h0d; 340 tti_data[6:0] = 7'h0d;
415 else if (tti_data[6:0] == 7'h1b) 341 else if (tti_data[6:0] == 7'h1b)
@@ -422,10 +348,11 @@ always_ff @(posedge clk) begin
422 can_skip = 0; 348 can_skip = 0;
423 skip = 0; 349 skip = 0;
424 injected_instruction = 0; 350 injected_instruction = 0;
425 mem_valid = 1; 351 if (!mem_command_valid) begin
426 mem_address = {inst_field, pc}; 352 mem_command_valid = 1;
427 mem_write = 0; 353 mem_command.address = {inst_field, pc};
428 if (`lag(mem_ready)) begin 354 mem_command.write = 0;
355 mem_hold_valid = 0;
429 state = DECODE; 356 state = DECODE;
430 page = pc[`PDP_ADDRESS_BITS-3-1:7]; 357 page = pc[`PDP_ADDRESS_BITS-3-1:7];
431 next_pc = pc + 1; 358 next_pc = pc + 1;
@@ -435,8 +362,6 @@ always_ff @(posedge clk) begin
435 DECODE: begin 362 DECODE: begin
436 automatic bit go; 363 automatic bit go;
437 go = 0; 364 go = 0;
438 mem_valid = 0;
439 mem_write = 0;
440`ifdef SYNTHESIS 365`ifdef SYNTHESIS
441 if (!switch_exam_observed && (int_enable && int_request)) begin 366 if (!switch_exam_observed && (int_enable && int_request)) begin
442`else 367`else
@@ -458,10 +383,9 @@ always_ff @(posedge clk) begin
458 next_pc = pc; 383 next_pc = pc;
459 injected_instruction = 1; 384 injected_instruction = 1;
460 go = 1; 385 go = 1;
461 end else if (`lag(mem_read_valid)) begin 386 end else if (mem_hold_valid) begin
462 state = RETIRE; 387 state = RETIRE;
463 led_memdata = `lag(mem_read_data); 388 {opcode, operand} = mem_hold.data;
464 {opcode, operand} = `lag(mem_read_data);
465 if (switch_exam_observed) begin 389 if (switch_exam_observed) begin
466 run = 0; 390 run = 0;
467 end else begin 391 end else begin
@@ -694,27 +618,24 @@ always_ff @(posedge clk) begin
694 end 618 end
695 619
696 INDIRECT: begin 620 INDIRECT: begin
697 mem_valid = 1; 621 if (!mem_command_valid) begin
698 mem_write = 0; 622 mem_command_valid = 1;
699 mem_address = address; 623 mem_command.write = 0;
700 state = `lag(mem_ready) ? INDIRECTED : INDIRECT; 624 mem_command.address = address;
625 mem_hold_valid = 0;
626 state = INDIRECTED;
627 end
701 end 628 end
702 629
703 INDIRECTED: begin 630 INDIRECTED: begin
704 if (`lag(mem_ready)) begin 631 if (mem_hold_valid) begin
705 mem_valid = 0;
706 mem_write = 0;
707 end
708 if (`lag(mem_read_valid)) begin
709 if (opcode != 'o5 && address[7:3] == 5'b00001) begin 632 if (opcode != 'o5 && address[7:3] == 5'b00001) begin
710 led_memdata = `lag(mem_read_data); 633 address = {3'b0, mem_hold.data};
711 address = {3'b0, `lag(mem_read_data)};
712 address += 1; 634 address += 1;
713 address[`PDP_ADDRESS_BITS-1:`PDP_ADDRESS_BITS-3] = data_field; 635 address[`PDP_ADDRESS_BITS-1:`PDP_ADDRESS_BITS-3] = data_field;
714 state = PREINC; 636 state = PREINC;
715 end else begin 637 end else begin
716 led_memdata = `lag(mem_read_data); 638 address = {data_field, mem_hold.data};
717 address = {data_field, `lag(mem_read_data)};
718 case (opcode) 639 case (opcode)
719 'o0, 'o1, 'o2: state = AGEN; 640 'o0, 'o1, 'o2: state = AGEN;
720 'o3, 'o4: state = EXEC; 641 'o3, 'o4: state = EXEC;
@@ -730,73 +651,73 @@ always_ff @(posedge clk) begin
730 end 651 end
731 652
732 PREINC: begin 653 PREINC: begin
733 mem_valid = 1; 654 if (!mem_command_valid) begin
734 mem_write = 1; 655 mem_command_valid = 1;
735 mem_write_data = address[`DATA_BITS-1:0]; 656 mem_command.write = 1;
736 led_memdata = mem_write_data; 657 mem_command.data = address[`DATA_BITS-1:0];
737 $display("preinc [%o] <- %o", mem_address, mem_write_data); 658 mem_hold_valid = 0;
738 case (opcode) 659 led_memdata = mem_command.data;
739 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC; 660 $display("preinc [%o] <- %o", mem_command.address, mem_command.data);
740 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC; 661 case (opcode)
741 endcase 662 'o0, 'o1, 'o2: state = AGEN;
663 'o3, 'o4, 'o5: state = EXEC;
664 endcase
665 end
742 end 666 end
743 667
744 AGEN: begin 668 AGEN: begin
745 mem_valid = 1; 669 if (!mem_command_valid) begin
746 case (opcode) 670 mem_command_valid = 1;
747 'o0, 'o1, 'o2: mem_write = 0; 671 case (opcode)
748 endcase 672 'o0, 'o1, 'o2: mem_command.write = 0;
749 mem_address = address; 673 endcase
750 state = `lag(mem_ready) ? EXEC : AGEN; 674 mem_command.address = address;
675 mem_hold_valid = 0;
676 state = EXEC;
677 end
751 end 678 end
752 679
753 EXEC: begin 680 EXEC: begin
754 automatic bit stall = 0; 681 automatic bit stall = mem_command_valid;
755 if (`lag(mem_ready)) begin
756 mem_valid = 0;
757 mem_write = 0;
758 end else if (mem_valid) begin
759 stall = 1;
760 end
761 case (opcode) 682 case (opcode)
762 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1; 683 'o0, 'o1, 'o2: if (! mem_hold_valid) stall = 1;
763 endcase 684 endcase
764 if (! stall) begin 685 if (! stall) begin
765 state = RETIRE; 686 state = RETIRE;
766 case (opcode) 687 case (opcode)
767 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end 688 'o0: begin acc &= mem_hold.data; end
768 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end 689 'o1: begin {link, acc} += {1'b0, mem_hold.data}; end
769 'o2: begin 690 'o2: begin
770 mem_valid = 1; 691 mem_command_valid = 1;
771 mem_address = address; 692 mem_command.address = address;
772 mem_write = 1; 693 mem_command.write = 1;
773 mem_write_data = `lag(mem_read_data) + 1; 694 mem_command.data = (mem_hold.data + 1) & 'hfff;
774 led_memdata = mem_write_data; 695 mem_hold_valid = 0;
775 $display("store [%o] <- %o", mem_address, mem_write_data); 696 led_memdata = mem_command.data;
697 $display("store [%o] <- %o", mem_command.address, mem_command.data);
776 can_skip = 1; 698 can_skip = 1;
777 if (mem_write_data == 0) skip = 1; 699 if (mem_command.data == 0) skip = 1;
778 state = MEMWAIT;
779 end 700 end
780 'o3: begin 701 'o3: begin
781 mem_valid = 1; 702 mem_command_valid = 1;
782 mem_address = address; 703 mem_command.address = address;
783 mem_write = 1; 704 mem_command.write = 1;
784 mem_write_data = acc; 705 mem_command.data = acc;
785 led_memdata = mem_write_data; 706 mem_hold_valid = 0;
786 $display("store [%o] <- %o", mem_address, mem_write_data); 707 led_memdata = mem_command.data;
708 $display("store [%o] <- %o", mem_command.address, mem_command.data);
787 acc = 0; 709 acc = 0;
788 state = MEMWAIT;
789 end 710 end
790 'o4: begin 711 'o4: begin
791 mem_valid = 1; 712 mem_command_valid = 1;
792 mem_address = address; 713 mem_command.address = address;
793 mem_write = 1; 714 mem_command.write = 1;
794 mem_write_data = next_pc[`DATA_BITS-1:0]; 715 mem_command.data = next_pc[`DATA_BITS-1:0];
795 led_memdata = mem_write_data; 716 mem_hold_valid = 0;
796 $display("store [%o] <- %o", mem_address, mem_write_data); 717 led_memdata = mem_command.data;
718 $display("store [%o] <- %o", mem_command.address, mem_command.data);
797 next_pc = address[`PDP_ADDRESS_BITS-3-1:0] + 1; 719 next_pc = address[`PDP_ADDRESS_BITS-3-1:0] + 1;
798 inst_field = inst_field_buffer; 720 inst_field = inst_field_buffer;
799 state = MEMWAIT;
800 end 721 end
801 'o5: begin 722 'o5: begin
802 next_pc = address[`PDP_ADDRESS_BITS-3-1:0]; 723 next_pc = address[`PDP_ADDRESS_BITS-3-1:0];
@@ -806,8 +727,6 @@ always_ff @(posedge clk) begin
806 end 727 end
807 end 728 end
808 729
809 MEMWAIT: state = `lag(mem_ready) ? RETIRE : MEMWAIT;
810
811 HALT: begin 730 HALT: begin
812 run = 0; 731 run = 0;
813 $display("\nhalt state reached"); 732 $display("\nhalt state reached");
@@ -815,12 +734,10 @@ always_ff @(posedge clk) begin
815 end 734 end
816 735
817 DEPOSIT: begin 736 DEPOSIT: begin
818 if (`lag(mem_ready)) begin 737 state = FETCH; // Not a retired instruction; go directly to decode
819 state = FETCH; // Not a retired instruction; go directly to decode 738 page = pc[`PDP_ADDRESS_BITS-3-1:7];
820 page = pc[`PDP_ADDRESS_BITS-3-1:7]; 739 ++pc; // Not a skip; normal part of panel deposit (because we are skipping RETIRE)
821 ++pc; // Not a skip; normal part of panel deposit (because we are skipping RETIRE) 740 run = 0;
822 run = 0;
823 end
824 end 741 end
825 endcase 742 endcase
826 743
@@ -878,6 +795,8 @@ always_ff @(posedge clk) begin
878 795
879 rx_ready = !tti_valid; 796 rx_ready = !tti_valid;
880 end 797 end
798
799 mem_read_ready = !mem_hold_valid;
881 end 800 end
882end 801end
883 802