-
Notifications
You must be signed in to change notification settings - Fork 22
/
gs4510.vhdl
5133 lines (4819 loc) · 230 KB
/
gs4510.vhdl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
-- Accelerated 6502-like CPU for the C65GS
--
-- Written by
-- Paul Gardner-Stephen <[email protected]> 2013-2014
--
-- * ADC/SBC algorithm derived from 6510core.c - WICE MOS6510 emulation core.
-- * Written by
-- * Ettore Perazzoli <[email protected]>
-- * Andreas Boose <[email protected]>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License as
-- * published by the Free Software Foundation; either version 3 of the
-- * License, or (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-- * 02111-1307 USA.
-- @IO:C65 $D0A0-$D0FF - Reserved for C65 RAM Expansion Controller.
use WORK.ALL;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use Std.TextIO.all;
use work.debugtools.all;
use work.cputypes.all;
entity gs4510 is
port (
Clock : in std_logic;
ioclock : in std_logic;
reset : in std_logic;
irq : in std_logic;
nmi : in std_logic;
hyper_trap : in std_logic;
cpu_hypervisor_mode : out std_logic;
iomode_set : out std_logic_vector(1 downto 0) := "11";
iomode_set_toggle : out std_logic := '0';
cpuis6502 : out std_logic;
cpuspeed : out unsigned(7 downto 0);
irq_hypervisor : in std_logic_vector(2 downto 0) := "000"; -- JBM
no_kickstart : in std_logic;
ddr_counter : in unsigned(7 downto 0);
ddr_state : in unsigned(7 downto 0);
reg_isr_out : in unsigned(7 downto 0);
imask_ta_out : in std_logic;
monitor_char : out unsigned(7 downto 0);
monitor_char_toggle : out std_logic;
monitor_proceed : out std_logic;
monitor_waitstates : out unsigned(7 downto 0);
monitor_request_reflected : out std_logic;
monitor_hypervisor_mode : out std_logic;
monitor_ddr_ram_banking : out std_logic;
monitor_pc : out unsigned(15 downto 0);
monitor_state : out unsigned(15 downto 0);
monitor_instruction : out unsigned(7 downto 0);
monitor_watch : in unsigned(27 downto 0);
monitor_watch_match : out std_logic;
monitor_instructionpc : out unsigned(15 downto 0);
monitor_opcode : out unsigned(7 downto 0);
monitor_ibytes : out std_logic_vector(3 downto 0);
monitor_arg1 : out unsigned(7 downto 0);
monitor_arg2 : out unsigned(7 downto 0);
monitor_a : out unsigned(7 downto 0);
monitor_b : out unsigned(7 downto 0);
monitor_x : out unsigned(7 downto 0);
monitor_y : out unsigned(7 downto 0);
monitor_z : out unsigned(7 downto 0);
monitor_sp : out unsigned(15 downto 0);
monitor_p : out unsigned(7 downto 0);
monitor_map_offset_low : out unsigned(11 downto 0);
monitor_map_offset_high : out unsigned(11 downto 0);
monitor_map_enables_low : out std_logic_vector(3 downto 0);
monitor_map_enables_high : out std_logic_vector(3 downto 0);
monitor_interrupt_inhibit : out std_logic;
---------------------------------------------------------------------------
-- Memory access interface used by monitor
---------------------------------------------------------------------------
monitor_mem_address : in unsigned(27 downto 0);
monitor_mem_rdata : out unsigned(7 downto 0);
monitor_mem_wdata : in unsigned(7 downto 0);
monitor_mem_read : in std_logic;
monitor_mem_write : in std_logic;
monitor_mem_setpc : in std_logic;
monitor_mem_attention_request : in std_logic;
monitor_mem_attention_granted : out std_logic;
monitor_mem_trace_mode : in std_logic;
monitor_mem_stage_trace_mode : in std_logic;
monitor_mem_trace_toggle : in std_logic;
---------------------------------------------------------------------------
-- Interface to ChipRAM in video controller (just 128KB for now)
---------------------------------------------------------------------------
chipram_we : OUT STD_LOGIC := '0';
chipram_address : OUT unsigned(16 DOWNTO 0) := "00000000000000000";
chipram_datain : OUT unsigned(7 DOWNTO 0);
---------------------------------------------------------------------------
-- Interface to Slow RAM (128MB DDR2 RAM (or 16MB cellular RAM chip on
-- original non-DDR Nexys4 boards)
---------------------------------------------------------------------------
slowram_addr_reflect : in std_logic_vector(26 downto 0);
slowram_datain_reflect : in std_logic_vector(7 downto 0);
slowram_addr : out std_logic_vector(26 downto 0);
slowram_we : out std_logic := '0';
slowram_request_toggle : out std_logic := '0';
slowram_done_toggle : in std_logic;
slowram_datain : out std_logic_vector(7 downto 0);
-- simple-dual-port cache RAM interface so that CPU doesn't have to read
-- data cross-clock
cache_address : out std_logic_vector(8 downto 0);
cache_read_data : in std_logic_vector(150 downto 0);
cpu_leds : out std_logic_vector(3 downto 0);
---------------------------------------------------------------------------
-- Control CPU speed. Use
---------------------------------------------------------------------------
-- C128 2MHZ ($D030) : C65 FAST ($D031) : C65GS FAST ($D054)
-- ~1MHz 0 : 0 : X
-- ~2MHz 1 : 0 : 0
-- ~3.5MHz 0 : 1 : 0
-- 48MHz 1 : X : 1
-- 48MHz X : 1 : 1
---------------------------------------------------------------------------
vicii_2mhz : in std_logic;
viciii_fast : in std_logic;
viciv_fast : in std_logic;
speed_gate : in std_logic;
speed_gate_enable : out std_logic := '1';
---------------------------------------------------------------------------
-- fast IO port (clocked at core clock). 1MB address space
---------------------------------------------------------------------------
fastio_addr : inout std_logic_vector(19 downto 0);
fastio_read : out std_logic;
fastio_write : out std_logic;
fastio_wdata : out std_logic_vector(7 downto 0);
fastio_rdata : in std_logic_vector(7 downto 0);
sector_buffer_mapped : in std_logic;
fastio_vic_rdata : in std_logic_vector(7 downto 0);
fastio_colour_ram_rdata : in std_logic_vector(7 downto 0);
colour_ram_cs : out std_logic;
charrom_write_cs : out std_logic;
viciii_iomode : in std_logic_vector(1 downto 0);
colourram_at_dc00 : in std_logic;
rom_at_e000 : in std_logic;
rom_at_c000 : in std_logic;
rom_at_a000 : in std_logic;
rom_at_8000 : in std_logic;
---------------------------------------------------------------------------
-- IO port to far call stack
---------------------------------------------------------------------------
farcallstack_we : out std_logic := '0';
farcallstack_addr : out std_logic_vector(8 downto 0) := (others => '0');
farcallstack_din : out std_logic_vector(63 downto 0) := (others => '0');
farcallstack_dout : in std_logic_vector(63 downto 0) := (others => '0')
);
end entity gs4510;
architecture Behavioural of gs4510 is
component shadowram is
port (Clk : in std_logic;
address : in integer range 0 to 131071;
we : in std_logic;
data_i : in unsigned(7 downto 0);
data_o : out unsigned(7 downto 0);
no_writes : out unsigned(7 downto 0);
writes : out unsigned(7 downto 0)
);
end component;
-- Pre-calculated long addresses for 16 by 4KB sections.
-- (used to flatten logic depth)
type address_block_array is array(31 downto 0) of unsigned(31 downto 0);
signal block_addresses : address_block_array;
signal block_update_number : integer range 0 to 31 := 0;
signal reset_drive : std_logic := '0';
signal force_fast : std_logic := '0';
signal speed_gate_enable_internal : std_logic := '1';
signal iomode_set_toggle_internal : std_logic := '0';
signal rom_from_colour_ram : std_logic := '0';
signal rom_writeprotect : std_logic := '0';
-- Instruction log
signal last_instruction_pc : unsigned(15 downto 0) := x"FFFF";
signal last_opcode : unsigned(7 downto 0);
signal last_byte2 : unsigned(7 downto 0);
signal last_byte3 : unsigned(7 downto 0);
signal last_bytecount : integer range 0 to 3 := 0;
signal last_action : character := ' ';
signal last_address : unsigned(27 downto 0);
signal last_value : unsigned(7 downto 0);
-- Shadow RAM control
signal shadow_bank : unsigned(7 downto 0);
signal shadow_address : integer range 0 to 131071;
signal shadow_rdata : unsigned(7 downto 0);
signal shadow_wdata : unsigned(7 downto 0);
signal shadow_write_count : unsigned(7 downto 0);
signal shadow_no_write_count : unsigned(7 downto 0);
signal shadow_try_write_count : unsigned(7 downto 0) := x"00";
signal shadow_observed_write_count : unsigned(7 downto 0) := x"00";
signal shadow_write : std_logic := '0';
-- ROM RAM control
signal rom_address : integer range 0 to 131071;
signal rom_rdata : unsigned(7 downto 0);
signal rom_wdata : unsigned(7 downto 0);
signal rom_write_count : unsigned(7 downto 0);
signal rom_no_write_count : unsigned(7 downto 0);
signal rom_write : std_logic := '0';
-- GeoRAM emulation: by default point it somewhere at the DDR RAM
signal georam_page : unsigned(19 downto 0) := x"e0000";
signal georam_blockmask : unsigned(7 downto 0) := x"ff";
signal georam_block : unsigned(7 downto 0) := x"00";
signal georam_blockpage : unsigned(7 downto 0) := x"00";
-- REU emulation
signal reu_reg_status : unsigned(7 downto 0) := x"00"; -- read only
signal reu_cmd_autoload : std_logic := '0';
signal reu_cmd_ff00decode : std_logic := '0';
signal reu_cmd_operation : std_logic_vector(1 downto 0) := "00";
signal reu_c64_startaddr : unsigned(15 downto 0) := x"0000";
signal reu_reu_startaddr : unsigned(23 downto 0) := x"000000";
signal reu_transfer_length : unsigned(15 downto 0) := x"0000";
signal reu_useless_interrupt_mask : unsigned(7 downto 5) := "000";
signal reu_hold_c64_address : std_logic := '0';
signal reu_hold_reu_address : std_logic := '0';
signal reu_ff00_pending : std_logic := '0';
signal last_fastio_addr : std_logic_vector(19 downto 0);
signal last_write_address : unsigned(27 downto 0);
signal shadow_write_flags : unsigned(3 downto 0) := "0000";
-- Registers to hold delayed write to hypervisor and related CPU registers
-- to improve CPU timing closure.
signal last_write_value : unsigned(7 downto 0);
signal last_write_pending : std_logic := '0';
-- On the original Nexys4 board:
-- SlowRAM has 70ns access time, so need some wait states.
-- At 48MHz we only need 4 cycles.
-- (had +2 extra for drive stages)
-- On the Nexys4DDR board, the DDR2 ram is annoying MUCH slower,
-- requiring $16 = 22 cycles to be reliable!
-- We really are going to want to have a slowram cache!
-- It will be fairly trivial to read 128 bits (16 bytes) of slowram at a time
-- and cache that, since that is exactly how the DDR RAM module wrapper works
-- internally. Thus for sequential memory accesses, we can get 16 bytes every
-- 22 cycles, and potentially service memory reads with just one wait-state on
-- average (although the CPU state machine would make this a little interesting
-- to achieve. 2 wait states on the other hand would be quite achievable, and
-- would still be 3x the speed of slowram currently.
-- Shadow RAM has 0 wait states by default
-- IO has one waitstate for reading, 0 for writing
-- (Reading incurrs an extra waitstate due to read_data_copy)
-- XXX An extra wait state seems to be necessary when reading from dual-port
-- memories like colour ram.
constant slowram_48mhz : unsigned(7 downto 0) := x"ff";
constant ioread_48mhz : unsigned(7 downto 0) := x"01";
constant colourread_48mhz : unsigned(7 downto 0) := x"02";
constant iowrite_48mhz : unsigned(7 downto 0) := x"00";
constant shadow_48mhz : unsigned(7 downto 0) := x"00";
--constant slowram_3mhz : unsigned(7 downto 0) := x"0d";
--constant ioread_3mhz : unsigned(7 downto 0) := x"0d";
--constant colourread_3mhz : unsigned(7 downto 0) := x"0d";
--constant iowrite_3mhz : unsigned(7 downto 0) := x"0d";
--constant shadow_3mhz : unsigned(7 downto 0) := x"0d";
--constant slowram_2mhz : unsigned(7 downto 0) := x"1b";
--constant ioread_2mhz : unsigned(7 downto 0) := x"1b";
--constant colourread_2mhz : unsigned(7 downto 0) := x"1b";
--constant iowrite_2mhz : unsigned(7 downto 0) := x"1b";
--constant shadow_2mhz : unsigned(7 downto 0) := x"1b";
--constant slowram_1mhz : unsigned(7 downto 0) := x"2f";
--constant ioread_1mhz : unsigned(7 downto 0) := x"2f";
--constant colourread_1mhz : unsigned(7 downto 0) := x"2f";
--constant iowrite_1mhz : unsigned(7 downto 0) := x"2f";
--constant shadow_1mhz : unsigned(7 downto 0) := x"2f";
signal slowram_waitstates : unsigned(7 downto 0) := slowram_48mhz;
signal shadow_wait_states : unsigned(7 downto 0) := shadow_48mhz;
signal io_read_wait_states : unsigned(7 downto 0) := ioread_48mhz;
signal colourram_read_wait_states : unsigned(7 downto 0) := colourread_48mhz;
signal io_write_wait_states : unsigned(7 downto 0) := iowrite_48mhz;
signal slowram_request_toggle_drive : std_logic := '0';
signal slowram_desired_done_toggle : std_logic := '0';
signal slowram_data_valid : std_logic := '0';
signal slowram_pending_write : std_logic := '0';
-- Number of pending wait states
signal wait_states : unsigned(7 downto 0) := x"05";
signal wait_states_non_zero : std_logic := '1';
signal word_flag : std_logic := '0';
-- DMAgic registers
signal dmagic_list_counter : integer range 0 to 12;
signal dmagic_first_read : std_logic;
signal reg_dmagic_addr : unsigned(27 downto 0) := x"0000000";
signal reg_dmagic_withio : std_logic;
signal reg_dmagic_status : unsigned(7 downto 0) := x"00";
signal reg_dmacount : unsigned(7 downto 0) := x"00"; -- number of DMA jobs done
signal dma_pending : std_logic := '0';
signal dma_checksum : unsigned(23 downto 0) := x"000000";
signal dmagic_cmd : unsigned(7 downto 0);
signal dmagic_count : unsigned(15 downto 0);
signal dmagic_tally : unsigned(15 downto 0);
signal reg_dmagic_src_mb : unsigned(7 downto 0);
signal dmagic_src_addr : unsigned(27 downto 0);
signal dmagic_src_io : std_logic;
signal dmagic_src_direction : std_logic;
signal dmagic_src_modulo : std_logic;
signal dmagic_src_hold : std_logic;
signal reg_dmagic_dst_mb : unsigned(7 downto 0);
signal dmagic_dest_addr : unsigned(27 downto 0);
signal dmagic_dest_io : std_logic;
signal dmagic_dest_direction : std_logic;
signal dmagic_dest_modulo : std_logic;
signal dmagic_dest_hold : std_logic;
signal dmagic_modulo : unsigned(15 downto 0);
-- Temporary registers used while loading DMA list
signal dmagic_dest_bank_temp : unsigned(7 downto 0);
signal dmagic_src_bank_temp : unsigned(7 downto 0);
-- CPU internal state
signal flag_c : std_logic; -- carry flag
signal flag_z : std_logic; -- zero flag
signal flag_d : std_logic; -- decimal mode flag
signal flag_n : std_logic; -- negative flag
signal flag_v : std_logic; -- positive flag
signal flag_i : std_logic; -- interrupt disable flag
signal flag_e : std_logic; -- 8-bit stack flag
signal reg_a : unsigned(7 downto 0);
signal reg_b : unsigned(7 downto 0);
signal reg_x : unsigned(7 downto 0);
signal reg_y : unsigned(7 downto 0);
signal reg_z : unsigned(7 downto 0);
signal reg_sp : unsigned(7 downto 0);
signal reg_sph : unsigned(7 downto 0);
signal reg_pc : unsigned(15 downto 0);
-- CPU RAM bank selection registers.
-- Now C65 style, but extended by 8 bits to give 256MB address space
signal reg_mb_low : unsigned(7 downto 0);
signal reg_mb_high : unsigned(7 downto 0);
signal reg_map_low : std_logic_vector(3 downto 0);
signal reg_map_high : std_logic_vector(3 downto 0);
signal reg_offset_low : unsigned(11 downto 0);
signal reg_offset_high : unsigned(11 downto 0);
-- Are we in hypervisor mode?
signal hypervisor_mode : std_logic := '1';
signal hypervisor_trap_port : unsigned (6 downto 0);
-- Have we ever replaced the hypervisor with another?
-- (used to allow once-only update of hypervisor by kick-up file)
signal hypervisor_upgraded : std_logic := '0';
-- Duplicates of all CPU registers to hold user-space contents when trapping
-- to hypervisor.
signal hyper_iomode : unsigned(7 downto 0);
signal hyper_dmagic_src_mb : unsigned(7 downto 0);
signal hyper_dmagic_dst_mb : unsigned(7 downto 0);
signal hyper_dmagic_list_addr : unsigned(27 downto 0);
signal hyper_p : unsigned(7 downto 0);
signal hyper_a : unsigned(7 downto 0);
signal hyper_b : unsigned(7 downto 0);
signal hyper_x : unsigned(7 downto 0);
signal hyper_y : unsigned(7 downto 0);
signal hyper_z : unsigned(7 downto 0);
signal hyper_sp : unsigned(7 downto 0);
signal hyper_sph : unsigned(7 downto 0);
signal hyper_pc : unsigned(15 downto 0);
signal hyper_mb_low : unsigned(7 downto 0);
signal hyper_mb_high : unsigned(7 downto 0);
signal hyper_port_00 : unsigned(7 downto 0);
signal hyper_port_01 : unsigned(7 downto 0);
signal hyper_map_low : std_logic_vector(3 downto 0);
signal hyper_map_high : std_logic_vector(3 downto 0);
signal hyper_map_offset_low : unsigned(11 downto 0);
signal hyper_map_offset_high : unsigned(11 downto 0);
-- Page table for virtual memory
signal reg_page0_logical : unsigned(15 downto 0);
signal reg_page0_physical : unsigned(15 downto 0);
signal reg_page1_logical : unsigned(15 downto 0);
signal reg_page1_physical : unsigned(15 downto 0);
signal reg_page2_logical : unsigned(15 downto 0);
signal reg_page2_physical : unsigned(15 downto 0);
signal reg_page3_logical : unsigned(15 downto 0);
signal reg_page3_physical : unsigned(15 downto 0);
signal reg_pagenumber : unsigned(17 downto 0);
signal reg_pages_dirty : std_logic_vector(3 downto 0);
signal reg_pageid : unsigned(1 downto 0);
signal reg_pageactive : std_logic := '0';
-- Flags to detect interrupts
signal map_interrupt_inhibit : std_logic := '0';
signal nmi_pending : std_logic := '0';
signal irq_pending : std_logic := '0';
signal nmi_state : std_logic := '1';
signal no_interrupt : std_logic := '0';
signal hyper_trap_pending : std_logic := '0';
signal hyper_trap_state : std_logic := '1';
-- Interrupt/reset vector being used
signal vector : unsigned(3 downto 0);
-- Information about instruction currently being executed
signal reg_opcode : unsigned(7 downto 0);
signal reg_arg1 : unsigned(7 downto 0);
signal reg_arg2 : unsigned(7 downto 0);
signal bbs_or_bbc : std_logic;
signal bbs_bit : unsigned(2 downto 0);
-- PC used for JSR is the value of reg_pc after reading only one of
-- of the argument bytes. We could subtract one, but it is less logic to
-- just remember PC after reading one argument byte.
signal reg_pc_jsr : unsigned(15 downto 0);
-- Temporary address register (used for indirect modes)
signal reg_addr : unsigned(15 downto 0);
-- ... and this one for 32-bit flat addressing modes
signal reg_addr32 : unsigned(31 downto 0);
-- ... and this one for pushing 32bit virtual address onto the stack
signal reg_addr32save : unsigned(31 downto 0);
-- Upper and lower
-- 16 bits of temporary address register. Used for 32-bit
-- absolute addresses
signal reg_addr_msbs : unsigned(15 downto 0);
signal reg_addr_lsbs : unsigned(15 downto 0);
-- Flag that indicates if a ($nn),Z access is using a 32-bit pointer
signal absolute32_addressing_enabled : std_logic := '0';
-- Flag that indicates far JMP, JSR or RTS
-- (set by two CLD's in a row before the instruction)
signal flat32_address : std_logic := '0';
signal flat32_address_prime : std_logic := '0';
signal flat32_enabled : std_logic := '1';
-- flag for progressive carry calculation when loading a 32-bit pointer
signal pointer_carry : std_logic;
-- Temporary value holder (used for RMW instructions)
signal reg_t : unsigned(7 downto 0);
signal reg_t_high : unsigned(7 downto 0);
signal instruction_phase : unsigned(3 downto 0);
-- Indicate source of operand for instructions
-- Note that ROM is actually implemented using
-- power-on initialised RAM in the FPGA mapped via our io interface.
signal accessing_shadow : std_logic;
signal accessing_rom : std_logic;
signal accessing_fastio : std_logic;
signal accessing_vic_fastio : std_logic;
signal accessing_colour_ram_fastio : std_logic;
-- signal accessing_ram : std_logic;
signal accessing_slowram : std_logic;
signal accessing_cpuport : std_logic;
signal accessing_hypervisor : std_logic;
signal cpuport_num : unsigned(3 downto 0);
signal hyperport_num : unsigned(5 downto 0);
signal cpuport_ddr : unsigned(7 downto 0) := x"FF";
signal cpuport_value : unsigned(7 downto 0) := x"3F";
signal the_read_address : unsigned(27 downto 0);
signal monitor_mem_trace_toggle_last : std_logic := '0';
-- Microcode data and ALU routing signals follow:
signal mem_reading : std_logic := '0';
signal pop_a : std_logic := '0';
signal pop_p : std_logic := '0';
signal pop_x : std_logic := '0';
signal pop_y : std_logic := '0';
signal pop_z : std_logic := '0';
signal mem_reading_p : std_logic := '0';
-- serial monitor is reading data
signal monitor_mem_reading : std_logic := '0';
-- Is CPU free to proceed with processing an instruction?
signal proceed : std_logic := '1';
signal read_data_copy : unsigned(7 downto 0);
type instruction_property is array(0 to 255) of std_logic;
signal op_is_single_cycle : instruction_property := (
16#03# => '1',
16#0A# => '1',
16#0B# => '1',
16#18# => '1',
16#1A# => '1',
16#1B# => '1',
16#2A# => '1',
16#2B# => '1',
16#38# => '1',
16#3A# => '1',
16#3B# => '1',
16#42# => '1',
16#43# => '1',
16#4A# => '1',
16#4B# => '1',
16#5B# => '1',
16#6A# => '1',
16#6B# => '1',
16#78# => '1',
16#7B# => '1',
16#88# => '1',
16#8A# => '1',
16#98# => '1',
16#9A# => '1',
16#A8# => '1',
16#AA# => '1',
16#B8# => '1',
16#BA# => '1',
16#C8# => '1',
16#CA# => '1',
16#D8# => '1',
16#E8# => '1',
16#EA# => '1',
16#F8# => '1',
others => '0'
);
-- Pause 1usec per cycle of instruction for 1MHz operation
-- This is only approximate, because it doesnt count the time spent
-- executing the instruction, or the cycle to setup the delay.
-- Offsetting this is the lack of badlines, so the end result is probably
-- close enough for now. It can be improved later to allow for more exact
-- timing for demos etc.
constant pause_per_cycle : integer := 48;
signal pause_cycles : unsigned(8 downto 0) := "000000000";
signal pause_cycles_counter : unsigned(8 downto 0) := "000000000";
signal cpu_pause_shift : integer range 0 to 2 := 0;
signal vector_read_stage : integer range 0 to 15 := 0;
type memory_source is (
DMAgicRegister,
HypervisorRegister,
CPUPort,
Shadow,
ROMRAM,
FastIO,
ColourRAM,
VICIV,
SlowRAM,
Unmapped
);
signal read_source : memory_source;
type processor_state is (
-- Reset and interrupts
ResetLow,
ResetReady,
Interrupt,InterruptPushPCL,InterruptPushP,
VectorRead,
-- Hypervisor traps
TrapToHypervisor,ReturnFromHypervisor,
-- DMAgic
DMAgicTrigger,DMAgicReadList,DMAgicGetReady,
DMAgicFill,
DMAgicCopyRead,DMAgicCopyWrite,
DMAgicRead,DMAgicWrite,
-- Normal instructions
InstructionWait, -- Wait for PC to become available on
-- interrupt/reset
ProcessorHold,
ProcessorPause,
ProcessorPausing,
MonitorMemoryAccess,
InstructionFetch,
InstructionDecode, -- $16
InstructionDecode6502,
Cycle2,Cycle3,
Flat32Got2ndArgument,Flat32Byte3,Flat32Byte4,
Flat32SaveAddress,
Flat32SaveAddress1,Flat32SaveAddress2,Flat32SaveAddress3,Flat32SaveAddress4,
Flat32Dereference0,
Flat32Dereference1,Flat32Dereference2,Flat32Dereference3,Flat32Dereference4,
Flat32Translate,Flat32Dispatch,
Flat32RTS,
Pull,
RTI,RTI2,
RTS,RTS1,RTS2,RTS3,
B16TakeBranch,
InnXReadVectorLow,
InnXReadVectorHigh,
InnSPYReadVectorLow,
InnSPYReadVectorHigh,
InnYReadVectorLow,
InnYReadVectorHigh,
InnZReadVectorLow,
InnZReadVectorHigh,
InnZReadVectorByte2,
InnZReadVectorByte3,
InnZReadVectorByte4,
CallSubroutine,CallSubroutine2,
ZPRelReadZP,
JumpAbsXReadArg2,
JumpIAbsReadArg2,
JumpIAbsXReadArg2,
JumpDereference,
JumpDereference2,
JumpDereference3,
TakeBranch8,
LoadTarget,
WriteCommit,DummyWrite,
WordOpReadHigh,
WordOpWriteLow,
WordOpWriteHigh,
PushWordLow,PushWordHigh,
Pop,
MicrocodeInterpret
);
signal state : processor_state := ResetLow;
signal fast_fetch_state : processor_state := InstructionDecode;
signal normal_fetch_state : processor_state := InstructionFetch;
signal reg_microcode : microcodeops;
constant mode_bytes_lut : mode_list := (
M_impl => 0,
M_InnX => 1,
M_nn => 1,
M_immnn => 1,
M_A => 0,
M_nnnn => 2,
M_nnrr => 2,
M_rr => 1,
M_InnY => 1,
M_InnZ => 1,
M_rrrr => 2,
M_nnX => 1,
M_nnnnY => 2,
M_nnnnX => 2,
M_Innnn => 2,
M_InnnnX => 2,
M_InnSPY => 1,
M_nnY => 1,
M_immnnnn => 2);
constant instruction_lut : ilut9bit := (
-- 4502 personality
I_BRK,I_ORA,I_CLE,I_SEE,I_TSB,I_ORA,I_ASL,I_RMB,I_PHP,I_ORA,I_ASL,I_TSY,I_TSB,I_ORA,I_ASL,I_BBR,
I_BPL,I_ORA,I_ORA,I_BPL,I_TRB,I_ORA,I_ASL,I_RMB,I_CLC,I_ORA,I_INC,I_INZ,I_TRB,I_ORA,I_ASL,I_BBR,
I_JSR,I_AND,I_JSR,I_JSR,I_BIT,I_AND,I_ROL,I_RMB,I_PLP,I_AND,I_ROL,I_TYS,I_BIT,I_AND,I_ROL,I_BBR,
I_BMI,I_AND,I_AND,I_BMI,I_BIT,I_AND,I_ROL,I_RMB,I_SEC,I_AND,I_DEC,I_DEZ,I_BIT,I_AND,I_ROL,I_BBR,
I_RTI,I_EOR,I_NEG,I_ASR,I_ASR,I_EOR,I_LSR,I_RMB,I_PHA,I_EOR,I_LSR,I_TAZ,I_JMP,I_EOR,I_LSR,I_BBR,
I_BVC,I_EOR,I_EOR,I_BVC,I_ASR,I_EOR,I_LSR,I_RMB,I_CLI,I_EOR,I_PHY,I_TAB,I_MAP,I_EOR,I_LSR,I_BBR,
I_RTS,I_ADC,I_RTS,I_BSR,I_STZ,I_ADC,I_ROR,I_RMB,I_PLA,I_ADC,I_ROR,I_TZA,I_JMP,I_ADC,I_ROR,I_BBR,
I_BVS,I_ADC,I_ADC,I_BVS,I_STZ,I_ADC,I_ROR,I_RMB,I_SEI,I_ADC,I_PLY,I_TBA,I_JMP,I_ADC,I_ROR,I_BBR,
I_BRA,I_STA,I_STA,I_BRA,I_STY,I_STA,I_STX,I_SMB,I_DEY,I_BIT,I_TXA,I_STY,I_STY,I_STA,I_STX,I_BBS,
I_BCC,I_STA,I_STA,I_BCC,I_STY,I_STA,I_STX,I_SMB,I_TYA,I_STA,I_TXS,I_STX,I_STZ,I_STA,I_STZ,I_BBS,
I_LDY,I_LDA,I_LDX,I_LDZ,I_LDY,I_LDA,I_LDX,I_SMB,I_TAY,I_LDA,I_TAX,I_LDZ,I_LDY,I_LDA,I_LDX,I_BBS,
I_BCS,I_LDA,I_LDA,I_BCS,I_LDY,I_LDA,I_LDX,I_SMB,I_CLV,I_LDA,I_TSX,I_LDZ,I_LDY,I_LDA,I_LDX,I_BBS,
I_CPY,I_CMP,I_CPZ,I_DEW,I_CPY,I_CMP,I_DEC,I_SMB,I_INY,I_CMP,I_DEX,I_ASW,I_CPY,I_CMP,I_DEC,I_BBS,
I_BNE,I_CMP,I_CMP,I_BNE,I_CPZ,I_CMP,I_DEC,I_SMB,I_CLD,I_CMP,I_PHX,I_PHZ,I_CPZ,I_CMP,I_DEC,I_BBS,
I_CPX,I_SBC,I_LDA,I_INW,I_CPX,I_SBC,I_INC,I_SMB,I_INX,I_SBC,I_EOM,I_ROW,I_CPX,I_SBC,I_INC,I_BBS,
I_BEQ,I_SBC,I_SBC,I_BEQ,I_PHW,I_SBC,I_INC,I_SMB,I_SED,I_SBC,I_PLX,I_PLZ,I_PHW,I_SBC,I_INC,I_BBS,
-- 6502 personality
-- XXX Currently just a copy of 4502 personality
I_BRK,I_ORA,I_KIL,I_SLO,I_NOP,I_ORA,I_ASL,I_SLO,I_PHP,I_ORA,I_ASL,I_ANC,I_NOP,I_ORA,I_ASL,I_SLO,
I_BPL,I_ORA,I_KIL,I_SLO,I_NOP,I_ORA,I_ASL,I_SLO,I_CLC,I_ORA,I_NOP,I_SLO,I_NOP,I_ORA,I_ASL,I_SLO,
I_JSR,I_AND,I_KIL,I_RLA,I_BIT,I_AND,I_ROL,I_RLA,I_PLP,I_AND,I_ROL,I_ANC,I_BIT,I_AND,I_ROL,I_RLA,
I_BMI,I_AND,I_KIL,I_RLA,I_NOP,I_AND,I_ROL,I_RLA,I_SEC,I_AND,I_NOP,I_RLA,I_NOP,I_AND,I_ROL,I_RLA,
I_RTI,I_EOR,I_KIL,I_SRE,I_NOP,I_EOR,I_LSR,I_SRE,I_PHA,I_EOR,I_LSR,I_ALR,I_JMP,I_EOR,I_LSR,I_SRE,
I_BVC,I_EOR,I_KIL,I_SRE,I_NOP,I_EOR,I_LSR,I_SRE,I_CLI,I_EOR,I_NOP,I_SRE,I_NOP,I_EOR,I_LSR,I_SRE,
I_RTS,I_ADC,I_KIL,I_RRA,I_NOP,I_ADC,I_ROR,I_RRA,I_PLA,I_ADC,I_ROR,I_ARR,I_JMP,I_ADC,I_ROR,I_RRA,
I_BVS,I_ADC,I_KIL,I_RRA,I_NOP,I_ADC,I_ROR,I_RRA,I_SEI,I_ADC,I_NOP,I_RRA,I_NOP,I_ADC,I_ROR,I_RRA,
I_NOP,I_STA,I_NOP,I_SAX,I_STY,I_STA,I_STX,I_SAX,I_DEY,I_NOP,I_TXA,I_XAA,I_STY,I_STA,I_STX,I_SAX,
I_BCC,I_STA,I_KIL,I_AHX,I_STY,I_STA,I_STX,I_SAX,I_TYA,I_STA,I_TXS,I_TAS,I_SHY,I_STA,I_SHX,I_AHX,
I_LDY,I_LDA,I_LDX,I_LAX,I_LDY,I_LDA,I_LDX,I_LAX,I_TAY,I_LDA,I_TAX,I_LAX,I_LDY,I_LDA,I_LDX,I_LAX,
I_BCS,I_LDA,I_KIL,I_LAX,I_LDY,I_LDA,I_LDX,I_LAX,I_CLV,I_LDA,I_TSX,I_LAS,I_LDY,I_LDA,I_LDX,I_LAX,
I_CPY,I_CMP,I_NOP,I_DCP,I_CPY,I_CMP,I_DEC,I_DCP,I_INY,I_CMP,I_DEX,I_AXS,I_CPY,I_CMP,I_DEC,I_DCP,
I_BNE,I_CMP,I_KIL,I_DCP,I_NOP,I_CMP,I_DEC,I_DCP,I_CLD,I_CMP,I_NOP,I_DCP,I_NOP,I_CMP,I_DEC,I_DCP,
I_CPX,I_SBC,I_NOP,I_ISC,I_CPX,I_SBC,I_INC,I_ISC,I_INX,I_SBC,I_NOP,I_SBC,I_CPX,I_SBC,I_INC,I_ISC,
I_BEQ,I_SBC,I_KIL,I_ISC,I_NOP,I_SBC,I_INC,I_ISC,I_SED,I_SBC,I_NOP,I_ISC,I_NOP,I_SBC,I_INC,I_ISC
);
type mlut9bit is array(0 to 511) of addressingmode;
constant mode_lut : mlut9bit := (
-- 4502 personality first
M_impl, M_InnX, M_impl, M_impl, M_nn, M_nn, M_nn, M_nn,
M_impl, M_immnn, M_A, M_impl, M_nnnn, M_nnnn, M_nnnn, M_nnrr,
M_rr, M_InnY, M_InnZ, M_rrrr, M_nn, M_nnX, M_nnX, M_nn,
M_impl, M_nnnnY, M_impl, M_impl, M_nnnn, M_nnnnX, M_nnnnX, M_nnrr,
M_nnnn, M_InnX, M_Innnn, M_InnnnX,M_nn, M_nn, M_nn, M_nn,
M_impl, M_immnn, M_A, M_impl, M_nnnn, M_nnnn, M_nnnn, M_nnrr,
M_rr, M_InnY, M_InnZ, M_rrrr, M_nnX, M_nnX, M_nnX, M_nn,
M_impl, M_nnnnY, M_impl, M_impl, M_nnnnX, M_nnnnX, M_nnnnX, M_nnrr,
M_impl, M_InnX, M_impl, M_impl, M_nn, M_nn, M_nn, M_nn,
M_impl, M_immnn, M_A, M_impl, M_nnnn, M_nnnn, M_nnnn, M_nnrr,
M_rr, M_InnY, M_InnZ, M_rrrr, M_nnX, M_nnX, M_nnX, M_nn,
M_impl, M_nnnnY, M_impl, M_impl, M_impl, M_nnnnX, M_nnnnX, M_nnrr,
-- $63 BSR $nnnn is 16-bit relative on the 4502. We treat it as absolute
-- mode, with microcode being used to select relative addressing.
M_impl, M_InnX, M_immnn, M_nnnn, M_nn, M_nn, M_nn, M_nn,
M_impl, M_immnn, M_A, M_impl, M_Innnn, M_nnnn, M_nnnn, M_nnrr,
M_rr, M_InnY, M_InnZ, M_rrrr, M_nnX, M_nnX, M_nnX, M_nn,
M_impl, M_nnnnY, M_impl, M_impl, M_InnnnX,M_nnnnX, M_nnnnX, M_nnrr,
M_rr, M_InnX, M_InnSPY,M_rrrr, M_nn, M_nn, M_nn, M_nn,
M_impl, M_immnn, M_impl, M_nnnnX, M_nnnn, M_nnnn, M_nnnn, M_nnrr,
M_rr, M_InnY, M_InnZ, M_rrrr, M_nnX, M_nnX, M_nnY, M_nn,
M_impl, M_nnnnY, M_impl, M_nnnnY, M_nnnn, M_nnnnX, M_nnnnX, M_nnrr,
M_immnn, M_InnX, M_immnn, M_immnn, M_nn, M_nn, M_nn, M_nn,
M_impl, M_immnn, M_impl, M_nnnn, M_nnnn, M_nnnn, M_nnnn, M_nnrr,
M_rr, M_InnY, M_InnZ, M_rrrr, M_nnX, M_nnX, M_nnY, M_nn,
M_impl, M_nnnnY, M_impl, M_nnnnX, M_nnnnX, M_nnnnX, M_nnnnY, M_nnrr,
M_immnn, M_InnX, M_immnn, M_nn, M_nn, M_nn, M_nn, M_nn,
M_impl, M_immnn, M_impl, M_nnnn, M_nnnn, M_nnnn, M_nnnn, M_nnrr,
M_rr, M_InnY, M_InnZ, M_rrrr, M_nn, M_nnX, M_nnX, M_nn,
M_impl, M_nnnnY, M_impl, M_impl, M_nnnn, M_nnnnX, M_nnnnX, M_nnrr,
M_immnn, M_InnX, M_InnSPY,M_nn, M_nn, M_nn, M_nn, M_nn,
M_impl, M_immnn, M_impl, M_nnnn, M_nnnn, M_nnnn, M_nnnn, M_nnrr,
M_rr, M_InnY, M_InnZ, M_rrrr, M_immnnnn,M_nnX, M_nnX, M_nn,
M_impl, M_nnnnY, M_impl, M_impl, M_nnnn, M_nnnnX, M_nnnnX, M_nnrr,
-- 6502 personality
-- XXX currently just a copy of 4502 personality
M_impl,M_InnX,M_impl,M_InnX,M_nn,M_nn,M_nn,M_nn,
M_impl,M_immnn,M_impl,M_immnn,M_nnnn,M_nnnn,M_nnnn,M_nnnn,
M_rr,M_InnY,M_impl,M_InnY,M_nnX,M_nnX,M_nnX,M_nnX,
M_impl,M_nnnnY,M_impl,M_nnnnY,M_nnnnX,M_nnnnX,M_nnnnX,M_nnnnX,
M_nnnn,M_InnX,M_impl,M_InnX,M_nn,M_nn,M_nn,M_nn,
M_impl,M_immnn,M_impl,M_immnn,M_nnnn,M_nnnn,M_nnnn,M_nnnn,
M_rr,M_InnY,M_impl,M_InnY,M_nnX,M_nnX,M_nnX,M_nnX,
M_impl,M_nnnnY,M_impl,M_nnnnY,M_nnnnX,M_nnnnX,M_nnnnX,M_nnnnX,
M_impl,M_InnX,M_impl,M_InnX,M_nn,M_nn,M_nn,M_nn,
M_impl,M_immnn,M_impl,M_immnn,M_nnnn,M_nnnn,M_nnnn,M_nnnn,
M_rr,M_InnY,M_impl,M_InnY,M_nnX,M_nnX,M_nnX,M_nnX,
M_impl,M_nnnnY,M_impl,M_nnnnY,M_nnnnX,M_nnnnX,M_nnnnX,M_nnnnX,
M_impl,M_InnX,M_impl,M_InnX,M_nn,M_nn,M_nn,M_nn,
M_impl,M_immnn,M_impl,M_immnn,M_Innnn,M_nnnn,M_nnnn,M_nnnn,
M_rr,M_InnY,M_impl,M_InnY,M_nnX,M_nnX,M_nnX,M_nnX,
M_impl,M_nnnnY,M_impl,M_nnnnY,M_nnnnX,M_nnnnX,M_nnnnX,M_nnnnX,
M_immnn,M_InnX,M_immnn,M_InnX,M_nn,M_nn,M_nn,M_nn,
M_impl,M_immnn,M_impl,M_immnn,M_nnnn,M_nnnn,M_nnnn,M_nnnn,
M_rr,M_InnY,M_impl,M_InnY,M_nnX,M_nnX,M_nnY,M_nnY,
M_impl,M_nnnnY,M_impl,M_nnnnY,M_nnnnX,M_nnnnX,M_nnnnY,M_nnnnY,
M_immnn,M_InnX,M_immnn,M_InnX,M_nn,M_nn,M_nn,M_nn,
M_impl,M_immnn,M_impl,M_immnn,M_nnnn,M_nnnn,M_nnnn,M_nnnn,
M_rr,M_InnY,M_impl,M_InnY,M_nnX,M_nnX,M_nnY,M_nnY,
M_impl,M_nnnnY,M_impl,M_nnnnY,M_nnnnX,M_nnnnX,M_nnnnY,M_nnnnY,
M_immnn,M_InnX,M_immnn,M_InnX,M_nn,M_nn,M_nn,M_nn,
M_impl,M_immnn,M_impl,M_immnn,M_nnnn,M_nnnn,M_nnnn,M_nnnn,
M_rr,M_InnY,M_impl,M_InnY,M_nnX,M_nnX,M_nnX,M_nnX,
M_impl,M_nnnnY,M_impl,M_nnnnY,M_nnnnX,M_nnnnX,M_nnnnX,M_nnnnX,
M_immnn,M_InnX,M_immnn,M_InnX,M_nn,M_nn,M_nn,M_nn,
M_impl,M_immnn,M_impl,M_immnn,M_nnnn,M_nnnn,M_nnnn,M_nnnn,
M_rr,M_InnY,M_impl,M_InnY,M_nnX,M_nnX,M_nnX,M_nnX,
M_impl,M_nnnnY,M_impl,M_nnnnY,M_nnnnX,M_nnnnX,M_nnnnX,M_nnnnX);
signal reg_addressingmode : addressingmode;
signal reg_instruction : instruction;
signal is_rmw : std_logic;
signal is_load : std_logic;
signal is_store : std_logic;
signal rmw_dummy_write_done : std_logic;
signal a_incremented : unsigned(7 downto 0);
signal a_decremented : unsigned(7 downto 0);
signal a_negated : unsigned(7 downto 0);
signal a_ror : unsigned(7 downto 0);
signal a_rol : unsigned(7 downto 0);
signal a_asl : unsigned(7 downto 0);
signal a_asr : unsigned(7 downto 0);
signal a_lsr : unsigned(7 downto 0);
signal a_ior : unsigned(7 downto 0);
signal a_xor : unsigned(7 downto 0);
signal a_and : unsigned(7 downto 0);
signal a_neg : unsigned(7 downto 0);
signal a_neg_z : std_logic;
signal a_add : unsigned(11 downto 0); -- has NVZC flags and result
signal a_sub : unsigned(11 downto 0); -- has NVZC flags and result
signal x_incremented : unsigned(7 downto 0);
signal x_decremented : unsigned(7 downto 0);
signal y_incremented : unsigned(7 downto 0);
signal y_decremented : unsigned(7 downto 0);
signal z_incremented : unsigned(7 downto 0);
signal z_decremented : unsigned(7 downto 0);
signal monitor_mem_attention_request_drive : std_logic;
signal monitor_mem_read_drive : std_logic;
signal monitor_mem_write_drive : std_logic;
signal monitor_mem_setpc_drive : std_logic;
signal monitor_mem_address_drive : unsigned(27 downto 0);
signal monitor_mem_wdata_drive : unsigned(7 downto 0);
signal debugging_single_stepping : std_logic := '0';
signal debug_count : integer range 0 to 5 := 0;
signal rmb_mask : unsigned(7 downto 0);
signal smb_mask : unsigned(7 downto 0);
signal ddr_ram_banking : std_logic := '0';
signal ddr_ram_bank : std_logic_vector(2 downto 0);
signal ddr_reply_counter : unsigned(7 downto 0) := x"00";
signal ddr_timeout_counter : unsigned(7 downto 0) := x"00";
signal ddr_cache_load_counter : unsigned(7 downto 0) := x"00";
signal ddr_write_ready_counter : unsigned(7 downto 0) := x"00";
signal ddr_got_reply : std_logic := '0';
signal slowram_addr_drive : std_logic_vector(26 downto 0);
signal slowram_addr_reflect_drive : std_logic_vector(26 downto 0);
signal slowram_data_in : std_logic_vector(7 downto 0);
signal slowram_datain_expected : std_logic_vector(7 downto 0);
signal slowram_datain_reflect_drive : std_logic_vector(7 downto 0);
signal slowram_we_drive : std_logic;
signal watchdog_reset : std_logic := '0';
signal watchdog_fed : std_logic := '0';
signal watchdog_countdown : integer range 0 to 65535;
signal emu6502 : std_logic := '0';
signal force_4502 : std_logic := '1';
signal monitor_char_toggle_internal : std_logic := '0';
type microcode_lut_t is array (instruction)
of microcodeops;
signal microcode_lut : microcode_lut_t := (
I_ADC => (mcADC => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_AND => (mcAND => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_ASL => (mcASL => '1', mcDelayedWrite => '1', others => '0'),
I_ASR => (mcASR => '1', mcDelayedWrite => '1', others => '0'),
I_ASW => (mcWordOp => '1', others => '0'),
-- I_BBR - handled elsewhere
-- I_BBS - handled elsewhere
-- I_BCC - handled elsewhere
-- I_BCS - handled elsewhere
-- I_BEQ - handled elsewhere
I_BIT => (mcBIT => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
-- I_BMI - handled elsewhere
-- I_BNE - handled elsewhere
-- I_BPL - handled elsewhere
-- I_BRA - handled elsewhere
I_BRK => (mcBRK => '1', others => '0'),
-- I_BSR - handled elsewhere
-- I_BVC - handled elsewhere
-- I_BVS - handled elsewhere
-- I_CLC - Handled as a single-cycle op elsewhere
-- I_CLD - handled as a single-cycle op elsewhere
I_CLE => (mcClearE => '1', mcDecPC => '1', others => '0'),
I_CLI => (mcClearI => '1', mcDecPC => '1', others => '0'),
-- I_CLV - handled as a single-cycle op elsewhere
I_CMP => (mcCMP => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_CPX => (mcCPX => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_CPY => (mcCPY => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_CPZ => (mcCPZ => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_DEC => (mcDEC => '1', mcDelayedWrite => '1', others => '0'),
I_DEW => (mcWordOp => '1', others => '0'),
-- I_EOM - handled as a single-cycle op elsewhere
I_EOR => (mcEOR => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_INC => (mcINC => '1', mcDelayedWrite => '1', others => '0'),
I_INW => (mcWordOp => '1', others => '0'),
-- I_INX - handled as a single-cycle op elsewhere
-- I_INY - handled as a single-cycle op elsewhere
-- I_INZ - handled as a single-cycle op elsewhere
I_JMP => (mcJump => '1', others => '0'),
I_JSR => (mcJump => '1', others => '0'),
I_LDA => (mcSetA => '1', mcSetNZ => '1', mcIncPC => '1',
mcInstructionFetch => '1', others => '0'),
I_LDX => (mcSetX => '1', mcSetNZ => '1', mcIncPC => '1',
mcInstructionFetch => '1', others => '0'),
I_LDY => (mcSetY => '1', mcSetNZ => '1', mcIncPC => '1',
mcInstructionFetch => '1', others => '0'),
I_LDZ => (mcSetZ => '1', mcSetNZ => '1', mcIncPC => '1',
mcInstructionFetch => '1', others => '0'),
I_LSR => (mcLSR => '1', mcDelayedWrite => '1', others => '0'),
I_MAP => (mcMap => '1', mcDecPC => '1', others => '0'),
-- I_NEG - handled as a single-cycle op elsewhere
I_ORA => (mcORA => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_PHA => (mcStoreA => '1', mcDecPC => '1', others => '0'),
I_PHP => (mcStoreP => '1', mcDecPC => '1', others => '0'),
I_PHW => (mcWordOp => '1', others => '0'),
I_PHX => (mcStoreX => '1', mcDecPC => '1', others => '0'),
I_PHY => (mcStoreY => '1', mcDecPC => '1', others => '0'),
I_PHZ => (mcStoreZ => '1', mcDecPC => '1', others => '0'),
I_PLA => (mcPop => '1', mcStackA => '1', mcDecPC => '1', others => '0'),
I_PLP => (mcPop => '1', mcStackP => '1', mcDecPC => '1', others => '0'),
I_PLX => (mcPop => '1', mcStackX => '1', mcDecPC => '1', others => '0'),
I_PLY => (mcPop => '1', mcStackY => '1', mcDecPC => '1', others => '0'),
I_PLZ => (mcPop => '1', mcStackZ => '1', mcDecPC => '1', others => '0'),
I_RMB => (mcRMB => '1', mcDelayedWrite => '1', others => '0'),
I_ROL => (mcROL => '1', mcDelayedWrite => '1', others => '0'),
I_ROR => (mcROR => '1', mcDelayedWrite => '1', others => '0'),
I_ROW => (mcWordOp => '1', others => '0'),
-- I_RTI - handled directly in gs4510.vhdl
-- I_RTS - handled directly in gs4510.vhdl
I_SBC => (mcSBC => '1', mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
-- I_SEC - handled as a single-cycle op elsewhere
-- I_SED - handled as a single-cycle op elsewhere
-- I_SEE - handled as a single-cycle op elsewhere
-- I_SEI - handled as a single-cycle op elsewhere
I_SMB => (mcSMB => '1', mcDelayedWrite => '1', others => '0'),
I_STA => (mcStoreA => '1', mcWriteMem => '1', mcInstructionFetch => '1',
mcWriteRegAddr => '1',mcIncPC => '1', others => '0'),
I_STX => (mcStoreX => '1', mcWriteMem => '1', mcInstructionFetch => '1',
mcWriteRegAddr => '1',mcIncPC => '1', others => '0'),
I_STY => (mcStoreY => '1', mcWriteMem => '1', mcInstructionFetch => '1',
mcWriteRegAddr => '1',mcIncPC => '1', others => '0'),
I_STZ => (mcStoreZ => '1', mcWriteMem => '1', mcInstructionFetch => '1',
mcWriteRegAddr => '1',mcIncPC => '1', others => '0'),
-- I_TAX - handled as a single-cycle op elsewhere
-- I_TAY - handled as a single-cycle op elsewhere
-- I_TAZ - handled as a single-cycle op elsewhere
-- I_TBA - handled as a single-cycle op elsewhere
I_TRB => (mcStoreTRB => '1', mcDelayedWrite => '1', mcTestAZ => '1',
others => '0'),
I_TSB => (mcStoreTSB => '1', mcDelayedWrite => '1', mcTestAZ => '1',
others => '0'),
-- I_TSX - handled as a single-cycle op elsewhere
-- I_TSY - handled as a single-cycle op elsewhere
-- I_TXA - handled as a single-cycle op elsewhere
-- I_TXS - handled as a single-cycle op elsewhere
-- I_TYA - handled as a single-cycle op elsewhere
-- I_TYS - handled as a single-cycle op elsewhere
-- I_TZA - handled as a single-cycle op elsewhere
-- 6502 illegals
-- XXX - incomplete: these have only the microcode for the "dominant" action
-- for the most part so far.
-- Shift left, then OR accumulator with result of operation
I_SLO => (mcASL => '1', mcORA => '1',
mcDelayedWrite => '1', others => '0'),
-- Rotate left, then AND accumulator with result of operation
I_RLA => (mcROL => '1', mcAND => '1',
mcDelayedWrite => '1', others => '0'),
-- LSR, then EOR accumulator with result of operation
I_SRE => (mcLSR => '1', mcEOR => '1',
mcDelayedWrite => '1', others => '0'),
-- Rotate right, then ADC accumulator with result of operation
I_RRA => (mcROR => '1', mcADC => '1',
mcDelayedWrite => '1', others => '0'),
-- Store AND of A and X: Doesn't touch any flags
I_SAX => (mcStoreA => '1', mcStoreX => '1',
mcWriteMem => '1', mcInstructionFetch => '1',
mcWriteRegAddr => '1',mcIncPC => '1', others => '0'),
-- Load A and X at the same time, one of the more useful results
I_LAX => (mcSetX => '1', mcSetA => '1',
mcSetNZ => '1', mcIncPC => '1',
mcInstructionFetch => '1', others => '0'),
-- Decrement, and then compare with accumulator
I_DCP => (mcDEC => '1', mcCMP => '1',
mcDelayedWrite => '1', others => '0'),
-- INC, then subtract result from accumulator
I_ISC => (mcINC => '1', mcSBC => '1',
mcDelayedWrite => '1', others => '0'),
-- Like AND, but pushes bit7 into C. Here we can simply enable both AND
-- and ROL in the microcode, and everything will already work.
I_ANC => (mcAND => '1', mcROL => '1',
mcInstructionFetch => '1', mcIncPC => '1',
-- XXX push bit7 to carry
others => '0'),
I_ALR => (mcAND => '1', mcLSR => '1',
mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_ARR => (mcROR => '1', mcDelayedWrite => '1', others => '0'),
I_XAA => (mcAND => '1',
mcInstructionFetch => '1', mcIncPC => '1', others => '0'),
I_AXS => (mcAND => '1', mcInstructionFetch => '1', mcIncPC => '1',