OSDN Git Service

debug env update, chr rom added
[motonesfpga/motonesfpga.git] / tools / qt_proj_test5 / ppu.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.motonesfpga_common.all;
4
5 entity ppu is 
6     port (  
7     signal dbg_ppu_ce_n    : out std_logic;
8     signal dbg_ppu_ctrl, dbg_ppu_mask, dbg_ppu_status : out std_logic_vector (7 downto 0);
9     signal dbg_ppu_addr : out std_logic_vector (13 downto 0);
10     signal dbg_ppu_data, dbg_ppu_scrl_x, dbg_ppu_scrl_y : out std_logic_vector (7 downto 0);
11
12     signal dbg_ppu_clk                      : out std_logic;
13     signal dbg_nes_x                        : out std_logic_vector (8 downto 0);
14     signal dbg_vga_x                        : out std_logic_vector (9 downto 0);
15     signal dbg_disp_nt, dbg_disp_attr : out std_logic_vector (7 downto 0);
16     signal dbg_disp_ptn_h, dbg_disp_ptn_l : out std_logic_vector (15 downto 0);
17     signal dbg_ppu_addr_we_n    : out std_logic;
18     signal dbg_ppu_clk_cnt          : out std_logic_vector(1 downto 0);
19
20     
21             clk         : in std_logic;
22             mem_clk     : in std_logic;
23             ce_n        : in std_logic;
24             rst_n       : in std_logic;
25             r_nw        : in std_logic;
26             cpu_addr    : in std_logic_vector (2 downto 0);
27             cpu_d       : inout std_logic_vector (7 downto 0);
28
29             vblank_n    : out std_logic;
30             rd_n        : out std_logic;
31             wr_n        : out std_logic;
32             ale         : out std_logic;
33             vram_ad     : inout std_logic_vector (7 downto 0);
34             vram_a      : out std_logic_vector (13 downto 8);
35
36             vga_clk     : in std_logic;
37             h_sync_n    : out std_logic;
38             v_sync_n    : out std_logic;
39             r           : out std_logic_vector(3 downto 0);
40             g           : out std_logic_vector(3 downto 0);
41             b           : out std_logic_vector(3 downto 0)
42
43     );
44 end ppu;
45
46 architecture rtl of ppu is
47
48 component ppu_render
49     port (  
50     signal dbg_ppu_clk                      : out std_logic;
51     signal dbg_nes_x                        : out std_logic_vector (8 downto 0);
52     signal dbg_vga_x                        : out std_logic_vector (9 downto 0);
53     signal dbg_disp_nt, dbg_disp_attr : out std_logic_vector (7 downto 0);
54     signal dbg_disp_ptn_h, dbg_disp_ptn_l : out std_logic_vector (15 downto 0);
55     
56     
57             clk         : in std_logic;
58             vga_clk     : in std_logic;
59             mem_clk     : in std_logic;
60             rst_n       : in std_logic;
61             rd_n        : out std_logic;
62             wr_n        : out std_logic;
63             ale         : out std_logic;
64             vram_ad     : inout std_logic_vector (7 downto 0);
65             vram_a      : out std_logic_vector (13 downto 8);
66
67             h_sync_n    : out std_logic;
68             v_sync_n    : out std_logic;
69             r           : out std_logic_vector (3 downto 0);
70             g           : out std_logic_vector (3 downto 0);
71             b           : out std_logic_vector (3 downto 0);
72
73             ppu_ctrl        : in std_logic_vector (7 downto 0);
74             ppu_mask        : in std_logic_vector (7 downto 0);
75             read_status     : in std_logic;
76             ppu_scroll_x    : in std_logic_vector (7 downto 0);
77             ppu_scroll_y    : in std_logic_vector (7 downto 0);
78             ppu_status      : out std_logic_vector (7 downto 0);
79             v_bus_busy_n    : out std_logic;
80
81             r_nw            : in std_logic;
82             oam_bus_ce_n    : in std_logic;
83             plt_bus_ce_n    : in std_logic;
84             oam_plt_addr    : in std_logic_vector (7 downto 0);
85             oam_plt_data    : inout std_logic_vector (7 downto 0)
86     );
87 end component;
88
89 component d_flip_flop
90     generic (
91             dsize : integer := 8
92             );
93     port (
94             clk     : in std_logic;
95             res_n   : in std_logic;
96             set_n   : in std_logic;
97             we_n    : in std_logic;
98             d       : in std_logic_vector (dsize - 1 downto 0);
99             q       : out std_logic_vector (dsize - 1 downto 0)
100         );
101 end component;
102
103 component counter_register
104     generic (
105         dsize       : integer := 8;
106         inc         : integer := 1
107     );
108     port (  clk         : in std_logic;
109             rst_n       : in std_logic;
110             ce_n        : in std_logic;
111             we_n        : in std_logic;
112             d           : in std_logic_vector(dsize - 1 downto 0);
113             q           : out std_logic_vector(dsize - 1 downto 0)
114     );
115 end component;
116
117 constant dsize     : integer := 8;
118
119 constant PPUCTRL   : std_logic_vector(2 downto 0) := "000";
120 constant PPUMASK   : std_logic_vector(2 downto 0) := "001";
121 constant PPUSTATUS : std_logic_vector(2 downto 0) := "010";
122 constant OAMADDR   : std_logic_vector(2 downto 0) := "011";
123 constant OAMDATA   : std_logic_vector(2 downto 0) := "100";
124 constant PPUSCROLL : std_logic_vector(2 downto 0) := "101";
125 constant PPUADDR   : std_logic_vector(2 downto 0) := "110";
126 constant PPUDATA   : std_logic_vector(2 downto 0) := "111";
127
128 constant PPUVAI     : integer := 2;  --vram address increment
129 constant PPUNEN     : integer := 7;  --nmi enable
130 constant ST_VBL     : integer := 7;  --vblank
131
132 signal clk_n            : std_logic;
133
134 signal ppu_clk_cnt_res_n    : std_logic;
135 signal ppu_clk_cnt          : std_logic_vector(1 downto 0);
136
137 signal ppu_ctrl_we_n    : std_logic;
138 signal ppu_mask_we_n    : std_logic;
139 signal oam_addr_ce_n    : std_logic;
140 signal oam_addr_we_n    : std_logic;
141 signal oam_data_we_n    : std_logic;
142 signal ppu_scroll_x_we_n    : std_logic;
143 signal ppu_scroll_y_we_n    : std_logic;
144 signal ppu_scroll_cnt_ce_n  : std_logic;
145 signal ppu_addr_we_n        : std_logic;
146 signal ppu_addr_cnt_ce_n    : std_logic;
147 signal ppu_data_we_n    : std_logic;
148
149 signal ppu_ctrl         : std_logic_vector (dsize - 1 downto 0);
150 signal ppu_mask         : std_logic_vector (dsize - 1 downto 0);
151 signal read_status      : std_logic;
152 signal ppu_status       : std_logic_vector (dsize - 1 downto 0);
153 signal ppu_stat_out     : std_logic_vector (dsize - 1 downto 0);
154 signal oam_addr         : std_logic_vector (dsize - 1 downto 0);
155 signal oam_data         : std_logic_vector (dsize - 1 downto 0);
156 signal ppu_scroll_x     : std_logic_vector (dsize - 1 downto 0);
157 signal ppu_scroll_y     : std_logic_vector (dsize - 1 downto 0);
158 signal ppu_scroll_cnt   : std_logic_vector (0 downto 0);
159 signal ppu_addr         : std_logic_vector (13 downto 0);
160 signal ppu_addr_inc1    : std_logic_vector (13 downto 0);
161 signal ppu_addr_inc32   : std_logic_vector (13 downto 0);
162 signal ppu_addr_in      : std_logic_vector (13 downto 0);
163 signal ppu_addr_cnt     : std_logic_vector (0 downto 0);
164 signal ppu_data         : std_logic_vector (dsize - 1 downto 0);
165 signal ppu_data_in      : std_logic_vector (dsize - 1 downto 0);
166 signal ppu_data_out     : std_logic_vector (dsize - 1 downto 0);
167 signal read_data_n      : std_logic;
168 signal ppu_latch_rst_n  : std_logic;
169 signal v_bus_busy_n     : std_logic;
170
171 signal oam_bus_ce_n     : std_logic;
172 signal plt_bus_ce_n     : std_logic;
173
174 signal oam_plt_addr     : std_logic_vector (dsize - 1 downto 0);
175 signal oam_plt_data     : std_logic_vector (dsize - 1 downto 0);
176 signal plt_data_out     : std_logic_vector (dsize - 1 downto 0);
177
178 begin
179
180
181     dbg_ppu_ce_n <= ce_n;
182     dbg_ppu_ctrl <= ppu_ctrl;
183     dbg_ppu_mask <= ppu_mask;
184     dbg_ppu_status <= ppu_status;
185     dbg_ppu_addr  <= ppu_addr;
186     dbg_ppu_data <= ppu_data;
187     dbg_ppu_scrl_x <= ppu_scroll_x;
188     dbg_ppu_scrl_y <= ppu_scroll_y;
189     dbg_ppu_addr_we_n <= ppu_addr_we_n;
190     dbg_ppu_clk_cnt <= ppu_clk_cnt;
191
192
193
194     render_inst : ppu_render port map (
195     dbg_ppu_clk                      ,
196     dbg_nes_x                        ,
197     dbg_vga_x                        ,
198     dbg_disp_nt, dbg_disp_attr, dbg_disp_ptn_h, dbg_disp_ptn_l,
199     
200             clk, vga_clk, mem_clk, rst_n,
201             rd_n, wr_n, ale, vram_ad, vram_a,
202             h_sync_n, v_sync_n, r, g, b, 
203             ppu_ctrl, ppu_mask, read_status, ppu_scroll_x, ppu_scroll_y,
204             ppu_status, v_bus_busy_n, 
205             r_nw, oam_bus_ce_n, plt_bus_ce_n, 
206             oam_plt_addr, oam_plt_data);
207
208     --PPU registers.
209     clk_n <= not clk;
210
211     ppu_clk_cnt_inst : counter_register generic map (2, 1)
212             port map (clk_n, ppu_clk_cnt_res_n, '0', '1', (others => '0'), ppu_clk_cnt); 
213
214     ppu_ctrl_inst : d_flip_flop generic map(dsize)
215             port map (clk_n, rst_n, '1', ppu_ctrl_we_n, cpu_d, ppu_ctrl);
216
217     ppu_mask_inst : d_flip_flop generic map(dsize)
218             port map (clk_n, rst_n, '1', ppu_mask_we_n, cpu_d, ppu_mask);
219
220     ppu_status_inst : d_flip_flop generic map(dsize)
221             port map (read_status, rst_n, '1', '0', ppu_status, ppu_stat_out);
222
223     oma_addr_inst : counter_register generic map(dsize, 1)
224             port map (clk_n, rst_n, oam_addr_ce_n, oam_addr_we_n, cpu_d, oam_addr);
225     oma_data_inst : d_flip_flop generic map(dsize)
226             port map (clk_n, rst_n, '1', oam_data_we_n, cpu_d, oam_data);
227
228     ppu_scroll_x_inst : d_flip_flop generic map(dsize)
229             port map (clk_n, rst_n, '1', ppu_scroll_x_we_n, cpu_d, ppu_scroll_x);
230     ppu_scroll_y_inst : d_flip_flop generic map(dsize)
231             port map (clk_n, rst_n, '1', ppu_scroll_y_we_n, cpu_d, ppu_scroll_y);
232     ppu_scroll_cnt_inst : counter_register generic map (1, 1)
233             port map (clk_n, ppu_latch_rst_n, ppu_scroll_cnt_ce_n, 
234                                             '1', (others => '0'), ppu_scroll_cnt);
235
236     ppu_addr_inst_inc1 : counter_register generic map(14, 1)
237             port map (clk_n, rst_n, ppu_data_we_n, ppu_addr_we_n, ppu_addr_in, ppu_addr_inc1);
238     ppu_addr_inst_inc32 : counter_register generic map(14, 32)
239             port map (clk_n, rst_n, ppu_data_we_n, ppu_addr_we_n, ppu_addr_in, ppu_addr_inc32);
240
241     ppu_addr <= ppu_addr_inc32 when ppu_ctrl(PPUVAI) = '1' else
242                 ppu_addr_inc1;
243
244     ppu_addr_cnt_inst : counter_register generic map (1, 1)
245             port map (clk_n, ppu_latch_rst_n, ppu_addr_cnt_ce_n, 
246                                             '1', (others => '0'), ppu_addr_cnt);
247     ppu_data_inst : d_flip_flop generic map(dsize)
248             port map (clk_n, rst_n, '1', ppu_data_we_n, cpu_d, ppu_data);
249
250     ppu_data_in_inst : d_flip_flop generic map(dsize)
251             port map (clk_n, rst_n, '1', ppu_data_we_n, vram_ad, ppu_data_in);
252
253     ppu_data_out_inst : d_flip_flop generic map(dsize)
254             port map (read_data_n, rst_n, '1', '0', ppu_data_in, ppu_data_out);
255
256     plt_data_out_inst : d_flip_flop generic map(dsize)
257             port map (clk_n, rst_n, '1', ppu_data_we_n, oam_plt_data, plt_data_out);
258
259     reg_set_p : process (rst_n, ce_n, r_nw, cpu_addr, cpu_d, 
260                         ppu_status(ST_VBL), ppu_ctrl(PPUNEN))
261     begin
262
263 --        if (ppu_status(ST_VBL)'event or ppu_ctrl(PPUNEN)'event) then
264 --            if (ppu_status(ST_VBL) = '1' and ppu_ctrl(PPUNEN) = '1') then
265 --                --start vblank.
266 --                vblank_n <= '0';
267 --            else
268 --                --clear flag.
269 --                vblank_n <= '1';
270 --            end if;
271 --        end if;
272
273         if (rst_n = '0') then
274             vblank_n <= '1';
275         elsif (rst_n = '1' and ce_n = '0') then
276
277             --register set.
278             if(cpu_addr = PPUCTRL) then
279                 ppu_ctrl_we_n <= '0';
280             else
281                 ppu_ctrl_we_n <= '1';
282             end if;
283
284             if(cpu_addr = PPUMASK) then
285                 ppu_mask_we_n <= '0';
286             else
287                 ppu_mask_we_n <= '1';
288             end if;
289
290             if(cpu_addr = PPUSTATUS and r_nw = '1') then
291                 --notify reading status
292                 read_status <= '1';
293             else
294                 read_status <= '0';
295             end if;
296
297             if(cpu_addr = OAMADDR) then
298                 oam_addr_we_n <= '0';
299             else
300                 oam_addr_we_n <= '1';
301             end if;
302
303             if(cpu_addr = OAMDATA) then
304                 oam_data_we_n <= '0';
305             else
306                 oam_data_we_n <= '1';
307             end if;
308
309             if(cpu_addr = PPUSCROLL) then
310                 ppu_scroll_cnt_ce_n <= '0';
311                 if (ppu_scroll_cnt(0) = '0') then
312                     ppu_scroll_x_we_n <= '0';
313                     ppu_scroll_y_we_n <= '1';
314                 else
315                     ppu_scroll_y_we_n <= '0';
316                     ppu_scroll_x_we_n <= '1';
317                 end if;
318             else
319                 ppu_scroll_x_we_n <= '1';
320                 ppu_scroll_y_we_n <= '1';
321                 ppu_scroll_cnt_ce_n <= '1';
322             end if;
323
324             if(cpu_addr = PPUADDR) then
325                 if (ppu_addr_cnt(0) = '0') then
326                     ppu_addr_in <= cpu_d(5 downto 0) & ppu_addr(7 downto 0);
327                 else
328                     ppu_addr_in <= ppu_addr(13 downto 8) & cpu_d;
329                 end if;
330             end if;
331
332             if (cpu_addr = PPUDATA and r_nw = '1') then
333                 read_data_n <= '0';
334             else
335                 read_data_n <= '1';
336             end if;
337         else
338             ppu_ctrl_we_n    <= '1';
339             ppu_mask_we_n    <= '1';
340             oam_addr_we_n    <= '1';
341             oam_data_we_n    <= '1';
342             ppu_scroll_x_we_n    <= '1';
343             ppu_scroll_y_we_n    <= '1';
344             ppu_scroll_cnt_ce_n  <= '1';
345             read_status <= '0';
346             read_data_n <= '1';
347         end if; --if (rst_n = '1' and ce_n = '0') 
348
349     end process;
350
351     ppu_clk_cnt_res_n <= not ce_n;
352     
353     --cpu and ppu clock timing adjustment...
354     clk_cnt_set_p : process (rst_n, ce_n, r_nw, cpu_addr, cpu_d, clk, 
355                                 oam_plt_data, vram_ad, ppu_stat_out)
356     begin
357         if (rst_n = '0') then
358             ppu_latch_rst_n <= '0';
359             ppu_addr_we_n    <= '1';
360             rd_n <= 'Z';
361             wr_n <= 'Z';
362             ale <= 'Z';
363             oam_plt_data <= (others => 'Z');
364             vram_ad <= (others => 'Z');
365             vram_a <= (others => 'Z');
366             cpu_d <= (others => 'Z');
367         elsif (rst_n = '1' and ce_n = '0') then
368             --set counter=0 on register write.   
369 --            if (ce_n'event or r_nw'event or cpu_addr'event or (cpu_d'event and r_nw = '0')) then
370 --                ppu_clk_cnt_res_n <= '0';
371 --                --d_print("write event");
372 --            end if;
373
374             --start counter.
375             if (clk'event and clk = '0') then
376                 if (read_status = '1') then
377                     --reading status resets ppu_addr/scroll cnt.
378                     ppu_latch_rst_n <= '0';
379                 else
380                     ppu_latch_rst_n <= '1';
381                 end if;
382                 --d_print("clk event");
383             end if;
384
385             --oam data set
386             if (cpu_addr = OAMDATA and ppu_clk_cnt = "00") then
387                 oam_bus_ce_n <= '0';
388                 oam_plt_addr <= oam_addr;
389                 if (r_nw = '1') then
390                     oam_plt_data <= (others => 'Z');
391                     cpu_d <= oam_plt_data;
392                 else
393                     oam_plt_data <= cpu_d;
394                 end if;
395                 --address increment for burst write. 
396                 oam_addr_ce_n <= '0';
397             else
398                 cpu_d <= (others => 'Z');
399                 oam_addr_ce_n <= '1';
400                 oam_bus_ce_n <= '1';
401             end if; --if (cpu_addr = OAMDATA and ppu_clk_cnt = "00") then
402
403             --vram address access.
404             if(cpu_addr = PPUADDR and ppu_clk_cnt = "00") then
405                 ppu_addr_we_n <= '0';
406             else
407                 ppu_addr_we_n <= '1';
408             end if;
409
410             if (cpu_addr = PPUADDR and ppu_clk_cnt = "00") then
411                 ppu_addr_cnt_ce_n <= '0';
412                 if (ppu_addr_cnt(0) = '0') then
413                     --load addr high
414                     ale <= '0';
415                 else
416                     --load addr low and output vram/plt bus.
417
418                     --if address is 3fxx, set palette table.
419                     if (ppu_addr(13 downto 8) = "111111") then
420                         oam_plt_addr <= cpu_d;
421                         ale <= '0';
422                     else
423                         vram_ad <= cpu_d;
424                         vram_a <= ppu_addr(13 downto 8);
425                         ale <= '1';
426                     end if;
427                 end if;
428             elsif (cpu_addr = PPUDATA and ppu_clk_cnt = "01") then
429                 ppu_addr_cnt_ce_n <= '1';
430                 --for burst write.
431                 if (ppu_addr(13 downto 8) = "111111") then
432                     oam_plt_addr <= ppu_addr(7 downto 0);
433                     ale <= '0';
434                 else
435                     vram_a <= ppu_addr(13 downto 8);
436                     vram_ad <= ppu_addr(7 downto 0);
437                     ale <= '1';
438                 end if;
439             else
440                 ppu_addr_cnt_ce_n <= '1';
441                 ale <= 'Z';
442             end if; --if (cpu_addr = PPUADDR and ppu_clk_cnt = "00") then
443
444             if (cpu_addr = PPUDATA and ppu_clk_cnt = "00") then
445                 ppu_data_we_n <= '0';
446                 vram_a <= ppu_addr(13 downto 8);
447                 if (ppu_addr(13 downto 8) = "111111") then
448                     --case palette tbl.
449                     plt_bus_ce_n <= '0';
450                     if (r_nw = '0') then
451                         oam_plt_data <= cpu_d;
452                     else
453                         oam_plt_data <= (others => 'Z');
454                         cpu_d <= oam_plt_data;
455                     end if;
456                     rd_n <= '1';
457                     wr_n <= '1';
458                 else
459                     rd_n <= not r_nw;
460                     wr_n <= r_nw;
461                     plt_bus_ce_n <= '1';
462                     if (r_nw = '0') then
463                         vram_ad <= cpu_d;
464                     else
465                         cpu_d <= ppu_data_out;
466                     end if;
467                 end if;
468             else
469                 plt_bus_ce_n <= '1';
470                 ppu_data_we_n <= '1';
471                 rd_n <= 'Z';
472                 wr_n <= 'Z';
473             end if; --if (cpu_addr = PPUDATA and ppu_clk_cnt = "00") then
474
475             --sustain cpu output data when reading.
476             if (cpu_addr = PPUDATA and r_nw = '1' and ppu_clk_cnt /= "00") then
477                 if (ppu_addr(13 downto 8) = "111111") then
478                     cpu_d <= plt_data_out;
479                 else
480                     cpu_d <= ppu_data_out;
481                 end if;
482             end if;
483             if (cpu_addr = OAMDATA and r_nw = '1' and ppu_clk_cnt /= "00") then
484                 cpu_d <= oam_data;
485             end if;
486
487             if(cpu_addr = PPUSTATUS and r_nw = '1') then
488                 cpu_d <= ppu_stat_out;
489             end if;
490
491         else
492             ppu_addr_we_n    <= '1';
493             ppu_data_we_n    <= '1';
494             plt_bus_ce_n <= '1';
495             oam_bus_ce_n     <= '1';
496             oam_addr_ce_n <= '1';
497             ppu_addr_cnt_ce_n    <= '1';
498             ppu_latch_rst_n <= '1';
499
500             rd_n <= 'Z';
501             wr_n <= 'Z';
502             ale <= 'Z';
503             oam_plt_data <= (others => 'Z');
504             vram_ad <= (others => 'Z');
505             vram_a <= (others => 'Z');
506             cpu_d <= (others => 'Z');
507         end if; --if (rst_n = '0') then
508     end process;
509
510 end rtl;
511