2 use ieee.std_logic_1164.all;
5 port ( clk : in std_logic;
9 cpu_addr : in std_logic_vector (2 downto 0);
10 cpu_d : inout std_logic_vector (7 downto 0);
11 vblank_n : out std_logic;
15 vram_ad : inout std_logic_vector (7 downto 0);
16 vram_a : out std_logic_vector (13 downto 8);
17 vga_clk : in std_logic;
18 h_sync_n : out std_logic;
19 v_sync_n : out std_logic;
20 r : out std_logic_vector(3 downto 0);
21 g : out std_logic_vector(3 downto 0);
22 b : out std_logic_vector(3 downto 0)
26 architecture rtl of ppu is
29 port ( clk : in std_logic;
31 vblank_n : out std_logic;
35 vram_ad : inout std_logic_vector (7 downto 0);
36 vram_a : out std_logic_vector (13 downto 8);
37 plt_bus_ce_n : in std_logic;
38 plt_r_nw : in std_logic;
39 plt_addr : in std_logic_vector (4 downto 0);
40 plt_data : inout std_logic_vector (5 downto 0);
41 pos_x : out std_logic_vector (8 downto 0);
42 pos_y : out std_logic_vector (8 downto 0);
43 r : out std_logic_vector (3 downto 0);
44 g : out std_logic_vector (3 downto 0);
45 b : out std_logic_vector (3 downto 0)
50 port ( ppu_clk : in std_logic;
51 vga_clk : in std_logic;
53 pos_x : in std_logic_vector (8 downto 0);
54 pos_y : in std_logic_vector (8 downto 0);
55 nes_r : in std_logic_vector (3 downto 0);
56 nes_g : in std_logic_vector (3 downto 0);
57 nes_b : in std_logic_vector (3 downto 0);
58 h_sync_n : out std_logic;
59 v_sync_n : out std_logic;
60 r : out std_logic_vector(3 downto 0);
61 g : out std_logic_vector(3 downto 0);
62 b : out std_logic_vector(3 downto 0)
75 d : in std_logic_vector (dsize - 1 downto 0);
76 q : out std_logic_vector (dsize - 1 downto 0)
80 component counter_register
84 port ( clk : in std_logic;
88 d : in std_logic_vector(dsize - 1 downto 0);
89 q : out std_logic_vector(dsize - 1 downto 0)
93 signal pos_x : std_logic_vector (8 downto 0);
94 signal pos_y : std_logic_vector (8 downto 0);
95 signal nes_r : std_logic_vector (3 downto 0);
96 signal nes_g : std_logic_vector (3 downto 0);
97 signal nes_b : std_logic_vector (3 downto 0);
99 signal plt_bus_ce_n : std_logic;
100 signal plt_r_nw : std_logic;
101 signal plt_addr : std_logic_vector (4 downto 0);
102 signal plt_data : std_logic_vector (5 downto 0);
104 constant dsize : integer := 8;
106 constant PPUCTRL : std_logic_vector(2 downto 0) := "000";
107 constant PPUMASK : std_logic_vector(2 downto 0) := "001";
108 constant PPUSTATUS : std_logic_vector(2 downto 0) := "010";
109 constant OAMADDR : std_logic_vector(2 downto 0) := "011";
110 constant OAMDATA : std_logic_vector(2 downto 0) := "100";
111 constant PPUSCROLL : std_logic_vector(2 downto 0) := "101";
112 constant PPUADDR : std_logic_vector(2 downto 0) := "110";
113 constant PPUDATA : std_logic_vector(2 downto 0) := "111";
115 signal ppu_ctrl_we_n : std_logic;
116 signal ppu_mask_we_n : std_logic;
117 signal ppu_status_we_n : std_logic;
118 signal oam_addr_we_n : std_logic;
119 signal oam_data_we_n : std_logic;
120 signal ppu_scroll_x_we_n : std_logic;
121 signal ppu_scroll_y_we_n : std_logic;
122 signal ppu_scroll_cnt_ce_n : std_logic;
123 signal ppu_addr_we_n : std_logic;
124 signal ppu_addr_cnt_ce_n : std_logic;
125 signal ppu_data_we_n : std_logic;
127 signal ppu_ctrl : std_logic_vector (dsize - 1 downto 0);
128 signal ppu_mask : std_logic_vector (dsize - 1 downto 0);
129 signal ppu_status : std_logic_vector (dsize - 1 downto 0);
130 signal oam_addr : std_logic_vector (dsize - 1 downto 0);
131 signal oam_data : std_logic_vector (dsize - 1 downto 0);
132 signal ppu_scroll_x : std_logic_vector (dsize - 1 downto 0);
133 signal ppu_scroll_y : std_logic_vector (dsize - 1 downto 0);
134 signal ppu_scroll_cnt : std_logic_vector (0 downto 0);
135 signal ppu_addr : std_logic_vector (13 downto 0);
136 signal ppu_addr_in : std_logic_vector (13 downto 0);
137 signal ppu_addr_cnt : std_logic_vector (0 downto 0);
138 signal ppu_data : std_logic_vector (dsize - 1 downto 0);
143 render_inst : ppu_render port map (clk, rst_n, vblank_n,
144 rd_n, wr_n, ale, vram_ad, vram_a,
145 plt_bus_ce_n, plt_r_nw, plt_addr, plt_data,
146 pos_x, pos_y, nes_r, nes_g, nes_b);
148 vga_inst : vga_ctl port map (clk, vga_clk, rst_n,
149 pos_x, pos_y, nes_r, nes_g, nes_b,
150 h_sync_n, v_sync_n, r, g, b);
153 ppu_ctrl_inst : d_flip_flop generic map(dsize)
154 port map (clk, rst_n, '1', ppu_ctrl_we_n, cpu_d, ppu_ctrl);
156 ppu_mask_inst : d_flip_flop generic map(dsize)
157 port map (clk, rst_n, '1', ppu_mask_we_n, cpu_d, ppu_mask);
159 ppu_status_inst : d_flip_flop generic map(dsize)
160 port map (clk, rst_n, '1', ppu_status_we_n, cpu_d, ppu_status);
162 oma_addr_inst : d_flip_flop generic map(dsize)
163 port map (clk, rst_n, '1', oam_addr_we_n, cpu_d, oam_addr);
164 oma_data_inst : d_flip_flop generic map(dsize)
165 port map (clk, rst_n, '1', oam_data_we_n, cpu_d, oam_data);
167 ppu_scroll_x_inst : d_flip_flop generic map(dsize)
168 port map (clk, rst_n, '1', ppu_scroll_x_we_n, cpu_d, ppu_scroll_x);
169 ppu_scroll_y_inst : d_flip_flop generic map(dsize)
170 port map (clk, rst_n, '1', ppu_scroll_y_we_n, cpu_d, ppu_scroll_y);
171 ppu_scroll_cnt_inst : counter_register generic map (1)
172 port map (clk, rst_n, '1', ppu_scroll_cnt_ce_n, (others => '0'), ppu_scroll_cnt);
174 ppu_addr_inst : d_flip_flop generic map(14)
175 port map (clk, rst_n, '1', ppu_addr_we_n, ppu_addr_in, ppu_addr);
176 ppu_addr_cnt_inst : counter_register generic map (1)
177 port map (clk, rst_n, '1', ppu_addr_cnt_ce_n, (others => '0'), ppu_addr_cnt);
178 ppu_data_inst : d_flip_flop generic map(dsize)
179 port map (clk, rst_n, '1', ppu_data_we_n, cpu_d, ppu_data);
182 clock_p : process (clk)
185 if (clk'event and clk = '1' and ce_n = '0') then
187 if(cpu_addr = PPUCTRL) then
188 ppu_ctrl_we_n <= '0';
190 ppu_ctrl_we_n <= '1';
193 if(cpu_addr = PPUMASK) then
194 ppu_mask_we_n <= '0';
196 ppu_mask_we_n <= '1';
199 if(cpu_addr = PPUSTATUS) then
200 ppu_status_we_n <= '0';
202 ppu_status_we_n <= '1';
205 if(cpu_addr = OAMADDR) then
206 oam_addr_we_n <= '0';
208 oam_addr_we_n <= '1';
211 if(cpu_addr = OAMDATA) then
212 oam_data_we_n <= '0';
214 oam_data_we_n <= '1';
217 if(cpu_addr = PPUSCROLL) then
218 ppu_scroll_cnt_ce_n <= '0';
219 if (ppu_scroll_cnt(0) = '0') then
220 ppu_scroll_x_we_n <= '0';
221 ppu_scroll_y_we_n <= '1';
223 ppu_scroll_y_we_n <= '0';
224 ppu_scroll_x_we_n <= '1';
227 ppu_scroll_x_we_n <= '1';
228 ppu_scroll_y_we_n <= '1';
229 ppu_scroll_cnt_ce_n <= '1';
232 if(cpu_addr = PPUADDR) then
233 ppu_addr_cnt_ce_n <= '0';
234 ppu_addr_we_n <= '0';
235 if (ppu_addr_cnt(0) = '0') then
236 ppu_addr_in <= ppu_addr(13 downto 8) & cpu_d;
238 ppu_addr_in <= cpu_d(5 downto 0) & ppu_addr(7 downto 0);
241 ppu_addr_cnt_ce_n <= '1';
242 ppu_addr_we_n <= '1';
245 if(cpu_addr = PPUDATA) then
246 ppu_data_we_n <= '0';
248 ppu_data_we_n <= '1';
257 --test init value set.
258 p_palette_init : process
259 variable i : integer := 0;
260 use ieee.std_logic_arith.all;
261 constant ppu_clk_time : time := 186 ns;
265 --fill palette teble.
268 for i in 0 to 32 loop
269 plt_addr <= conv_std_logic_vector(i, 5);
270 plt_data <= conv_std_logic_vector((i - 1) * 4 + 17, 6);
271 wait for ppu_clk_time;
275 ---TODO: for the time being...
278 plt_addr <= (others => 'Z');
279 plt_data <= (others => 'Z');