OSDN Git Service

- env update.
[motonesfpga/motonesfpga.git] / de1_nes / apu / apu.vhd
diff --git a/de1_nes/apu/apu.vhd b/de1_nes/apu/apu.vhd
new file mode 100644 (file)
index 0000000..55d9bc8
--- /dev/null
@@ -0,0 +1,194 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity apu is 
+    port (  clk         : in std_logic;
+            ce_n        : in std_logic;
+            rst_n       : in std_logic;
+            r_nw        : inout std_logic;
+            cpu_addr    : inout std_logic_vector (15 downto 0);
+            cpu_d       : inout std_logic_vector (7 downto 0);
+            rdy         : out std_logic
+    );
+end apu;
+
+architecture rtl of apu is
+
+
+component d_flip_flop
+    generic (
+            dsize : integer := 8
+            );
+    port (
+            clk     : in std_logic;
+            res_n   : in std_logic;
+            set_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)
+        );
+end component;
+
+component counter_register
+    generic (
+        dsize       : integer := 8;
+        inc         : integer := 1
+    );
+    port (  clk         : in std_logic;
+            rst_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)
+    );
+end component;
+
+constant dsize     : integer := 8;
+constant OAM_DMA   : std_logic_vector(4 downto 0) := "10100";
+constant OAM_JP1   : std_logic_vector(4 downto 0) := "10110";
+constant OAM_JP2   : std_logic_vector(4 downto 0) := "10111";
+
+--oamaddr=0x2003
+constant OAMADDR   : std_logic_vector(15 downto 0) := "0010000000000011";
+--oamdata=0x2004
+constant OAMDATA   : std_logic_vector(15 downto 0) := "0010000000000100";
+
+signal clk_n            : std_logic;
+
+signal oam_data         : std_logic_vector (dsize - 1 downto 0);
+
+signal oam_bus_ce_n     : std_logic;
+
+signal dma_addr         : std_logic_vector (dsize * 2 - 1 downto 0);
+signal dma_cnt_ce_n     : std_logic_vector(0 downto 0);
+signal dma_cnt_ce       : std_logic;
+signal dma_start_n      : std_logic;
+signal dma_end_n        : std_logic;
+signal dma_process_n    : std_logic;
+signal dma_rst_n        : std_logic;
+signal dma_status_we_n  : std_logic;
+signal dma_status       : std_logic_vector(1 downto 0);
+signal dma_next_status  : std_logic_vector(1 downto 0);
+
+constant DMA_ST_IDLE    : std_logic_vector(1 downto 0) := "00";
+constant DMA_ST_SETUP   : std_logic_vector(1 downto 0) := "01";
+constant DMA_ST_PROCESS : std_logic_vector(1 downto 0) := "10";
+
+begin
+
+    clk_n <= not clk;
+
+    dma_rst_n <= not dma_process_n;
+
+    dma_l_up_inst : counter_register generic map (1, 1)
+            port map (clk_n, dma_rst_n, dma_process_n, '1', (others => '0'), dma_cnt_ce_n);
+
+    dma_cnt_ce <= not dma_cnt_ce_n(0);
+    dma_l_inst : counter_register generic map (dsize, 1)
+            port map (clk, dma_rst_n, dma_cnt_ce, '1', (others => '0'), 
+                                                dma_addr(dsize - 1 downto 0));
+    dma_h_inst : d_flip_flop generic map(dsize)
+            port map (clk_n, '1', '1', dma_start_n, cpu_d, 
+                                                dma_addr(dsize * 2 - 1 downto dsize));
+
+    dma_status_inst : d_flip_flop generic map(2)
+            port map (clk_n, rst_n, '1', dma_status_we_n, dma_next_status, dma_status);
+
+    dma_val_inst : d_flip_flop generic map(dsize)
+            port map (clk_n, rst_n, '1', dma_process_n, cpu_d, oam_data);
+
+    --apu register access process
+    reg_set_p : process (rst_n, ce_n, r_nw, cpu_addr, cpu_d)
+    begin
+        if (rst_n = '1' and ce_n = '0') then
+            if (r_nw = '0') then
+                --apu write
+                cpu_d <= (others => 'Z');
+                if (cpu_addr(4 downto 0) = OAM_DMA) then
+                    dma_start_n <= '0';
+                else
+                    dma_start_n <= '1';
+                end if;
+            elsif (r_nw = '1') then
+                --apu read
+                if (cpu_addr(4 downto 0) = OAM_JP1) then
+                    cpu_d <= (others => '0');
+                elsif (cpu_addr(4 downto 0) = OAM_JP2) then
+                    cpu_d <= (others => '0');
+                else
+                    --return dummy zero vale.
+                    cpu_d <= (others => '0');
+                end if;
+            end if;
+        else
+            cpu_d <= (others => 'Z');
+            dma_start_n <= '1';
+        end if; --if (rst_n = '1' and ce_n = '0') 
+    end process;
+
+    --dma operation process
+    dma_p : process (rst_n, clk)
+    begin
+        if (rst_n = '0') then
+            dma_next_status <= DMA_ST_IDLE;
+            dma_end_n <= '1';
+            rdy <= '1';
+            dma_process_n <= '1';
+            cpu_addr <= (others => 'Z');
+            cpu_d <= (others => 'Z');
+            r_nw <= 'Z';
+        else
+            if (clk'event and clk = '0') then
+                if (dma_start_n = '0') then
+                    --pull rdy pin down to stop cpu bus accessing.
+                    rdy <= '0';
+                end if;
+                if (dma_end_n = '0') then
+                    --pull rdy pin up to re-enable cpu bus accessing.
+                    rdy <= '1';
+                end if;
+            end if;
+
+            if (clk'event and clk = '1') then
+                if (dma_status = DMA_ST_IDLE) then
+                    if (dma_start_n = '0') then
+                        dma_status_we_n <= '0';
+                        dma_next_status <= DMA_ST_SETUP;
+                    end if;
+                    dma_process_n <= '1';
+                    dma_end_n <= '1';
+                    cpu_addr <= (others => 'Z');
+                    cpu_d <= (others => 'Z');
+                    r_nw <= 'Z';
+                elsif (dma_status = DMA_ST_SETUP) then
+                    cpu_addr <= OAMADDR;
+                    cpu_d <= (others => '0');
+                    r_nw <= '0';
+                    dma_next_status <= DMA_ST_PROCESS;
+                elsif (dma_status = DMA_ST_PROCESS) then
+                    if (dma_addr(dsize - 1 downto 0) = "11111111" and dma_cnt_ce_n(0) = '1') then
+                        dma_status_we_n <= '0';
+                        dma_next_status <= DMA_ST_IDLE;
+                        dma_end_n <= '0';
+                    else
+                        dma_status_we_n <= '1';
+                        dma_process_n <= '0';
+                        dma_end_n <= '1';
+                    end if;
+
+                    if (dma_cnt_ce_n(0) = '0') then
+                        r_nw <= '1';
+                        cpu_addr <= dma_addr;
+                        cpu_d <= (others => 'Z');
+                    elsif (dma_cnt_ce_n(0) = '1') then
+                        r_nw <= '0';
+                        cpu_addr <= OAMDATA;
+                        cpu_d <= oam_data;
+                    end if;
+                end if;--if (dma_status = DMA_ST_IDLE) then
+            end if;--if (clk'event and clk = '1') then
+        end if;
+    end process;
+
+end rtl;
+