From 9f38ab7fd66698c43b78b508eebc85730ba114b8 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 29 Mar 2023 17:42:07 +0200 Subject: update pipeline --- assets/ppu-level-2.svg | 2 +- assets/ppu-pipeline.svg | 3 + basys3/basys3.srcs/ppu.vhd | 45 +-- basys3/basys3.srcs/ppu_comp.vhd | 24 +- basys3/basys3.srcs/ppu_consts.vhd | 1 - basys3/basys3.srcs/ppu_dispctl.vhd | 4 +- basys3/basys3.srcs/ppu_pceg.vhd | 60 ++-- basys3/basys3.srcs/ppu_pceg_consts.vhd | 18 ++ basys3/basys3.srcs/ppu_pceg_tb.vhd | 17 +- basys3/basys3.srcs/ppu_sprite_bg.vhd | 46 ++- basys3/basys3.srcs/ppu_sprite_fg.vhd | 31 +- basys3/basys3.xpr | 23 +- basys3/ppu_tb_behav.wcfg | 505 +++++++++++++++++++++++++++++++++ docs/architecture.md | 19 +- docs/ppu.drawio | 2 +- 15 files changed, 669 insertions(+), 131 deletions(-) create mode 100644 assets/ppu-pipeline.svg create mode 100644 basys3/basys3.srcs/ppu_pceg_consts.vhd create mode 100644 basys3/ppu_tb_behav.wcfg diff --git a/assets/ppu-level-2.svg b/assets/ppu-level-2.svg index a7f343f..ea5ca29 100644 --- a/assets/ppu-level-2.svg +++ b/assets/ppu-level-2.svg @@ -1,3 +1,3 @@ -
pipeline stage 1-2
pipeline s...
pipeline stage 5
pipeline s...
pipeline stage 3-4
pipeline s...
sprite info
sprite info
TMM
TMM
Background sprite info
Background sp...
sprite info
sprite info
TMM
TMM
Foreground sprite info
Foreground sp...
global palette index
global palette index
Compositor
Compositor
VGA signal
VGA signal
tiny VGA signal generator
tiny VGA sign...
rgb value
rgb value
PAL
PAL
Palette lookup
Palette lookup
BAM
BAM
AUX
AUX
Sprite render
Sprite render
pixel data
pixel data
FAM
FAM
Sprite render
Sprite render
TMM
TMM
Tilemap memory
Tilemap memory
BAM
BAM
Background attribute memory
Background attribute...
screen position
screen position
PPU RAM bus
PPU RAM bus
PPU RAM bus
PPU RAM bus
native VGA signal generator
native VGA si...
VGA signal
VGA signal
Text is not SVG - cannot display
\ No newline at end of file +
sprite info
sprite info
TMM
TMM
Background sprite info
Background sp...
sprite info
sprite info
TMM
TMM
Foreground sprite info
Foreground sp...
global palette index
global palette index
Compositor
Compositor
VGA signal
VGA signal
tiny VGA signal generator
tiny VGA sign...
rgb value
rgb value
PAL
PAL
Palette lookup
Palette lookup
BAM
BAM
AUX
AUX
Sprite render
Sprite render
pixel data
pixel data
FAM
FAM
Sprite render
Sprite render
TMM
TMM
Tilemap memory
Tilemap memory
BAM
BAM
Background attribute memory
Background attribute...
screen position
screen position
PPU RAM bus
PPU RAM bus
PPU RAM bus
PPU RAM bus
native VGA signal generator
native VGA si...
VGA signal
VGA signal
Text is not SVG - cannot display
\ No newline at end of file diff --git a/assets/ppu-pipeline.svg b/assets/ppu-pipeline.svg new file mode 100644 index 0000000..167ef3b --- /dev/null +++ b/assets/ppu-pipeline.svg @@ -0,0 +1,3 @@ + + +
ppu_sprite_bg
ppu_sprite_bg
0
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
BAM address
BAM address
ppu_sprite_fg
ppu_sprite_fg
TMM address
TMM address
clk
clk
ppu_pceg
ppu_pceg
pixel done
pixel done
TMM data
TMM data
TMM address
TMM address
pixel ready
pixel ready
8
8
9
9
BAM data
BAM data
TMM data
TMM data
idle
idle
input
stability
input...
idle
idle
idle
idle
idle
idle
idle
idle
idle
idle
idle
idle
Text is not SVG - cannot display
\ No newline at end of file diff --git a/basys3/basys3.srcs/ppu.vhd b/basys3/basys3.srcs/ppu.vhd index 0955506..c6864df 100644 --- a/basys3/basys3.srcs/ppu.vhd +++ b/basys3/basys3.srcs/ppu.vhd @@ -3,6 +3,7 @@ library work; use ieee.std_logic_1164.all; use work.ppu_consts.all; +use work.ppu_pceg_consts.all; entity ppu is port( CLK100 : in std_logic; -- system clock @@ -16,12 +17,11 @@ entity ppu is port( end ppu; architecture Behavioral of ppu is - -- TODO: separate SPRITE_BG and SPRITE_FG lines (foreground_sprite only needs 2 clock cycles) - component ppu_pceg port( -- pipeline clock edge generator + component ppu_pceg port( CLK : in std_logic; -- system clock RESET : in std_logic; -- async reset - SPRITE_BG : out std_logic; -- sprite info fetch + sprite pixel fetch - SPRITE_FG : out std_logic; -- sprite pixel fetch + SPRITE_BG : out ppu_sprite_bg_pl_state := PL_BG_IDLE; -- sprite info fetch + sprite pixel fetch + SPRITE_FG : out ppu_sprite_fg_pl_state := PL_FG_IDLE; -- sprite pixel fetch DONE : out std_logic; -- last pipeline stage done READY : out std_logic); -- rgb buffer propagation ready end component; @@ -79,9 +79,9 @@ architecture Behavioral of ppu is end component; component ppu_sprite_bg port( -- background sprite -- inputs - CLK : in std_logic; -- pipeline clock + CLK : in std_logic; -- system clock RESET : in std_logic; -- reset clock counter - PL_RESET : in std_logic; -- reset pipeline clock counters + PL_STAGE : in ppu_sprite_bg_pl_state; -- pipeline stage 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,8 +106,7 @@ 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 + PL_STAGE : in ppu_sprite_fg_pl_state; -- pipeline stage 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 @@ -128,9 +127,10 @@ architecture Behavioral of ppu is 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)); + OE : in std_logic; -- global output enable (screen active) + FG_HIT : in std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0); -- foreground hit array + BG_EN : out std_logic; -- background enable output + FG_EN : out std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0)); -- foreground enable output end component; component ppu_plut port( -- palette lookup table CLK : in std_logic; -- system clock @@ -155,12 +155,15 @@ architecture Behavioral of ppu is RO,GO,BO : out std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- VGA color out NVSYNC, NHSYNC : out std_logic; -- VGA sync out - THBLANK, TVBLANK : out std_logic); -- tiny sync signals + THBLANK, TVBLANK : out std_logic; -- tiny sync signals + ACTIVE : out std_logic); -- screen currently active (currently same for tiny/native, TODO: offset tiny for first scanline) end component; -- signals signal SYSCLK, SYSRST : std_logic; -- system clock and reset - signal PL_SPRITE_FG, PL_SPRITE_BG, PL_DONE, PL_READY : std_logic; -- pipeline stages + signal PL_DONE, PL_READY : std_logic; -- pipeline stages + signal PL_SPRITE_BG : ppu_sprite_bg_pl_state; + signal PL_SPRITE_FG : ppu_sprite_fg_pl_state; signal TMM_WEN, BAM_WEN, FAM_WEN, PAL_WEN, AUX_WEN : std_logic; 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) @@ -179,6 +182,7 @@ architecture Behavioral of ppu is signal BG_SHIFT_Y : std_logic_vector(PPU_POS_V_WIDTH-1 downto 0); signal FG_FETCH : std_logic; signal NVSYNC, NHSYNC, THBLANK, TVBLANK : std_logic; + signal ACTIVE : std_logic; signal PCEG_RESET : std_logic; begin SYSCLK <= CLK100; @@ -187,12 +191,12 @@ begin VSYNC <= NVSYNC; HSYNC <= NHSYNC; - PCEG_RESET <= SYSRST or THBLANK; + PCEG_RESET <= SYSRST or (not ACTIVE); VBLANK <= TVBLANK; pipeline_clock_edge_generator : component ppu_pceg port map( CLK => SYSCLK, - RESET => SYSRST, + RESET => PCEG_RESET, SPRITE_FG => PL_SPRITE_FG, SPRITE_BG => PL_SPRITE_BG, DONE => PL_DONE, @@ -246,9 +250,9 @@ begin FG_FETCH => FG_FETCH); background_sprite : component ppu_sprite_bg port map( - CLK => PL_SPRITE_BG, + CLK => SYSCLK, RESET => SYSRST, - PL_RESET => PL_READY, + PL_STAGE => PL_SPRITE_BG, OE => BG_EN, X => X, Y => Y, @@ -266,8 +270,7 @@ begin port map( CLK => SYSCLK, RESET => SYSRST, - PL_CLK => PL_SPRITE_FG, - PL_RESET => PL_READY, + PL_STAGE => PL_SPRITE_FG, OE => FG_EN(FG_IDX), X => X, Y => Y, @@ -283,6 +286,7 @@ begin end generate; compositor : component ppu_comp port map( -- compositor + OE => ACTIVE, FG_HIT => FG_HIT, BG_EN => BG_EN, FG_EN => FG_EN); @@ -313,5 +317,6 @@ begin NVSYNC => NVSYNC, NHSYNC => NHSYNC, TVBLANK => TVBLANK, - THBLANK => THBLANK); + THBLANK => THBLANK, + ACTIVE => ACTIVE); end Behavioral; diff --git a/basys3/basys3.srcs/ppu_comp.vhd b/basys3/basys3.srcs/ppu_comp.vhd index e79738f..30b161c 100644 --- a/basys3/basys3.srcs/ppu_comp.vhd +++ b/basys3/basys3.srcs/ppu_comp.vhd @@ -2,35 +2,41 @@ library ieee; use ieee.std_logic_1164.all; use work.ppu_consts.all; -entity ppu_comp is port ( - 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)); +entity ppu_comp is port ( + OE : in std_logic; -- global output enable (screen active) + FG_HIT : in std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0); -- foreground hit array + BG_EN : out std_logic; -- background enable output + FG_EN : out std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0)); -- foreground enable output end ppu_comp; architecture Behavioral of ppu_comp is signal FG_HIT_EMPTY : std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0) := (others => '0'); + signal TMP_BG_EN : std_logic; -- background enable output + signal TMP_FG_EN : std_logic_vector(PPU_FG_SPRITE_COUNT-1 downto 0); -- foreground enable output begin + BG_EN <= TMP_BG_EN and OE; + FG_EN <= TMP_FG_EN and OE; + process (FG_HIT) variable HIT : boolean := false; begin -- check if FG_HIT is not empty if FG_HIT /= FG_HIT_EMPTY then - BG_EN <= '0'; + TMP_BG_EN <= '0'; for i in 0 to PPU_FG_SPRITE_COUNT-1 loop -- if FG_HIT is the first one then enable it if(FG_HIT(i) = '1' and HIT = false) then - FG_EN(i) <= '1'; + TMP_FG_EN(i) <= '1'; HIT := true; else -- make rest low - FG_EN(i) <= '0'; + TMP_FG_EN(i) <= '0'; end if; end loop; HIT := false; else - BG_EN <= '1'; - FG_EN <= (others => '0'); + TMP_BG_EN <= '1'; + TMP_FG_EN <= (others => '0'); end if; end process; end Behavioral; diff --git a/basys3/basys3.srcs/ppu_consts.vhd b/basys3/basys3.srcs/ppu_consts.vhd index 4784950..6232667 100644 --- a/basys3/basys3.srcs/ppu_consts.vhd +++ b/basys3/basys3.srcs/ppu_consts.vhd @@ -49,7 +49,6 @@ package ppu_consts is constant PPU_TMM_CACHE_FETCH_A_COUNT : natural := PPU_TMM_CACHE_FETCH_C_COUNT * PPU_FG_SPRITE_COUNT; -- amount of clocks to fetch new TMM cache constant PPU_TMM_CACHE_FETCH_A_WIDTH : natural := ceil_log2(PPU_TMM_CACHE_FETCH_A_COUNT); constant PPU_ACCURATE_FG_SPRITE_COUNT : natural := 16; - constant PPU_PL_TOTAL_STAGES : natural := 14; -- VGA signal timings (https://tomverbeure.github.io/video_timings_calculator) constant PPU_VGA_H_ACTIVE : natural := PPU_NATIVE_SCREEN_WIDTH; constant PPU_VGA_H_PORCH_FRONT : natural := 96; diff --git a/basys3/basys3.srcs/ppu_dispctl.vhd b/basys3/basys3.srcs/ppu_dispctl.vhd index 1d3d922..4f017f3 100644 --- a/basys3/basys3.srcs/ppu_dispctl.vhd +++ b/basys3/basys3.srcs/ppu_dispctl.vhd @@ -15,7 +15,8 @@ entity ppu_dispctl is port( RO,GO,BO : out std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- VGA color out NVSYNC, NHSYNC : out std_logic; -- VGA sync out - THBLANK, TVBLANK : out std_logic); -- tiny sync signals + THBLANK, TVBLANK : out std_logic; -- tiny sync signals + ACTIVE : out std_logic); -- screen currently active (currently same for tiny/native, TODO: offset tiny for first scanline) end ppu_dispctl; architecture Behavioral of ppu_dispctl is @@ -145,6 +146,7 @@ begin if TMP_NHCOUNT = PPU_VGA_H_PORCH_BACK + PPU_VGA_H_ACTIVE + PPU_VGA_H_SYNC then TMP_NHSYNC := '0'; end if; end if; end process; + ACTIVE <= NACTIVE; scanline_buffer : component ppu_dispctl_slbuf port map( clka => SYSCLK, diff --git a/basys3/basys3.srcs/ppu_pceg.vhd b/basys3/basys3.srcs/ppu_pceg.vhd index d53d86a..3de3d23 100644 --- a/basys3/basys3.srcs/ppu_pceg.vhd +++ b/basys3/basys3.srcs/ppu_pceg.vhd @@ -1,46 +1,66 @@ library ieee; use ieee.std_logic_1164.all; use work.ppu_consts.all; +use work.ppu_pceg_consts.all; entity ppu_pceg is port( CLK : in std_logic; -- system clock RESET : in std_logic; -- async reset - SPRITE_BG : out std_logic; -- sprite info fetch + sprite pixel fetch - SPRITE_FG : out std_logic; -- sprite pixel fetch + SPRITE_BG : out ppu_sprite_bg_pl_state := PL_BG_IDLE; -- sprite info fetch + sprite pixel fetch + SPRITE_FG : out ppu_sprite_fg_pl_state := PL_FG_IDLE; -- sprite pixel fetch DONE : out std_logic; -- last pipeline stage done READY : out std_logic); -- rgb buffer propagation ready end ppu_pceg; architecture Behavioral of ppu_pceg is - signal PL_SPRITE_BG, PL_SPRITE_FG, PL_DONE, PL_READY : boolean := false; begin - -- output drivers - SPRITE_BG <= CLK when RESET = '0' and PL_SPRITE_BG else '0'; - SPRITE_FG <= CLK when RESET = '0' and PL_SPRITE_FG else '0'; - DONE <= CLK when RESET = '0' and PL_DONE else '0'; - READY <= '1' when RESET = '0' and PL_READY else '0'; - process(CLK, RESET) - variable CLK_IDX : natural range 0 to PPU_PL_TOTAL_STAGES+1 := 0; + variable CLK_IDX : natural range 0 to PPU_PCEG_TOTAL_STAGES+1 := 0; begin if RESET = '1' then CLK_IDX := 0; - PL_SPRITE_BG <= false; - PL_SPRITE_FG <= false; - PL_DONE <= false; - PL_READY <= false; + + SPRITE_BG <= PL_BG_IDLE; + SPRITE_FG <= PL_FG_IDLE; + DONE <= '0'; + READY <= '0'; elsif rising_edge(CLK) then - -- clock counter ranges - PL_SPRITE_BG <= true when CLK_IDX >= 0 and CLK_IDX <= 3 else false; - PL_SPRITE_FG <= true when CLK_IDX >= 1 and CLK_IDX <= 2 else false; - PL_DONE <= true when CLK_IDX = 4 else false; - PL_READY <= true when CLK_IDX >= 5 else false; + case CLK_IDX is + when 0 => + DONE <= '0'; + READY <= '0'; + SPRITE_BG <= PL_BG_IDLE; + SPRITE_FG <= PL_FG_IDLE; + when 1 => + SPRITE_BG <= PL_BG_BAM_ADDR; + SPRITE_FG <= PL_FG_TMM_ADDR; + when 3 => + SPRITE_BG <= PL_BG_IDLE; + SPRITE_FG <= PL_FG_IDLE; + when 4 => + SPRITE_BG <= PL_BG_BAM_DATA; + SPRITE_FG <= PL_FG_TMM_DATA; + when 5 => + SPRITE_BG <= PL_BG_TMM_ADDR; + SPRITE_FG <= PL_FG_IDLE; + when 6 => null; + when 7 => + SPRITE_BG <= PL_BG_IDLE; + when 8 => + DONE <= '1'; + SPRITE_BG <= PL_BG_TMM_DATA; + when 9 => + SPRITE_BG <= PL_BG_IDLE; + READY <= '1'; + when others => null; + end case; -- increment clock counter CLK_IDX := CLK_IDX + 1; - if CLK_IDX = PPU_PL_TOTAL_STAGES then + if CLK_IDX = PPU_PCEG_TOTAL_STAGES then CLK_IDX := 0; end if; end if; end process; end Behavioral; + diff --git a/basys3/basys3.srcs/ppu_pceg_consts.vhd b/basys3/basys3.srcs/ppu_pceg_consts.vhd new file mode 100644 index 0000000..eac4d23 --- /dev/null +++ b/basys3/basys3.srcs/ppu_pceg_consts.vhd @@ -0,0 +1,18 @@ +library ieee; +use ieee.std_logic_1164.all; +use work.ppu_consts.all; + +package ppu_pceg_consts is + constant PPU_PCEG_TOTAL_STAGES : natural := 16; + type ppu_sprite_bg_pl_state is ( + PL_BG_IDLE, + PL_BG_BAM_ADDR, + PL_BG_BAM_DATA, + PL_BG_TMM_ADDR, + PL_BG_TMM_DATA); + type ppu_sprite_fg_pl_state is ( + PL_FG_IDLE, + PL_FG_TMM_ADDR, + PL_FG_TMM_DATA); +end package ppu_pceg_consts; + diff --git a/basys3/basys3.srcs/ppu_pceg_tb.vhd b/basys3/basys3.srcs/ppu_pceg_tb.vhd index 1c2c855..adc437a 100644 --- a/basys3/basys3.srcs/ppu_pceg_tb.vhd +++ b/basys3/basys3.srcs/ppu_pceg_tb.vhd @@ -4,6 +4,7 @@ library unisim; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use unisim.vcomponents.all; +use work.ppu_pceg_consts.all; entity ppu_pceg_tb is end ppu_pceg_tb; @@ -12,26 +13,22 @@ architecture behavioral of ppu_pceg_tb is component ppu_pceg port( CLK : in std_logic; -- system clock RESET : in std_logic; -- async reset - SPRITE_BG : out std_logic; -- sprite info fetch + sprite pixel fetch - SPRITE_FG : out std_logic; -- sprite pixel fetch + SPRITE_BG : out ppu_sprite_bg_pl_state := PL_BG_IDLE; -- sprite info fetch + sprite pixel fetch + SPRITE_FG : out ppu_sprite_fg_pl_state := PL_FG_IDLE; -- sprite pixel fetch DONE : out std_logic; -- last pipeline stage done READY : out std_logic); -- rgb buffer propagation ready end component; signal CLK : std_logic := '0'; signal RESET : std_logic := '0'; - signal SPRITE_BG : std_logic; - signal SPRITE_FG : std_logic; - signal DONE : std_logic; - signal READY : std_logic; begin uut : ppu_pceg port map( CLK => CLK, RESET => RESET, - SPRITE_BG => SPRITE_BG, - SPRITE_FG => SPRITE_FG, - DONE => DONE, - READY => READY); + SPRITE_BG => open, + SPRITE_FG => open, + DONE => open, + READY => open); tb : process begin diff --git a/basys3/basys3.srcs/ppu_sprite_bg.vhd b/basys3/basys3.srcs/ppu_sprite_bg.vhd index 417210c..1a91b5e 100644 --- a/basys3/basys3.srcs/ppu_sprite_bg.vhd +++ b/basys3/basys3.srcs/ppu_sprite_bg.vhd @@ -5,13 +5,14 @@ use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use work.ppu_consts.all; +use work.ppu_pceg_consts.all; -- TODO: add input stable / output stable pipeline stages if this doesn't work with propagation delays entity ppu_sprite_bg is port( -- inputs - CLK : in std_logic; -- pipeline clock + CLK : in std_logic; -- system clock RESET : in std_logic; -- reset clock counter - PL_RESET : in std_logic; -- reset pipeline clock counters + PL_STAGE : in ppu_sprite_bg_pl_state; -- pipeline stage 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 @@ -45,10 +46,6 @@ architecture Behavioral of ppu_sprite_bg is signal T_TMM_ADDR, R_TMM_ADDR : std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0) := (others => '0'); signal T_TMM_DATA, R_TMM_DATA : std_logic_vector(PPU_TMM_DATA_WIDTH-1 downto 0) := (others => '0'); - -- state machine for synchronizing pipeline stages - type states is (PL_BAM_ADDR, PL_BAM_DATA, PL_TMM_ADDR, PL_TMM_DATA); - signal state : states := PL_BAM_ADDR; - -- docs/architecture.md#background-attribute-memory alias BAM_DATA_FLIP_H is R_BAM_DATA(14); -- flip horizontally alias BAM_DATA_FLIP_V is R_BAM_DATA(13); -- flip vertically @@ -68,8 +65,8 @@ architecture Behavioral of ppu_sprite_bg is begin -- output drivers CIDX <= T_CIDX when OE = '1' else (others => 'Z'); - BAM_ADDR <= R_BAM_ADDR when state = PL_BAM_ADDR else (others => 'Z'); - TMM_ADDR <= R_TMM_ADDR when state = PL_TMM_ADDR else (others => 'Z'); + BAM_ADDR <= R_BAM_ADDR when PL_STAGE = PL_BG_BAM_ADDR else (others => 'Z'); + TMM_ADDR <= R_TMM_ADDR when PL_STAGE = PL_BG_TMM_ADDR else (others => 'Z'); T_BAM_DATA <= BAM_DATA; T_TMM_DATA <= TMM_DATA; -- CIDX combination @@ -109,32 +106,25 @@ begin (others => '0') when others; -- state machine (pipeline stage counter) + sync r/w - process(CLK, RESET, PL_RESET) + process(CLK, RESET) begin - if RESET = '1' or PL_RESET = '1' then - -- reset state - state <= PL_BAM_ADDR; - if RESET = '1' then - -- reset internal pipeline registers - R_BAM_ADDR <= (others => '0'); - R_BAM_DATA <= (others => '0'); - R_TMM_ADDR <= (others => '0'); - R_TMM_DATA <= (others => '0'); - end if; + if RESET = '1' then + -- reset internal pipeline registers + R_BAM_ADDR <= (others => '0'); + R_BAM_DATA <= (others => '0'); + R_TMM_ADDR <= (others => '0'); + R_TMM_DATA <= (others => '0'); elsif rising_edge(CLK) then - case state is - when PL_BAM_ADDR => - state <= PL_BAM_DATA; + case PL_STAGE is + when PL_BG_BAM_ADDR => R_BAM_ADDR <= T_BAM_ADDR; - when PL_BAM_DATA => - state <= PL_TMM_ADDR; + when PL_BG_BAM_DATA => R_BAM_DATA <= T_BAM_DATA; - when PL_TMM_ADDR => - state <= PL_TMM_DATA; + when PL_BG_TMM_ADDR => R_TMM_ADDR <= T_TMM_ADDR; - when PL_TMM_DATA => - state <= PL_BAM_ADDR; + when PL_BG_TMM_DATA => R_TMM_DATA <= T_TMM_DATA; + when others => null; end case; end if; end process; diff --git a/basys3/basys3.srcs/ppu_sprite_fg.vhd b/basys3/basys3.srcs/ppu_sprite_fg.vhd index 3b4d2c6..89e6e66 100644 --- a/basys3/basys3.srcs/ppu_sprite_fg.vhd +++ b/basys3/basys3.srcs/ppu_sprite_fg.vhd @@ -5,6 +5,7 @@ use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use work.ppu_consts.all; +use work.ppu_pceg_consts.all; -- TODO: add input stable / output stable pipeline stages if this doesn't work with propagation delays entity ppu_sprite_fg is -- foreground sprite @@ -14,8 +15,7 @@ entity ppu_sprite_fg is -- foreground sprite -- 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 + PL_STAGE : in ppu_sprite_fg_pl_state; -- pipeline stage 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 @@ -135,12 +135,10 @@ begin inaccurate_occlusion_shims: if IDX >= PPU_ACCURATE_FG_SPRITE_COUNT generate -- state machine for synchronizing pipeline stages - type states is (PL_TMM_ADDR, PL_TMM_DATA); - signal state : states := PL_TMM_ADDR; begin HIT <= SPRITE_ACTIVE; -- only fetch if OE is high, and during the second pipeline stage - TMM_ADDR <= R_TMM_ADDR when OE = '1' and state = PL_TMM_ADDR else (others => 'Z'); + TMM_ADDR <= R_TMM_ADDR when OE = '1' and PL_STAGE = PL_FG_TMM_ADDR else (others => 'Z'); T_TMM_ADDR <= std_logic_vector(TILEMAP_WORD + to_unsigned(TILEMAP_WORD_OFFSET, PPU_TMM_ADDR_WIDTH)); -- TMM address -- TMM DATA @@ -152,24 +150,19 @@ begin R_TMM_DATA(14 downto 12) when 4, (others => '0') when others; - process(PL_CLK, RESET, PL_RESET) + process(CLK, RESET) begin - if RESET = '1' or PL_RESET = '1' then - -- reset state - state <= PL_TMM_ADDR; - if RESET = '1' then - -- reset internal pipeline registers - R_TMM_ADDR <= (others => '0'); - R_TMM_DATA <= (others => '0'); - end if; + if RESET = '1' then + -- reset internal pipeline registers + R_TMM_ADDR <= (others => '0'); + R_TMM_DATA <= (others => '0'); elsif rising_edge(CLK) then - case state is - when PL_TMM_ADDR => - state <= PL_TMM_DATA; + case PL_STAGE is + when PL_FG_TMM_ADDR => R_TMM_ADDR <= T_TMM_ADDR; - when PL_TMM_DATA => - state <= PL_TMM_ADDR; + when PL_FG_TMM_DATA => R_TMM_DATA <= T_TMM_DATA; + when others => null; end case; end if; end process; diff --git a/basys3/basys3.xpr b/basys3/basys3.xpr index acb43b0..b4e930e 100644 --- a/basys3/basys3.xpr +++ b/basys3/basys3.xpr @@ -60,7 +60,7 @@