1 -------------------------------------------------------------
\r
2 -------------------------------------------------------------
\r
3 ------------------- PPU VGA Output Control ------------------
\r
4 -------------------------------------------------------------
\r
5 -------------------------------------------------------------
\r
7 use ieee.std_logic_1164.all;
\r
8 use ieee.std_logic_unsigned.conv_integer;
\r
9 use ieee.std_logic_arith.conv_std_logic_vector;
\r
10 use ieee.std_logic_unsigned.all;
\r
14 pi_rst_n : in std_logic;
\r
15 pi_base_clk : in std_logic;
\r
16 pi_rnd_en : in std_logic_vector (3 downto 0);
\r
19 pi_ppu_ctrl : in std_logic_vector (7 downto 0);
\r
20 pi_ppu_mask : in std_logic_vector (7 downto 0);
\r
21 po_ppu_status : out std_logic_vector (7 downto 0);
\r
22 pi_ppu_scroll_x : in std_logic_vector (7 downto 0);
\r
23 pi_ppu_scroll_y : in std_logic_vector (7 downto 0);
\r
26 po_v_ce_n : out std_logic;
\r
27 po_v_rd_n : out std_logic;
\r
28 po_v_wr_n : out std_logic;
\r
29 po_v_addr : out std_logic_vector (13 downto 0);
\r
30 pi_v_data : in std_logic_vector (7 downto 0);
\r
33 po_plt_ce_n : out std_logic;
\r
34 po_plt_rd_n : out std_logic;
\r
35 po_plt_wr_n : out std_logic;
\r
36 po_plt_addr : out std_logic_vector (4 downto 0);
\r
37 pi_plt_data : in std_logic_vector (7 downto 0);
\r
40 po_spr_ce_n : out std_logic;
\r
41 po_spr_rd_n : out std_logic;
\r
42 po_spr_wr_n : out std_logic;
\r
43 po_spr_addr : out std_logic_vector (7 downto 0);
\r
44 pi_spr_data : in std_logic_vector (7 downto 0);
\r
47 po_h_sync_n : out std_logic;
\r
48 po_v_sync_n : out std_logic;
\r
49 po_r : out std_logic_vector(3 downto 0);
\r
50 po_g : out std_logic_vector(3 downto 0);
\r
51 po_b : out std_logic_vector(3 downto 0)
\r
55 architecture rtl of render is
\r
58 --------- VGA screen constant -----------
\r
59 constant VGA_W : integer := 640;
\r
60 constant VGA_H : integer := 480;
\r
61 constant VGA_W_MAX : integer := 800;
\r
62 constant VGA_H_MAX : integer := 525;
\r
63 constant H_SYNC_S : integer := 660;
\r
64 constant H_SYNC_E : integer := 756;
\r
65 constant V_SYNC_S : integer := 494;
\r
66 constant V_SYNC_E : integer := 495;
\r
68 --nes screen size is emulated to align with the vga timing...
\r
69 constant HSCAN : integer := 256;
\r
70 constant VSCAN : integer := 240;
\r
71 constant HSCAN_NEXT_START : integer := 382;
\r
72 constant VSCAN_NEXT_START : integer := 262;
\r
73 constant HSCAN_SPR_MAX : integer := 321;
\r
74 constant HSCAN_OAM_EVA_START : integer := 64;
\r
76 constant PREFETCH_INT : integer := 16;
\r
78 constant PPUBNA : integer := 1; --base name address
\r
79 constant PPUVAI : integer := 2; --vram address increment
\r
80 constant PPUSPA : integer := 3; --sprite pattern table address
\r
81 constant PPUBPA : integer := 4; --background pattern table address
\r
82 constant PPUSPS : integer := 5; --sprite size
\r
83 constant PPUMS : integer := 6; --ppu master/slave
\r
84 constant PPUNEN : integer := 7; --nmi enable
\r
86 constant PPUGS : integer := 0; --grayscale
\r
87 constant PPUSBL : integer := 1; --show 8 left most bg pixel
\r
88 constant PPUSSL : integer := 2; --show 8 left most sprite pixel
\r
89 constant PPUSBG : integer := 3; --show bg
\r
90 constant PPUSSP : integer := 4; --show sprie
\r
91 constant PPUIR : integer := 5; --intensify red
\r
92 constant PPUIG : integer := 6; --intensify green
\r
93 constant PPUIB : integer := 7; --intensify blue
\r
95 constant SPRHFL : integer := 6; --flip sprigte horizontally
\r
96 constant SPRVFL : integer := 7; --flip sprigte vertically
\r
98 constant ST_BSY : integer := 4; --vram busy
\r
99 constant ST_SOF : integer := 5; --sprite overflow
\r
100 constant ST_SP0 : integer := 6; --sprite 0 hits
\r
101 constant ST_VBL : integer := 7; --vblank
\r
104 subtype nes_color_data is std_logic_vector (11 downto 0);
\r
105 type nes_color_array is array (0 to 63) of nes_color_data;
\r
106 --ref: http://hlc6502.web.fc2.com/NesPal2.htm
\r
107 constant nes_color_palette : nes_color_array := (
\r
108 conv_std_logic_vector(16#777#, 12),
\r
109 conv_std_logic_vector(16#20b#, 12),
\r
110 conv_std_logic_vector(16#20b#, 12),
\r
111 conv_std_logic_vector(16#61a#, 12),
\r
112 conv_std_logic_vector(16#927#, 12),
\r
113 conv_std_logic_vector(16#b13#, 12),
\r
114 conv_std_logic_vector(16#a30#, 12),
\r
115 conv_std_logic_vector(16#740#, 12),
\r
116 conv_std_logic_vector(16#450#, 12),
\r
117 conv_std_logic_vector(16#360#, 12),
\r
118 conv_std_logic_vector(16#360#, 12),
\r
119 conv_std_logic_vector(16#364#, 12),
\r
120 conv_std_logic_vector(16#358#, 12),
\r
121 conv_std_logic_vector(16#000#, 12),
\r
122 conv_std_logic_vector(16#000#, 12),
\r
123 conv_std_logic_vector(16#000#, 12),
\r
124 conv_std_logic_vector(16#bbb#, 12),
\r
125 conv_std_logic_vector(16#46f#, 12),
\r
126 conv_std_logic_vector(16#44f#, 12),
\r
127 conv_std_logic_vector(16#94f#, 12),
\r
128 conv_std_logic_vector(16#d4c#, 12),
\r
129 conv_std_logic_vector(16#d46#, 12),
\r
130 conv_std_logic_vector(16#e50#, 12),
\r
131 conv_std_logic_vector(16#c70#, 12),
\r
132 conv_std_logic_vector(16#880#, 12),
\r
133 conv_std_logic_vector(16#5a0#, 12),
\r
134 conv_std_logic_vector(16#4a1#, 12),
\r
135 conv_std_logic_vector(16#4a6#, 12),
\r
136 conv_std_logic_vector(16#49c#, 12),
\r
137 conv_std_logic_vector(16#000#, 12),
\r
138 conv_std_logic_vector(16#000#, 12),
\r
139 conv_std_logic_vector(16#000#, 12),
\r
140 conv_std_logic_vector(16#fff#, 12),
\r
141 conv_std_logic_vector(16#6af#, 12),
\r
142 conv_std_logic_vector(16#58f#, 12),
\r
143 conv_std_logic_vector(16#a7f#, 12),
\r
144 conv_std_logic_vector(16#f6f#, 12),
\r
145 conv_std_logic_vector(16#f6b#, 12),
\r
146 conv_std_logic_vector(16#f73#, 12),
\r
147 conv_std_logic_vector(16#fa0#, 12),
\r
148 conv_std_logic_vector(16#ed2#, 12),
\r
149 conv_std_logic_vector(16#9e0#, 12),
\r
150 conv_std_logic_vector(16#7f4#, 12),
\r
151 conv_std_logic_vector(16#7e9#, 12),
\r
152 conv_std_logic_vector(16#6de#, 12),
\r
153 conv_std_logic_vector(16#777#, 12),
\r
154 conv_std_logic_vector(16#000#, 12),
\r
155 conv_std_logic_vector(16#000#, 12),
\r
156 conv_std_logic_vector(16#fff#, 12),
\r
157 conv_std_logic_vector(16#9df#, 12),
\r
158 conv_std_logic_vector(16#abf#, 12),
\r
159 conv_std_logic_vector(16#cbf#, 12),
\r
160 conv_std_logic_vector(16#ebf#, 12),
\r
161 conv_std_logic_vector(16#fbe#, 12),
\r
162 conv_std_logic_vector(16#fcb#, 12),
\r
163 conv_std_logic_vector(16#fda#, 12),
\r
164 conv_std_logic_vector(16#ff9#, 12),
\r
165 conv_std_logic_vector(16#cf8#, 12),
\r
166 conv_std_logic_vector(16#afa#, 12),
\r
167 conv_std_logic_vector(16#afc#, 12),
\r
168 conv_std_logic_vector(16#aff#, 12),
\r
169 conv_std_logic_vector(16#aaa#, 12),
\r
170 conv_std_logic_vector(16#000#, 12),
\r
171 conv_std_logic_vector(16#000#, 12)
\r
175 pm_sbg : in std_logic;
\r
176 pm_nes_x : in integer range 0 to VGA_W_MAX - 1;
\r
177 pm_nes_y : in integer range 0 to VGA_H_MAX - 1
\r
180 if (pm_sbg = '1'and
\r
181 (pm_nes_x <= HSCAN or pm_nes_x >= HSCAN_NEXT_START) and
\r
182 (pm_nes_y < VSCAN or pm_nes_y = VSCAN_NEXT_START)) then
\r
189 signal reg_vga_x : integer range 0 to VGA_W_MAX - 1;
\r
190 signal reg_vga_y : integer range 0 to VGA_H_MAX - 1;
\r
192 signal reg_nes_x : integer range 0 to VGA_W_MAX / 2 - 1;
\r
193 signal reg_nes_y : integer range 0 to VGA_W_MAX / 2 - 1;
\r
194 --prefech is wider by scroll reg size.
\r
195 signal reg_prf_x : integer range 0 to VGA_W_MAX / 2 + 256 - 1;
\r
196 signal reg_prf_y : integer range 0 to VGA_W_MAX / 2 + 256 - 1;
\r
198 type vac_state is (
\r
210 signal reg_v_cur_state : vac_state;
\r
211 signal reg_v_next_state : vac_state;
\r
213 signal reg_v_ce_n : std_logic;
\r
214 signal reg_v_rd_n : std_logic;
\r
215 signal reg_v_wr_n : std_logic;
\r
216 signal reg_v_addr : std_logic_vector (13 downto 0);
\r
217 signal reg_v_data : std_logic_vector (7 downto 0);
\r
219 signal reg_disp_nt : std_logic_vector (7 downto 0);
\r
220 signal reg_disp_attr : std_logic_vector (7 downto 0);
\r
221 signal reg_tmp_ptn_l : std_logic_vector (7 downto 0);
\r
222 signal reg_sft_ptn_l : std_logic_vector (15 downto 0);
\r
223 signal reg_sft_ptn_h : std_logic_vector (15 downto 0);
\r
225 signal reg_plt_ce_n : std_logic;
\r
226 signal reg_plt_rd_n : std_logic;
\r
227 signal reg_plt_wr_n : std_logic;
\r
228 signal reg_plt_addr : std_logic_vector (4 downto 0);
\r
229 signal reg_plt_data : std_logic_vector (7 downto 0);
\r
233 --position and sync signal generate.
\r
234 pos_p : process (pi_rst_n, pi_base_clk)
\r
236 if (pi_rst_n = '0') then
\r
243 elsif (rising_edge(pi_base_clk)) then
\r
244 if ((pi_rnd_en(0) or pi_rnd_en(2))= '1') then
\r
245 if (reg_vga_x = VGA_W_MAX - 1) then
\r
248 if (reg_vga_y = VGA_H_MAX - 1) then
\r
252 reg_vga_y <= reg_vga_y + 1;
\r
253 reg_nes_y <= (reg_vga_y + 1) / 2;
\r
256 reg_vga_x <= reg_vga_x + 1;
\r
257 reg_nes_x <= (reg_vga_x + 1) / 2;
\r
260 --sync signal assert.
\r
261 if (reg_vga_x >= H_SYNC_S and reg_vga_x < H_SYNC_E) then
\r
262 po_h_sync_n <= '0';
\r
264 po_h_sync_n <= '1';
\r
267 if (reg_vga_y >= V_SYNC_S and reg_vga_y < V_SYNC_E) then
\r
268 po_v_sync_n <= '0';
\r
270 po_v_sync_n <= '1';
\r
272 end if;--if (pi_rnd_en(1) = '1' or pi_rnd_en(3) = '1' ) then
\r
274 --pre-fetch x/y position...
\r
275 if (reg_vga_x < HSCAN_NEXT_START * 2) then
\r
276 reg_prf_x <= reg_vga_x / 2 + conv_integer(pi_ppu_scroll_x) + PREFETCH_INT;
\r
278 reg_prf_x <= reg_vga_x / 2 + conv_integer(pi_ppu_scroll_x)
\r
279 - HSCAN_NEXT_START + PREFETCH_INT;
\r
282 if (reg_vga_y < VSCAN * 2) then
\r
283 if (reg_vga_x < HSCAN_NEXT_START * 2) then
\r
284 reg_prf_y <= reg_vga_y / 2 + conv_integer(pi_ppu_scroll_y);
\r
286 reg_prf_y <= (reg_vga_y + 1) / 2 + conv_integer(pi_ppu_scroll_y);
\r
291 end if;--if (pi_rst_n = '0') then
\r
294 --vram access state machine (state transition)...
\r
295 vac_set_stat_p : process (pi_rst_n, pi_base_clk)
\r
297 if (pi_rst_n = '0') then
\r
298 reg_v_cur_state <= IDLE;
\r
299 elsif (rising_edge(pi_base_clk)) then
\r
300 reg_v_cur_state <= reg_v_next_state;
\r
301 end if;--if (pi_rst_n = '0') then
\r
304 --state change to next.
\r
305 vac_next_stat_p : process (reg_v_cur_state, pi_rnd_en, pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y)
\r
306 function bg_process (
\r
307 pm_sbg : in std_logic;
\r
308 pm_nes_x : in integer range 0 to VGA_W_MAX - 1;
\r
309 pm_nes_y : in integer range 0 to VGA_H_MAX - 1
\r
312 if (pm_sbg = '1'and
\r
313 (pm_nes_x <= HSCAN or pm_nes_x >= HSCAN_NEXT_START) and
\r
314 (pm_nes_y < VSCAN or pm_nes_y = VSCAN_NEXT_START)) then
\r
322 pm_sbg : in std_logic;
\r
323 pm_nes_x : in integer range 0 to VGA_W_MAX - 1;
\r
324 pm_nes_y : in integer range 0 to VGA_H_MAX - 1
\r
327 if (pm_sbg = '0' or
\r
328 (pm_nes_x > HSCAN and pm_nes_x < HSCAN_NEXT_START) or
\r
329 (pm_nes_y >= VSCAN and pm_nes_y < VSCAN_NEXT_START)) then
\r
336 case reg_v_cur_state is
\r
338 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
339 pi_rnd_en(2) = '1' and
\r
340 reg_nes_x mod 8 = 0) then
\r
341 --start vram access process.
\r
342 reg_v_next_state <= AD_SET0;
\r
344 reg_v_next_state <= reg_v_cur_state;
\r
347 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
350 reg_v_next_state <= AD_SET1;
\r
351 elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
352 ---when nes_x=257, fall to idle
\r
353 reg_v_next_state <= IDLE;
\r
355 reg_v_next_state <= reg_v_cur_state;
\r
358 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
361 reg_v_next_state <= AD_SET2;
\r
362 elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
363 ---when nes_x=257, fall to idle
\r
364 reg_v_next_state <= IDLE;
\r
366 reg_v_next_state <= reg_v_cur_state;
\r
369 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
372 reg_v_next_state <= AD_SET3;
\r
373 elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
374 ---when nes_x=257, fall to idle
\r
375 reg_v_next_state <= IDLE;
\r
377 reg_v_next_state <= reg_v_cur_state;
\r
380 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
383 reg_v_next_state <= REG_SET0;
\r
384 elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
385 ---when nes_x=257, fall to idle
\r
386 reg_v_next_state <= IDLE;
\r
388 reg_v_next_state <= reg_v_cur_state;
\r
391 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
394 reg_v_next_state <= REG_SET1;
\r
395 elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
396 ---when nes_x=257, fall to idle
\r
397 reg_v_next_state <= IDLE;
\r
399 reg_v_next_state <= reg_v_cur_state;
\r
402 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
405 reg_v_next_state <= REG_SET2;
\r
406 elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
407 ---when nes_x=257, fall to idle
\r
408 reg_v_next_state <= IDLE;
\r
410 reg_v_next_state <= reg_v_cur_state;
\r
413 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
416 reg_v_next_state <= REG_SET3;
\r
417 elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
418 ---when nes_x=257, fall to idle
\r
419 reg_v_next_state <= IDLE;
\r
421 reg_v_next_state <= reg_v_cur_state;
\r
424 if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
427 reg_v_next_state <= AD_SET0;
\r
428 elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
429 ---when nes_x=257, fall to idle
\r
430 reg_v_next_state <= IDLE;
\r
432 reg_v_next_state <= reg_v_cur_state;
\r
437 po_v_ce_n <= reg_v_ce_n;
\r
438 po_v_rd_n <= reg_v_rd_n;
\r
439 po_v_wr_n <= reg_v_wr_n;
\r
440 po_v_addr <= reg_v_addr;
\r
442 po_plt_ce_n <= reg_plt_ce_n;
\r
443 po_plt_rd_n <= reg_plt_rd_n;
\r
444 po_plt_wr_n <= reg_plt_wr_n;
\r
445 po_plt_addr <= reg_plt_addr;
\r
447 --vram r/w selector state machine...
\r
448 vac_main_stat_p : process (reg_v_cur_state)
\r
450 case reg_v_cur_state is
\r
454 when AD_SET0 | AD_SET1 | REG_SET2 | REG_SET3 =>
\r
457 when AD_SET2 | AD_SET3 | REG_SET0 | REG_SET1 =>
\r
462 case reg_v_cur_state is
\r
465 reg_plt_ce_n <= 'Z';
\r
466 reg_plt_rd_n <= 'Z';
\r
467 reg_plt_wr_n <= 'Z';
\r
468 when AD_SET0 | AD_SET1 | REG_SET2 | REG_SET3 | AD_SET2 | AD_SET3 | REG_SET0 | REG_SET1 =>
\r
470 reg_plt_ce_n <= '0';
\r
471 reg_plt_rd_n <= '0';
\r
472 reg_plt_wr_n <= '1';
\r
476 --vram address state machine...
\r
477 vaddr_stat_p : process (pi_rst_n, pi_base_clk)
\r
479 if (pi_rst_n = '0') then
\r
480 reg_v_addr <= (others => 'Z');
\r
481 reg_v_data <= (others => 'Z');
\r
482 reg_disp_nt <= (others => 'Z');
\r
483 reg_disp_attr <= (others => 'Z');
\r
484 elsif (rising_edge(pi_base_clk)) then
\r
485 reg_v_data <= pi_v_data;
\r
487 if (is_bg(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
488 ----fetch next tile byte.
\r
489 if (reg_prf_x mod 8 = 1) then
\r
490 --vram addr is incremented every 8 cycle.
\r
491 --name table at 0x2000
\r
492 reg_v_addr(9 downto 0)
\r
493 <= conv_std_logic_vector(reg_prf_y, 9)(7 downto 3)
\r
494 & conv_std_logic_vector(reg_prf_x, 9)(7 downto 3);
\r
495 reg_v_addr(13 downto 10) <= "10" & pi_ppu_ctrl(PPUBNA downto 0)
\r
496 + ("000" & conv_std_logic_vector(reg_prf_x, 9)(8));
\r
498 elsif (reg_prf_x mod 8 = 2 and reg_v_cur_state = REG_SET1) then
\r
499 reg_disp_nt <= reg_v_data;
\r
501 ----fetch attr table byte.
\r
502 elsif (reg_prf_x mod 8 = 3) then
\r
503 --attr table at 0x23c0
\r
504 reg_v_addr(7 downto 0) <= "11000000" +
\r
505 ("00" & conv_std_logic_vector(reg_prf_y, 9)(7 downto 5)
\r
506 & conv_std_logic_vector(reg_prf_x, 9)(7 downto 5));
\r
507 reg_v_addr(13 downto 8) <= "10" &
\r
508 pi_ppu_ctrl(PPUBNA downto 0) & "11"
\r
509 + ("000" & conv_std_logic_vector(reg_prf_x, 9)(8) & "00");
\r
511 elsif (reg_prf_x mod 8 = 4 and reg_v_cur_state = REG_SET1) then
\r
512 reg_disp_attr <= reg_v_data;
\r
514 ----fetch pattern table low byte.
\r
515 elsif (reg_prf_x mod 8 = 5) then
\r
516 --vram addr is incremented every 8 cycle.
\r
517 reg_v_addr <= "0" & pi_ppu_ctrl(PPUBPA) &
\r
518 reg_disp_nt(7 downto 0)
\r
519 & "0" & conv_std_logic_vector(reg_prf_y, 9)(2 downto 0);
\r
521 ----fetch pattern table high byte.
\r
522 elsif (reg_prf_x mod 8 = 7) then
\r
523 --vram addr is incremented every 8 cycle.
\r
524 reg_v_addr <= "0" & pi_ppu_ctrl(PPUBPA) &
\r
525 reg_disp_nt(7 downto 0)
\r
526 & "0" & conv_std_logic_vector(reg_prf_y, 9)(2 downto 0)
\r
527 + "00000000001000";
\r
530 end if;--if (pi_rst_n = '0') then
\r
533 --pattern table state machine...
\r
534 bg_ptn_p : process (pi_rst_n, pi_base_clk)
\r
536 if (pi_rst_n = '0') then
\r
537 reg_tmp_ptn_l <= (others => '0');
\r
538 reg_sft_ptn_l <= (others => '0');
\r
539 reg_sft_ptn_h <= (others => '0');
\r
540 elsif (rising_edge(pi_base_clk)) then
\r
542 if (is_bg(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then
\r
544 if (reg_prf_x mod 8 = 6 and reg_v_cur_state = REG_SET1) then
\r
545 reg_tmp_ptn_l <= reg_v_data;
\r
548 if (reg_prf_x mod 8 = 0) then
\r
549 if (reg_v_cur_state = REG_SET1) then
\r
550 --copy low & shift.
\r
551 reg_sft_ptn_l <= reg_tmp_ptn_l & reg_sft_ptn_l(8 downto 1);
\r
552 --fetch high & shift.
\r
553 reg_sft_ptn_h <= reg_v_data & reg_sft_ptn_h(8 downto 1);
\r
556 if (reg_v_cur_state = AD_SET1 or reg_v_cur_state = REG_SET1) then
\r
557 reg_sft_ptn_l <= "0" & reg_sft_ptn_l(15 downto 1);
\r
558 reg_sft_ptn_h <= "0" & reg_sft_ptn_h(15 downto 1);
\r
562 end if;--if (pi_rst_n = '0') then
\r
565 --palette table state machine...
\r
566 plt_ac_p : process (pi_rst_n, pi_base_clk)
\r
568 if (pi_rst_n = '0') then
\r
569 reg_plt_addr <= (others => 'Z');
\r
570 reg_plt_data <= (others => 'Z');
\r
571 elsif (rising_edge(pi_base_clk)) then
\r
573 reg_plt_data <= pi_plt_data;
\r
574 --shift pattern propageted 1 cycle later.
\r
575 if (is_bg(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and
\r
576 (reg_v_cur_state = AD_SET2 or reg_v_cur_state = REG_SET2)) then
\r
577 if (conv_std_logic_vector(reg_nes_y, 9)(4) = '0'
\r
578 and (reg_sft_ptn_h(0) or reg_sft_ptn_l(0)) = '1') then
\r
580 "0" & reg_disp_attr(1 downto 0) & reg_sft_ptn_h(0) & reg_sft_ptn_l(0);
\r
581 elsif (conv_std_logic_vector(reg_nes_y, 9)(4) = '1'
\r
582 and (reg_sft_ptn_h(0) or reg_sft_ptn_l(0)) = '1') then
\r
584 "0" & reg_disp_attr(5 downto 4) & reg_sft_ptn_h(0) & reg_sft_ptn_l(0);
\r
586 ---else: no output color >> universal bg color output.
\r
587 --0x3f00 is the universal bg palette.
\r
588 reg_plt_addr <= (others => '0');
\r
591 end if;--if (pi_rst_n = '0') then
\r
594 rgb_out_p : process (pi_rst_n, pi_base_clk)
\r
596 if (pi_rst_n = '0') then
\r
597 po_b <= (others => '0');
\r
598 po_g <= (others => '0');
\r
599 po_r <= (others => '0');
\r
601 if (rising_edge(pi_base_clk)) then
\r
602 if (reg_nes_x < HSCAN and reg_nes_y < VSCAN) then
\r
603 --if or if not bg/sprite is shown, output color anyway
\r
604 --sinse universal bg color is included..
\r
605 po_b <= nes_color_palette(conv_integer(reg_plt_data(5 downto 0))) (11 downto 8);
\r
606 po_g <= nes_color_palette(conv_integer(reg_plt_data(5 downto 0))) (7 downto 4);
\r
607 po_r <= nes_color_palette(conv_integer(reg_plt_data(5 downto 0))) (3 downto 0);
\r
609 po_b <= (others => '0');
\r
610 po_g <= (others => '0');
\r
611 po_r <= (others => '0');
\r
613 end if; --if (rising_edge(emu_ppu_clk)) then
\r
614 end if;--if (rst_n = '0') then
\r
615 end process;--output_p
\r
617 po_ppu_status <= (others => '0');
\r
619 po_spr_ce_n <= 'Z';
\r
620 po_spr_rd_n <= 'Z';
\r
621 po_spr_wr_n <= 'Z';
\r
622 po_spr_addr <= (others => 'Z');
\r