OSDN Git Service

ppu integration start...
authorastoria-d@fc <astoria-d@fc>
Fri, 9 Sep 2016 09:45:47 +0000 (18:45 +0900)
committerastoria-d@fc <astoria-d@fc>
Fri, 9 Sep 2016 09:45:47 +0000 (18:45 +0900)
de0_cv_nes/de0_cv_nes.vhd
de0_cv_nes/dummy-mos6502.vhd
de0_cv_nes/mos6502-timing.sdc
de0_cv_nes/ppu.vhd [new file with mode: 0644]

index 05ea01c..6ba47a5 100644 (file)
@@ -28,11 +28,11 @@ end de0_cv_nes;
 
 architecture rtl of de0_cv_nes is
     component mos6502
-        port (  
-                pi_base_clk    : in std_logic;\r
-                pi_cpu_en       : in std_logic_vector (7 downto 0);\r
-                pi_rdy         : in std_logic;\r
+        port (
                 pi_rst_n       : in std_logic;\r
+                pi_base_clk    : in std_logic;\r
+                pi_cpu_en      : in std_logic_vector (7 downto 0);\r
+                pi_rdy         : in std_logic;\r
                 pi_irq_n       : in std_logic;\r
                 pi_nmi_n       : in std_logic;\r
                 po_r_nw        : out std_logic;\r
@@ -42,7 +42,7 @@ architecture rtl of de0_cv_nes is
     end component;
 
     component clock_selector\r
-        port (  \r
+        port (\r
                 pi_rst_n        : in std_logic;\r
                 pi_base_clk     : in std_logic;\r
                 po_cpu_en       : out std_logic_vector (7 downto 0);\r
@@ -51,18 +51,19 @@ architecture rtl of de0_cv_nes is
     end component;\r
 \r
     component ppu port (
+                pi_rst_n       : in std_logic;\r
                 pi_base_clk    : in std_logic;
+                pi_ppu_en      : in std_logic_vector (3 downto 0);\r
                 pi_ce_n        : in std_logic;
-                pi_rst_n       : in std_logic;
                 pi_r_nw        : in std_logic;
                 pi_cpu_addr    : in std_logic_vector (2 downto 0);
-                pio_cpu_d       : inout std_logic_vector (7 downto 0);
+                pio_cpu_d      : inout std_logic_vector (7 downto 0);
 
                 po_rd_n        : out std_logic;
                 po_wr_n        : out std_logic;
                 po_ale_n       : out std_logic;
                 po_vram_addr   : out std_logic_vector (13 downto 0);
-                pio_vram_data   : inout std_logic_vector (7 downto 0)
+                pio_vram_data  : inout std_logic_vector (7 downto 0)
     );
     end component;
 
@@ -120,10 +121,10 @@ begin
 \r
     --mos 6502 cpu instance\r
     cpu_inst : mos6502 port map (\r
+            pi_rst_n, \r
             pi_base_clk, \r
             wr_cpu_en, \r
             wr_rdy,\r
-            pi_rst_n, \r
             wr_irq_n, \r
             wr_nmi_n, \r
             wr_r_nw, \r
@@ -152,4 +153,3 @@ begin
     po_g           <= (others => '0');\r
     po_b           <= (others => '0');\r
 end rtl;
-
index 19ab7de..b8a85ca 100644 (file)
@@ -3,10 +3,10 @@ use ieee.std_logic_1164.all;
 \r
 entity mos6502 is \r
     port (  \r
+            pi_rst_n       : in std_logic;\r
             pi_base_clk        : in std_logic;\r
             pi_cpu_en       : in std_logic_vector (7 downto 0);\r
             pi_rdy         : in std_logic;\r
-            pi_rst_n       : in std_logic;\r
             pi_irq_n       : in std_logic;\r
             pi_nmi_n       : in std_logic;\r
             po_r_nw        : out std_logic;\r
index 87fa99a..613ab79 100644 (file)
@@ -1,3 +1,3 @@
-create_clock -name base_clock -period 20 [get_ports {base_clk}]\r
+create_clock -name base_clock -period 20 [get_ports {pi_base_clk}]\r
 #create_generated_clock -name cpu_clock -source [get_ports {base_clk}] -divide_by 24 -invert [get_registers {clock_divider:clock_inst|cpu_clk_wk}]\r
 #create_generated_clock -name emu_ppu_clock -source [get_ports {base_clk}] -divide_by 4 -invert [get_registers {clock_divider:clock_inst|counter_register:cpu_clk_cnt|d_flip_flop:counter_reg_inst|q[1]}]\r
diff --git a/de0_cv_nes/ppu.vhd b/de0_cv_nes/ppu.vhd
new file mode 100644 (file)
index 0000000..eb52503
--- /dev/null
@@ -0,0 +1,261 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use work.motonesfpga_common.all;
+
+entity ppu is 
+    port (
+                pi_base_clk    : in std_logic;
+                pi_ppu_en      : in std_logic_vector (3 downto 0);
+                pi_ce_n        : in std_logic;
+                pi_rst_n       : in std_logic;
+                pi_r_nw        : in std_logic;
+                pi_cpu_addr    : in std_logic_vector (2 downto 0);
+                pio_cpu_d      : inout std_logic_vector (7 downto 0);
+
+                po_rd_n        : out std_logic;
+                po_wr_n        : out std_logic;
+                po_ale_n       : out std_logic;
+                po_vram_addr   : out std_logic_vector (13 downto 0);
+                pio_vram_data  : inout std_logic_vector (7 downto 0)
+    );
+end ppu;
+
+architecture rtl of ppu is
+
+constant PPUCTRL   : std_logic_vector(2 downto 0) := "000";
+constant PPUMASK   : std_logic_vector(2 downto 0) := "001";
+constant PPUSTATUS : std_logic_vector(2 downto 0) := "010";
+constant OAMADDR   : std_logic_vector(2 downto 0) := "011";
+constant OAMDATA   : std_logic_vector(2 downto 0) := "100";
+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
+
+constant WR0 : std_logic_vector (0 downto 0) := "0";
+constant WR1 : std_logic_vector (0 downto 0) := "1";
+
+signal ppu_ctrl_we_n    : std_logic;
+signal ppu_mask_we_n    : std_logic;
+signal ppu_addr_we_n        : std_logic;
+signal ppu_addr_inc_n       : std_logic;
+signal ppu_addr_upd_n       : std_logic;
+signal ppu_data_we_n    : std_logic;
+signal ppu_scroll_x_we_n    : std_logic;
+signal ppu_scroll_y_we_n    : std_logic;
+signal oam_addr_inc_n    : std_logic;
+signal oam_addr_we_n    : std_logic;
+signal oam_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 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_wr_cycle    : std_logic_vector (0 downto 0);
+
+signal ppu_status       : std_logic_vector (dsize - 1 downto 0);
+signal rdr_ppu_stat     : std_logic_vector (dsize - 1 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 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_scr_wr_cycle    : std_logic_vector (0 downto 0);
+
+signal oam_bus_ce_n     : std_logic;
+signal plt_bus_ce_n     : std_logic;
+
+signal rnd_rd_n, rnd_wr_n, rnd_ale_n : std_logic;
+signal rnd_vram_addr    : std_logic_vector (13 downto 0);
+signal rnd_vram_data    : std_logic_vector (7 downto 0);
+
+signal rnd_plt_data_out     : std_logic_vector (7 downto 0);
+signal rnd_oam_data_out     : std_logic_vector (7 downto 0);
+
+begin
+
+    -----------------------------
+    --PPU register set..
+    -----------------------------
+    --ppu ctl reg.
+    ppu_ctrl_we_n <= '0' when ce_n = '0' and cpu_addr = PPUCTRL and r_nw = '0' else
+                     '1';
+    ppu_ctrl_inst : d_flip_flop generic map(dsize)
+            port map (dl_cpu_clk, rst_n, '1', ppu_ctrl_we_n, cpu_d, ppu_ctrl);
+
+    --ppu mask reg.
+    ppu_mask_we_n <= '0' when ce_n = '0' and cpu_addr = PPUMASK and r_nw = '0' else
+                     '1';
+    ppu_mask_inst : d_flip_flop generic map(dsize)
+            port map (dl_cpu_clk, rst_n, '1', ppu_mask_we_n, cpu_d, ppu_mask);
+
+    ppu_status_inst : d_flip_flop generic map(dsize)
+            port map (cpu_clk, rst_n, '1', '0', rdr_ppu_stat, ppu_status);
+
+    --ppu addr reg.
+    ppu_addr_in <=  cpu_d(5 downto 0) & ppu_addr(7 downto 0)
+                        when ppu_addr_wr_cycle = WR0 else
+                    ppu_addr(13 downto 8) & cpu_d;
+    ppu_addr_we_n <= '0' when ce_n = '0' and cpu_addr = PPUADDR and r_nw = '0' else
+                     '1';
+    ppu_addr_inc_en_inst : d_flip_flop_bit
+            port map (dl_cpu_clk, '1', rst_n, '0', ppu_data_we_n, ppu_addr_inc_n);
+    ppu_addr_inst_inc1 : counter_register generic map(14, 1)
+            port map (dl_cpu_clk, rst_n, ppu_addr_inc_n, ppu_addr_we_n, ppu_addr_in, ppu_addr_inc1);
+    ppu_addr_inst_inc32 : counter_register generic map(14, 32)
+            port map (dl_cpu_clk, rst_n, ppu_addr_inc_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 write cycle update.
+    clk_addr_wr_p : process (rst_n, dl_cpu_clk)
+    begin
+        if (rst_n = '0') then
+            ppu_addr_wr_cycle <= WR0;
+            ppu_scr_wr_cycle <= WR0;
+        elsif (rising_edge(dl_cpu_clk) and ce_n = '0') then
+            --ppu addr cycle.
+            if (cpu_addr = PPUADDR and r_nw = '0') then
+                if (ppu_addr_wr_cycle = WR1) then
+                    ppu_addr_wr_cycle <= WR0;
+                else
+                    ppu_addr_wr_cycle <= WR1;
+                end if;
+            elsif (cpu_addr = PPUSTATUS and r_nw = '1') then
+                --reset read count after reading status res.
+                ppu_addr_wr_cycle <= WR0;
+            end if;
+
+            --ppu scroll cycle.
+            if (cpu_addr = PPUSCROLL and r_nw = '0') then
+                if (ppu_scr_wr_cycle = WR1) then
+                    ppu_scr_wr_cycle <= WR0;
+                else
+                    ppu_scr_wr_cycle <= WR1;
+                end if;
+            elsif (cpu_addr = PPUSTATUS and r_nw = '1') then
+                --reset read count after reading status res.
+                ppu_scr_wr_cycle <= WR0;
+            end if;
+
+        end if;
+    end process;
+
+    --ppu data reg.
+    ppu_data_we_n <= '0' when ce_n = '0' and cpu_addr = PPUDATA and r_nw = '0' else
+                     '1';
+    ppu_data_inst : d_flip_flop generic map(dsize)
+            port map (dl_cpu_clk, rst_n, '1', ppu_data_we_n, cpu_d, ppu_data);
+
+    --oam addr reg.
+    oam_addr_we_n <= '0' when ce_n = '0' and cpu_addr = OAMADDR and r_nw = '0' else
+                     '1';
+    oam_addr_inc_en_inst : d_flip_flop_bit
+            port map (dl_cpu_clk, '1', rst_n, '0', oam_data_we_n, oam_addr_inc_n);
+    oma_addr_inst : counter_register generic map(dsize, 1)
+            port map (dl_cpu_clk, rst_n, oam_addr_inc_n, oam_addr_we_n, cpu_d, oam_addr);
+
+    --oam data reg.
+    oam_data_we_n <= '0' when ce_n = '0' and cpu_addr = OAMDATA and r_nw = '0' else
+                     '1';
+    oma_data_inst : d_flip_flop generic map(dsize)
+            port map (dl_cpu_clk, rst_n, '1', oam_data_we_n, cpu_d, oam_data);
+
+    --oam chip enable.
+    oam_bus_ce_n <= '0' when ce_n = '0' and cpu_addr = OAMDATA else
+                    '1';
+    
+    --scroll reg.
+    ppu_scroll_x_we_n <= '0' when ce_n = '0' and cpu_addr = PPUSCROLL and 
+                                  r_nw = '0' and ppu_scr_wr_cycle = WR0 else
+                     '1';
+    ppu_scroll_x_inst : d_flip_flop generic map(dsize)
+            port map (dl_cpu_clk, rst_n, '1', ppu_scroll_x_we_n, cpu_d, ppu_scroll_x);
+    ppu_scroll_y_we_n <= '0' when ce_n = '0' and cpu_addr = PPUSCROLL and 
+                                  r_nw = '0' and ppu_scr_wr_cycle = WR1 else
+                     '1';
+    ppu_scroll_y_inst : d_flip_flop generic map(dsize)
+            port map (dl_cpu_clk, rst_n, '1', ppu_scroll_y_we_n, cpu_d, ppu_scroll_y);
+
+
+    -----------------------------
+    --vram access.
+    -----------------------------
+    dbg_ppu_scrl_y(0) <= ppu_addr_upd_n;
+    dbg_ppu_scrl_y(1) <= ppu_addr_inc_n;
+    dbg_ppu_scrl_y(2) <= ppu_data_we_n;
+
+    ppu_addr_upd_en_inst : d_flip_flop_bit
+            port map (dl_cpu_clk, rst_n, '1', '0', ppu_addr_inc_n, ppu_addr_upd_n);
+    ale_n <= '0' when ce_n = '0' and cpu_addr = PPUADDR and r_nw = '0' else
+           '0' when ppu_addr_upd_n = '0' else
+           '1' when ce_n = '0' and cpu_addr = PPUDATA and r_nw = '0' else
+           rnd_ale_n;
+    wr_n <= '0' when ce_n = '0' and cpu_addr = PPUDATA and r_nw = '0' else
+            '1' when ppu_addr_upd_n = '0' else
+            '1' when ce_n = '0' and cpu_addr = PPUADDR and r_nw = '0' else
+            rnd_wr_n;
+    rd_n <= '1' when ce_n = '0' and cpu_addr = PPUADDR and r_nw = '0' else
+            '1' when ppu_addr_upd_n = '0' else
+            '0' when ce_n = '0' and cpu_addr = PPUDATA and r_nw = '1' else
+            rnd_rd_n;
+
+    vram_addr <= ppu_addr when ce_n = '0' and cpu_addr = PPUADDR and r_nw = '0' else
+              ppu_addr when ppu_addr_upd_n = '0' else
+              ppu_addr when ce_n = '0' and cpu_addr = PPUDATA else
+              rnd_vram_addr when rnd_ale_n = '0' else
+              (others => 'Z');
+    vram_data <= cpu_d when ce_n = '0' and cpu_addr = PPUDATA and r_nw = '0' else
+               (others => 'Z');
+
+   rnd_vram_data <= vram_data;
+
+
+    -----------------------------
+    --palette ram access..
+    -----------------------------
+    plt_bus_ce_n <= '0' when ce_n = '0' and cpu_addr = PPUDATA and ppu_addr(13 downto 8) = "111111" else
+                    '1';
+
+    -----------------------------
+    --cpu nmi generation...
+    -----------------------------
+    clk_nmi_p : process (rst_n, ppu_clk)
+    begin
+        if (rst_n = '0') then
+            vblank_n <= '1';
+        elsif (rising_edge(ppu_clk)) then
+            if (rdr_ppu_stat(ST_VBL) = '1' and ppu_ctrl(PPUNEN) = '1') then
+                --nmi takes place only when ST_VBL arises...
+                --doesn't work....
+--                if (ST_VBL_old = '0') then
+                    --start vblank.
+                    vblank_n <= '0';
+--                end if;
+            else
+                --clear flag.
+                vblank_n <= '1';
+            end if;
+        end if;
+    end process;
+
+    -----------------------------
+    --read from cpu...
+    -----------------------------
+    --TODO! palette ram read sequence must be re-worked!!
+    cpu_d <= ppu_status when ce_n = '0' and cpu_addr = PPUSTATUS and r_nw = '1' else
+             rnd_plt_data_out when ce_n = '0' and cpu_addr = PPUDATA and
+                                           ppu_addr(13 downto 8) = "111111" and r_nw = '1' else
+             vram_data when ce_n = '0' and cpu_addr = PPUDATA and r_nw = '1' else
+             (others => 'Z');
+
+end rtl;
+