aboutsummaryrefslogtreecommitdiff
path: root/basys3/basys3.srcs
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2023-02-18 15:09:01 +0100
committerlonkaars <loek@pipeframe.xyz>2023-02-18 15:09:01 +0100
commitdb386aab71014ffb37fb24e02c4b8a9194a0b4f9 (patch)
treebf645a27420451f9053055730eb8cd2f82518494 /basys3/basys3.srcs
parent94e6cdf0b1594363c9ec3ac5cd364d3c2e9218fc (diff)
ppu pceg done + ppu top.vhdl done
Diffstat (limited to 'basys3/basys3.srcs')
-rw-r--r--basys3/basys3.srcs/ppu.vhd78
-rw-r--r--basys3/basys3.srcs/ppu_pceg.vhdl46
-rw-r--r--basys3/basys3.srcs/ppu_pceg_tb.vhdl47
3 files changed, 140 insertions, 31 deletions
diff --git a/basys3/basys3.srcs/ppu.vhd b/basys3/basys3.srcs/ppu.vhd
index 59e64c3..efe2125 100644
--- a/basys3/basys3.srcs/ppu.vhd
+++ b/basys3/basys3.srcs/ppu.vhd
@@ -2,17 +2,16 @@ 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
+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
@@ -21,7 +20,6 @@ architecture Behavioral of ppu is
constant PPU_PALETTE_IDX_WIDTH: natural := 3; -- palette index width (within sprite)
constant PPU_PALETTE_WIDTH: natural := 3; -- palette index width (palette table)
constant PPU_PALETTE_CIDX_WIDTH: natural := PPU_PALETTE_IDX_WIDTH + PPU_PALETTE_WIDTH; -- global palette index width
- constant PPU_PIPELINE_STAGE_COUNT: natural := 5; -- amount of pipeline clock edges to generate
constant PPU_TMM_ADDR_WIDTH: natural := 16;
constant PPU_TMM_DATA_WIDTH: natural := 16;
constant PPU_BAM_ADDR_WIDTH: natural := 11;
@@ -37,8 +35,10 @@ architecture Behavioral of ppu is
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
+ 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
end component;
component ppu_addr_dec port( -- pipeline clock edge generator
WEN: in std_logic; -- EXT write enable
@@ -95,6 +95,7 @@ architecture Behavioral of ppu is
component ppu_sprite_bg port( -- background sprite
-- inputs
CLK: in std_logic; -- system clock
+ RESET: in std_logic; -- reset clock counter
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
@@ -115,7 +116,7 @@ architecture Behavioral of ppu is
component ppu_sprite_fg port( -- foreground sprite
-- inputs
CLK: in std_logic; -- system clock
- RESET: in std_logic; -- reset internal memory
+ RESET: in std_logic; -- reset internal memory and 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
@@ -157,7 +158,6 @@ architecture Behavioral of ppu is
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
- PREADY: out std_logic; -- current pixel ready (pixel color is stable)
VSYNC, VBLANK,
HSYNC, HBLANK: out std_logic); -- VGA sync outputs
@@ -177,7 +177,7 @@ architecture Behavioral of ppu is
-- 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 PL_SPRITE, PL_COMP_PAL, PL_DONE: 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);
@@ -194,8 +194,8 @@ architecture Behavioral of ppu is
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 TR,TG,TB: std_logic_vector(PPU_COLOR_OUTPUT_DEPTH-1 downto 0); -- tiny RGB out (to be buffered)
- signal PREADY: std_logic; -- current pixel color stable
+ 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 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;
@@ -205,8 +205,10 @@ begin
pipeline_clock_edge_generator: component ppu_pceg port map(
CLK => SYSCLK,
- R => SYSRST,
- S => PL_S);
+ RESET => SYSRST,
+ SPRITE => PL_SPRITE,
+ COMP_PAL => PL_COMP_PAL,
+ DONE => PL_DONE);
address_decoder: component ppu_addr_dec port map(
EN => EN,
@@ -256,7 +258,8 @@ begin
FG_FETCH => FG_FETCH);
background_sprite: component ppu_sprite_bg port map(
- CLK => SYSCLK,
+ CLK => PL_SPRITE,
+ RESET => SYSRST,
OE => BG_EN,
X => X,
Y => Y,
@@ -270,7 +273,7 @@ begin
foreground_sprites: for FG_IDX in 0 to PPU_FG_SPRITE_COUNT-1 generate
foreground_sprite: component ppu_sprite_fg port map(
- CLK => SYSCLK,
+ CLK => PL_SPRITE,
RESET => SYSRST,
OE => FG_EN(FG_IDX),
X => X,
@@ -297,16 +300,29 @@ begin
PAL_WEN => PAL_WEN,
PAL_ADDR => PAL_AO,
PAL_DATA => DATA(PPU_PAL_DATA_WIDTH-1 downto 0),
- R => TR,
- G => TG,
- B => TB);
+ 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,
- PREADY => PREADY,
VSYNC => TVSYNC,
VBLANK => TVBLANK,
HSYNC => THSYNC,
@@ -317,10 +333,10 @@ begin
RESET => SYSRST,
X => X,
Y => Y,
- PREADY => PREADY,
- RI => TR,
- GI => TG,
- BI => TB,
+ PREADY => PL_DONE,
+ RI => SR,
+ GI => SG,
+ BI => SB,
RO => R,
GO => G,
BO => B,
diff --git a/basys3/basys3.srcs/ppu_pceg.vhdl b/basys3/basys3.srcs/ppu_pceg.vhdl
new file mode 100644
index 0000000..a5b86ae
--- /dev/null
+++ b/basys3/basys3.srcs/ppu_pceg.vhdl
@@ -0,0 +1,46 @@
+library ieee;
+use ieee.std_logic_1164.all;
+--use ieee.numeric_std.all;
+
+entity ppu_pceg is port(
+ 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
+end ppu_pceg;
+
+architecture Behavioral of ppu_pceg is
+ constant PPU_PL_TOTAL_STAGES: natural := 14;
+
+ type states is (PL_SPRITE, PL_COMP_PAL, PL_DONE);
+ signal state: states := PL_SPRITE;
+begin
+ -- output drivers
+ SPRITE <= CLK when state = PL_SPRITE else '0';
+ COMP_PAL <= CLK when state = PL_COMP_PAL else '0';
+ DONE <= '1' when state = PL_DONE else '0';
+
+ process(CLK, RESET)
+ variable CLK_IDX: natural range 0 to PPU_PL_TOTAL_STAGES+1 := 0;
+ begin
+ if RESET = '1' then
+ state <= PL_SPRITE;
+ elsif rising_edge(CLK) then
+ -- clock counter ranges
+ if CLK_IDX < 4 then
+ state <= PL_SPRITE;
+ elsif CLK_IDX < 5 then
+ state <= PL_COMP_PAL;
+ else
+ state <= PL_DONE;
+ end if;
+
+ -- increment clock counter
+ CLK_IDX := CLK_IDX + 1;
+ if CLK_IDX = PPU_PL_TOTAL_STAGES then
+ CLK_IDX := 0;
+ end if;
+ end if;
+ end process;
+end Behavioral;
diff --git a/basys3/basys3.srcs/ppu_pceg_tb.vhdl b/basys3/basys3.srcs/ppu_pceg_tb.vhdl
new file mode 100644
index 0000000..137d4b4
--- /dev/null
+++ b/basys3/basys3.srcs/ppu_pceg_tb.vhdl
@@ -0,0 +1,47 @@
+library ieee;
+library unisim;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use unisim.vcomponents.all;
+
+entity ppu_pceg_tb is
+end ppu_pceg_tb;
+
+architecture behavioral of ppu_pceg_tb is
+ component ppu_pceg port(
+ 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
+ end component;
+ signal CLK: std_logic := '0';
+ signal RESET: std_logic := '0';
+ signal SPRITE: std_logic;
+ signal COMP_PAL: std_logic;
+ signal DONE: std_logic;
+
+begin
+ uut: ppu_pceg port map(
+ CLK => CLK,
+ RESET => RESET,
+ SPRITE => SPRITE,
+ COMP_PAL => COMP_PAL,
+ DONE => DONE);
+
+ tb: process
+ begin
+ for i in 0 to 32 loop
+ if i > 20 then
+ RESET <= '1';
+ end if;
+
+ wait for 5 ns;
+ CLK <= '1';
+ wait for 5 ns;
+ CLK <= '0';
+ end loop;
+ wait; -- stop for simulator
+ end process;
+end;