aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--basys3/basys3.srcs/ppu.vhd40
-rw-r--r--basys3/basys3.srcs/ppu_addr_dec.vhdl51
-rw-r--r--basys3/basys3.srcs/ppu_addr_dec_tb.vhdl86
-rw-r--r--basys3/basys3.srcs/ppu_consts.vhd22
-rw-r--r--basys3/basys3.xpr23
-rw-r--r--docs/abbreviations.md20
-rw-r--r--docs/architecture.md85
-rw-r--r--docs/gen/doc.m44
-rw-r--r--docs/makefile8
9 files changed, 290 insertions, 49 deletions
diff --git a/basys3/basys3.srcs/ppu.vhd b/basys3/basys3.srcs/ppu.vhd
index efe2125..28134c6 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..d3c8403
--- /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..5df2675 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"/>
@@ -116,15 +128,22 @@
</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>
<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