aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--basys3/basys3.xpr27
4 files changed, 157 insertions, 41 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;
diff --git a/basys3/basys3.xpr b/basys3/basys3.xpr
index a8821cb..a08109b 100644
--- a/basys3/basys3.xpr
+++ b/basys3/basys3.xpr
@@ -59,7 +59,7 @@
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="DSABoardId" Val="basys3"/>
- <Option Name="WTXSimLaunchSim" Val="0"/>
+ <Option Name="WTXSimLaunchSim" Val="2"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
@@ -90,6 +90,12 @@
<FileSets Version="1" Minor="31">
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1" RelGenDir="$PGENDIR/sources_1">
<Filter Type="Srcs"/>
+ <File Path="$PSRCDIR/ppu_pceg.vhdl">
+ <FileInfo>
+ <Attr Name="UsedIn" Val="synthesis"/>
+ <Attr Name="UsedIn" Val="simulation"/>
+ </FileInfo>
+ </File>
<File Path="$PSRCDIR/ppu.vhd">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
@@ -99,7 +105,7 @@
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="ppu"/>
- <Option Name="TopAutoSet" Val="TRUE"/>
+ <Option Name="dataflowViewerSettings" Val="min_width=16"/>
</Config>
</FileSet>
<FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR/constrs_1" RelGenDir="$PGENDIR/constrs_1">
@@ -110,11 +116,16 @@
</FileSet>
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
<Filter Type="Srcs"/>
+ <File Path="$PSRCDIR/ppu_pceg_tb.vhdl">
+ <FileInfo>
+ <Attr Name="UsedIn" Val="synthesis"/>
+ <Attr Name="UsedIn" Val="simulation"/>
+ </FileInfo>
+ </File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
- <Option Name="TopModule" Val="ppu"/>
+ <Option Name="TopModule" Val="ppu_pceg_tb"/>
<Option Name="TopLib" Val="xil_defaultlib"/>
- <Option Name="TopAutoSet" Val="TRUE"/>
<Option Name="TransportPathDelay" Val="0"/>
<Option Name="TransportIntDelay" Val="0"/>
<Option Name="SelectedSimModel" Val="rtl"/>
@@ -201,9 +212,7 @@
</Run>
<Run Id="ppu_tmm_synth_1" Type="Ft3:Synth" SrcSet="ppu_tmm" Part="xc7a35tcpg236-1" ConstrsSet="ppu_tmm" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" Dir="$PRUNDIR/ppu_tmm_synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/ppu_tmm_synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/ppu_tmm_synth_1">
<Strategy Version="1" Minor="2">
- <StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2022">
- <Desc>Vivado Synthesis Defaults</Desc>
- </StratHandle>
+ <StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2022"/>
<Step Id="synth_design"/>
</Strategy>
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
@@ -247,9 +256,7 @@
</Run>
<Run Id="ppu_tmm_impl_1" Type="Ft2:EntireDesign" Part="xc7a35tcpg236-1" ConstrsSet="ppu_tmm" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" SynthRun="ppu_tmm_synth_1" IncludeInArchive="false" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/ppu_tmm_impl_1" AutoRQSDir="$PSRCDIR/utils_1/imports/ppu_tmm_impl_1">
<Strategy Version="1" Minor="2">
- <StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2022">
- <Desc>Default settings for Implementation.</Desc>
- </StratHandle>
+ <StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2022"/>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="power_opt_design"/>