From 2d03105a83151a111cbeb580de5e516e8fc8f4f8 Mon Sep 17 00:00:00 2001 From: astoria-d Date: Fri, 20 Sep 2013 17:36:12 +0900 Subject: [PATCH] - env update. - model sim setting update. --- de1_nes/.gitignore | 5 +- de1_nes/address_decoder.vhd | 8 +- de1_nes/apu/apu.vhd | 194 ++++++++++++++++++++++ de1_nes/clock/clock_divider.vhd | 122 +++++++------- de1_nes/cpu/alu.vhd | 45 ++---- de1_nes/cpu/decoder.vhd | 69 ++++---- de1_nes/cpu/mos6502.vhd | 20 +-- de1_nes/de1_nes.pin | 78 ++++----- de1_nes/de1_nes.qsf | 14 +- de1_nes/de1_nes.qws | 66 -------- de1_nes/de1_nes.vhd | 316 ++++++++++++++++++------------------ de1_nes/mem/ram.vhd | 37 +++++ de1_nes/motonesfpga_common.vhd | 65 ++++++++ de1_nes/ppu/ppu.vhd | 123 ++++++++------ de1_nes/ppu/render.vhd | 330 +++++++++++++++++++------------------- de1_nes/ppu/vga.vhd | 302 ++++++++++++++++++++++++++++++++++ de1_nes/testbench_motones_sim.vhd | 85 ++++++++++ 17 files changed, 1248 insertions(+), 631 deletions(-) create mode 100644 de1_nes/apu/apu.vhd create mode 100644 de1_nes/motonesfpga_common.vhd create mode 100644 de1_nes/ppu/vga.vhd create mode 100644 de1_nes/testbench_motones_sim.vhd diff --git a/de1_nes/.gitignore b/de1_nes/.gitignore index 81e80d1..bafe3f7 100644 --- a/de1_nes/.gitignore +++ b/de1_nes/.gitignore @@ -8,8 +8,5 @@ *.html db/* no-need/* -simulation/modelsim/gate_work/* -simulation/modelsim/rtl_work/* -simulation/modelsim/msim_transcript -simulation/modelsim/vsim.wlf +simulation/* undo_redo.txt diff --git a/de1_nes/address_decoder.vhd b/de1_nes/address_decoder.vhd index e3519c8..3a41860 100644 --- a/de1_nes/address_decoder.vhd +++ b/de1_nes/address_decoder.vhd @@ -220,7 +220,7 @@ begin nt1_ce_n <= '1'; if (wr_n = '0') then --write - nt0_ce_n <= not clk; + nt0_ce_n <= clk; elsif (rd_n = '0') then --read nt0_ce_n <= '0'; @@ -232,7 +232,7 @@ begin nt0_ce_n <= '1'; if (wr_n = '0') then --write - nt1_ce_n <= not clk; + nt1_ce_n <= clk; elsif (rd_n = '0') then --read nt1_ce_n <= '0'; @@ -248,7 +248,7 @@ begin nt1_ce_n <= '1'; if (wr_n = '0') then --write - nt0_ce_n <= not clk; + nt0_ce_n <= clk; elsif (rd_n = '0') then --read nt0_ce_n <= '0'; @@ -260,7 +260,7 @@ begin nt0_ce_n <= '1'; if (wr_n = '0') then --write - nt1_ce_n <= not clk; + nt1_ce_n <= clk; elsif (rd_n = '0') then --read nt1_ce_n <= '0'; diff --git a/de1_nes/apu/apu.vhd b/de1_nes/apu/apu.vhd new file mode 100644 index 0000000..55d9bc8 --- /dev/null +++ b/de1_nes/apu/apu.vhd @@ -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; + diff --git a/de1_nes/clock/clock_divider.vhd b/de1_nes/clock/clock_divider.vhd index 83d8562..8820b7f 100644 --- a/de1_nes/clock/clock_divider.vhd +++ b/de1_nes/clock/clock_divider.vhd @@ -6,66 +6,80 @@ entity clock_divider is port ( base_clk : in std_logic; reset_n : in std_logic; cpu_clk : out std_logic; - ppu_clk : out std_logic; - vga_clk : out std_logic + ppu_clk : out std_logic; + vga_clk : out std_logic ); end clock_divider; architecture rtl of clock_divider is -signal loop2 : std_logic_vector (0 downto 0); +signal loop2 : std_logic_vector (0 downto 0); signal loop6 : std_logic_vector (2 downto 0); -signal cpu_cnt_rst_n : std_logic; -signal cpu_clk_new : std_logic; -signal cpu_clk_old : std_logic; -signal cpu_we_n : std_logic; - -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; - -component d_flip_flop_bit - port ( - clk : in std_logic; - res_n : in std_logic; - set_n : in std_logic; - we_n : in std_logic; - d : in std_logic; - q : out std_logic - ); -end component; - +signal base_clk_n : std_logic; +signal cpu_cnt_rst_n : std_logic; +signal cpu_we_n : std_logic; +signal cpu_clk_new : std_logic; +signal cpu_clk_old : std_logic; + +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; + +component d_flip_flop_bit + port ( + clk : in std_logic; + res_n : in std_logic; + set_n : in std_logic; + we_n : in std_logic; + d : in std_logic; + q : out std_logic + ); +end component; + begin - ---base clock 25 MHz = VGA clock. - cpu_clk_old <= not cpu_clk_new; - cpu_clk <= cpu_clk_new; - ppu_clk <= not loop2(0); - vga_clk <= base_clk; - - cpu_cnt_rst_n <= '0' when reset_n = '0' else - '0' when loop6 = "110" else - '1'; - cpu_we_n <= '0' when loop6 = "101" else - '1'; - - ppu_clk_cnt : counter_register generic map (1) port map - (base_clk, reset_n, '0', '1', (others=>'0'), loop2); - - cpu_clk_cnt : counter_register generic map (3) port map - (base_clk, cpu_cnt_rst_n, '0', '1', (others=>'0'), loop6); - - cpu_clk_cnt2 : d_flip_flop_bit port map - (base_clk, reset_n, '1', cpu_we_n, cpu_clk_old, cpu_clk_new); - + base_clk_n <= not base_clk; + ---base clock 25 MHz = VGA clock. + cpu_clk_old <= not cpu_clk_new; + cpu_clk <= cpu_clk_new; + ppu_clk <= not loop2(0); + vga_clk <= base_clk; + + cpu_we_n <= '0' when loop6 = "001" else + '0' when loop6 = "100" else + '1'; + ppu_clk_cnt : counter_register generic map (1) port map + (base_clk, reset_n, '0', '1', (others=>'0'), loop2); + + cpu_clk_cnt : counter_register generic map (3) port map + (base_clk_n, cpu_cnt_rst_n, '0', '1', (others=>'0'), loop6); + + cpu_clk_cnt2 : d_flip_flop_bit port map + (base_clk, reset_n, '1', cpu_we_n, cpu_clk_old, cpu_clk_new); + + clock_p : process (base_clk) + begin + if (reset_n = '0') then + cpu_cnt_rst_n <= '0'; + else + if (base_clk'event and base_clk = '1') then + if (loop6 = "101") then + cpu_cnt_rst_n <= '0'; + else + cpu_cnt_rst_n <= '1'; + end if; + end if; + end if; + end process; + end rtl; diff --git a/de1_nes/cpu/alu.vhd b/de1_nes/cpu/alu.vhd index 841d889..e8e0b4d 100644 --- a/de1_nes/cpu/alu.vhd +++ b/de1_nes/cpu/alu.vhd @@ -5,6 +5,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.conv_std_logic_vector; +use work.motonesfpga_common.all; entity alu is generic ( dsize : integer := 8 @@ -247,15 +248,6 @@ begin end if; end procedure; -procedure d_print(msg : string) is -use std.textio.all; ---use ieee.std_logic_textio.all; ---variable out_l : line; -begin --- write(out_l, msg); --- writeline(output, out_l); -end procedure; - procedure set_nz is begin negative <= n; @@ -632,19 +624,19 @@ end procedure; d1 <= arith_reg_out; int_d_bus <= d_out; --- if (clk = '0') then --- --d_print("clk hi"); --- if (m2m_stat_1 = '0') then --- --first cycle. keep input variable. --- --d_print("inc first."); --- m2m_stat_1 <= '1'; --- arith_buf_we_n <= '0'; --- arith_buf_oe_n <= '1'; --- d_oe_n <= '1'; --- --- end if; --- end if; --- + if (clk = '0') then + --d_print("clk hi"); + if (m2m_stat_1 = '0') then + --first cycle. keep input variable. + --d_print("inc first."); + m2m_stat_1 <= '1'; + arith_buf_we_n <= '0'; + arith_buf_oe_n <= '1'; + d_oe_n <= '1'; + + end if; + end if; + -- if (clk'event and clk = '0') then -- if (m2m_stat_2 = '0') then -- --second cycle read from register, output modified data. @@ -839,15 +831,6 @@ end alu_core; architecture rtl of alu_core is -procedure d_print(msg : string) is -use std.textio.all; ---use ieee.std_logic_textio.all; -variable out_l : line; -begin --- write(out_l, msg); --- writeline(output, out_l); -end procedure; - constant ALU_AND : std_logic_vector (3 downto 0) := "0000"; constant ALU_EOR : std_logic_vector (3 downto 0) := "0001"; constant ALU_OR : std_logic_vector (3 downto 0) := "0010"; diff --git a/de1_nes/cpu/decoder.vhd b/de1_nes/cpu/decoder.vhd index cdb78fb..c87be34 100644 --- a/de1_nes/cpu/decoder.vhd +++ b/de1_nes/cpu/decoder.vhd @@ -2,6 +2,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.conv_std_logic_vector; use ieee.std_logic_unsigned.conv_integer; +use work.motonesfpga_common.all; entity decoder is generic (dsize : integer := 8); @@ -73,25 +74,6 @@ component d_flip_flop_bit ); end component; -procedure d_print(msg : string) is -use std.textio.all; ---use ieee.std_logic_textio.all; -variable out_l : line; -begin --- write(out_l, msg); --- writeline(output, out_l); -end procedure; - ----ival : 0x0000 - 0xffff -function conv_hex8(ival : integer) return string is -variable tmp1, tmp2 : integer; -variable hex_chr: string (1 to 16) := "0123456789abcdef"; -begin - tmp2 := (ival mod 16 ** 2) / 16 ** 1; - tmp1 := ival mod 16 ** 1; - return hex_chr(tmp2 + 1) & hex_chr(tmp1 + 1); -end; - --cycle bit format -- bit 5 : pcl increment carry flag -- bit 4,3 : cycle type: 00 normal, 01 reset , 10 nmi, 11 irq @@ -150,6 +132,9 @@ constant st_C : integer := 0; ---for pch_inc_n. signal pch_inc_input : std_logic; +---for nmi handling +signal nmi_handled_n : std_logic; + -- page boundary handling signal a2_abs_xy_next_cycle : std_logic_vector (5 downto 0); signal a2_indir_y_next_cycle : std_logic_vector (5 downto 0); @@ -174,10 +159,6 @@ begin main_p : process (set_clk, res_n, nmi_n, a2_abs_xy_next_cycle, a2_indir_y_next_cycle, a58_branch_next_cycle) - ----for nmi handling -variable nmi_handled_n : std_logic; - ------------------------------------------------------------- ------------------------------------------------------------- @@ -236,6 +217,15 @@ end procedure; procedure disable_pins is begin +--following pins are not set in this function. +-- inst_we_n : out std_logic; +-- ad_oe_n : out std_logic; +-- dl_al_oe_n : out std_logic; +-- pcl_inc_n : out std_logic; +-- pcl_cmd : out std_logic_vector(3 downto 0); +-- pch_cmd : out std_logic_vector(3 downto 0); +-- r_nw : out std_logic + --disable the last opration pins. dbuf_int_oe_n <= '1'; dl_al_we_n <= '1'; @@ -974,7 +964,6 @@ end procedure; ---------------- main state machine start.... --------------- ------------------------------------------------------------- ------------------------------------------------------------- - begin -- if (res_n = '0') then @@ -986,10 +975,10 @@ end procedure; -- pcl_cmd <= "1111"; -- pch_cmd <= "1111"; -- end if; --- + -- if (nmi_n'event and nmi_n = '1') then -- --reset nmi handle status --- nmi_handled_n := '1'; +-- nmi_handled_n <= '1'; -- end if; @@ -1023,16 +1012,21 @@ end procedure; -- end if; -- end if; - --if (set_clk'event and set_clk = '1' and res_n = '1') then if (res_n = '0') then - --pc l/h is reset vector. - pcl_cmd <= "1110"; - pch_cmd <= "1110"; - next_cycle <= R0; - elsif (rising_edge(set_clk)) then + elsif (set_clk'event and set_clk = '1' and res_n = '1') then d_print(string'("-")); - if exec_cycle = T0 then + if rdy = '0' then + --case dma is runnting. + disable_pins; + inst_we_n <= '1'; + ad_oe_n <= '0'; + dl_al_oe_n <= '1'; + pcl_inc_n <= '1'; + pcl_cmd <= "1111"; + pch_cmd <= "1111"; + r_nw <= 'Z'; + elsif exec_cycle = T0 then --cycle #1 t0_cycle; @@ -2629,7 +2623,7 @@ end procedure; r_vec_oe_n <= '1'; n_vec_oe_n <= '1'; i_vec_oe_n <= '1'; - nmi_handled_n := '1'; + nmi_handled_n <= '1'; r_nw <= '1'; next_cycle <= R1; @@ -2719,7 +2713,7 @@ end procedure; indir_n <= '0'; if exec_cycle = N5 then - nmi_handled_n := '0'; + nmi_handled_n <= '0'; end if; --start execute cycle. next_cycle <= T0; @@ -2749,14 +2743,15 @@ end procedure; --disable previous we_n gate. --t1 cycle is fetch low oprand. dl_al_we_n <= '1'; + dl_ah_we_n <= '1'; elsif ('0' & exec_cycle(4 downto 0) = T3) then --t2 cycle is fetch high oprand. dl_ah_we_n <= '1'; end if; - end if; --if exec_cycle = T0 then + end if; --if rdy = '0' then - end if; --if (set_clk'event and set_clk = '1') + end if; --if (set_clk'event and set_clk = '1' and res_n = '1') then end process; diff --git a/de1_nes/cpu/mos6502.vhd b/de1_nes/cpu/mos6502.vhd index a8d7326..52c3115 100644 --- a/de1_nes/cpu/mos6502.vhd +++ b/de1_nes/cpu/mos6502.vhd @@ -519,27 +519,11 @@ begin ------------------------------------------------------------ dbg_p : process (set_clk) -use std.textio.all; ---use ieee.std_logic_textio.all; +use work.motonesfpga_common.all; use ieee.std_logic_unsigned.conv_integer; -procedure d_print(msg : string) is -variable out_l : line; -begin --- write(out_l, msg); --- writeline(output, out_l); -end procedure; - -function conv_hex8(ival : integer) return string is -variable tmp1, tmp2 : integer; -variable hex_chr: string (1 to 16) := "0123456789abcdef"; -begin - tmp2 := (ival mod 16 ** 2) / 16 ** 1; - tmp1 := ival mod 16 ** 1; - return hex_chr(tmp2 + 1) & hex_chr(tmp1 + 1); -end; begin - if (set_clk = '0' and exec_cycle = "000000") then + if (set_clk = '0' and rdy = '1' and exec_cycle = "000000") then --show pc on the T0 (fetch) cycle. d_print("pc : " & conv_hex8(conv_integer(abh)) & conv_hex8(conv_integer(abl))); diff --git a/de1_nes/de1_nes.pin b/de1_nes/de1_nes.pin index bb13649..1309a19 100644 --- a/de1_nes/de1_nes.pin +++ b/de1_nes/de1_nes.pin @@ -83,9 +83,9 @@ GND* : A7 : : : GND* : A8 : : : : 3 : GND* : A9 : : : : 3 : GND* : A10 : : : : 3 : -GND* : A11 : : : : 3 : +vga_clk : A11 : output : 3.3-V LVTTL : : 3 : N GND+ : A12 : : : : 4 : -GND* : A13 : : : : 4 : +g[2] : A13 : output : 3.3-V LVTTL : : 4 : N GND* : A14 : : : : 4 : GND* : A15 : : : : 4 : GND* : A16 : : : : 4 : @@ -102,8 +102,8 @@ GND* : AA4 : : : GND* : AA5 : : : : 8 : GND* : AA6 : : : : 8 : GND* : AA7 : : : : 8 : -GND* : AA8 : : : : 8 : -dbg_pin0 : AA9 : output : 3.3-V LVTTL : : 8 : N +joypad1[2] : AA8 : input : 3.3-V LVTTL : : 8 : N +GND* : AA9 : : : : 8 : GND* : AA10 : : : : 8 : GND* : AA11 : : : : 8 : GND* : AA12 : : : : 7 : @@ -125,7 +125,7 @@ GND* : AB5 : : : GND* : AB6 : : : : 8 : GND* : AB7 : : : : 8 : GND* : AB8 : : : : 8 : -GND* : AB9 : : : : 8 : +joypad2[4] : AB9 : input : 3.3-V LVTTL : : 8 : N GND* : AB10 : : : : 8 : GND* : AB11 : : : : 8 : GND* : AB12 : : : : 7 : @@ -142,19 +142,19 @@ GND : AB22 : gnd : : VCCIO2 : B1 : power : : 3.3V : 2 : GND : B2 : gnd : : : : GND* : B3 : : : : 3 : -GND* : B4 : : : : 3 : -GND* : B5 : : : : 3 : -GND* : B6 : : : : 3 : +g[3] : B4 : output : 3.3-V LVTTL : : 3 : N +joypad2[2] : B5 : input : 3.3-V LVTTL : : 3 : N +b[3] : B6 : output : 3.3-V LVTTL : : 3 : N GND* : B7 : : : : 3 : GND* : B8 : : : : 3 : GND* : B9 : : : : 3 : GND* : B10 : : : : 3 : -dbg_pin2 : B11 : output : 3.3-V LVTTL : : 3 : N +GND* : B11 : : : : 3 : GND+ : B12 : : : : 4 : GND* : B13 : : : : 4 : GND* : B14 : : : : 4 : GND* : B15 : : : : 4 : -dbg_pin4 : B16 : output : 3.3-V LVTTL : : 4 : N +GND* : B16 : : : : 4 : GND* : B17 : : : : 4 : GND* : B18 : : : : 4 : GND* : B19 : : : : 4 : @@ -162,7 +162,7 @@ GND* : B20 : : : GND : B21 : gnd : : : : VCCIO5 : B22 : power : : 3.3V : 5 : GND* : C1 : : : : 2 : -GND* : C2 : : : : 2 : +r[1] : C2 : output : 3.3-V LVTTL : : 2 : N ~nCSO~ / RESERVED_INPUT_WITH_WEAK_PULLUP : C3 : input : 3.3-V LVTTL : : 2 : N ~ASDO~ / RESERVED_INPUT_WITH_WEAK_PULLUP : C4 : input : 3.3-V LVTTL : : 2 : N GND : C5 : gnd : : : : @@ -173,7 +173,7 @@ GND* : C9 : : : GND* : C10 : : : : 3 : VCCIO3 : C11 : power : : 3.3V : 3 : VCCIO4 : C12 : power : : 3.3V : 4 : -GND* : C13 : : : : 4 : +r[2] : C13 : output : 3.3-V LVTTL : : 4 : N GND* : C14 : : : : 4 : GND : C15 : gnd : : : : GND* : C16 : : : : 4 : @@ -184,7 +184,7 @@ GND* : C20 : : : GND* : C21 : : : : 5 : GND* : C22 : : : : 5 : GND* : D1 : : : : 2 : -GND* : D2 : : : : 2 : +joypad2[0] : D2 : input : 3.3-V LVTTL : : 2 : N GND* : D3 : : : : 2 : GND* : D4 : : : : 2 : GND* : D5 : : : : 2 : @@ -215,14 +215,14 @@ GND* : E7 : : : GND* : E8 : : : : 3 : GND* : E9 : : : : 3 : VCCIO3 : E10 : power : : 3.3V : 3 : -GND* : E11 : : : : 3 : +joypad2[1] : E11 : input : 3.3-V LVTTL : : 3 : N GND+ : E12 : : : : 3 : VCCIO4 : E13 : power : : 3.3V : 4 : GND* : E14 : : : : 4 : GND* : E15 : : : : 4 : GNDA_PLL2 : E16 : gnd : : : : GND_PLL2 : E17 : gnd : : : : -dbg_pin3 : E18 : output : 3.3-V LVTTL : : 5 : N +GND* : E18 : : : : 5 : GND* : E19 : : : : 5 : GND* : E20 : : : : 5 : GND* : E21 : : : : 5 : @@ -235,11 +235,11 @@ GND_PLL3 : F5 : gnd : : GND_PLL3 : F6 : gnd : : : : GNDA_PLL3 : F7 : gnd : : : : GND* : F8 : : : : 3 : -dbg_pin7 : F9 : output : 3.3-V LVTTL : : 3 : N -dbg_pin1 : F10 : output : 3.3-V LVTTL : : 3 : N +GND* : F9 : : : : 3 : +GND* : F10 : : : : 3 : GND* : F11 : : : : 3 : -dbg_pin6 : F12 : output : 3.3-V LVTTL : : 4 : N -GND* : F13 : : : : 4 : +GND* : F12 : : : : 4 : +r[3] : F13 : output : 3.3-V LVTTL : : 4 : N GND* : F14 : : : : 4 : GND* : F15 : : : : 4 : VCCA_PLL2 : F16 : power : : 1.2V : : @@ -251,7 +251,7 @@ GND* : F21 : : : GND* : F22 : : : : 5 : NC : G1 : : : : : NC : G2 : : : : : -GND* : G3 : : : : 2 : +joypad2[5] : G3 : input : 3.3-V LVTTL : : 2 : N GND : G4 : gnd : : : : GND* : G5 : : : : 2 : GND* : G6 : : : : 2 : @@ -264,27 +264,27 @@ GND* : G12 : : : GND : G13 : gnd : : : : VCCIO4 : G14 : power : : 3.3V : 4 : GND* : G15 : : : : 4 : -dbg_pin5 : G16 : output : 3.3-V LVTTL : : 4 : N +GND* : G16 : : : : 4 : GND* : G17 : : : : 5 : GND* : G18 : : : : 5 : VCCIO5 : G19 : power : : 3.3V : 5 : GND* : G20 : : : : 5 : GND* : G21 : : : : 5 : GND* : G22 : : : : 5 : -GND* : H1 : : : : 2 : +joypad2[7] : H1 : input : 3.3-V LVTTL : : 2 : N GND* : H2 : : : : 2 : GND* : H3 : : : : 2 : GND* : H4 : : : : 2 : GND* : H5 : : : : 2 : GND* : H6 : : : : 2 : -GND* : H7 : : : : 3 : -GND* : H8 : : : : 3 : +joypad1[5] : H7 : input : 3.3-V LVTTL : : 3 : N +joypad1[3] : H8 : input : 3.3-V LVTTL : : 3 : N GND* : H9 : : : : 3 : GND* : H10 : : : : 3 : GND* : H11 : : : : 3 : GND* : H12 : : : : 4 : GND* : H13 : : : : 4 : -GND* : H14 : : : : 4 : +joypad1[6] : H14 : input : 3.3-V LVTTL : : 4 : N GND* : H15 : : : : 4 : GND* : H16 : : : : 5 : GND* : H17 : : : : 5 : @@ -401,7 +401,7 @@ MSEL1 : N17 : : : CONF_DONE : N18 : : : : 6 : GND : N19 : gnd : : : : nSTATUS : N20 : : : : 6 : -GND* : N21 : : : : 6 : +joypad2[6] : N21 : input : 3.3-V LVTTL : : 6 : N GND* : N22 : : : : 6 : GND* : P1 : : : : 1 : GND* : P2 : : : : 1 : @@ -420,7 +420,7 @@ NC : P14 : : : GND* : P15 : : : : 6 : VCCIO6 : P16 : power : : 3.3V : 6 : GND* : P17 : : : : 6 : -GND* : P18 : : : : 6 : +r[0] : P18 : output : 3.3-V LVTTL : : 6 : N NC : P19 : : : : : NC : P20 : : : : : NC : P21 : : : : : @@ -437,14 +437,14 @@ GND* : R9 : : : GND* : R10 : : : : 8 : GND* : R11 : : : : 8 : GND* : R12 : : : : 7 : -GND* : R13 : : : : 7 : -GND* : R14 : : : : 7 : -GND* : R15 : : : : 7 : +b[1] : R13 : output : 3.3-V LVTTL : : 7 : N +v_sync_n : R14 : output : 3.3-V LVTTL : : 7 : N +joypad1[0] : R15 : input : 3.3-V LVTTL : : 7 : N GND* : R16 : : : : 7 : GND* : R17 : : : : 6 : GND* : R18 : : : : 6 : GND* : R19 : : : : 6 : -GND* : R20 : : : : 6 : +joypad1[4] : R20 : input : 3.3-V LVTTL : : 6 : N GND* : R21 : : : : 6 : rst_n : R22 : input : 3.3-V LVTTL : : 6 : Y GND* : T1 : : : : 1 : @@ -453,7 +453,7 @@ GND* : T3 : : : VCCIO1 : T4 : power : : 3.3V : 1 : GND* : T5 : : : : 1 : GND* : T6 : : : : 1 : -GND* : T7 : : : : 8 : +h_sync_n : T7 : output : 3.3-V LVTTL : : 8 : N GND* : T8 : : : : 8 : VCCIO8 : T9 : power : : 3.3V : 8 : GND : T10 : gnd : : : : @@ -464,13 +464,13 @@ VCCIO7 : T14 : power : : 3.3V GND* : T15 : : : : 7 : GND* : T16 : : : : 7 : GND_PLL4 : T17 : gnd : : : : -GND* : T18 : : : : 6 : +joypad1[1] : T18 : input : 3.3-V LVTTL : : 6 : N VCCIO6 : T19 : power : : 3.3V : 6 : GND : T20 : gnd : : : : GND* : T21 : : : : 6 : GND* : T22 : : : : 6 : GND* : U1 : : : : 1 : -GND* : U2 : : : : 1 : +b[2] : U2 : output : 3.3-V LVTTL : : 1 : N GND* : U3 : : : : 1 : GND* : U4 : : : : 1 : GND_PLL1 : U5 : gnd : : : : @@ -492,7 +492,7 @@ GND* : U20 : : : GND* : U21 : : : : 6 : GND* : U22 : : : : 6 : GND* : V1 : : : : 1 : -GND* : V2 : : : : 1 : +joypad2[3] : V2 : input : 3.3-V LVTTL : : 1 : N GND : V3 : gnd : : : : GND* : V4 : : : : 1 : GND_PLL1 : V5 : gnd : : : : @@ -505,7 +505,7 @@ GND* : V11 : : : GND+ : V12 : : : : 7 : VCCIO7 : V13 : power : : 3.3V : 7 : GND* : V14 : : : : 7 : -GND* : V15 : : : : 7 : +joypad1[7] : V15 : input : 3.3-V LVTTL : : 7 : N GNDA_PLL4 : V16 : gnd : : : : GND : V17 : gnd : : : : GND_PLL4 : V18 : gnd : : : : @@ -534,7 +534,7 @@ NC : W18 : : : GND : W19 : gnd : : : : ~LVDS91p/nCEO~ : W20 : output : 3.3-V LVTTL : : 6 : N GND* : W21 : : : : 6 : -GND* : W22 : : : : 6 : +g[1] : W22 : output : 3.3-V LVTTL : : 6 : N GND* : Y1 : : : : 1 : GND* : Y2 : : : : 1 : GND* : Y3 : : : : 1 : @@ -547,8 +547,8 @@ GND* : Y9 : : : GND* : Y10 : : : : 8 : VCCIO8 : Y11 : power : : 3.3V : 8 : VCCIO7 : Y12 : power : : 3.3V : 7 : -GND* : Y13 : : : : 7 : -GND* : Y14 : : : : 7 : +b[0] : Y13 : output : 3.3-V LVTTL : : 7 : N +g[0] : Y14 : output : 3.3-V LVTTL : : 7 : N GND : Y15 : gnd : : : : GND* : Y16 : : : : 7 : GND* : Y17 : : : : 7 : diff --git a/de1_nes/de1_nes.qsf b/de1_nes/de1_nes.qsf index 6ef70d2..583a0ed 100644 --- a/de1_nes/de1_nes.qsf +++ b/de1_nes/de1_nes.qsf @@ -41,11 +41,17 @@ set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region" set_location_assignment PIN_D12 -to base_clk set_location_assignment PIN_R22 -to rst_n set_global_assignment -name INCREMENTAL_VECTOR_INPUT_SOURCE de1_nes.vwf +set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)" +set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation +set_global_assignment -name VHDL_FILE motonesfpga_common.vhd +set_global_assignment -name VHDL_FILE ppu/vga.vhd set_global_assignment -name VHDL_FILE mem/prg_rom.vhd +set_global_assignment -name VHDL_FILE mem/chr_rom.vhd set_global_assignment -name VHDL_FILE mem/ram.vhd set_global_assignment -name VHDL_FILE ppu/ppu_registers.vhd set_global_assignment -name VHDL_FILE cpu/cpu_registers.vhd set_global_assignment -name VHDL_FILE clock/clock_divider.vhd +set_global_assignment -name VHDL_FILE apu/apu.vhd set_global_assignment -name VHDL_FILE ppu/ppu.vhd set_global_assignment -name VHDL_FILE ppu/render.vhd set_global_assignment -name VHDL_FILE cpu/decoder.vhd @@ -54,5 +60,9 @@ set_global_assignment -name VHDL_FILE cpu/mos6502.vhd set_global_assignment -name VHDL_FILE address_decoder.vhd set_global_assignment -name VHDL_FILE de1_nes.vhd set_global_assignment -name VECTOR_WAVEFORM_FILE de1_nes.vwf -set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)" -set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation \ No newline at end of file +set_global_assignment -name EDA_TEST_BENCH_ENABLE_STATUS TEST_BENCH_MODE -section_id eda_simulation +set_global_assignment -name EDA_NATIVELINK_SIMULATION_TEST_BENCH testbench_motones_sim -section_id eda_simulation +set_global_assignment -name EDA_TEST_BENCH_NAME testbench_motones_sim -section_id eda_simulation +set_global_assignment -name EDA_DESIGN_INSTANCE_NAME sim_board -section_id testbench_motones_sim +set_global_assignment -name EDA_TEST_BENCH_MODULE_NAME testbench_motones_sim -section_id testbench_motones_sim +set_global_assignment -name EDA_TEST_BENCH_FILE testbench_motones_sim.vhd -section_id testbench_motones_sim \ No newline at end of file diff --git a/de1_nes/de1_nes.qws b/de1_nes/de1_nes.qws index 35822df..9a6578f 100644 --- a/de1_nes/de1_nes.qws +++ b/de1_nes/de1_nes.qws @@ -5,69 +5,3 @@ ptn_Child1=ChildFrames [ProjectWorkspace.Frames.ChildFrames] ptn_Child1=Document-0 ptn_Child2=Document-1 -ptn_Child3=Document-2 -ptn_Child4=Document-3 -ptn_Child5=Document-4 -ptn_Child6=Document-5 -ptn_Child7=Document-6 -ptn_Child8=Document-7 -[ProjectWorkspace.Frames.ChildFrames.Document-0] -ptn_Child1=ViewFrame-0 -[ProjectWorkspace.Frames.ChildFrames.Document-0.ViewFrame-0] -DocPathName=clock/clock_divider.vhd -DocumentCLSID={ca385d57-a4c7-11d1-a098-0020affa43f2} -IsChildFrameDetached=False -IsActiveChildFrame=False -ptn_Child1=StateMap -[ProjectWorkspace.Frames.ChildFrames.Document-0.ViewFrame-0.StateMap] -AFC_IN_REPORT=False -[ProjectWorkspace.Frames.ChildFrames.Document-1] -ptn_Child1=ViewFrame-0 -[ProjectWorkspace.Frames.ChildFrames.Document-1.ViewFrame-0] -DocPathName=cpu/decoder.vhd -DocumentCLSID={ca385d57-a4c7-11d1-a098-0020affa43f2} -IsChildFrameDetached=False -IsActiveChildFrame=False -ptn_Child1=StateMap -[ProjectWorkspace.Frames.ChildFrames.Document-1.ViewFrame-0.StateMap] -AFC_IN_REPORT=False -[ProjectWorkspace.Frames.ChildFrames.Document-2] -ptn_Child1=ViewFrame-0 -[ProjectWorkspace.Frames.ChildFrames.Document-2.ViewFrame-0] -DocPathName=cpu/alu.vhd -DocumentCLSID={ca385d57-a4c7-11d1-a098-0020affa43f2} -IsChildFrameDetached=False -IsActiveChildFrame=False -ptn_Child1=StateMap -[ProjectWorkspace.Frames.ChildFrames.Document-2.ViewFrame-0.StateMap] -AFC_IN_REPORT=False -[ProjectWorkspace.Frames.ChildFrames.Document-3] -ptn_Child1=ViewFrame-0 -[ProjectWorkspace.Frames.ChildFrames.Document-3.ViewFrame-0] -DocPathName=cpu/mos6502.vhd -DocumentCLSID={ca385d57-a4c7-11d1-a098-0020affa43f2} -IsChildFrameDetached=False -IsActiveChildFrame=False -ptn_Child1=StateMap -[ProjectWorkspace.Frames.ChildFrames.Document-3.ViewFrame-0.StateMap] -AFC_IN_REPORT=False -[ProjectWorkspace.Frames.ChildFrames.Document-4] -ptn_Child1=ViewFrame-0 -[ProjectWorkspace.Frames.ChildFrames.Document-4.ViewFrame-0] -DocPathName=ppu/ppu.vhd -DocumentCLSID={ca385d57-a4c7-11d1-a098-0020affa43f2} -IsChildFrameDetached=False -IsActiveChildFrame=False -ptn_Child1=StateMap -[ProjectWorkspace.Frames.ChildFrames.Document-4.ViewFrame-0.StateMap] -AFC_IN_REPORT=False -[ProjectWorkspace.Frames.ChildFrames.Document-5] -ptn_Child1=ViewFrame-0 -[ProjectWorkspace.Frames.ChildFrames.Document-5.ViewFrame-0] -DocPathName=ppu/render.vhd -DocumentCLSID={ca385d57-a4c7-11d1-a098-0020affa43f2} -IsChildFrameDetached=False -IsActiveChildFrame=False -ptn_Child1=StateMap -[ProjectWorkspace.Frames.ChildFrames.Document-5.ViewFrame-0.StateMap] -AFC_IN_REPORT=False diff --git a/de1_nes/de1_nes.vhd b/de1_nes/de1_nes.vhd index a84ab35..f38fa3c 100644 --- a/de1_nes/de1_nes.vhd +++ b/de1_nes/de1_nes.vhd @@ -1,154 +1,162 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.conv_integer; - --- --- MOTO NES FPGA On GHDL Simulation Environment Virtual Cuicuit Board --- All of the components are assembled and instanciated on this board. --- - -entity de1_nes is - port ( - base_clk : in std_logic; - rst_n : in std_logic; - dbg_pin0 : out std_logic; - dbg_pin1 : out std_logic; - dbg_pin2 : out std_logic; - dbg_pin3 : out std_logic; - dbg_pin4 : out std_logic; - dbg_pin5 : out std_logic; - dbg_pin6 : out std_logic; - dbg_pin7 : out std_logic - ); -end de1_nes; - -architecture rtl of de1_nes is - component mos6502 - generic ( dsize : integer := 8; - asize : integer :=16 - ); - port ( input_clk : in std_logic; --phi0 input pin. - rdy : in std_logic; - rst_n : in std_logic; - irq_n : in std_logic; - nmi_n : in std_logic; - dbe : in std_logic; - r_nw : out std_logic; - phi1 : out std_logic; - phi2 : out std_logic; - addr : out std_logic_vector ( asize - 1 downto 0); - d_io : inout std_logic_vector ( dsize - 1 downto 0) - ); - end component; - - component clock_divider - port ( base_clk : in std_logic; - reset_n : in std_logic; - cpu_clk : out std_logic; - ppu_clk : out std_logic; - vga_clk : out std_logic - ); - end component; - - component address_decoder - generic (abus_size : integer := 16; dbus_size : integer := 8); - port ( phi2 : in std_logic; - R_nW : in std_logic; - addr : in std_logic_vector (abus_size - 1 downto 0); - d_io : inout std_logic_vector (dbus_size - 1 downto 0); - ppu_ce_n : out std_logic - ); - end component; - - component ppu - port ( clk : in std_logic; - ce_n : in std_logic; - rst_n : in std_logic; - r_nw : in std_logic; - cpu_addr : in std_logic_vector (2 downto 0); - cpu_d : inout std_logic_vector (7 downto 0); - vblank_n : out std_logic; - rd_n : out std_logic; - wr_n : out std_logic; - ale : out std_logic; - vram_ad : inout std_logic_vector (7 downto 0); - vram_a : out std_logic_vector (13 downto 8); - vga_clk : in std_logic; - h_sync_n : out std_logic; - v_sync_n : out std_logic; - r : out std_logic_vector(3 downto 0); - g : out std_logic_vector(3 downto 0); - b : out std_logic_vector(3 downto 0) - ); - end component; - - component v_address_decoder - generic (abus_size : integer := 14; dbus_size : integer := 8); - port ( clk : in std_logic; - rd_n : in std_logic; - wr_n : in std_logic; - ale : in std_logic; - vram_ad : inout std_logic_vector (7 downto 0); - vram_a : in std_logic_vector (13 downto 8) - ); - end component; - - constant data_size : integer := 8; - constant addr_size : integer := 16; - constant size14 : integer := 14; - - signal cpu_clk : std_logic; - signal ppu_clk : std_logic; - - signal rdy, irq_n, nmi_n, dbe, r_nw : std_logic; - signal phi1, phi2 : std_logic; - signal addr : std_logic_vector( addr_size - 1 downto 0); - signal d_io : std_logic_vector( data_size - 1 downto 0); - - signal ppu_ce_n : std_logic; - signal rd_n : std_logic; - signal wr_n : std_logic; - signal ale : std_logic; - signal vram_ad : std_logic_vector (7 downto 0); - signal vram_a : std_logic_vector (13 downto 8); - - signal vga_clk : std_logic; - signal h_sync_n : std_logic; - signal v_sync_n : std_logic; - signal r : std_logic_vector(3 downto 0); - signal g : std_logic_vector(3 downto 0); - signal b : std_logic_vector(3 downto 0); - -begin - - irq_n <= '0'; - rdy <= '1'; - - --ppu/cpu clock generator - clock_inst : clock_divider port map - (base_clk, rst_n, cpu_clk, ppu_clk, vga_clk); - - --mos 6502 cpu instance - cpu_inst : mos6502 generic map (data_size, addr_size) - port map (cpu_clk, rdy, rst_n, irq_n, nmi_n, dbe, r_nw, - phi1, phi2, addr, d_io); - - addr_dec_inst : address_decoder generic map (addr_size, data_size) - port map (phi2, r_nw, addr, d_io, ppu_ce_n); - - --nes ppu instance --- ppu_inst : ppu --- port map (ppu_clk, ppu_ce_n, rst_n, r_nw, addr(2 downto 0), d_io, --- nmi_n, rd_n, wr_n, ale, vram_ad, vram_a, --- vga_clk, h_sync_n, v_sync_n, r, g, b); - --- ppu_addr_decoder : v_address_decoder generic map (size14, data_size) --- port map (ppu_clk, rd_n, wr_n, ale, vram_ad, vram_a); - ------debug----- - dbg_pin0 <= cpu_clk; - dbg_pin1 <= ppu_clk; - dbg_pin2 <= vga_clk; - -end rtl; - +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.conv_integer; + +-- +-- MOTO NES FPGA On GHDL Simulation Environment Virtual Cuicuit Board +-- All of the components are assembled and instanciated on this board. +-- + +entity de1_nes is + port ( + base_clk : in std_logic; + rst_n : in std_logic; + joypad1 : in std_logic_vector(7 downto 0); + joypad2 : in std_logic_vector(7 downto 0); + vga_clk : out std_logic; + h_sync_n : out std_logic; + v_sync_n : out std_logic; + r : out std_logic_vector(3 downto 0); + g : out std_logic_vector(3 downto 0); + b : out std_logic_vector(3 downto 0) + ); +end de1_nes; + +architecture rtl of de1_nes is + component mos6502 + generic ( dsize : integer := 8; + asize : integer :=16 + ); + port ( input_clk : in std_logic; --phi0 input pin. + rdy : in std_logic; + rst_n : in std_logic; + irq_n : in std_logic; + nmi_n : in std_logic; + dbe : in std_logic; + r_nw : out std_logic; + phi1 : out std_logic; + phi2 : out std_logic; + addr : out std_logic_vector ( asize - 1 downto 0); + d_io : inout std_logic_vector ( dsize - 1 downto 0) + ); + end component; + + component clock_divider + port ( base_clk : in std_logic; + reset_n : in std_logic; + cpu_clk : out std_logic; + ppu_clk : out std_logic; + vga_clk : out std_logic + ); + end component; + + component address_decoder + generic (abus_size : integer := 16; dbus_size : integer := 8); + port ( phi2 : in std_logic; + R_nW : in std_logic; + addr : in std_logic_vector (abus_size - 1 downto 0); + d_io : inout std_logic_vector (dbus_size - 1 downto 0); + ppu_ce_n : out std_logic; + apu_ce_n : out std_logic + ); + end component; + + component ppu + port ( clk : in std_logic; + ce_n : in std_logic; + rst_n : in std_logic; + r_nw : in std_logic; + cpu_addr : in std_logic_vector (2 downto 0); + cpu_d : inout std_logic_vector (7 downto 0); + vblank_n : out std_logic; + rd_n : out std_logic; + wr_n : out std_logic; + ale : out std_logic; + vram_ad : inout std_logic_vector (7 downto 0); + vram_a : out std_logic_vector (13 downto 8); + vga_clk : in std_logic; + h_sync_n : out std_logic; + v_sync_n : out std_logic; + r : out std_logic_vector(3 downto 0); + g : out std_logic_vector(3 downto 0); + b : out std_logic_vector(3 downto 0) + ); + end component; + + component v_address_decoder + generic (abus_size : integer := 14; dbus_size : integer := 8); + port ( clk : in std_logic; + rd_n : in std_logic; + wr_n : in std_logic; + ale : in std_logic; + vram_ad : inout std_logic_vector (7 downto 0); + vram_a : in std_logic_vector (13 downto 8) + ); + end component; + + component apu + 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 component; + + constant data_size : integer := 8; + constant addr_size : integer := 16; + constant size14 : integer := 14; + + signal cpu_clk : std_logic; + signal ppu_clk : std_logic; + signal vga_out_clk : std_logic; + + signal rdy, irq_n, nmi_n, dbe, r_nw : std_logic; + signal phi1, phi2 : std_logic; + signal addr : std_logic_vector( addr_size - 1 downto 0); + signal d_io : std_logic_vector( data_size - 1 downto 0); + + signal ppu_ce_n : std_logic; + signal apu_ce_n : std_logic; + signal rd_n : std_logic; + signal wr_n : std_logic; + signal ale : std_logic; + signal vram_ad : std_logic_vector (7 downto 0); + signal vram_a : std_logic_vector (13 downto 8); + + --test... + signal nmi_n2 : std_logic; + +begin + + irq_n <= '0'; + vga_clk <= vga_out_clk; + + --ppu/cpu clock generator + clock_inst : clock_divider port map + (base_clk, rst_n, cpu_clk, ppu_clk, vga_out_clk); + + --mos 6502 cpu instance + cpu_inst : mos6502 generic map (data_size, addr_size) + port map (cpu_clk, rdy, rst_n, irq_n, nmi_n, dbe, r_nw, + phi1, phi2, addr, d_io); + + addr_dec_inst : address_decoder generic map (addr_size, data_size) + port map (phi2, r_nw, addr, d_io, ppu_ce_n, apu_ce_n); + + --nes ppu instance + ppu_inst : ppu + port map (ppu_clk, ppu_ce_n, rst_n, r_nw, addr(2 downto 0), d_io, + nmi_n, rd_n, wr_n, ale, vram_ad, vram_a, + vga_out_clk, h_sync_n, v_sync_n, r, g, b); + + ppu_addr_decoder : v_address_decoder generic map (size14, data_size) + port map (ppu_clk, rd_n, wr_n, ale, vram_ad, vram_a); + + apu_inst : apu + port map (cpu_clk, apu_ce_n, rst_n, r_nw, addr, d_io, rdy); + +end rtl; + diff --git a/de1_nes/mem/ram.vhd b/de1_nes/mem/ram.vhd index cc1855c..08cab96 100644 --- a/de1_nes/mem/ram.vhd +++ b/de1_nes/mem/ram.vhd @@ -42,3 +42,40 @@ begin end process; end rtl; +----------------------------------------------------- +----------------------------------------------------- +-------------------- palette ram -------------------- +----------------------------------------------------- +----------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity palette_ram is + generic (abus_size : integer := 16; dbus_size : integer := 8); + port ( ce_n, oe_n, we_n : in std_logic; --select pin active low. + addr : in std_logic_vector (abus_size - 1 downto 0); + d_io : inout std_logic_vector (dbus_size - 1 downto 0) + ); +end palette_ram; + +architecture rtl of palette_ram is +component ram + generic (abus_size : integer := 5; dbus_size : integer := 8); + port ( ce_n, oe_n, we_n : in std_logic; --select pin active low. + addr : in std_logic_vector (abus_size - 1 downto 0); + d_io : inout std_logic_vector (dbus_size - 1 downto 0) + ); +end component; + +signal plt_addr : std_logic_vector (abus_size - 1 downto 0); +begin + --palette ram is following characteristic. + --Addresses $3F10/$3F14/$3F18/$3F1C are mirrors of $3F00/$3F04/$3F08/$3F0C + plt_addr <= "0" & addr(3 downto 0) when addr (4) = '1' and addr (1) = '0' and addr (0) = '0' else + addr; + palette_ram_inst : ram generic map (abus_size, dbus_size) + port map (ce_n, oe_n, we_n, plt_addr, d_io); + +end rtl; + diff --git a/de1_nes/motonesfpga_common.vhd b/de1_nes/motonesfpga_common.vhd new file mode 100644 index 0000000..1776a69 --- /dev/null +++ b/de1_nes/motonesfpga_common.vhd @@ -0,0 +1,65 @@ +-- +-- MOTO NES FPGA Common Routines +-- + +library ieee; +use ieee.std_logic_1164.all; + +package motonesfpga_common is + +procedure d_print(msg : string); + +function conv_hex8(ival : integer) return string; + +function conv_hex8(ival : std_logic_vector) return string; + +function conv_hex16(ival : integer) return string; + +function conv_hex16(ival : std_logic_vector) return string; + +end motonesfpga_common; + +package body motonesfpga_common is + +use ieee.std_logic_unsigned.conv_integer; + +procedure d_print(msg : string) is +--use std.textio.all; +--use ieee.std_logic_textio.all; +--variable out_l : line; +begin +-- write(out_l, msg); +-- writeline(output, out_l); +end procedure; + +---ival : 0x0000 - 0xffff +function conv_hex8(ival : integer) return string is +variable tmp1, tmp2 : integer; +variable hex_chr: string (1 to 16) := "0123456789abcdef"; +begin + tmp2 := (ival mod 16 ** 2) / 16 ** 1; + tmp1 := ival mod 16 ** 1; + return hex_chr(tmp2 + 1) & hex_chr(tmp1 + 1); +end; + +function conv_hex8(ival : std_logic_vector) return string is +begin + return conv_hex8(conv_integer(ival)); +end; + +function conv_hex16(ival : integer) return string is +variable tmp1, tmp2 : integer; +variable hex_chr: string (1 to 16) := "0123456789abcdef"; +begin + tmp2 := ival / 256; + tmp1 := ival mod 256; + return conv_hex8(tmp2) & conv_hex8(tmp1); +end; + +function conv_hex16(ival : std_logic_vector) return string is +begin + return conv_hex16(conv_integer(ival)); +end; + +end motonesfpga_common; + diff --git a/de1_nes/ppu/ppu.vhd b/de1_nes/ppu/ppu.vhd index c6c7b9c..387852a 100644 --- a/de1_nes/ppu/ppu.vhd +++ b/de1_nes/ppu/ppu.vhd @@ -1,5 +1,6 @@ library ieee; use ieee.std_logic_1164.all; +use work.motonesfpga_common.all; entity ppu is port ( clk : in std_logic; @@ -98,15 +99,6 @@ component counter_register ); end component; -procedure d_print(msg : string) is -use std.textio.all; ---use ieee.std_logic_textio.all; -variable out_l : line; -begin --- write(out_l, msg); --- writeline(output, out_l); -end procedure; - signal pos_x : std_logic_vector (8 downto 0); signal pos_y : std_logic_vector (8 downto 0); signal nes_r : std_logic_vector (3 downto 0); @@ -124,6 +116,7 @@ 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 @@ -155,9 +148,12 @@ 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; @@ -166,8 +162,9 @@ 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 @@ -178,9 +175,9 @@ begin r_nw, oam_bus_ce_n, plt_bus_ce_n, 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, - h_sync_n, v_sync_n, r, g, b); +-- vga_inst : vga_ctl port map (clk, vga_clk, rst_n, +-- pos_x, pos_y, nes_r, nes_g, nes_b, +-- h_sync_n, v_sync_n, r, g, b); --PPU registers. clk_n <= not clk; @@ -210,37 +207,46 @@ begin port map (clk_n, ppu_latch_rst_n, ppu_scroll_cnt_ce_n, '1', (others => '0'), ppu_scroll_cnt); - ppu_addr_inst : 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); + 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_cnt_inst : counter_register generic map (1, 1) 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 (clk_n, rst_n, '1', read_data_n, ppu_data, ppu_data_out); + port map (read_data_n, rst_n, '1', '0', ppu_data_in, ppu_data_out); + 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 = '0') then - ppu_latch_rst_n <= '0'; - vblank_n <= '1'; - end if; - 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 (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 = '1' and ce_n = '0') then + if (rst_n = '0') then + vblank_n <= '1'; + elsif (rst_n = '1' and ce_n = '0') then --register set. if(cpu_addr = PPUCTRL) then @@ -256,12 +262,9 @@ begin end if; if(cpu_addr = PPUSTATUS and r_nw = '1') then - --reading status resets ppu_addr/scroll cnt. - ppu_latch_rst_n <= '0'; --notify reading status read_status <= '1'; else - ppu_latch_rst_n <= '1'; read_status <= '0'; end if; @@ -293,7 +296,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); @@ -301,11 +303,10 @@ 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 = '0') then + if (cpu_addr = PPUDATA and r_nw = '1') then read_data_n <= '0'; else read_data_n <= '1'; @@ -319,7 +320,6 @@ begin 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') @@ -330,12 +330,14 @@ begin 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'; - --d_print("write event"); - end if; +-- 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'; +-- --d_print("write event"); +-- end if; --start counter. if (clk'event and clk = '0') then @@ -344,6 +346,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; @@ -363,10 +372,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'; @@ -384,6 +394,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); @@ -394,8 +405,9 @@ begin ale <= '1'; end if; else - ale <= '0'; - end if; + ppu_addr_cnt_ce_n <= '1'; + ale <= 'Z'; + 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'; @@ -418,20 +430,23 @@ begin if (r_nw = '0') then vram_ad <= cpu_d; else - vram_ad <= (others => 'Z'); - cpu_d <= vram_ad; + 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'; - end if; + 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 - cpu_d <= ppu_data; + 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; @@ -447,6 +462,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'; @@ -455,7 +472,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; diff --git a/de1_nes/ppu/render.vhd b/de1_nes/ppu/render.vhd index 616dd31..f2ba44e 100644 --- a/de1_nes/ppu/render.vhd +++ b/de1_nes/ppu/render.vhd @@ -2,6 +2,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.conv_std_logic_vector; use ieee.std_logic_unsigned.all; +use work.motonesfpga_common.all; entity ppu_render is port ( clk : in std_logic; @@ -94,42 +95,13 @@ component ram ); end component; -procedure d_print(msg : string) is -use std.textio.all; ---use ieee.std_logic_textio.all; -variable out_l : line; -begin --- write(out_l, msg); --- writeline(output, out_l); -end procedure; - -function conv_hex8(ival : integer) return string is -variable tmp1, tmp2 : integer; -variable hex_chr: string (1 to 16) := "0123456789abcdef"; -begin - tmp2 := (ival mod 16 ** 2) / 16 ** 1; - tmp1 := ival mod 16 ** 1; - return hex_chr(tmp2 + 1) & hex_chr(tmp1 + 1); -end; - -function conv_hex8(ival : std_logic_vector) return string is -begin - return conv_hex8(conv_integer(ival)); -end; - -function conv_hex16(ival : integer) return string is -variable tmp1, tmp2 : integer; -variable hex_chr: string (1 to 16) := "0123456789abcdef"; -begin - tmp2 := ival / 256; - tmp1 := ival mod 256; - return conv_hex8(tmp2) & conv_hex8(tmp1); -end; - -function conv_hex16(ival : std_logic_vector) return string is -begin - return conv_hex16(conv_integer(ival)); -end; +component palette_ram + generic (abus_size : integer := 16; dbus_size : integer := 8); + port ( ce_n, oe_n, we_n : in std_logic; --select pin active low. + addr : in std_logic_vector (abus_size - 1 downto 0); + d_io : inout std_logic_vector (dbus_size - 1 downto 0) + ); +end component; constant X_SIZE : integer := 9; constant dsize : integer := 8; @@ -239,21 +211,25 @@ constant nes_color_palette : nes_color_array := ( signal clk_n : std_logic; --timing adjust -signal io_cnt : std_logic_vector(0 downto 0); +signal bg_io_cnt : std_logic_vector(0 downto 0); +signal spr_io_cnt : std_logic_vector(0 downto 0); --vram i/o signal io_oe_n : std_logic; -signal d_oe_n : std_logic; +signal ah_oe_n : std_logic; -signal cnt_x_en_n : std_logic; signal cnt_x_res_n : std_logic; +signal bg_cnt_res_n : std_logic; signal cnt_y_en_n : std_logic; signal cnt_y_res_n : std_logic; +--current drawing position 340 x 261 signal cur_x : std_logic_vector(X_SIZE - 1 downto 0); signal cur_y : std_logic_vector(X_SIZE - 1 downto 0); -signal next_x : std_logic_vector(X_SIZE - 1 downto 0); -signal next_y : std_logic_vector(X_SIZE - 1 downto 0); +--bg prefetch position (scroll + 16 cycle ahead of current pos) +--511 x 239 (or 255 x 479) +signal prf_x : std_logic_vector(X_SIZE - 1 downto 0); +signal prf_y : std_logic_vector(X_SIZE - 1 downto 0); signal nt_we_n : std_logic; signal disp_nt : std_logic_vector (dsize - 1 downto 0); @@ -264,8 +240,6 @@ signal attr_val : std_logic_vector (dsize - 1 downto 0); signal disp_attr_we_n : std_logic; signal disp_attr : std_logic_vector (dsize - 1 downto 0); -signal ptn_en_n : std_logic; - signal ptn_l_we_n : std_logic; signal ptn_l_in : std_logic_vector (dsize - 1 downto 0); signal ptn_l_val : std_logic_vector (dsize - 1 downto 0); @@ -346,61 +320,72 @@ begin clk_n <= not clk; - cnt_x_en_n <= '0'; - - ale <= io_cnt(0) when ppu_mask(PPUSBG) = '1' and + ale <= bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or - cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else - io_cnt(0) when ppu_mask(PPUSSP) = '1' and + cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and + (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or + cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else + spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or - cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else + cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and + (cur_x > conv_std_logic_vector(256, X_SIZE) and + cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else 'Z'; - rd_n <= io_cnt(0) when ppu_mask(PPUSBG) = '1' and + + rd_n <= bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or - cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else - io_cnt(0) when ppu_mask(PPUSSP) = '1' and + cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and + (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or + cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else + spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or - cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else + cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and + (cur_x > conv_std_logic_vector(256, X_SIZE) and + cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else 'Z'; - wr_n <= '1' when ppu_mask(PPUSBG) = '1' and - (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or - cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else - '1' when ppu_mask(PPUSSP) = '1' and + wr_n <= '1' when (ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else 'Z'; - io_oe_n <= not io_cnt(0) when ppu_mask(PPUSBG) = '1' and + io_oe_n <= not bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or - cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else - not io_cnt(0) when ppu_mask(PPUSSP) = '1' and + cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and + (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or + cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else + not spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or - cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else + cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and + (cur_x > conv_std_logic_vector(256, X_SIZE) and + cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else '1'; - d_oe_n <= '0' when ppu_mask(PPUSBG) = '1' and - (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or - cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else - '0' when ppu_mask(PPUSSP) = '1' and + ah_oe_n <= '0' when (ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else '1'; - v_bus_busy_n <= d_oe_n; - - io_cnt_inst : counter_register generic map (1, 1) - port map (clk, cnt_x_res_n, '0', '1', (others => '0'), io_cnt); - - ---x pos is 8 cycle ahead of current pos. - next_x <= cur_x + "000010000" - when cur_x < conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE) else - cur_x + "011000000"; - next_y <= cur_y - when cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) else - "000000000" - when cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else - cur_y + "000000001"; + v_bus_busy_n <= ah_oe_n; + + bg_io_cnt_inst : counter_register generic map (1, 1) + port map (clk, bg_cnt_res_n, '0', '1', (others => '0'), bg_io_cnt); + spr_io_cnt_inst : counter_register generic map (1, 1) + port map (clk, cnt_x_res_n, '0', '1', (others => '0'), spr_io_cnt); + + ---bg prefetch x pos is 16 + scroll cycle ahead of current pos. + prf_x <= cur_x + ppu_scroll_x + "000010000" + when cur_x < conv_std_logic_vector(HSCAN, X_SIZE) else + cur_x + ppu_scroll_x + "010111011"; -- +16 -341 + + prf_y <= cur_y + ppu_scroll_y + when cur_x < conv_std_logic_vector(HSCAN, X_SIZE) and + cur_y + ppu_scroll_y < + conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else + cur_y + ppu_scroll_y + "000000001" + when cur_y + ppu_scroll_y < + conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else + "000000000"; --current x,y pos cur_x_inst : counter_register generic map (X_SIZE, 1) - port map (clk_n, cnt_x_res_n, cnt_x_en_n, '1', (others => '0'), cur_x); + port map (clk_n, cnt_x_res_n, '0', '1', (others => '0'), cur_x); cur_y_inst : counter_register generic map (X_SIZE, 1) port map (clk_n, cnt_y_res_n, cnt_y_en_n, '1', (others => '0'), cur_y); @@ -421,26 +406,22 @@ begin vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7)) & disp_ptn_h (dsize downto 1); - ptn_en_n <= '1' when cur_x = conv_std_logic_vector(0, X_SIZE) else - '0' when cur_x <= conv_std_logic_vector(HSCAN_NEXT_EXTRA, X_SIZE) else - '1'; - ptn_l_inst : d_flip_flop generic map(dsize) port map (clk_n, rst_n, '1', ptn_l_we_n, ptn_l_in, ptn_l_val); disp_ptn_l_in <= ptn_l_val & disp_ptn_l (dsize downto 1); disp_ptn_l_inst : shift_register generic map(dsize * 2, 1) - port map (clk_n, rst_n, ptn_en_n, ptn_h_we_n, disp_ptn_l_in, disp_ptn_l); + port map (clk_n, rst_n, '0', ptn_h_we_n, disp_ptn_l_in, disp_ptn_l); ptn_h_inst : shift_register generic map(dsize * 2, 1) - port map (clk_n, rst_n, ptn_en_n, ptn_h_we_n, ptn_h_in, disp_ptn_h); + port map (clk_n, rst_n, '0', ptn_h_we_n, ptn_h_in, disp_ptn_h); --vram i/o vram_io_buf : tri_state_buffer generic map (dsize) port map (io_oe_n, vram_addr(dsize - 1 downto 0), vram_ad); vram_a_buf : tri_state_buffer generic map (6) - port map (d_oe_n, vram_addr(asize - 1 downto dsize), vram_a); + port map (ah_oe_n, vram_addr(asize - 1 downto dsize), vram_a); pos_x <= cur_x; pos_y <= cur_y; @@ -506,13 +487,17 @@ begin (spr_ptn_h(7)(0) or spr_ptn_l(7)(0)) = '1' else "0" & disp_attr(1 downto 0) & disp_ptn_h(0) & disp_ptn_l(0) when ppu_mask(PPUSBG) = '1' and cur_y(4) = '0' and + ((disp_ptn_h(0) or disp_ptn_l(0)) = '1') and (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) else "0" & disp_attr(5 downto 4) & disp_ptn_h(0) & disp_ptn_l(0) when ppu_mask(PPUSBG) = '1' and cur_y(4) = '1' and + ((disp_ptn_h(0) or disp_ptn_l(0)) = '1') and (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) else - (others => 'Z'); + ---else: no output color >> universal bg color output. + --0x3f00 is the universal bg palette. + (others => '0'); plt_r_n <= not r_nw when plt_bus_ce_n = '0' else '0' when ppu_mask(PPUSBG) = '1' else @@ -523,7 +508,7 @@ begin port map (r_nw, oam_plt_data, plt_data); plt_d_buf_r : tri_state_buffer generic map (dsize) port map (r_n, plt_data, oam_plt_data); - palette_inst : ram generic map (5, dsize) + palette_inst : palette_ram generic map (5, dsize) port map (plt_ram_ce_n, plt_r_n, plt_w_n, plt_addr, plt_data); ---primary oam @@ -641,20 +626,18 @@ begin -- d_print("output_rgb"); -- d_print("pl_addr:" & conv_hex8(pl_addr)); -- d_print("pl_index:" & conv_hex8(pl_index)); --- d_print("rgb:" & --- conv_hex16(nes_color_palette(pl_index))); end if; - if (dot_output = true) then - pl_index := conv_integer(plt_data(5 downto 0)); - b <= nes_color_palette(pl_index) (11 downto 8); - g <= nes_color_palette(pl_index) (7 downto 4); - r <= nes_color_palette(pl_index) (3 downto 0); - else - b <= (others => '0'); - g <= (others => '0'); - r <= (others => '0'); - end if; --if (dot_output = false) then + --if or if not bg/sprite is shown, output color anyway + --sinse universal bg color is included.. + pl_index := conv_integer(plt_data(5 downto 0)); + b <= nes_color_palette(pl_index) (11 downto 8); + g <= nes_color_palette(pl_index) (7 downto 4); + r <= nes_color_palette(pl_index) (3 downto 0); +-- d_print("rgb:" & +-- conv_hex8(nes_color_palette(pl_index) (11 downto 8)) & +-- conv_hex8(nes_color_palette(pl_index) (7 downto 4)) & +-- conv_hex8(nes_color_palette(pl_index) (3 downto 0))); end; begin @@ -662,6 +645,7 @@ end; cnt_x_res_n <= '0'; cnt_y_res_n <= '0'; nt_we_n <= '1'; + bg_cnt_res_n <= '0'; ppu_status <= (others => '0'); @@ -669,23 +653,33 @@ end; g <= (others => '0'); r <= (others => '0'); else - if (clk'event) then - --x pos reset. - if (clk = '0' and - cur_x = conv_std_logic_vector(HSCAN_MAX - 1, X_SIZE)) then - cnt_x_res_n <= '0'; - - --y pos reset. - if (cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) then - cnt_y_res_n <= '0'; - else - cnt_y_res_n <= '1'; - end if; - else - cnt_x_res_n <= '1'; - cnt_y_res_n <= '1'; - end if; - end if; --if (clk'event) then +-- if (clk'event) then +-- --x pos reset. +-- if (clk = '0' and +-- cur_x = conv_std_logic_vector(HSCAN_MAX - 1, X_SIZE)) then +-- cnt_x_res_n <= '0'; +-- +-- --y pos reset. +-- if (cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) then +-- cnt_y_res_n <= '0'; +-- else +-- cnt_y_res_n <= '1'; +-- end if; +-- else +-- cnt_x_res_n <= '1'; +-- cnt_y_res_n <= '1'; +-- end if; +-- +-- if (clk = '0' and +-- ppu_scroll_x(0) = '0' and cur_x = conv_std_logic_vector(HSCAN, X_SIZE)) then +-- bg_cnt_res_n <= '0'; +-- elsif (clk = '0' and +-- ppu_scroll_x(0) = '1' and cur_x = conv_std_logic_vector(HSCAN - 1, X_SIZE)) then +-- bg_cnt_res_n <= '0'; +-- else +-- bg_cnt_res_n <= '1'; +-- end if; +-- end if; --if (clk'event) then if (clk'event and clk = '1') then --y pos increment. @@ -704,84 +698,87 @@ end; --fetch bg pattern and display. if (ppu_mask(PPUSBG) = '1' and + (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or + cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) and (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE))) then + --visible area bg image + d_print("*"); d_print("cur_x: " & conv_hex16(conv_integer(cur_x))); d_print("cur_y: " & conv_hex16(conv_integer(cur_y))); ----fetch next tile byte. - if (cur_x (2 downto 0) = "001" ) then + if (prf_x (2 downto 0) = "001") then --vram addr is incremented every 8 cycle. --name table at 0x2000 vram_addr(9 downto 0) - <= next_y(dsize - 1 downto 3) - & next_x(dsize - 1 downto 3); - vram_addr(asize - 1 downto 10) <= "10" & ppu_ctrl(PPUBNA downto 0); + <= prf_y(dsize - 1 downto 3) + & prf_x(dsize - 1 downto 3); + vram_addr(asize - 1 downto 10) <= "10" & ppu_ctrl(PPUBNA downto 0) + + ("000" & prf_x(dsize)); end if; - if (cur_x (2 downto 0) = "010" ) then + if (prf_x (2 downto 0) = "010") then nt_we_n <= '0'; else nt_we_n <= '1'; end if; + --TODO must load 8 cycle each for the first two tiles!!! ----fetch attr table byte. - if (cur_x (4 downto 0) = "00011" ) then + if (prf_x (4 downto 0) = "00011") then --attribute table is loaded every 32 cycle. --attr table at 0x23c0 vram_addr(dsize - 1 downto 0) <= "11000000" + - ("00" & next_y(7 downto 5) & next_x(7 downto 5)); + ("00" & prf_y(7 downto 5) & prf_x(7 downto 5)); vram_addr(asize - 1 downto dsize) <= "10" & - ppu_ctrl(PPUBNA downto 0) & "11"; - end if;--if (cur_x (2 downto 0) = "010" ) then - if (cur_x (4 downto 0) = "00100" ) then + ppu_ctrl(PPUBNA downto 0) & "11" + + ("000" & prf_x(dsize) & "00"); + end if; + if (prf_x (4 downto 0) = "00100") then attr_we_n <= '0'; else attr_we_n <= '1'; end if; - if (cur_x (4 downto 0) = "00000" ) then + if (prf_x (4 downto 0) = "10000") then disp_attr_we_n <= '0'; else disp_attr_we_n <= '1'; end if; ---attribute is shifted every 16 bit. - if (cur_x (3 downto 0) = "0000" ) then + if (prf_x (3 downto 0) = "0000") then attr_ce_n <= '0'; else attr_ce_n <= '1'; end if; - --visible area bg image - if ((cur_x <= conv_std_logic_vector(HSCAN, X_SIZE)) or - cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) then - ----fetch pattern table low byte. - if (cur_x (2 downto 0) = "101" ) then + if (prf_x (2 downto 0) = "101") then --vram addr is incremented every 8 cycle. vram_addr <= "0" & ppu_ctrl(PPUBPA) & disp_nt(dsize - 1 downto 0) - & "0" & next_y(2 downto 0); - end if;--if (cur_x (2 downto 0) = "100" ) then - if (cur_x (2 downto 0) = "110" ) then + & "0" & prf_y(2 downto 0); + end if; + if (prf_x (2 downto 0) = "110") then ptn_l_we_n <= '0'; else ptn_l_we_n <= '1'; end if; ----fetch pattern table high byte. - if (cur_x (2 downto 0) = "111" ) then + if (prf_x (2 downto 0) = "111") then --vram addr is incremented every 8 cycle. vram_addr <= "0" & ppu_ctrl(PPUBPA) & disp_nt(dsize - 1 downto 0) - & "0" & next_y(2 downto 0) + "00000000001000"; - end if; --if (cur_x (2 downto 0) = "110" ) then - if (cur_x (2 downto 0) = "000" and cur_x /= "000000000") then + & "0" & prf_y(2 downto 0) + "00000000001000"; + end if; + if (prf_x (2 downto 0) = "000") then ptn_h_we_n <= '0'; else ptn_h_we_n <= '1'; - end if;--if (cur_x (2 downto 0) = "001" ) then - end if; --if (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE)) and - end if;--if (ppu_mask(PPUSBG) = '1') then + end if; + + end if;--if (ppu_mask(PPUSBG) = '1') and --fetch sprite and display. if (ppu_mask(PPUSSP) = '1' and @@ -878,12 +875,10 @@ end; spr_attr_we_n <= "11111111"; spr_ptn_l_we_n <= "11111111"; spr_ptn_h_we_n <= "11111111"; - spr_x_ce_n <= "11111111"; - spr_ptn_ce_n <= "11111111"; --sprite pattern fetch elsif (cur_x > conv_std_logic_vector(256, X_SIZE) and - cur_x <= conv_std_logic_vector(320, X_SIZE)) then + cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) then s_oam_addr_cpy_n <= '0'; s_oam_r_n <= '0'; @@ -925,12 +920,12 @@ end; if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL) = '0') then vram_addr <= "0" & ppu_ctrl(PPUSPA) & spr_tile_tmp(dsize - 1 downto 0) & "0" & - (next_y(2 downto 0) - spr_y_tmp(2 downto 0)); + (cur_y(2 downto 0) + "001" - spr_y_tmp(2 downto 0)); else --flip sprite vertically. vram_addr <= "0" & ppu_ctrl(PPUSPA) & spr_tile_tmp(dsize - 1 downto 0) & "0" & - (spr_y_tmp(2 downto 0) - next_y(2 downto 0) - "001"); + (spr_y_tmp(2 downto 0) - cur_y(2 downto 0) - "010"); end if; end if; @@ -945,14 +940,14 @@ end; if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL) = '0') then vram_addr <= "0" & ppu_ctrl(PPUSPA) & spr_tile_tmp(dsize - 1 downto 0) & "0" & - (next_y(2 downto 0) - spr_y_tmp(2 downto 0)) + (cur_y(2 downto 0) + "001" - spr_y_tmp(2 downto 0)) + "00000000001000"; else --flip sprite vertically. vram_addr <= "0" & ppu_ctrl(PPUSPA) & spr_tile_tmp(dsize - 1 downto 0) & "0" & - (spr_y_tmp(2 downto 0) - next_y(2 downto 0)) - + "00000000000111"; + (spr_y_tmp(2 downto 0) - cur_y(2 downto 0) - "010") + + "00000000001000"; end if; end if; @@ -983,21 +978,18 @@ end; spr_ptn_ce_n(i) <= '0'; end if; end loop; + else + spr_x_ce_n <= "11111111"; + spr_ptn_ce_n <= "11111111"; end if; --if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) end if; --if (ppu_mask(PPUSSP) = '1') then - if (ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') then - --output visible area only. - if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and - (cur_y < conv_std_logic_vector(VSCAN, X_SIZE))) then - --output image. - output_rgb; - end if; - else - b <= (others => '1'); - g <= (others => '0'); - r <= (others => '1'); - end if;--if (ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') then + --output visible area only. + if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and + (cur_y < conv_std_logic_vector(VSCAN, X_SIZE))) then + --output image. + output_rgb; + end if; --flag operation if ((cur_x = conv_std_logic_vector(1, X_SIZE)) and @@ -1014,10 +1006,10 @@ end; end if; end if; --if (clk'event and clk = '1') then - if (read_status'event and read_status = '1') then - --reading ppu status clears vblank bit. - ppu_status(ST_VBL) <= '0'; - end if; +-- if (read_status'event and read_status = '1') then +-- --reading ppu status clears vblank bit. +-- ppu_status(ST_VBL) <= '0'; +-- end if; end if;--if (rst_n = '0') then end process; diff --git a/de1_nes/ppu/vga.vhd b/de1_nes/ppu/vga.vhd new file mode 100644 index 0000000..5cd3a9b --- /dev/null +++ b/de1_nes/ppu/vga.vhd @@ -0,0 +1,302 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.conv_integer; +use ieee.std_logic_arith.conv_std_logic_vector; +use work.motonesfpga_common.all; + +entity vga_ctl is + port ( ppu_clk : in std_logic; + vga_clk : in std_logic; + rst_n : in std_logic; + pos_x : in std_logic_vector (8 downto 0); + pos_y : in std_logic_vector (8 downto 0); + nes_r : in std_logic_vector (3 downto 0); + nes_g : in std_logic_vector (3 downto 0); + nes_b : in std_logic_vector (3 downto 0); + h_sync_n : out std_logic; + v_sync_n : out std_logic; + r : out std_logic_vector(3 downto 0); + g : out std_logic_vector(3 downto 0); + b : out std_logic_vector(3 downto 0) + ); +end vga_ctl; + +architecture rtl of vga_ctl is + +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 COLOR_SIZE : integer := 12; +constant VGA_SIZE : integer := 10; + +constant VGA_W : integer := 640; +constant VGA_H : integer := 480; +constant VGA_W_MAX : integer := 800; +constant VGA_H_MAX : integer := 525; +constant H_FP : integer := 16; +constant H_SP : integer := 96; +constant H_BP : integer := 48; +constant V_FP : integer := 10; +constant V_SP : integer := 2; +constant V_BP : integer := 33; + +subtype bit_data is std_logic_vector (COLOR_SIZE -1 downto 0); +type bit_array is array (0 to 256*256 - 1) of bit_data; +signal nes_screen : bit_array := (others => (others => '0')); + +signal vga_x_en_n : std_logic; +signal vga_x_res_n : std_logic; +signal vga_y_en_n : std_logic; +signal vga_y_res_n : std_logic; +signal vga_x : std_logic_vector(VGA_SIZE - 1 downto 0); +signal vga_y : std_logic_vector(VGA_SIZE - 1 downto 0); + +signal count5_res_n : std_logic; +signal count5 : std_logic_vector(2 downto 0); +signal nes_x_en_n : std_logic; +signal nes_x : std_logic_vector(7 downto 0); + +begin + + p_write : process (pos_x, pos_y, nes_r, nes_g, nes_b) + begin + --draw pixel on the virtual screen + --if (rst_n = '1' and ppu_clk'event and ppu_clk = '1') then + if (pos_x(8) = '0' and pos_y(8) = '0') then + nes_screen(conv_integer(pos_y(7 downto 0) & pos_x(7 downto 0))) <= + nes_b & nes_g & nes_r; +-- d_print("vga set"); +-- d_print("x,y:" & +-- conv_hex8(pos_x) & "," & conv_hex8(pos_y)); +-- d_print("r,g,b:" & +-- conv_hex8(nes_r) & "," & conv_hex8(nes_g) & "," & conv_hex8(nes_b)); + end if; + --end if; --if (ppu_clk'event and ppu_clk = '1') then + end process; + + vga_x_en_n <= '0'; + vga_x_inst : counter_register generic map (VGA_SIZE, 1) + port map (vga_clk, vga_x_res_n, vga_x_en_n, '1', (others => '0'), vga_x); + + count5_inst : counter_register generic map (3, 1) + port map (vga_clk, count5_res_n, '0', '1', (others => '0'), count5); + nes_x_inst : counter_register generic map (8, 1) + port map (vga_clk, vga_x_res_n, nes_x_en_n, '1', (others => '0'), nes_x); + + ---test dummy value... + vga_y_inst : counter_register generic map (VGA_SIZE, 1) + port map (vga_clk, vga_y_res_n, vga_y_en_n, rst_n, + conv_std_logic_vector(VGA_H - 2, VGA_SIZE), vga_y); + + p_vga_out : process (rst_n, vga_clk) + begin + if (rst_n = '0') then + vga_x_res_n <= '0'; + --for dummy init value set. + --vga_y_res_n <= '0'; + vga_y_res_n <= '1'; + count5_res_n <= '0'; + else +-- if (vga_clk'event) then +-- --x pos reset. +-- if (vga_clk = '1' and +-- vga_x = conv_std_logic_vector(VGA_W_MAX - 1, VGA_SIZE)) then +-- vga_x_res_n <= '0'; +-- +-- --y pos reset. +-- if (vga_y = conv_std_logic_vector(VGA_H_MAX - 1, VGA_SIZE)) then +-- vga_y_res_n <= '0'; +-- else +-- vga_y_res_n <= '1'; +-- end if; +-- else +-- vga_x_res_n <= '1'; +-- vga_y_res_n <= '1'; +-- end if; +-- +-- if (vga_clk = '1' and count5 = "100") then +-- count5_res_n <= '0'; +-- else +-- count5_res_n <= '1'; +-- end if; +-- end if; --if (vga_clk'event) then + + if (vga_clk'event and vga_clk = '0') then + --y pos increment. + if (vga_x = conv_std_logic_vector(VGA_W_MAX - 1, VGA_SIZE)) then + vga_y_en_n <= '0'; + else + vga_y_en_n <= '1'; + end if; + + if (count5 = "010" or count5 = "100") then + nes_x_en_n <= '0'; + else + nes_x_en_n <= '1'; + end if; + end if; --if (vga_clk'event) then + + if (vga_clk'event and vga_clk = '1') then + if (vga_x < conv_std_logic_vector(VGA_W, VGA_SIZE) and + vga_y < conv_std_logic_vector(VGA_H, VGA_SIZE)) then + + --d_print("vga_ctl: rgb out. x:" & conv_hex16(conv_integer(vga_x))); + + b <= nes_screen(conv_integer( + vga_y(8 downto 1) & nes_x(7 downto 0)))(11 downto 8); + g <= nes_screen(conv_integer( + vga_y(8 downto 1) & nes_x(7 downto 0)))(7 downto 4); + r <= nes_screen(conv_integer( + vga_y(8 downto 1) & nes_x(7 downto 0)))(3 downto 0); + else + r <= (others => '0'); + g <= (others => '0'); + b <= (others => '0'); + end if; + + --sync signal assert. + if (vga_x >= conv_std_logic_vector(VGA_W + H_FP, VGA_SIZE) and + vga_x < conv_std_logic_vector(VGA_W + H_FP + H_SP, VGA_SIZE)) then + h_sync_n <= '0'; + + --d_print("vga_ctl: h_sync."); + else + h_sync_n <= '1'; + end if; + + if (vga_y >= conv_std_logic_vector(VGA_H + V_FP, VGA_SIZE) and + vga_y < conv_std_logic_vector(VGA_H + V_FP + V_SP, VGA_SIZE)) then + v_sync_n <= '0'; + + --d_print("vga_ctl: v_sync."); + else + v_sync_n <= '1'; + end if; + end if; --if (vga_clk'event and vga_clk = '1') then + + end if;--if (rst_n = '0') then + end process; +end rtl; + + + + +------------------------------------------------------- +------------------------------------------------------- +----------- dummy vga outpu device. ------------------ +------------------------------------------------------- +------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.conv_integer; +use work.motonesfpga_common.all; + +entity vga_device is + port ( vga_clk : in std_logic; + rst_n : in std_logic; + h_sync_n : in std_logic; + v_sync_n : in std_logic; + r : in std_logic_vector(3 downto 0); + g : in std_logic_vector(3 downto 0); + b : in std_logic_vector(3 downto 0) + ); +end vga_device; + +architecture rtl of vga_device is + +constant VGA_W : integer := 640; +constant VGA_H : integer := 480; +constant VGA_W_MAX : integer := 800; +constant VGA_H_MAX : integer := 525; +constant H_FP : integer := 16; +constant H_SP : integer := 96; +constant H_BP : integer := 48; +constant V_FP : integer := 10; +constant V_SP : integer := 2; +constant V_BP : integer := 33; + +function conv_color_hex ( + r : in std_logic_vector(3 downto 0); + g : in std_logic_vector(3 downto 0); + b : in std_logic_vector(3 downto 0) + ) return string is +variable tmp1, tmp2, tmp3 : integer; +variable hex_chr: string (1 to 16) := "0123456789abcdef"; +begin + tmp1 := conv_integer(r); + tmp2 := conv_integer(g); + tmp3 := conv_integer(b); + return hex_chr(tmp3 + 1) & hex_chr(tmp2 + 1) & hex_chr(tmp1 + 1); +end; + +procedure write_vga_pipe(msg : string) is +--use std.textio.all; +--use ieee.std_logic_textio.all; +--variable out_l : line; +--file vga_file: TEXT open write_mode is "vga-port"; +begin +-- write(out_l, msg); +-- writeline(vga_file, out_l); + --d_print("pipe: " & msg); +end procedure; + + +---ival : 0x0000 - 0xffff +begin + + clk_p : process (rst_n, vga_clk, h_sync_n, v_sync_n) + variable x, y : integer; + + begin + if (rst_n = '0') then + x := 0; + y := 0; + --d_print("vga_device: ****"); + else + if (vga_clk'event and vga_clk = '1') then + if ( x < VGA_W and y < VGA_H) then + --d_print(conv_color_hex(r, g, b)); + write_vga_pipe(conv_color_hex(b, g, r)); + --write_vga_pipe("0" & conv_hex8(x)); + --d_print("vga_device: rgb out x:" & conv_hex16(x)); + end if; + + if (x = VGA_W_MAX - 1) then + x := 0; + y := y + 1; + else + x := x + 1; + end if; + + if (y = VGA_H_MAX - 1) then + y := 0; + end if; + end if; + + if (h_sync_n'event and h_sync_n = '0') then + --d_print("vga_device: h_sync"); + write_vga_pipe("---"); + x := VGA_W + H_FP + 1; + end if; + if (v_sync_n'event and v_sync_n = '0') then + --d_print("vga_device: v_sync"); + write_vga_pipe("___"); + y := VGA_H + V_FP + 1; + end if; + end if; + end process; + +end rtl; + diff --git a/de1_nes/testbench_motones_sim.vhd b/de1_nes/testbench_motones_sim.vhd new file mode 100644 index 0000000..32b1ac8 --- /dev/null +++ b/de1_nes/testbench_motones_sim.vhd @@ -0,0 +1,85 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use ieee.std_logic_arith.all; + +entity testbench_motones_sim is +end testbench_motones_sim; + +architecture stimulus of testbench_motones_sim is + component de1_nes + port ( + base_clk : in std_logic; + rst_n : in std_logic; + joypad1 : in std_logic_vector(7 downto 0); + joypad2 : in std_logic_vector(7 downto 0); + vga_clk : out std_logic; + h_sync_n : out std_logic; + v_sync_n : out std_logic; + r : out std_logic_vector(3 downto 0); + g : out std_logic_vector(3 downto 0); + b : out std_logic_vector(3 downto 0) + ); + end component; + + component vga_device + port ( vga_clk : in std_logic; + rst_n : in std_logic; + h_sync_n : in std_logic; + v_sync_n : in std_logic; + r : in std_logic_vector(3 downto 0); + g : in std_logic_vector(3 downto 0); + b : in std_logic_vector(3 downto 0) + ); + end component; + + signal base_clk : std_logic; + signal vga_clk : std_logic; + signal reset_input : std_logic; + + signal h_sync_n : std_logic; + signal v_sync_n : std_logic; + signal r : std_logic_vector(3 downto 0); + signal g : std_logic_vector(3 downto 0); + signal b : std_logic_vector(3 downto 0); + signal joypad1 : std_logic_vector(7 downto 0); + signal joypad2 : std_logic_vector(7 downto 0); + + constant powerup_time : time := 5000 ns; + constant reset_time : time := 10 us; + + ---clock frequency = 21,477,270 (21 MHz) + --constant base_clock_time : time := 46 ns; + --base clock frequency shares vga clock. + constant base_clock_time : time := 40 ns; + +begin + + sim_board : de1_nes port map (base_clk, reset_input, joypad1, joypad2, + vga_clk, h_sync_n, v_sync_n, r, g, b); + +-- dummy_vga_disp : vga_device +-- port map (vga_clk, reset_input, h_sync_n, v_sync_n, r, g, b); + + --- input reset. + reset_p: process + begin + wait for powerup_time; + reset_input <= '0'; + + wait for reset_time; + reset_input <= '1'; + + wait; + end process; + + --- generate base clock. + clock_p: process + begin + base_clk <= '1'; + wait for base_clock_time / 2; + base_clk <= '0'; + wait for base_clock_time / 2; + end process; + +end stimulus; + -- 2.11.0