OSDN Git Service

ppu addr reset latch timing changed.
[motonesfpga/motonesfpga.git] / simulation / ppu / ppu.vhd
index 1c5d3b8..e33065c 100644 (file)
@@ -28,7 +28,6 @@ architecture rtl of ppu is
 component ppu_render
     port (  clk         : in std_logic;
             rst_n       : in std_logic;
-            vblank_n    : out std_logic;
             rd_n        : out std_logic;
             wr_n        : out std_logic;
             ale         : out std_logic;
@@ -41,6 +40,7 @@ component ppu_render
             b           : out std_logic_vector (3 downto 0);
             ppu_ctrl        : in std_logic_vector (7 downto 0);
             ppu_mask        : in std_logic_vector (7 downto 0);
+            read_status     : in std_logic;
             ppu_status      : out std_logic_vector (7 downto 0);
             ppu_scroll_x    : in std_logic_vector (7 downto 0);
             ppu_scroll_y    : in std_logic_vector (7 downto 0);
@@ -48,7 +48,8 @@ component ppu_render
             oam_bus_ce_n    : in std_logic;
             plt_bus_ce_n    : in std_logic;
             oam_plt_addr    : in std_logic_vector (7 downto 0);
-            oam_plt_data    : inout std_logic_vector (7 downto 0)
+            oam_plt_data    : inout std_logic_vector (7 downto 0);
+            v_bus_busy_n    : out std_logic
     );
 end component;
 
@@ -90,8 +91,8 @@ component counter_register
     );
     port (  clk         : in std_logic;
             rst_n       : in std_logic;
-            set_n       : in std_logic;
             ce_n        : in std_logic;
+            we_n        : in std_logic;
             d           : in std_logic_vector(dsize - 1 downto 0);
             q           : out std_logic_vector(dsize - 1 downto 0)
     );
@@ -123,6 +124,10 @@ constant PPUSCROLL : std_logic_vector(2 downto 0) := "101";
 constant PPUADDR   : std_logic_vector(2 downto 0) := "110";
 constant PPUDATA   : std_logic_vector(2 downto 0) := "111";
 
+constant PPUVAI     : integer := 2;  --vram address increment
+constant PPUNEN     : integer := 7;  --nmi enable
+constant ST_VBL     : integer := 7;  --vblank
+
 signal clk_n            : std_logic;
 
 signal ppu_clk_cnt_res_n    : std_logic;
@@ -130,7 +135,6 @@ signal ppu_clk_cnt          : std_logic_vector(1 downto 0);
 
 signal ppu_ctrl_we_n    : std_logic;
 signal ppu_mask_we_n    : std_logic;
-signal ppu_status_we_n  : std_logic;
 signal oam_addr_ce_n    : std_logic;
 signal oam_addr_we_n    : std_logic;
 signal oam_data_we_n    : std_logic;
@@ -143,31 +147,41 @@ signal ppu_data_we_n    : std_logic;
 
 signal ppu_ctrl         : std_logic_vector (dsize - 1 downto 0);
 signal ppu_mask         : std_logic_vector (dsize - 1 downto 0);
+signal read_status      : std_logic;
 signal ppu_status       : std_logic_vector (dsize - 1 downto 0);
+signal ppu_stat_out     : std_logic_vector (dsize - 1 downto 0);
 signal oam_addr         : std_logic_vector (dsize - 1 downto 0);
 signal oam_data         : std_logic_vector (dsize - 1 downto 0);
 signal ppu_scroll_x     : std_logic_vector (dsize - 1 downto 0);
 signal ppu_scroll_y     : std_logic_vector (dsize - 1 downto 0);
 signal ppu_scroll_cnt   : std_logic_vector (0 downto 0);
 signal ppu_addr         : std_logic_vector (13 downto 0);
+signal ppu_addr_inc1    : std_logic_vector (13 downto 0);
+signal ppu_addr_inc32   : std_logic_vector (13 downto 0);
 signal ppu_addr_in      : std_logic_vector (13 downto 0);
 signal ppu_addr_cnt     : std_logic_vector (0 downto 0);
 signal ppu_data         : std_logic_vector (dsize - 1 downto 0);
+signal ppu_data_in      : std_logic_vector (dsize - 1 downto 0);
+signal ppu_data_out     : std_logic_vector (dsize - 1 downto 0);
+signal read_data_n      : std_logic;
+signal ppu_latch_rst_n  : std_logic;
+signal v_bus_busy_n     : std_logic;
 
 signal oam_bus_ce_n     : std_logic;
 signal plt_bus_ce_n     : std_logic;
 
-signal oam_plt_addr     : std_logic_vector (7 downto 0);
-signal oam_plt_data     : std_logic_vector (7 downto 0);
+signal oam_plt_addr     : std_logic_vector (dsize - 1 downto 0);
+signal oam_plt_data     : std_logic_vector (dsize - 1 downto 0);
+signal plt_data_out     : std_logic_vector (dsize - 1 downto 0);
 
 begin
 
-    render_inst : ppu_render port map (clk, rst_n, vblank_n, 
+    render_inst : ppu_render port map (clk, rst_n,
             rd_n, wr_n, ale, vram_ad, vram_a,
             pos_x, pos_y, nes_r, nes_g, nes_b,
-            ppu_ctrl, ppu_mask, ppu_status, ppu_scroll_x, ppu_scroll_y,
+            ppu_ctrl, ppu_mask, read_status, ppu_status, ppu_scroll_x, ppu_scroll_y,
             r_nw, oam_bus_ce_n, plt_bus_ce_n, 
-            oam_plt_addr, oam_plt_data);
+            oam_plt_addr, oam_plt_data, v_bus_busy_n);
 
     vga_inst : vga_ctl port map (clk, vga_clk, rst_n, 
             pos_x, pos_y, nes_r, nes_g, nes_b,
@@ -177,7 +191,7 @@ begin
     clk_n <= not clk;
 
     ppu_clk_cnt_inst : counter_register generic map (2, 1)
-            port map (clk_n, ppu_clk_cnt_res_n, '1', '0', (others => '0'), ppu_clk_cnt); 
+            port map (clk_n, ppu_clk_cnt_res_n, '0', '1', (others => '0'), ppu_clk_cnt); 
 
     ppu_ctrl_inst : d_flip_flop generic map(dsize)
             port map (clk_n, rst_n, '1', ppu_ctrl_we_n, cpu_d, ppu_ctrl);
@@ -186,10 +200,10 @@ begin
             port map (clk_n, rst_n, '1', ppu_mask_we_n, cpu_d, ppu_mask);
 
     ppu_status_inst : d_flip_flop generic map(dsize)
-            port map (clk_n, rst_n, '1', ppu_status_we_n, cpu_d, ppu_status);
+            port map (read_status, rst_n, '1', '0', ppu_status, ppu_stat_out);
 
     oma_addr_inst : counter_register generic map(dsize, 1)
-            port map (clk_n, rst_n, oam_addr_we_n, oam_addr_ce_n, cpu_d, oam_addr);
+            port map (clk_n, rst_n, oam_addr_ce_n, oam_addr_we_n, cpu_d, oam_addr);
     oma_data_inst : d_flip_flop generic map(dsize)
             port map (clk_n, rst_n, '1', oam_data_we_n, cpu_d, oam_data);
 
@@ -198,20 +212,49 @@ begin
     ppu_scroll_y_inst : d_flip_flop generic map(dsize)
             port map (clk_n, rst_n, '1', ppu_scroll_y_we_n, cpu_d, ppu_scroll_y);
     ppu_scroll_cnt_inst : counter_register generic map (1, 1)
-            port map (clk_n, rst_n, '1', ppu_scroll_cnt_ce_n, (others => '0'), ppu_scroll_cnt);
+            port map (clk_n, ppu_latch_rst_n, ppu_scroll_cnt_ce_n, 
+                                            '1', (others => '0'), ppu_scroll_cnt);
+
+    ppu_addr_inst_inc1 : counter_register generic map(14, 1)
+            port map (clk_n, rst_n, ppu_data_we_n, ppu_addr_we_n, ppu_addr_in, ppu_addr_inc1);
+    ppu_addr_inst_inc32 : counter_register generic map(14, 32)
+            port map (clk_n, rst_n, ppu_data_we_n, ppu_addr_we_n, ppu_addr_in, ppu_addr_inc32);
+
+    ppu_addr <= ppu_addr_inc32 when ppu_ctrl(PPUVAI) = '1' else
+                ppu_addr_inc1;
 
-    ppu_addr_inst : counter_register generic map(14, 1)
-            port map (clk_n, rst_n, ppu_addr_we_n, ppu_data_we_n, ppu_addr_in, ppu_addr);
     ppu_addr_cnt_inst : counter_register generic map (1, 1)
-            port map (clk_n, rst_n, '1', ppu_addr_cnt_ce_n, (others => '0'), ppu_addr_cnt);
+            port map (clk_n, ppu_latch_rst_n, ppu_addr_cnt_ce_n, 
+                                            '1', (others => '0'), ppu_addr_cnt);
     ppu_data_inst : d_flip_flop generic map(dsize)
             port map (clk_n, rst_n, '1', ppu_data_we_n, cpu_d, ppu_data);
 
+    ppu_data_in_inst : d_flip_flop generic map(dsize)
+            port map (clk_n, rst_n, '1', ppu_data_we_n, vram_ad, ppu_data_in);
+
+    ppu_data_out_inst : d_flip_flop generic map(dsize)
+            port map (read_data_n, rst_n, '1', '0', ppu_data_in, ppu_data_out);
 
-    reg_set_p : process (rst_n, ce_n, r_nw, cpu_addr, cpu_d)
+    plt_data_out_inst : d_flip_flop generic map(dsize)
+            port map (clk_n, rst_n, '1', ppu_data_we_n, oam_plt_data, plt_data_out);
+
+    reg_set_p : process (rst_n, ce_n, r_nw, cpu_addr, cpu_d, 
+                        ppu_status(ST_VBL), ppu_ctrl(PPUNEN))
     begin
 
-        if (rst_n = '1' and ce_n = '0') then
+        if (ppu_status(ST_VBL)'event or ppu_ctrl(PPUNEN)'event) then
+            if (ppu_status(ST_VBL) = '1' and ppu_ctrl(PPUNEN) = '1') then
+                --start vblank.
+                vblank_n <= '0';
+            else
+                --clear flag.
+                vblank_n <= '1';
+            end if;
+        end if;
+
+        if (rst_n = '0') then
+            vblank_n <= '1';
+        elsif (rst_n = '1' and ce_n = '0') then
 
             --register set.
             if(cpu_addr = PPUCTRL) then
@@ -226,10 +269,11 @@ begin
                 ppu_mask_we_n <= '1';
             end if;
 
-            if(cpu_addr = PPUSTATUS) then
-                ppu_status_we_n <= '0';
+            if(cpu_addr = PPUSTATUS and r_nw = '1') then
+                --notify reading status
+                read_status <= '1';
             else
-                ppu_status_we_n <= '1';
+                read_status <= '0';
             end if;
 
             if(cpu_addr = OAMADDR) then
@@ -260,7 +304,6 @@ begin
             end if;
 
             if(cpu_addr = PPUADDR) then
-                ppu_addr_cnt_ce_n <= '0';
                 ppu_addr_we_n <= '0';
                 if (ppu_addr_cnt(0) = '0') then
                     ppu_addr_in <= cpu_d(5 downto 0) & ppu_addr(7 downto 0);
@@ -268,28 +311,36 @@ begin
                     ppu_addr_in <= ppu_addr(13 downto 8) & cpu_d;
                 end if;
             else
-                ppu_addr_cnt_ce_n <= '1';
                 ppu_addr_we_n <= '1';
             end if;
+
+            if (cpu_addr = PPUDATA and r_nw = '1') then
+                read_data_n <= '0';
+            else
+                read_data_n <= '1';
+            end if;
         else
             ppu_ctrl_we_n    <= '1';
             ppu_mask_we_n    <= '1';
-            ppu_status_we_n  <= '1';
             oam_addr_we_n    <= '1';
             oam_data_we_n    <= '1';
             ppu_scroll_x_we_n    <= '1';
             ppu_scroll_y_we_n    <= '1';
             ppu_scroll_cnt_ce_n  <= '1';
             ppu_addr_we_n        <= '1';
-            ppu_addr_cnt_ce_n    <= '1';
+            read_status <= '0';
+            read_data_n <= '1';
         end if; --if (rst_n = '1' and ce_n = '0') 
 
     end process;
 
     --cpu and ppu clock timing adjustment...
-    clk_cnt_set_p : process (rst_n, ce_n, r_nw, cpu_addr, cpu_d, clk, oam_plt_data)
+    clk_cnt_set_p : process (rst_n, ce_n, r_nw, cpu_addr, cpu_d, clk, 
+                                oam_plt_data, vram_ad, ppu_stat_out)
     begin
-        if (rst_n = '1' and ce_n = '0') then
+        if (rst_n = '0') then
+            ppu_latch_rst_n <= '0';
+        elsif (rst_n = '1' and ce_n = '0') then
             --set counter=0 on register write.   
             if (ce_n'event or r_nw'event or cpu_addr'event or (cpu_d'event and r_nw = '0')) then
                 ppu_clk_cnt_res_n <= '0';
@@ -303,6 +354,13 @@ begin
                 elsif (ppu_clk_cnt = "00") then
                     ppu_clk_cnt_res_n <= '1';
                 end if;
+
+                if (read_status = '1') then
+                    --reading status resets ppu_addr/scroll cnt.
+                    ppu_latch_rst_n <= '0';
+                else
+                    ppu_latch_rst_n <= '1';
+                end if;
                 --d_print("clk event");
             end if;
 
@@ -322,10 +380,11 @@ begin
                 cpu_d <= (others => 'Z');
                 oam_addr_ce_n <= '1';
                 oam_bus_ce_n <= '1';
-            end if;
+            end if; --if (cpu_addr = OAMDATA and ppu_clk_cnt = "00") then
 
             --vram address access.
             if (cpu_addr = PPUADDR and ppu_clk_cnt = "00") then
+                ppu_addr_cnt_ce_n <= '0';
                 if (ppu_addr_cnt(0) = '0') then
                     --load addr high
                     ale <= '0';
@@ -343,6 +402,7 @@ begin
                     end if;
                 end if;
             elsif (cpu_addr = PPUDATA and ppu_clk_cnt = "01") then
+                ppu_addr_cnt_ce_n <= '1';
                 --for burst write.
                 if (ppu_addr(13 downto 8) = "111111") then
                     oam_plt_addr <= ppu_addr(7 downto 0);
@@ -353,15 +413,22 @@ begin
                     ale <= '1';
                 end if;
             else
+                ppu_addr_cnt_ce_n <= '1';
                 ale <= '0';
-            end if;
+            end if; --if (cpu_addr = PPUADDR and ppu_clk_cnt = "00") then
 
             if (cpu_addr = PPUDATA and ppu_clk_cnt = "00") then
                 ppu_data_we_n <= '0';
+                vram_a <= ppu_addr(13 downto 8);
                 if (ppu_addr(13 downto 8) = "111111") then
                     --case palette tbl.
                     plt_bus_ce_n <= '0';
-                    oam_plt_data <= cpu_d;
+                    if (r_nw = '0') then
+                        oam_plt_data <= cpu_d;
+                    else
+                        oam_plt_data <= (others => 'Z');
+                        cpu_d <= oam_plt_data;
+                    end if;
                     rd_n <= '1';
                     wr_n <= '1';
                 else
@@ -370,13 +437,31 @@ begin
                     plt_bus_ce_n <= '1';
                     if (r_nw = '0') then
                         vram_ad <= cpu_d;
+                    else
+                        cpu_d <= ppu_data_out;
                     end if;
                 end if;
             else
                 plt_bus_ce_n <= '1';
                 ppu_data_we_n <= '1';
-                rd_n <= '1';
-                wr_n <= '1';
+                rd_n <= 'Z';
+                wr_n <= 'Z';
+            end if; --if (cpu_addr = PPUDATA and ppu_clk_cnt = "00") then
+
+            --sustain cpu output data when reading.
+            if (cpu_addr = PPUDATA and r_nw = '1' and ppu_clk_cnt /= "00") then
+                if (ppu_addr(13 downto 8) = "111111") then
+                    cpu_d <= plt_data_out;
+                else
+                    cpu_d <= ppu_data_out;
+                end if;
+            end if;
+            if (cpu_addr = OAMDATA and r_nw = '1' and ppu_clk_cnt /= "00") then
+                cpu_d <= oam_data;
+            end if;
+
+            if(cpu_addr = PPUSTATUS and r_nw = '1') then
+                cpu_d <= ppu_stat_out;
             end if;
 
         else
@@ -385,6 +470,8 @@ begin
             ppu_clk_cnt_res_n <= '0';
             oam_bus_ce_n     <= '1';
             oam_addr_ce_n <= '1';
+            ppu_addr_cnt_ce_n    <= '1';
+            ppu_latch_rst_n <= '1';
 
             rd_n <= 'Z';
             wr_n <= 'Z';
@@ -393,7 +480,7 @@ begin
             vram_ad <= (others => 'Z');
             vram_a <= (others => 'Z');
             cpu_d <= (others => 'Z');
-        end if;
+        end if; --if (rst_n = '0') then
     end process;
 
 end rtl;