aboutsummaryrefslogtreecommitdiff
path: root/basys3/basys3.srcs/ppu.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'basys3/basys3.srcs/ppu.vhd')
-rw-r--r--basys3/basys3.srcs/ppu.vhd264
1 files changed, 264 insertions, 0 deletions
diff --git a/basys3/basys3.srcs/ppu.vhd b/basys3/basys3.srcs/ppu.vhd
new file mode 100644
index 0000000..2f16956
--- /dev/null
+++ b/basys3/basys3.srcs/ppu.vhd
@@ -0,0 +1,264 @@
+library ieee;
+use ieee.std_logic_1164.all;
+--use ieee.numeric_std.all;
+
+entity ppu is
+ port(
+ CLK100: in std_logic; -- system clock
+ RESET: in std_logic; -- global (async) system reset
+ EN: in std_logic; -- PPU VRAM enable (enable ADDR and DATA tri-state drivers)
+ WEN: in std_logic; -- PPU VRAM write enable
+ ADDR: in std_logic_vector(15 downto 0); -- PPU VRAM ADDR
+ DATA: in std_logic_vector(15 downto 0);
+ R,G,B: out std_logic_vector(3 downto 0);
+ NVSYNC, NHSYNC: out std_logic; -- native VGA out
+ TVSYNC, TVBLANK, THSYNC, THBLANK: out std_logic); -- tiny VGA out
+end ppu;
+
+architecture Behavioral of ppu is
+ constant PPU_FG_SPRITE_COUNT: natural := 128;
+ constant PPU_PALETTE_IDX_SIZE: natural := 3;
+ constant PPU_PALETTE_SIZE: natural := 3;
+ constant PPU_PALETTE_CIDX_SIZE: natural := PPU_PALETTE_IDX_SIZE + PPU_PALETTE_SIZE;
+ constant PPU_PIPELINE_STAGE_COUNT: natural := 5;
+
+ component ppu_pceg port( -- pipeline clock edge generator
+ CLK: in std_logic; -- system clock
+ R: in std_logic; -- async reset
+ S: out std_logic_vector(PPU_PIPELINE_STAGE_COUNT-1 downto 0)); -- pipeline stages
+ end component;
+ component ppu_addr_dec port( -- pipeline clock edge generator
+ EN: in std_logic; -- ADDR enable (tri-state driver)
+ WEN: in std_logic; -- write enable
+ ADDR: in std_logic_vector(15 downto 0); -- address in
+
+ ADDR_DRV: out std_logic_vector(15 downto 0); -- address out driver
+ TMM_WEN,
+ BAM_WEN,
+ FAM_WEN,
+ PAL_WEN,
+ AUX_WEN: out std_logic);
+
+ end component;
+ component ppu_bam port( -- BAM block memory
+ clka: in std_logic;
+ rsta: in std_logic;
+ wea: in std_logic_vector(0 downto 0);
+ addra: in std_logic_vector(10 downto 0);
+ dina: in std_logic_vector(14 downto 0);
+ douta: out std_logic_vector(14 downto 0);
+ rsta_busy: out std_logic);
+ end component;
+ component ppu_tmm port( -- TMM block memory
+ clka: in std_logic;
+ rsta: in std_logic;
+ wea: in std_logic_vector(0 downto 0);
+ addra: in std_logic_vector(15 downto 0);
+ dina: in std_logic_vector(15 downto 0);
+ douta: out std_logic_vector(15 downto 0);
+ rsta_busy: out std_logic);
+ end component;
+ component ppu_sprite_bg port( -- background sprite
+ -- inputs
+ CLK: in std_logic; -- system clock
+ OE: in std_logic; -- output enable (of CIDX)
+ X: in std_logic_vector(8 downto 0); -- current screen pixel x
+ Y: in std_logic_vector(7 downto 0); -- current screen pixel y
+
+ -- internal memory block (AUX)
+ AUX_WEN: in std_logic; -- VRAM AUX write enable
+ AUX_ADDR: in std_logic_vector(1 downto 0); -- VRAM AUX address
+ AUX_DATA: in std_logic_vector(15 downto 0); -- VRAM AUX data
+
+ -- used memory blocks
+ BAM_ADDR: out std_logic_vector(10 downto 0);
+ BAM_DATA: in std_logic_vector(15 downto 0);
+ TMM_ADDR: out std_logic_vector(15 downto 0);
+ TMM_DATA: in std_logic_vector(15 downto 0);
+
+ -- outputs
+ CIDX: out std_logic_vector(PPU_PALETTE_CIDX_SIZE-1 downto 0)); -- output color
+ end component;
+ component ppu_sprite_fg port( -- foreground sprite
+ -- inputs
+ CLK: in std_logic; -- system clock
+ OE: in std_logic; -- output enable (of CIDX)
+ X: in std_logic_vector(8 downto 0); -- current screen pixel x
+ Y: in std_logic_vector(7 downto 0); -- current screen pixel y
+ FETCH: in std_logic; -- fetch sprite data from TMM (TODO: generic map, set foreground sprite component index)
+
+ -- internal memory block (FAM)
+ FAM_WEN: in std_logic; -- VRAM FAM write enable
+ FAM_ADDR: in std_logic_vector(1 downto 0); -- VRAM fam address
+ FAM_DATA: in std_logic_vector(15 downto 0); -- VRAM fam data
+
+ -- used memory blocks
+ TMM_ADDR: out std_logic_vector(15 downto 0);
+ TMM_DATA: in std_logic_vector(15 downto 0);
+
+ -- outputs
+ CIDX: out std_logic_vector(PPU_PALETTE_CIDX_SIZE-1 downto 0); -- output color
+ HIT: out std_logic); -- current pixel is not transparent
+ end component;
+ component ppu_comp port( -- compositor
+ FG_HIT: in std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0);
+ BG_EN: out std_logic;
+ FG_EN: out std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0));
+ end component;
+ component ppu_plut port( -- palette lookup table
+ CLK: in std_logic; -- system clock
+ CIDX: in std_logic_vector(PPU_PALETTE_CIDX_SIZE-1 downto 0); -- color in
+ RESET: in std_logic;
+
+ -- internal memory block (AUX)
+ PAL_WEN: in std_logic; -- VRAM PAL write enable
+ PAL_ADDR: in std_logic_vector(5 downto 0); -- VRAM PAL address
+ PAL_DATA: in std_logic_vector(11 downto 0); -- VRAM PAL data
+
+ R,G,B: out std_logic_vector(3 downto 0)); -- VGA color out
+ end component;
+ component ppu_vga_tiny port( -- tiny vga signal generator
+ CLK: in std_logic; -- system clock
+ RESET: in std_logic;
+
+ X: out std_logic_vector(8 downto 0); -- current screen pixel x
+ Y: out std_logic_vector(7 downto 0); -- current screen pixel y
+ PREADY: out std_logic; -- current pixel ready (pixel color is stable)
+
+ VSYNC, VBLANK,
+ HSYNC, HBLANK: out std_logic); -- VGA sync outputs
+ end component;
+ component ppu_vga_native port( -- native vga signal generator (upscaler)
+ CLK: in std_logic; -- system clock
+ RESET: in std_logic;
+
+ X: in std_logic_vector(8 downto 0); -- current screen pixel x
+ Y: in std_logic_vector(7 downto 0); -- current screen pixel y
+ PREADY: in std_logic; -- current pixel ready (pixel color is stable)
+ RI,GI,BI: in std_logic_vector(3 downto 0); -- VGA color in
+
+ RO,GO,BO: out std_logic_vector(3 downto 0); -- VGA color out
+ VSYNC, HSYNC: out std_logic); -- VGA sync outputs
+ end component;
+
+ -- signals
+ signal SYSCLK, SYSRST: std_logic; -- system clock and reset
+ signal PL_S: std_logic_vector(PPU_PIPELINE_STAGE_COUNT-1 downto 0); -- pipeline stages
+ signal TMM_WEN, BAM_WEN, FAM_WEN, PAL_WEN, AUX_WEN: std_logic;
+ signal ADDR_BUS: std_logic_vector(15 downto 0);
+ signal CIDX: std_logic_vector(PPU_PALETTE_CIDX_SIZE-1 downto 0);
+ signal BG_EN: std_logic;
+ signal FG_EN, FG_HIT: std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0);
+ signal X: std_logic_vector(8 downto 0); -- current screen pixel x
+ signal Y: std_logic_vector(7 downto 0); -- current screen pixel y
+ signal TR,TG,TB: std_logic_vector(3 downto 0); -- tiny RGB out (to be buffered)
+ signal PREADY: std_logic; -- current pixel color stable
+begin
+ SYSCLK <= CLK100;
+ SYSRST <= RESET;
+
+ pipeline_clock_edge_generator: component ppu_pceg port map(
+ CLK => SYSCLK,
+ R => SYSRST,
+ S => PL_S);
+
+ address_decoder: component ppu_addr_dec port map(
+ EN => EN,
+ WEN => WEN,
+ ADDR => ADDR,
+ ADDR_DRV => ADDR_BUS,
+ TMM_WEN => TMM_WEN,
+ BAM_WEN => BAM_WEN,
+ FAM_WEN => FAM_WEN,
+ PAL_WEN => PAL_WEN,
+ AUX_WEN => AUX_WEN);
+
+ background_attribute_memory: component ppu_bam port map(
+ clka => SYSCLK,
+ rsta => SYSRST,
+ wea => (others => BAM_WEN),
+ addra => ADDR_BUS(10 downto 0),
+ dina => DATA(14 downto 0),
+ douta => open,
+ rsta_busy => open);
+ tilemap_memory: component ppu_tmm port map(
+ clka => SYSCLK,
+ rsta => SYSRST,
+ wea => (others => TMM_WEN),
+ addra => ADDR_BUS(15 downto 0),
+ dina => DATA(15 downto 0),
+ douta => open,
+ rsta_busy => open);
+
+ background_sprite: component ppu_sprite_bg port map(
+ CLK => SYSCLK,
+ OE => BG_EN,
+ X => X,
+ Y => Y,
+ AUX_WEN => AUX_WEN,
+ AUX_ADDR => ADDR_BUS(1 downto 0),
+ AUX_DATA => DATA(15 downto 0),
+ BAM_ADDR => open,
+ BAM_DATA => (others => '0'),
+ TMM_ADDR => open,
+ TMM_DATA => (others => '0'),
+ CIDX => CIDX);
+
+ foreground_sprites: for FG_IDX in 0 to PPU_FG_SPRITE_COUNT-1 generate
+ foreground_sprite: component ppu_sprite_fg port map(
+ CLK => SYSCLK,
+ OE => FG_EN(FG_IDX),
+ X => X,
+ Y => Y,
+ FETCH => '0',
+ FAM_WEN => FAM_WEN,
+ FAM_ADDR => (others => '0'),
+ FAM_DATA => (others => '0'),
+ TMM_ADDR => open,
+ TMM_DATA => (others => '0'),
+ CIDX => CIDX,
+ HIT => FG_HIT(FG_IDX));
+ end generate;
+
+ compositor: component ppu_comp port map( -- compositor
+ FG_HIT => FG_HIT,
+ BG_EN => BG_EN,
+ FG_EN => FG_EN);
+
+ palette_lookup: component ppu_plut port map( -- palette lookup table
+ CLK => SYSCLK,
+ CIDX => CIDX,
+ RESET => SYSRST,
+ PAL_WEN => '0',
+ PAL_ADDR => (others => '0'),
+ PAL_DATA => (others => '0'),
+ R => TR,
+ G => TG,
+ B => TB);
+
+ tiny_vga_signal_generator: component ppu_vga_tiny port map( -- tiny vga signal generator
+ CLK => SYSCLK,
+ RESET => SYSRST,
+ X => X,
+ Y => Y,
+ PREADY => PREADY,
+ VSYNC => TVSYNC,
+ VBLANK => TVBLANK,
+ HSYNC => THSYNC,
+ HBLANK => THBLANK);
+
+ native_vga_signal_generator: component ppu_vga_native port map( -- native vga signal generator (upscaler)
+ CLK => SYSCLK,
+ RESET => SYSRST,
+ X => X,
+ Y => Y,
+ PREADY => PREADY,
+ RI => TR,
+ GI => TG,
+ BI => TB,
+ RO => R,
+ GO => G,
+ BO => B,
+ VSYNC => NVSYNC,
+ HSYNC => NHSYNC);
+end Behavioral;