diff options
Diffstat (limited to 'basys3/basys3.srcs/ppu.vhd')
-rw-r--r-- | basys3/basys3.srcs/ppu.vhd | 235 |
1 files changed, 99 insertions, 136 deletions
diff --git a/basys3/basys3.srcs/ppu.vhd b/basys3/basys3.srcs/ppu.vhd index d6407df..0955506 100644 --- a/basys3/basys3.srcs/ppu.vhd +++ b/basys3/basys3.srcs/ppu.vhd @@ -2,19 +2,17 @@ library ieee; library work; use ieee.std_logic_1164.all; ---use ieee.numeric_std.all; use work.ppu_consts.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(PPU_RAM_BUS_ADDR_WIDTH-1 downto 0); -- PPU VRAM ADDR DATA : in std_logic_vector(PPU_RAM_BUS_DATA_WIDTH-1 downto 0); R,G,B : out std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); - NVSYNC, NHSYNC : out std_logic; -- native VGA out - TVBLANK, THBLANK : out std_logic); -- tiny VGA out + VSYNC, HSYNC : out std_logic; -- VGA sync out + VBLANK : out std_logic); -- vblank for synchronization end ppu; architecture Behavioral of ppu is @@ -22,47 +20,48 @@ architecture Behavioral of ppu is component ppu_pceg port( -- pipeline clock edge generator CLK : in std_logic; -- system clock RESET : in std_logic; -- async reset - SPRITE : out std_logic; -- sprite info fetch + sprite pixel fetch - COMP_PAL : out std_logic; -- compositor + palette lookup - DONE : out std_logic); -- last pipeline stage done + SPRITE_BG : out std_logic; -- sprite info fetch + sprite pixel fetch + SPRITE_FG : out std_logic; -- sprite pixel fetch + DONE : out std_logic; -- last pipeline stage done + READY : out std_logic); -- rgb buffer propagation ready end component; - component ppu_addr_dec port( -- pipeline clock edge generator + component ppu_addr_dec port( -- address decoder WEN : in std_logic; -- EXT write enable TMM_WEN, BAM_WEN, FAM_WEN, PAL_WEN, AUX_WEN : out std_logic; -- write enable MUX - EN : in std_logic; -- EXT *ADDR enable (switch *AO to ADDR instead of *AI) ADDR : in std_logic_vector(PPU_RAM_BUS_ADDR_WIDTH-1 downto 0); -- address in - TMM_AI : in std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); - BAM_AI : in std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); - FAM_AI : in std_logic_vector(PPU_FAM_ADDR_WIDTH-1 downto 0); - PAL_AI : in std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); - AUX_AI : in std_logic_vector(PPU_AUX_ADDR_WIDTH-1 downto 0); - TMM_AO : out std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); - BAM_AO : out std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); - FAM_AO : out std_logic_vector(PPU_FAM_ADDR_WIDTH-1 downto 0); - PAL_AO : out std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); - AUX_AO : out std_logic_vector(PPU_AUX_ADDR_WIDTH-1 downto 0)); + TMM_ADDR : out std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); + BAM_ADDR : out std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); + FAM_ADDR : out std_logic_vector(PPU_FAM_ADDR_WIDTH-1 downto 0); + PAL_ADDR : out std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); + AUX_ADDR : out std_logic_vector(PPU_AUX_ADDR_WIDTH-1 downto 0)); 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); + wea : in std_logic_vector(0 to 0); addra : in std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); dina : in std_logic_vector(PPU_BAM_DATA_WIDTH-1 downto 0); - douta : out std_logic_vector(PPU_BAM_DATA_WIDTH-1 downto 0); - rsta_busy : out std_logic); + clkb : in std_logic; + rstb : in std_logic; + addrb : in std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); + doutb : out std_logic_vector(PPU_BAM_DATA_WIDTH-1 downto 0); + rsta_busy : out std_logic; + rstb_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); + wea : in std_logic_vector(0 to 0); addra : in std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); dina : in std_logic_vector(PPU_TMM_DATA_WIDTH-1 downto 0); - douta : out std_logic_vector(PPU_TMM_DATA_WIDTH-1 downto 0); - rsta_busy : out std_logic); + clkb : in std_logic; + rstb : in std_logic; + addrb : in std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); + doutb : out std_logic_vector(PPU_TMM_DATA_WIDTH-1 downto 0); + rsta_busy : out std_logic; + rstb_busy : out std_logic); end component; component ppu_aux port( CLK : in std_logic; -- system clock @@ -82,6 +81,7 @@ architecture Behavioral of ppu is -- inputs CLK : in std_logic; -- pipeline clock RESET : in std_logic; -- reset clock counter + PL_RESET : in std_logic; -- reset pipeline clock counters OE : in std_logic; -- output enable (of CIDX) X : in std_logic_vector(PPU_POS_H_WIDTH-1 downto 0); -- current screen pixel x Y : in std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- current screen pixel y @@ -106,6 +106,8 @@ architecture Behavioral of ppu is -- inputs CLK : in std_logic; -- system clock RESET : in std_logic; -- reset internal memory and clock counters + PL_CLK : in std_logic; -- pipeline clock + PL_RESET : in std_logic; -- reset pipeline clock counters OE : in std_logic; -- output enable (of CIDX) X : in std_logic_vector(PPU_POS_H_WIDTH-1 downto 0); -- current screen pixel x Y : in std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- current screen pixel y @@ -142,94 +144,68 @@ architecture Behavioral of ppu is R,G,B : out std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 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(PPU_POS_H_WIDTH-1 downto 0); -- current screen pixel x - Y : out std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- current screen pixel y - - 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 + component ppu_dispctl port( + SYSCLK : in std_logic; -- system clock RESET : in std_logic; - X : in std_logic_vector(PPU_POS_H_WIDTH-1 downto 0); -- current screen pixel x - Y : in std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- current screen pixel y + X : out std_logic_vector(PPU_POS_H_WIDTH-1 downto 0); -- tiny screen pixel x + Y : out std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- tiny screen pixel y + RI,GI,BI : in std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- color in PREADY : in std_logic; -- current pixel ready (pixel color is stable) - RI,GI,BI : in std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- VGA color in - + RO,GO,BO : out std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- VGA color out - VSYNC, HSYNC : out std_logic); -- VGA sync outputs + NVSYNC, NHSYNC : out std_logic; -- VGA sync out + THBLANK, TVBLANK : out std_logic); -- tiny sync signals end component; -- signals signal SYSCLK, SYSRST : std_logic; -- system clock and reset - signal PL_SPRITE, PL_COMP_PAL, PL_DONE : std_logic; -- pipeline stages + signal PL_SPRITE_FG, PL_SPRITE_BG, PL_DONE, PL_READY : std_logic; -- pipeline stages signal TMM_WEN, BAM_WEN, FAM_WEN, PAL_WEN, AUX_WEN : std_logic; - signal TMM_AI, TMM_AO : std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); - signal BAM_AI, BAM_AO : std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); - signal FAM_AI, FAM_AO : std_logic_vector(PPU_FAM_ADDR_WIDTH-1 downto 0); - signal PAL_AI, PAL_AO : std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); - signal AUX_AI, AUX_AO : std_logic_vector(PPU_AUX_ADDR_WIDTH-1 downto 0); - signal TMM_DO : std_logic_vector(PPU_TMM_DATA_WIDTH-1 downto 0); - signal BAM_DO : std_logic_vector(PPU_BAM_DATA_WIDTH-1 downto 0); - signal FAM_DO : std_logic_vector(PPU_FAM_DATA_WIDTH-1 downto 0); - signal PAL_DO : std_logic_vector(PPU_PAL_DATA_WIDTH-1 downto 0); - signal AUX_DO : std_logic_vector(PPU_AUX_DATA_WIDTH-1 downto 0); + signal TMM_W_ADDR, TMM_R_ADDR : std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); -- read/write TMM addr (dual port) + signal BAM_W_ADDR, BAM_R_ADDR : std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); -- read/write BAM addr (dual port) + signal TMM_R_DATA : std_logic_vector(PPU_TMM_DATA_WIDTH-1 downto 0); -- internal read TMM data + signal BAM_R_DATA : std_logic_vector(PPU_BAM_DATA_WIDTH-1 downto 0); -- internal read BAM data + signal FAM_W_ADDR : std_logic_vector(PPU_FAM_ADDR_WIDTH-1 downto 0); -- write only FAM addr + signal PAL_W_ADDR : std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); -- write only PAL addr + signal AUX_W_ADDR : std_logic_vector(PPU_AUX_ADDR_WIDTH-1 downto 0); -- write only AUX addr signal CIDX : std_logic_vector(PPU_PALETTE_CIDX_WIDTH-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(PPU_POS_H_WIDTH-1 downto 0); -- current screen pixel x signal Y : std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); -- current screen pixel y - signal UR,UG,UB : std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- unstable RGB (to be buffered) - signal SR,SG,SB : std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- stable RGB (buffered until PL_COMP_PAL) + signal UR,UG,UB : std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- palette lookup output RGB signal BG_SHIFT_X : std_logic_vector(PPU_POS_H_WIDTH-1 downto 0); signal BG_SHIFT_Y : std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); signal FG_FETCH : std_logic; - signal TINY_VBLANK, TINY_HBLANK, - NATIVE_VSYNC, NATIVE_HSYNC : std_logic; + signal NVSYNC, NHSYNC, THBLANK, TVBLANK : std_logic; + signal PCEG_RESET : std_logic; begin SYSCLK <= CLK100; SYSRST <= RESET; - -- internal unused lines - -- - -- these lines would be used if components use memory blocks as RAM blocks - -- (like how TMM and BAM work), the registers of these memory regions are - -- directly exposed internally, and are as such not used as RAM blocks - AUX_AI <= (others => '0'); - FAM_AI <= (others => '0'); - PAL_AI <= (others => '0'); + VSYNC <= NVSYNC; + HSYNC <= NHSYNC; - TVBLANK <= TINY_VBLANK; - THBLANK <= TINY_HBLANK; - NVSYNC <= NATIVE_VSYNC; - NHSYNC <= NATIVE_HSYNC; + PCEG_RESET <= SYSRST or THBLANK; + VBLANK <= TVBLANK; pipeline_clock_edge_generator : component ppu_pceg port map( CLK => SYSCLK, RESET => SYSRST, - SPRITE => PL_SPRITE, - COMP_PAL => PL_COMP_PAL, - DONE => PL_DONE); + SPRITE_FG => PL_SPRITE_FG, + SPRITE_BG => PL_SPRITE_BG, + DONE => PL_DONE, + READY => PL_READY); address_decoder : component ppu_addr_dec port map( - EN => EN, WEN => WEN, ADDR => ADDR, - TMM_AI => TMM_AI, - BAM_AI => BAM_AI, - FAM_AI => FAM_AI, - PAL_AI => PAL_AI, - AUX_AI => AUX_AI, - TMM_AO => TMM_AO, - BAM_AO => BAM_AO, - FAM_AO => FAM_AO, - PAL_AO => PAL_AO, - AUX_AO => AUX_AO, + TMM_ADDR => TMM_W_ADDR, + BAM_ADDR => BAM_W_ADDR, + FAM_ADDR => FAM_W_ADDR, + PAL_ADDR => PAL_W_ADDR, + AUX_ADDR => AUX_W_ADDR, TMM_WEN => TMM_WEN, BAM_WEN => BAM_WEN, FAM_WEN => FAM_WEN, @@ -238,43 +214,50 @@ begin background_attribute_memory : component ppu_bam port map( clka => SYSCLK, - rsta => SYSRST, wea => (others => BAM_WEN), - addra => BAM_AO, + addra => BAM_W_ADDR, dina => DATA(PPU_BAM_DATA_WIDTH-1 downto 0), - douta => BAM_DO, - rsta_busy => open); + clkb => SYSCLK, + rstb => SYSRST, + addrb => BAM_R_ADDR, + doutb => BAM_R_DATA, + rsta_busy => open, + rstb_busy => open); tilemap_memory : component ppu_tmm port map( clka => SYSCLK, - rsta => SYSRST, wea => (others => TMM_WEN), - addra => TMM_AO, + addra => TMM_W_ADDR, dina => DATA(PPU_TMM_DATA_WIDTH-1 downto 0), - douta => TMM_DO, - rsta_busy => open); + clkb => SYSCLK, + rstb => SYSRST, + addrb => TMM_R_ADDR, + doutb => TMM_R_DATA, + rsta_busy => open, + rstb_busy => open); aux : component ppu_aux port map( CLK => SYSCLK, RESET => SYSRST, AUX_WEN => AUX_WEN, - AUX_ADDR => AUX_AO, + AUX_ADDR => AUX_W_ADDR, AUX_DATA => DATA(PPU_AUX_DATA_WIDTH-1 downto 0), BG_SHIFT_X => BG_SHIFT_X, BG_SHIFT_Y => BG_SHIFT_Y, FG_FETCH => FG_FETCH); background_sprite : component ppu_sprite_bg port map( - CLK => PL_SPRITE, + CLK => PL_SPRITE_BG, RESET => SYSRST, + PL_RESET => PL_READY, OE => BG_EN, X => X, Y => Y, BG_SHIFT_X => BG_SHIFT_X, BG_SHIFT_Y => BG_SHIFT_Y, - BAM_ADDR => BAM_AI, - BAM_DATA => BAM_DO, - TMM_ADDR => TMM_AI, - TMM_DATA => TMM_DO, + BAM_ADDR => BAM_R_ADDR, + BAM_DATA => BAM_R_DATA, + TMM_ADDR => TMM_R_ADDR, + TMM_DATA => TMM_R_DATA, CIDX => CIDX); foreground_sprites : for FG_IDX in 0 to PPU_FG_SPRITE_COUNT-1 generate @@ -283,16 +266,18 @@ begin port map( CLK => SYSCLK, RESET => SYSRST, + PL_CLK => PL_SPRITE_FG, + PL_RESET => PL_READY, OE => FG_EN(FG_IDX), X => X, Y => Y, FETCH => FG_FETCH, - VBLANK => TINY_VBLANK, + VBLANK => TVBLANK, FAM_WEN => FAM_WEN, - FAM_ADDR => FAM_AO, + FAM_ADDR => FAM_W_ADDR, FAM_DATA => DATA(PPU_FAM_DATA_WIDTH-1 downto 0), - TMM_ADDR => TMM_AI, - TMM_DATA => TMM_DO, + TMM_ADDR => TMM_R_ADDR, + TMM_DATA => TMM_R_DATA, CIDX => CIDX, HIT => FG_HIT(FG_IDX)); end generate; @@ -307,48 +292,26 @@ begin CIDX => CIDX, RESET => SYSRST, PAL_WEN => PAL_WEN, - PAL_ADDR => PAL_AO, + PAL_ADDR => PAL_W_ADDR, PAL_DATA => DATA(PPU_PAL_DATA_WIDTH-1 downto 0), R => UR, G => UG, B => UB); - -- palette lookup output buffer (pipeline stage 5) - process(PL_COMP_PAL, SYSRST) - begin - if SYSRST = '1' then - SR <= x"0"; - SG <= x"0"; - SB <= x"0"; - elsif rising_edge(PL_COMP_PAL) then - SR <= UR; - SG <= UG; - SB <= UB; - end if; - end process; - - tiny_vga_signal_generator : component ppu_vga_tiny port map( -- tiny vga signal generator - CLK => SYSCLK, - RESET => SYSRST, - X => X, - Y => Y, - VSYNC => open, - VBLANK => TINY_VBLANK, - HSYNC => open, - HBLANK => TINY_HBLANK); - - native_vga_signal_generator : component ppu_vga_native port map( -- native vga signal generator (upscaler) - CLK => SYSCLK, + display_controller : component ppu_dispctl port map( + SYSCLK => SYSCLK, RESET => SYSRST, + PREADY => PL_READY, X => X, Y => Y, - PREADY => PL_DONE, - RI => SR, - GI => SG, - BI => SB, + RI => UR, + GI => UG, + BI => UB, RO => R, GO => G, BO => B, - VSYNC => NATIVE_VSYNC, - HSYNC => NATIVE_HSYNC); + NVSYNC => NVSYNC, + NHSYNC => NHSYNC, + TVBLANK => TVBLANK, + THBLANK => THBLANK); end Behavioral; |