diff options
| -rw-r--r-- | basys3/basys3.srcs/apu.vhd | 46 | ||||
| -rw-r--r-- | basys3/basys3.srcs/apu_note_to_frequency.vhd | 22 | ||||
| -rw-r--r-- | basys3/basys3.srcs/apu_note_to_frequency_tb.vhd | 33 | ||||
| -rw-r--r-- | basys3/basys3.srcs/apu_tb_note_to_frequency.vhd | 40 | ||||
| -rw-r--r-- | basys3/basys3.srcs/ppu.vhd | 40 | ||||
| -rw-r--r-- | basys3/basys3.srcs/ppu_addr_dec.vhdl | 51 | ||||
| -rw-r--r-- | basys3/basys3.srcs/ppu_addr_dec_tb.vhdl | 86 | ||||
| -rw-r--r-- | basys3/basys3.srcs/ppu_consts.vhd | 22 | ||||
| -rw-r--r-- | basys3/basys3.xpr | 47 | ||||
| -rw-r--r-- | docs/abbreviations.md | 20 | ||||
| -rw-r--r-- | docs/architecture.md | 85 | ||||
| -rw-r--r-- | docs/gen/doc.m4 | 4 | ||||
| -rw-r--r-- | docs/makefile | 8 | ||||
| -rw-r--r-- | style.md | 2 | 
14 files changed, 380 insertions, 126 deletions
| diff --git a/basys3/basys3.srcs/apu.vhd b/basys3/basys3.srcs/apu.vhd index ea2a342..4a594ab 100644 --- a/basys3/basys3.srcs/apu.vhd +++ b/basys3/basys3.srcs/apu.vhd @@ -2,35 +2,31 @@ library ieee;  use ieee.std_logic_1164.all;  --use ieee.numeric_std.all; -entity apu is -	port( -		CLK100: in std_logic; -- system clock -		RESET: in std_logic; -- global (async) system reset -		DATA: in std_logic_vector(15 downto 0); -        SOUND: out std_logic); +entity apu is port( +	CLK100: in std_logic; -- system clock +	RESET: in std_logic; -- global (async) system reset +	DATA: in std_logic_vector(15 downto 0); +	SOUND: out std_logic); -		-- 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 -		-- 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 +	-- 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 +	-- 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 apu;  architecture Behavioral of apu is - -	component apu_note_to_frequency port ( -			data : in std_logic_vector(7 downto 0); -			freq : out std_logic_vector(7 downto 0) --frequency -		); +	component apu_note_to_frequency port( +		data: in std_logic_vector(7 downto 0); +		freq: out std_logic_vector(7 downto 0)); --frequency  	end component; -	component apu_LUT_reader port ( -			clk   : in std_logic; -			rst : in std_logic; -			wave : in std_logic_vector(1 downto 0); -			level : out std_logic_vector(7 downto 0) -		); +	component apu_LUT_reader port( +		clk: in std_logic; +		rst: in std_logic; +		wave: in std_logic_vector(1 downto 0); +		level: out std_logic_vector(7 downto 0));  	end component; -  begin -end architecture;
\ No newline at end of file + +end architecture; diff --git a/basys3/basys3.srcs/apu_note_to_frequency.vhd b/basys3/basys3.srcs/apu_note_to_frequency.vhd index b8f561b..8a7b3d6 100644 --- a/basys3/basys3.srcs/apu_note_to_frequency.vhd +++ b/basys3/basys3.srcs/apu_note_to_frequency.vhd @@ -2,19 +2,17 @@ library ieee;  use ieee.std_logic_1164.all;  use ieee.numeric_std.all; -entity apu_note_to_frequency is -    port ( -        -- clk : in std_logic; -        -- rst : in std_logic; -        data : in std_logic_vector(6 downto 0); -        freq : out std_logic_vector(11 downto 0) -- frequency -    ); +entity apu_note_to_frequency is port ( +	-- clk : in std_logic; +	-- rst : in std_logic; +	data : in std_logic_vector(6 downto 0); +	freq : out std_logic_vector(11 downto 0)); -- frequency  end entity;  architecture Behavioral of apu_note_to_frequency is -signal buffSmall : std_logic_vector(7 downto 0) := (others => '0'); -signal buff : std_logic_vector(11 downto 0) := (others => '0'); -signal shift : integer; +	signal buff_small: std_logic_vector(7 downto 0) := (others => '0'); +	signal buff: std_logic_vector(11 downto 0) := (others => '0'); +	signal shift: integer;  begin      shift <= to_integer(unsigned( data(2 downto 0) )); @@ -34,8 +32,8 @@ begin          x"100" when data(6 downto 3) = (x"C") else -- B     256          x"000"; -    -- buff <= x"1" & buffSmall; +    -- buff <= x"1" & buff_small;      freq <= std_logic_vector( shift_right(unsigned(buff), shift) );      -- freq <= (others => '0') & buff(11 downto shift); -- bitshift values out (or div by powers of 2) -- TODO: NO WORKY!!! (concat (others => '0');) -end architecture;
\ No newline at end of file +end architecture; diff --git a/basys3/basys3.srcs/apu_note_to_frequency_tb.vhd b/basys3/basys3.srcs/apu_note_to_frequency_tb.vhd new file mode 100644 index 0000000..6814c1f --- /dev/null +++ b/basys3/basys3.srcs/apu_note_to_frequency_tb.vhd @@ -0,0 +1,33 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity apu_note_to_frequency_tb is +end entity; + +architecture Behavioral of apu_note_to_frequency_tb is +	component apu_note_to_frequency is port( +		data: in std_logic_vector(7 downto 0); +		freq: out std_logic_vector(11 downto 0)); -- frequency +	end component; + +	signal data: std_logic_vector(7 downto 0) := (others => '0'); +	signal freq: std_logic_vector(11 downto 0) := (others => '0'); + +	signal ok: boolean := false; +begin +	uut: apu_note_to_frequency port map( +		data => data, +		freq => freq); +	 +	tb: process +	begin +		for i in 0 to 255 loop +			data <= std_logic_vector(to_unsigned(i, 8)); +			wait for 4 ps; +		end loop; +	end process; +end architecture; diff --git a/basys3/basys3.srcs/apu_tb_note_to_frequency.vhd b/basys3/basys3.srcs/apu_tb_note_to_frequency.vhd deleted file mode 100644 index 385071e..0000000 --- a/basys3/basys3.srcs/apu_tb_note_to_frequency.vhd +++ /dev/null @@ -1,40 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library UNISIM; -use UNISIM.VComponents.all; - -entity apu_tb_note_to_frequency is -end entity; - -architecture Behavioral of apu_tb_note_to_frequency is - -    component apu_note_to_frequency is -        port ( -            data : in std_logic_vector(7 downto 0); -            freq : out std_logic_vector(11 downto 0) --frequency -        ); -    end component; - -    signal data : std_logic_vector(7 downto 0) := (others => '0'); -    signal freq : std_logic_vector(11 downto 0) := (others => '0'); - -    signal OK : boolean := false; - -begin -    UUT: apu_note_to_frequency -    port map ( -        data => data, -        freq => freq -    ); -     -    TB: process -    begin -        for I in 0 to 255 loop -            data <= std_logic_vector(to_unsigned(I, 8)); -            wait for 4 ps; -        end loop; -    end process; - -end architecture;
\ No newline at end of file diff --git a/basys3/basys3.srcs/ppu.vhd b/basys3/basys3.srcs/ppu.vhd index efe2125..663f3ab 100644 --- a/basys3/basys3.srcs/ppu.vhd +++ b/basys3/basys3.srcs/ppu.vhd @@ -1,38 +1,23 @@  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(15 downto 0); -- PPU VRAM ADDR -	DATA: in std_logic_vector(15 downto 0); -	R,G,B: out std_logic_vector(3 downto 0); +	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  	TVSYNC, TVBLANK, THSYNC, THBLANK: out std_logic); -- tiny VGA out  end ppu;  architecture Behavioral of ppu is -	constant PPU_FG_SPRITE_COUNT: natural := 128; -- amount of foreground sprites -	constant PPU_COLOR_OUTPUT_DEPTH: natural := 4; -- VGA output channel depth -	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_TMM_ADDR_WIDTH: natural := 16; -	constant PPU_TMM_DATA_WIDTH: natural := 16; -	constant PPU_BAM_ADDR_WIDTH: natural := 11; -	constant PPU_BAM_DATA_WIDTH: natural := 15; -	constant PPU_FAM_ADDR_WIDTH: natural := 8; -	constant PPU_FAM_DATA_WIDTH: natural := 16; -	constant PPU_PAL_ADDR_WIDTH: natural := 6; -	constant PPU_PAL_DATA_WIDTH: natural := 12; -	constant PPU_AUX_ADDR_WIDTH: natural := 2; -	constant PPU_AUX_DATA_WIDTH: natural := 16; -	constant PPU_POS_H_WIDTH: natural := 9; -- amount of bits for horizontal screen offset -	constant PPU_POS_V_WIDTH: natural := 8; -- amount of bits for vertical screen offset -  	component ppu_pceg port( -- pipeline clock edge generator  		CLK: in std_logic; -- system clock  		RESET: in std_logic; -- async reset @@ -48,7 +33,7 @@ architecture Behavioral of ppu is  		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(15 downto 0); -- address in +		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); @@ -150,7 +135,7 @@ architecture Behavioral of ppu is  		PAL_ADDR: in std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); -- VRAM PAL address  		PAL_DATA: in std_logic_vector(PPU_PAL_DATA_WIDTH-1 downto 0); -- VRAM PAL data -		R,G,B: out std_logic_vector(3 downto 0)); -- VGA color out +		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 @@ -203,6 +188,15 @@ 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'); +  	pipeline_clock_edge_generator: component ppu_pceg port map(  		CLK => SYSCLK,  		RESET => SYSRST, diff --git a/basys3/basys3.srcs/ppu_addr_dec.vhdl b/basys3/basys3.srcs/ppu_addr_dec.vhdl new file mode 100644 index 0000000..28c22fc --- /dev/null +++ b/basys3/basys3.srcs/ppu_addr_dec.vhdl @@ -0,0 +1,51 @@ +library ieee; +library work; +use ieee.std_logic_1164.all; +--use ieee.numeric_std.all; +use work.ppu_consts.all; + +entity ppu_addr_dec is port( +	EN: in std_logic; -- EXT *ADDR enable (switch *AO to ADDR instead of *AI) +	WEN: in std_logic; -- EXT write enable +	TMM_WEN, +	BAM_WEN, +	FAM_WEN, +	PAL_WEN, +	AUX_WEN: out std_logic; -- write enable MUX +	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)); +end ppu_addr_dec; + +architecture Behavioral of ppu_addr_dec is +	signal TMM_RANGE, BAM_RANGE, FAM_RANGE, PAL_RANGE, AUX_RANGE: std_logic := '0'; -- ADDR in range of memory area +begin +	-- address MUX +	TMM_AO <= ADDR(PPU_TMM_ADDR_WIDTH-1 downto 0) when EN = '1' else TMM_AI; +	BAM_AO <= ADDR(PPU_BAM_ADDR_WIDTH-1 downto 0) when EN = '1' else BAM_AI; +	FAM_AO <= ADDR(PPU_FAM_ADDR_WIDTH-1 downto 0) when EN = '1' else FAM_AI; +	PAL_AO <= ADDR(PPU_PAL_ADDR_WIDTH-1 downto 0) when EN = '1' else PAL_AI; +	AUX_AO <= ADDR(PPU_AUX_ADDR_WIDTH-1 downto 0) when EN = '1' else AUX_AI; + +	-- WEN MUX +	TMM_WEN <= TMM_RANGE and WEN; +	BAM_WEN <= BAM_RANGE and WEN; +	FAM_WEN <= FAM_RANGE and WEN; +	PAL_WEN <= PAL_RANGE and WEN; +	AUX_WEN <= AUX_RANGE and WEN; + +	-- address ranges +	TMM_RANGE <= '1' when not (ADDR(15) = '1' and ADDR(14) = '1') else '0'; +	BAM_RANGE <= '1' when (ADDR(15) = '1' and ADDR(14) = '1') and (ADDR(11) = '0') else '0'; +	FAM_RANGE <= '1' when (ADDR(15) = '1' and ADDR(14) = '1') and (ADDR(11) = '1' and ADDR(10) = '0') else '0'; +	PAL_RANGE <= '1' when (ADDR(15) = '1' and ADDR(14) = '1') and (ADDR(11) = '1' and ADDR(10) = '1' and ADDR(9) = '0') else '0'; +	AUX_RANGE <= '1' when (ADDR(15) = '1' and ADDR(14) = '1') and (ADDR(11) = '1' and ADDR(10) = '1' and ADDR(9) = '1') else '0'; +end Behavioral; diff --git a/basys3/basys3.srcs/ppu_addr_dec_tb.vhdl b/basys3/basys3.srcs/ppu_addr_dec_tb.vhdl new file mode 100644 index 0000000..5c7119d --- /dev/null +++ b/basys3/basys3.srcs/ppu_addr_dec_tb.vhdl @@ -0,0 +1,86 @@ +library ieee; +library unisim; +library work; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use unisim.vcomponents.all; +use work.ppu_consts.all; + +entity ppu_addr_dec_tb is +end ppu_addr_dec_tb; + +architecture behavioral of ppu_addr_dec_tb is +	component ppu_addr_dec port( +		EN: in std_logic; -- EXT *ADDR enable (switch *AO to ADDR instead of *AI) +		WEN: in std_logic; -- EXT write enable +		TMM_WEN, +		BAM_WEN, +		FAM_WEN, +		PAL_WEN, +		AUX_WEN: out std_logic; -- write enable MUX +		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)); +	end component; +	signal EN: std_logic; +	signal WEN: std_logic; +	signal TMM_WEN, BAM_WEN, FAM_WEN, PAL_WEN, AUX_WEN: std_logic; +	signal ADDR: std_logic_vector(PPU_RAM_BUS_ADDR_WIDTH-1 downto 0); +	signal TMM_AI: std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); +	signal BAM_AI: std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); +	signal FAM_AI: std_logic_vector(PPU_FAM_ADDR_WIDTH-1 downto 0); +	signal PAL_AI: std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); +	signal AUX_AI: std_logic_vector(PPU_AUX_ADDR_WIDTH-1 downto 0); +	signal TMM_AO: std_logic_vector(PPU_TMM_ADDR_WIDTH-1 downto 0); +	signal BAM_AO: std_logic_vector(PPU_BAM_ADDR_WIDTH-1 downto 0); +	signal FAM_AO: std_logic_vector(PPU_FAM_ADDR_WIDTH-1 downto 0); +	signal PAL_AO: std_logic_vector(PPU_PAL_ADDR_WIDTH-1 downto 0); +	signal AUX_AO: std_logic_vector(PPU_AUX_ADDR_WIDTH-1 downto 0); +begin +	uut: ppu_addr_dec port map( +    EN => EN, +    WEN => WEN, +    TMM_WEN => TMM_WEN, +    BAM_WEN => BAM_WEN, +    FAM_WEN => FAM_WEN, +    PAL_WEN => PAL_WEN, +    AUX_WEN => AUX_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); + +  EN <= '1'; +  WEN <= '1'; + +  TMM_AI <= (others => '1'); +  BAM_AI <= (others => '0'); +  FAM_AI <= (others => '1'); +  PAL_AI <= (others => '0'); +  AUX_AI <= (others => '0'); + +	tb: process +	begin +		for i in 0 to 65535 loop +      ADDR <= std_logic_vector(to_unsigned(i,16)); +      wait for 10 ps; +		end loop; +		wait; -- stop for simulator +	end process; +end; diff --git a/basys3/basys3.srcs/ppu_consts.vhd b/basys3/basys3.srcs/ppu_consts.vhd new file mode 100644 index 0000000..c063586 --- /dev/null +++ b/basys3/basys3.srcs/ppu_consts.vhd @@ -0,0 +1,22 @@ +package ppu_consts is +	constant PPU_RAM_BUS_ADDR_WIDTH: natural := 16; -- RAM bus address width +	constant PPU_RAM_BUS_DATA_WIDTH: natural := 16; -- RAM bus data width +	constant PPU_FG_SPRITE_COUNT: natural := 128; -- amount of foreground sprites +	constant PPU_COLOR_OUTPUT_DEPTH: natural := 4; -- VGA output channel depth +	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_TMM_ADDR_WIDTH: natural := 16; +	constant PPU_TMM_DATA_WIDTH: natural := 16; +	constant PPU_BAM_ADDR_WIDTH: natural := 11; +	constant PPU_BAM_DATA_WIDTH: natural := 15; +	constant PPU_FAM_ADDR_WIDTH: natural := 8; +	constant PPU_FAM_DATA_WIDTH: natural := 16; +	constant PPU_PAL_ADDR_WIDTH: natural := 6; +	constant PPU_PAL_DATA_WIDTH: natural := 12; +	constant PPU_AUX_ADDR_WIDTH: natural := 2; +	constant PPU_AUX_DATA_WIDTH: natural := 16; +	constant PPU_POS_H_WIDTH: natural := 9; -- amount of bits for horizontal screen offset +	constant PPU_POS_V_WIDTH: natural := 8; -- amount of bits for vertical screen offset +end package ppu_consts; + diff --git a/basys3/basys3.xpr b/basys3/basys3.xpr index 1a6d509..466cc1f 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="4"/> +    <Option Name="WTXSimLaunchSim" Val="12"/>      <Option Name="WTModelSimLaunchSim" Val="0"/>      <Option Name="WTQuestaLaunchSim" Val="0"/>      <Option Name="WTIesLaunchSim" Val="0"/> @@ -90,6 +90,18 @@    <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_consts.vhd"> +        <FileInfo> +          <Attr Name="UsedIn" Val="synthesis"/> +          <Attr Name="UsedIn" Val="simulation"/> +        </FileInfo> +      </File> +      <File Path="$PSRCDIR/ppu_addr_dec.vhdl"> +        <FileInfo> +          <Attr Name="UsedIn" Val="synthesis"/> +          <Attr Name="UsedIn" Val="simulation"/> +        </FileInfo> +      </File>        <File Path="$PSRCDIR/ppu_pceg.vhdl">          <FileInfo>            <Attr Name="UsedIn" Val="synthesis"/> @@ -102,6 +114,22 @@            <Attr Name="UsedIn" Val="simulation"/>          </FileInfo>        </File> +      <File Path="$PSRCDIR/apu.vhd"> +        <FileInfo> +          <Attr Name="UserDisabled" Val="1"/> +          <Attr Name="AutoDisabled" Val="1"/> +          <Attr Name="UsedIn" Val="synthesis"/> +          <Attr Name="UsedIn" Val="simulation"/> +        </FileInfo> +      </File> +      <File Path="$PSRCDIR/apu_note_to_frequency.vhd"> +        <FileInfo> +          <Attr Name="UserDisabled" Val="1"/> +          <Attr Name="AutoDisabled" Val="1"/> +          <Attr Name="UsedIn" Val="synthesis"/> +          <Attr Name="UsedIn" Val="simulation"/> +        </FileInfo> +      </File>        <Config>          <Option Name="DesignMode" Val="RTL"/>          <Option Name="TopModule" Val="ppu"/> @@ -116,15 +144,30 @@      </FileSet>      <FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">        <Filter Type="Srcs"/> +      <File Path="$PSRCDIR/ppu_addr_dec_tb.vhdl"> +        <FileInfo> +          <Attr Name="UsedIn" Val="synthesis"/> +          <Attr Name="UsedIn" Val="simulation"/> +        </FileInfo> +      </File>        <File Path="$PSRCDIR/ppu_pceg_tb.vhdl">          <FileInfo> +          <Attr Name="AutoDisabled" Val="1"/> +          <Attr Name="UsedIn" Val="synthesis"/> +          <Attr Name="UsedIn" Val="simulation"/> +        </FileInfo> +      </File> +      <File Path="$PSRCDIR/apu_note_to_frequency_tb.vhd"> +        <FileInfo> +          <Attr Name="UserDisabled" Val="1"/> +          <Attr Name="AutoDisabled" Val="1"/>            <Attr Name="UsedIn" Val="synthesis"/>            <Attr Name="UsedIn" Val="simulation"/>          </FileInfo>        </File>        <Config>          <Option Name="DesignMode" Val="RTL"/> -        <Option Name="TopModule" Val="ppu_pceg_tb"/> +        <Option Name="TopModule" Val="ppu_addr_dec_tb"/>          <Option Name="TopLib" Val="xil_defaultlib"/>          <Option Name="TransportPathDelay" Val="0"/>          <Option Name="TransportIntDelay" Val="0"/> diff --git a/docs/abbreviations.md b/docs/abbreviations.md new file mode 100644 index 0000000..76bd046 --- /dev/null +++ b/docs/abbreviations.md @@ -0,0 +1,20 @@ +# List of abbreviations + +- MSB (most significant bit) +- LSB (least significant bit) +- DMA (direct memory access) +- LUT (lookup table) +- RAM (random access memory) +- PPU (picture processing unit) +  - NES (Nintendo entertainment system) +    - OAM (object attribute memory) +  - TMM (tilemap memory) +  - BAM (background attribute memory) +  - FAM (foreground attribute memory) +  - PAL (palette memory) +  - AUX (auxiliary memory) +  - HUD (heads-up display) +- APU (audio processing unit) +  - PWM (pulse width modulation) +  - ADSR (attack, decay, sustain, release) +- CPU (central processing unit) diff --git a/docs/architecture.md b/docs/architecture.md index 6b37604..a60e0da 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -224,51 +224,96 @@ Important notes:  ## Registers -|Address|Size (bytes)|Alias|Description| +- The PPU's memory bus has 16-bit addresses and 16-bit words. +- Some memory regions use physical word sizes smaller than 16-bits, so +  "unneeded" bits will be discarded by the PPU. +- All "fields" or words containing multiple bit strings representing different +  pieces of information are ordered from MSB to LSB. + +|Address offset|Size (16-bit words)|Alias|Description|  |-|-|-|-| -|`0x00000`|`0x00000`|TMM  |[tilemap memory][TMM]| -|`0x00000`|`0x00000`|BAM  |[background attribute memory][BAM]| -|`0x00000`|`0x00000`|FAM  |[foreground attribute memory][FAM]| -|`0x00000`|`0x00000`|PAL  |[palettes][PAL]| -|`0x00000`|`0x00000`|AUX  |[auxiliary memory][AUX]| +|`0x0000`|`0xc000`|TMM  |[tilemap memory][TMM]| +|`0xc000`|`0x04b0`|BAM  |[background attribute memory][BAM]| +|`0xc800`|`0x0100`|FAM  |[foreground attribute memory][FAM]| +|`0xcc00`|`0x0040`|PAL  |[palettes][PAL]| +|`0xce00`|`0x0002`|AUX  |[auxiliary memory][AUX]| + +This table contains the "official" PPU register offsets and sizes. Due to the +way the address decoder works, some of these memory regions might be duplicated +in the address ranges between the memory regions. This is considered undefined +behavior, so the CPU should not attempt to write in these locations because +there is no address validity checking.  [TMM]: #tilemap-memory  ### Tilemap memory -- TODO: list format +- Each sprite takes up 768 bits spread across 48 16-bit words +- Sprites and pixels are stored adjacently in memory without padding +- Pixel order is from top-left to bottom-right in (English) reading order.  [BAM]: #background-attribute-memory  ### Background attribute memory -- 15-bit words (padded with 1 bit) -- 11-bit address width (1200 15-bit words with padding 1) +- 15-bit words (MSB discarded in hardware) +- Address indicates which background sprite is currently targeted in reading order   +  e.g. $\textrm{addr} = c000_{\textrm{hex}} + x + y*w$ where $x$ and $y$ are the background tile, and $w$ is the amount of horizontal tiles fit on the background layer (40) + +Word format: -- TODO: list format +|Range (VHDL)|Description| +|-|-| +|`15`|Flip horizontally| +|`14`|Flip vertically| +|`13`|(unused)| +|`12 downto 10`|Palette index for tile| +|`9 downto 0`|Tilemap index|  [FAM]: #foreground-attribute-memory  ### Foreground attribute memory -- 2 * 16-bit words -- 8-bit address width (256 16-bit words for 128 * 32-bit) +- 32-bit words +- Sprites with lower addresses are drawn "before" sprites with higher addresses + +Word format: -- TODO: list format +|Range (VHDL)|Description| +|-|-| +|`31`|Flip horizontally| +|`30`|Flip vertically| +|`29 downto 21`|horizontal position (offset by -16)| +|`20 downto 13`|vertical position (offset by -16)| +|`12 downto 10`|Palette index for tile| +|`9 downto 0`|Tilemap index|  [PAL]: #palettes  ### Palettes -- 12-bit words -- 6-bit address width (2^6 = 64 colors total) +- 12-bit words (4 MSB discarded in hardware) +- Address formula for palette color is $p_i*8 + p_c$ where $p_i$ is the palette +  index and $p_c$ is the color index within a given palette. -- TODO: list format +Word format: + +|Range (VHDL)|Description| +|-|-| +|`15 downto 13`|(discarded)| +|`12 downto 8`|Red value| +|`7 downto 4`|Green value| +|`3 downto 0`|Blue value|  [AUX]: #auxiliary-memory  ### Auxiliary memory -- background scrolling (8 + 9 bits) -- fetch foreground sprites bit (1 bit) +- no words + +Format: -- 16-bit words -- 1-bit address width +|Range (VHDL)|Description| +|-|-| +|`31 downto 18`|(unused)| +|`17`|Fetch foreground sprites flag| +|`16 downto 8`|Horizontal background scroll (offset from left edge)| +|`7 downto 0`|Vertical background scroll (offset from top edge)|  [custompputimings]: https://docs.google.com/spreadsheets/d/1MU6K4c4PtMR_JXIpc3I0ZJdLZNnoFO7G2P3olCz6LSc diff --git a/docs/gen/doc.m4 b/docs/gen/doc.m4 index b98eb64..c9cbcf5 100644 --- a/docs/gen/doc.m4 +++ b/docs/gen/doc.m4 @@ -6,7 +6,8 @@ define(`docname',  	       NAME, `gameplay', `Game design document',  	       NAME, `architecture', `Architecture document',  				 `UNKNOWN???'))dnl - +define(`abbreviations',`undivert(`abbreviations.con')')dnl +dnl  <!DOCTYPE html>  <html lang="en-US">  <link> @@ -43,6 +44,7 @@ define(`docname',  			Niels Stunnebrink <b>(2184532)</b>  		</span>  	</div> +	ifelse(NAME, `architecture', `abbreviations', `')  	<h1>Table of contents</h1>  	undivert(NAME`.toc')  	undivert(NAME`.con') diff --git a/docs/makefile b/docs/makefile index e4fcb15..a729024 100644 --- a/docs/makefile +++ b/docs/makefile @@ -5,7 +5,9 @@ CHROME = chromium --headless --run-all-compositor-stages-before-draw --virtual-t  CURL = curl  PUP = pup -SRCS = $(wildcard *.md) +SRCS += gameplay.md \ +				research.md \ +				architecture.md  HTML_T = $(SRCS:.md=.html)  PDF_T = $(SRCS:.md=.pdf) @@ -22,8 +24,8 @@ gen/paged.polyfill.js:  %.toc: %.md  	$(PANDOC) $< -s --toc --to=html 2> /dev/null | $(PUP) '#TOC' | sed -r 's/<(.?)ul>/<\1ol>/g' > $@ -%.html: %.con %.toc gen/doc.m4 gen/paged.polyfill.js gen/style.css -	$(M4) -Igen -DNAME=$(basename $<) gen/doc.m4 > $@ +%.html: %.con %.toc gen/doc.m4 gen/paged.polyfill.js gen/style.css abbreviations.con +	$(M4) -Igen -I. -DNAME=$(basename $<) gen/doc.m4 > $@  %.pdf: %.html  	$(CHROME) --print-to-pdf=$@ $< 2> /dev/null @@ -48,4 +48,6 @@ before formatting as a failsafe.  - use snake case for naming components  - use uppercase snake case for naming signals and I/O lines  - use lower case keywords +- testbench name is the component name with `_tb` as suffix +- vhdl filename is the same as the component name |