@@ -54,7 +54,14 @@ entity SPPU is
5454 HDE : out std_logic ;
5555 VDE : out std_logic ;
5656
57- BG_EN : in std_logic_vector (4 downto 0 )
57+ BG_EN : in std_logic_vector (4 downto 0 );
58+
59+ -- Savestate: PPU register vector (640b). Layout is defined by the SS_DO
60+ -- concatenation in the architecture; the load branches in the owning
61+ -- processes slice SS_DI identically. SS_LOAD pulses while the core is paused.
62+ SS_DO : out std_logic_vector (639 downto 0 );
63+ SS_DI : in std_logic_vector (639 downto 0 ) := (others => '0' );
64+ SS_LOAD : in std_logic := '0'
5865 );
5966end SPPU;
6067
@@ -277,6 +284,34 @@ signal HIRES : std_logic;
277284
278285begin
279286
287+ -- Savestate save vector (640b). The load branches (in the owning processes)
288+ -- slice SS_DI in this exact same order; CGRAM_Lsb loads in the CGRAM process and
289+ -- H_CNT/V_CNT/FIELD/IN_HBL/IN_VBL load in the HV-counter process.
290+ SS_DO <= "00" & x"000000000000000" & -- [639:578] pad (62b)
291+ CGRAM_Lsb & -- [577:570]
292+ IN_VBL & IN_HBL & FIELD & -- [569:567]
293+ std_logic_vector (V_CNT) & std_logic_vector (H_CNT) & -- [566:549]
294+ EXTLATCHr & OAM_PRIO & OAM_PRIO_INDEX & OAM_ADDR & -- [548:530]
295+ OAM_latch & BGHOFS_latch & BGOFS_latch & M7_latch & -- [529:503]
296+ F_LATCH & OPVCT_latch & OPHCT_latch & -- [502:500]
297+ VRAMDATA_Prefetch & std_logic_vector (VMADD_INC) & -- [499:476]
298+ SUBCOLBD & OPVCT & OPHCT & -- [475:443]
299+ CGADSUB & CGWSEL & TSW & TMW & -- [442:411]
300+ WOBJLOG & WBGLOG & WOBJSEL & W34SEL & W12SEL & -- [410:371]
301+ WH3 & WH2 & WH1 & WH0 & -- [370:339]
302+ M7Y & M7X & M7VOFS & M7HOFS & -- [338:287]
303+ M7D & M7C & M7B & M7A & M7SEL & -- [286:215]
304+ BG_VOFS(3 ) & BG_VOFS(2 ) & BG_VOFS(1 ) & BG_VOFS(0 ) & -- [214:175]
305+ BG_HOFS(3 ) & BG_HOFS(2 ) & BG_HOFS(1 ) & BG_HOFS(0 ) & -- [174:135]
306+ VMADD & VMAIN_ADDRTRANS & VMAIN_ADDRINC & CGADD & -- [134:107]
307+ BG_NBA(3 ) & BG_NBA(2 ) & BG_NBA(1 ) & BG_NBA(0 ) & -- [106:91]
308+ BG_SC_SIZE(3 ) & BG_SC_SIZE(2 ) & BG_SC_SIZE(1 ) & BG_SC_SIZE(0 ) & -- [90:83]
309+ BG_SC_ADDR(3 ) & BG_SC_ADDR(2 ) & BG_SC_ADDR(1 ) & BG_SC_ADDR(0 ) & -- [82:59]
310+ MOSAIC_SIZE & BG_MOSAIC_EN & BG_SIZE & BG3PRIO & BG_MODE & -- [58:43]
311+ M7EXTBG & PSEUDOHIRES & OVERSCAN & OBJINTERLACE & BGINTERLACE & -- [42:38]
312+ TS & TM & OAMADD & -- [37:13]
313+ OBJSIZE & OBJNAME & OBJADDR & MB & FORCE_BLANK; -- [12:0]
314+
280315process ( RST_N, CLK )
281316variable DOT_CYCLES: unsigned (2 downto 0 );
282317begin
@@ -693,6 +728,93 @@ begin
693728 F_LATCH <= '1' ;
694729 end if ;
695730 end if ;
731+
732+ -- Savestate restore (last in the process so it overrides; core paused).
733+ -- Slices mirror the SS_DO concatenation exactly. H/V counters and the
734+ -- HV-latch state load in their own process.
735+ if SS_LOAD = '1' then
736+ FORCE_BLANK <= SS_DI(0 );
737+ MB <= SS_DI(4 downto 1 );
738+ OBJADDR <= SS_DI(7 downto 5 );
739+ OBJNAME <= SS_DI(9 downto 8 );
740+ OBJSIZE <= SS_DI(12 downto 10 );
741+ OAMADD <= SS_DI(21 downto 13 );
742+ TM <= SS_DI(29 downto 22 );
743+ TS <= SS_DI(37 downto 30 );
744+ BGINTERLACE <= SS_DI(38 );
745+ OBJINTERLACE <= SS_DI(39 );
746+ OVERSCAN <= SS_DI(40 );
747+ PSEUDOHIRES <= SS_DI(41 );
748+ M7EXTBG <= SS_DI(42 );
749+ BG_MODE <= SS_DI(45 downto 43 );
750+ BG3PRIO <= SS_DI(46 );
751+ BG_SIZE <= SS_DI(50 downto 47 );
752+ BG_MOSAIC_EN <= SS_DI(54 downto 51 );
753+ MOSAIC_SIZE <= SS_DI(58 downto 55 );
754+ BG_SC_ADDR(0 ) <= SS_DI(64 downto 59 );
755+ BG_SC_ADDR(1 ) <= SS_DI(70 downto 65 );
756+ BG_SC_ADDR(2 ) <= SS_DI(76 downto 71 );
757+ BG_SC_ADDR(3 ) <= SS_DI(82 downto 77 );
758+ BG_SC_SIZE(0 ) <= SS_DI(84 downto 83 );
759+ BG_SC_SIZE(1 ) <= SS_DI(86 downto 85 );
760+ BG_SC_SIZE(2 ) <= SS_DI(88 downto 87 );
761+ BG_SC_SIZE(3 ) <= SS_DI(90 downto 89 );
762+ BG_NBA(0 ) <= SS_DI(94 downto 91 );
763+ BG_NBA(1 ) <= SS_DI(98 downto 95 );
764+ BG_NBA(2 ) <= SS_DI(102 downto 99 );
765+ BG_NBA(3 ) <= SS_DI(106 downto 103 );
766+ CGADD <= SS_DI(115 downto 107 );
767+ VMAIN_ADDRINC <= SS_DI(116 );
768+ VMAIN_ADDRTRANS <= SS_DI(118 downto 117 );
769+ VMADD <= SS_DI(134 downto 119 );
770+ BG_HOFS(0 ) <= SS_DI(144 downto 135 );
771+ BG_HOFS(1 ) <= SS_DI(154 downto 145 );
772+ BG_HOFS(2 ) <= SS_DI(164 downto 155 );
773+ BG_HOFS(3 ) <= SS_DI(174 downto 165 );
774+ BG_VOFS(0 ) <= SS_DI(184 downto 175 );
775+ BG_VOFS(1 ) <= SS_DI(194 downto 185 );
776+ BG_VOFS(2 ) <= SS_DI(204 downto 195 );
777+ BG_VOFS(3 ) <= SS_DI(214 downto 205 );
778+ M7SEL <= SS_DI(222 downto 215 );
779+ M7A <= SS_DI(238 downto 223 );
780+ M7B <= SS_DI(254 downto 239 );
781+ M7C <= SS_DI(270 downto 255 );
782+ M7D <= SS_DI(286 downto 271 );
783+ M7HOFS <= SS_DI(299 downto 287 );
784+ M7VOFS <= SS_DI(312 downto 300 );
785+ M7X <= SS_DI(325 downto 313 );
786+ M7Y <= SS_DI(338 downto 326 );
787+ WH0 <= SS_DI(346 downto 339 );
788+ WH1 <= SS_DI(354 downto 347 );
789+ WH2 <= SS_DI(362 downto 355 );
790+ WH3 <= SS_DI(370 downto 363 );
791+ W12SEL <= SS_DI(378 downto 371 );
792+ W34SEL <= SS_DI(386 downto 379 );
793+ WOBJSEL <= SS_DI(394 downto 387 );
794+ WBGLOG <= SS_DI(402 downto 395 );
795+ WOBJLOG <= SS_DI(410 downto 403 );
796+ TMW <= SS_DI(418 downto 411 );
797+ TSW <= SS_DI(426 downto 419 );
798+ CGWSEL <= SS_DI(434 downto 427 );
799+ CGADSUB <= SS_DI(442 downto 435 );
800+ OPHCT <= SS_DI(451 downto 443 );
801+ OPVCT <= SS_DI(460 downto 452 );
802+ SUBCOLBD <= SS_DI(475 downto 461 );
803+ VMADD_INC <= unsigned (SS_DI(483 downto 476 ));
804+ VRAMDATA_Prefetch <= SS_DI(499 downto 484 );
805+ OPHCT_latch <= SS_DI(500 );
806+ OPVCT_latch <= SS_DI(501 );
807+ F_LATCH <= SS_DI(502 );
808+ M7_latch <= SS_DI(510 downto 503 );
809+ BGOFS_latch <= SS_DI(518 downto 511 );
810+ BGHOFS_latch <= SS_DI(521 downto 519 );
811+ OAM_latch <= SS_DI(529 downto 522 );
812+ OAM_ADDR <= SS_DI(539 downto 530 );
813+ OAM_PRIO_INDEX <= SS_DI(546 downto 540 );
814+ OAM_PRIO <= SS_DI(547 );
815+ EXTLATCHr <= SS_DI(548 );
816+ CGRAM_Lsb <= SS_DI(577 downto 570 );
817+ end if ;
696818 end if ;
697819end process ;
698820
@@ -895,6 +1017,15 @@ begin
8951017 if V_CNT = VSYNC_LINE+ 3 then VSYNC <= '0' ; end if ;
8961018 end if ;
8971019 end if ;
1020+
1021+ -- Savestate restore (last -> overrides; core paused). Slices mirror SS_DO.
1022+ if SS_LOAD = '1' then
1023+ H_CNT <= unsigned (SS_DI(557 downto 549 ));
1024+ V_CNT <= unsigned (SS_DI(566 downto 558 ));
1025+ FIELD <= SS_DI(567 );
1026+ IN_HBL <= SS_DI(568 );
1027+ IN_VBL <= SS_DI(569 );
1028+ end if ;
8981029 end if ;
8991030end process ;
9001031
0 commit comments