aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/ppu-level-2.svg2
-rw-r--r--assets/ppu-pipeline.svg3
-rw-r--r--basys3/basys3.srcs/ppu.vhd45
-rw-r--r--basys3/basys3.srcs/ppu_comp.vhd24
-rw-r--r--basys3/basys3.srcs/ppu_consts.vhd1
-rw-r--r--basys3/basys3.srcs/ppu_dispctl.vhd4
-rw-r--r--basys3/basys3.srcs/ppu_pceg.vhd60
-rw-r--r--basys3/basys3.srcs/ppu_pceg_consts.vhd18
-rw-r--r--basys3/basys3.srcs/ppu_pceg_tb.vhd17
-rw-r--r--basys3/basys3.srcs/ppu_sprite_bg.vhd46
-rw-r--r--basys3/basys3.srcs/ppu_sprite_fg.vhd31
-rw-r--r--basys3/basys3.xpr23
-rw-r--r--basys3/ppu_tb_behav.wcfg505
-rw-r--r--docs/architecture.md19
-rw-r--r--docs/ppu.drawio2
15 files changed, 669 insertions, 131 deletions
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 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="632px" height="596px" viewBox="-0.5 -0.5 632 596" style="background-color: rgb(255, 255, 255);"><defs/><g><path d="M 0 117 L 630 117" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 114px; margin-left: 628px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">pipeline stage 1-2</div></div></div></foreignObject><text x="628" y="114" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="end">pipeline s...</text></switch></g><path d="M 0 357 L 630 357" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 354px; margin-left: 628px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">pipeline stage 5</div></div></div></foreignObject><text x="628" y="354" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="end">pipeline s...</text></switch></g><path d="M 0 207 L 630 207" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 204px; margin-left: 628px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">pipeline stage 3-4</div></div></div></foreignObject><text x="628" y="204" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="end">pipeline s...</text></switch></g><path d="M 280 107 L 280 140.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 280 145.88 L 276.5 138.88 L 280 140.63 L 283.5 138.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 136px; margin-left: 280px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">sprite info</div></div></div></foreignObject><text x="280" y="136" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">sprite info</text></switch></g><path d="M 339.5 172 L 339.5 182.5 L 320.5 167 L 339.5 151.5 L 339.5 162 L 350 162 L 399.5 162 L 399.5 172 L 350 172 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 339.5 172 L 339.5 182.5 L 320.5 167 L 339.5 151.5 L 339.5 162" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 167px; margin-left: 360px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">TMM</div></div></div></foreignObject><text x="360" y="170" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">TMM</text></switch></g><rect x="240" y="27" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 67px; margin-left: 241px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Background sprite info</div></div></div></foreignObject><text x="280" y="71" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Background sp...</text></switch></g><path d="M 190 67 L 190 140.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 190 145.88 L 186.5 138.88 L 190 140.63 L 193.5 138.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 136px; margin-left: 190px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">sprite info</div></div></div></foreignObject><text x="190" y="136" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">sprite info</text></switch></g><path d="M 70.5 172 L 70.5 162 L 110 162 L 130.5 162 L 130.5 151.5 L 149.5 167 L 130.5 182.5 L 130.5 172 L 110 172 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" stroke-dasharray="3 3" pointer-events="all"/><path d="M 130.5 162 L 130.5 151.5 L 149.5 167 L 130.5 182.5 L 130.5 172" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 167px; margin-left: 110px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">TMM</div></div></div></foreignObject><text x="110" y="170" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">TMM</text></switch></g><rect x="150" y="27" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 47px; margin-left: 151px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Foreground sprite info</div></div></div></foreignObject><text x="190" y="51" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Foreground sp...</text></switch></g><path d="M 280 267 L 280 300.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 280 305.88 L 276.5 298.88 L 280 300.63 L 283.5 298.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 287px; margin-left: 280px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">global palette index</div></div></div></foreignObject><text x="280" y="290" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">global palette index</text></switch></g><rect x="240" y="227" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 247px; margin-left: 241px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Compositor</div></div></div></foreignObject><text x="280" y="251" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Compositor</text></switch></g><path d="M 260 447 L 260 467 L 20 467 L 20 7 L 190 7 L 190 20.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 190 25.88 L 186.5 18.88 L 190 20.63 L 193.5 18.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 260 447 L 260 467 L 20 467 L 20 7 L 280 7 L 280 20.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 280 25.88 L 276.5 18.88 L 280 20.63 L 283.5 18.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 300 447 L 300 487 L 300 490.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 300 495.88 L 296.5 488.88 L 300 490.63 L 303.5 488.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 472px; margin-left: 300px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">VGA signal</div></div></div></foreignObject><text x="300" y="475" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">VGA signal</text></switch></g><rect x="240" y="387" width="80" height="60" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 417px; margin-left: 241px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">tiny VGA signal generator</div></div></div></foreignObject><text x="280" y="421" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">tiny VGA sign...</text></switch></g><path d="M 280 347 L 280 380.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 280 385.88 L 276.5 378.88 L 280 380.63 L 283.5 378.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 280 347 L 280 380.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 280 385.88 L 276.5 378.88 L 280 380.63 L 283.5 378.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 367px; margin-left: 280px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">rgb value</div></div></div></foreignObject><text x="280" y="370" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">rgb value</text></switch></g><path d="M 339.5 332 L 339.5 342.5 L 320.5 327 L 339.5 311.5 L 339.5 322 L 360 322 L 380.5 322 L 380.5 311.5 L 399.5 327 L 380.5 342.5 L 380.5 332 L 360 332 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 339.5 332 L 339.5 342.5 L 320.5 327 L 339.5 311.5 L 339.5 322" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><path d="M 380.5 322 L 380.5 311.5 L 399.5 327 L 380.5 342.5 L 380.5 332" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 327px; margin-left: 360px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">PAL</div></div></div></foreignObject><text x="360" y="330" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">PAL</text></switch></g><rect x="240" y="307" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 327px; margin-left: 241px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Palette lookup</div></div></div></foreignObject><text x="280" y="331" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Palette lookup</text></switch></g><path d="M 280 187 L 280 220.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 280 225.88 L 276.5 218.88 L 280 220.63 L 283.5 218.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 399.5 42 L 399.5 52 L 340 52 L 339.5 52 L 339.5 62.5 L 320.5 47 L 339.5 31.5 L 339.5 42 L 340 42 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 339.5 52 L 339.5 62.5 L 320.5 47 L 339.5 31.5 L 339.5 42" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 47px; margin-left: 360px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BAM</div></div></div></foreignObject><text x="360" y="50" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BAM</text></switch></g><path d="M 339.5 92 L 339.5 102.5 L 320.5 87 L 339.5 71.5 L 339.5 82 L 360 82 L 380.5 82 L 380.5 71.5 L 399.5 87 L 380.5 102.5 L 380.5 92 L 360 92 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 339.5 92 L 339.5 102.5 L 320.5 87 L 339.5 71.5 L 339.5 82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><path d="M 380.5 82 L 380.5 71.5 L 399.5 87 L 380.5 102.5 L 380.5 92" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 87px; margin-left: 360px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">AUX</div></div></div></foreignObject><text x="360" y="90" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">AUX</text></switch></g><rect x="240" y="147" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 167px; margin-left: 241px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Sprite render</div></div></div></foreignObject><text x="280" y="171" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Sprite render</text></switch></g><path d="M 220 187 L 220 197 L 280 197 L 280 220.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 280 225.88 L 276.5 218.88 L 280 220.63 L 283.5 218.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 197px; margin-left: 250px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">pixel data</div></div></div></foreignObject><text x="250" y="200" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">pixel data</text></switch></g><path d="M 130.5 42 L 130.5 31.5 L 149.5 47 L 130.5 62.5 L 130.5 52 L 90 52 L 89.5 52 L 89.5 62.5 L 70.5 47 L 89.5 31.5 L 89.5 42 L 90 42 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 130.5 42 L 130.5 31.5 L 149.5 47 L 130.5 62.5 L 130.5 52" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><path d="M 89.5 52 L 89.5 62.5 L 70.5 47 L 89.5 31.5 L 89.5 42" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 47px; margin-left: 110px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">FAM</div></div></div></foreignObject><text x="110" y="50" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">FAM</text></switch></g><rect x="150" y="147" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 167px; margin-left: 151px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Sprite render</div></div></div></foreignObject><text x="190" y="171" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Sprite render</text></switch></g><path d="M 490.5 162 L 490.5 151.5 L 509.5 167 L 490.5 182.5 L 490.5 172 L 490 172 L 430.5 172 L 430.5 162 L 490 162 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 490.5 162 L 490.5 151.5 L 509.5 167 L 490.5 182.5 L 490.5 172" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 167px; margin-left: 470px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">TMM</div></div></div></foreignObject><text x="470" y="170" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">TMM</text></switch></g><rect x="510" y="147" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 167px; margin-left: 511px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Tilemap memory</div></div></div></foreignObject><text x="570" y="171" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tilemap memory</text></switch></g><path d="M 430.5 52 L 430.5 42 L 460 42 L 490.5 42 L 490.5 31.5 L 509.5 47 L 490.5 62.5 L 490.5 52 L 460 52 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 490.5 42 L 490.5 31.5 L 509.5 47 L 490.5 62.5 L 490.5 52" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 47px; margin-left: 470px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BAM</div></div></div></foreignObject><text x="470" y="50" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BAM</text></switch></g><rect x="510" y="27" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 47px; margin-left: 511px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Background attribute memory</div></div></div></foreignObject><text x="570" y="51" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Background attribute...</text></switch></g><rect x="160" y="457" width="100" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 467px; margin-left: 161px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: normal; overflow-wrap: normal;">screen position</div></div></div></foreignObject><text x="210" y="471" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">screen position</text></switch></g><rect x="400" y="27" width="30" height="320" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" transform="rotate(180,415,187)" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 407 37)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-end; width: 310px; height: 1px; padding-top: 37px; margin-left: 97px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PPU RAM bus</div></div></div></foreignObject><text x="407" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">PPU RAM bus</text></switch></g><rect x="40" y="27" width="30" height="160" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" transform="rotate(180,55,107)" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 47 37)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-end; width: 150px; height: 1px; padding-top: 37px; margin-left: -103px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PPU RAM bus</div></div></div></foreignObject><text x="47" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">PPU RAM bus</text></switch></g><rect x="240" y="497" width="80" height="50" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 522px; margin-left: 241px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">native VGA signal generator</div></div></div></foreignObject><text x="280" y="526" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">native VGA si...</text></switch></g><path d="M 280 547 L 280 577 L 280 580.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 280 585.88 L 276.5 578.88 L 280 580.63 L 283.5 578.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 567px; margin-left: 280px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">VGA signal</div></div></div></foreignObject><text x="280" y="570" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">VGA signal</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="618px" height="596px" viewBox="-0.5 -0.5 618 596" style="background-color: rgb(255, 255, 255);"><defs/><g><path d="M 267 107 L 267 140.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267 145.88 L 263.5 138.88 L 267 140.63 L 270.5 138.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 123px; margin-left: 267px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">sprite info</div></div></div></foreignObject><text x="267" y="126" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">sprite info</text></switch></g><path d="M 326.5 172 L 326.5 182.5 L 307.5 167 L 326.5 151.5 L 326.5 162 L 337 162 L 386.5 162 L 386.5 172 L 337 172 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 326.5 172 L 326.5 182.5 L 307.5 167 L 326.5 151.5 L 326.5 162" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 167px; margin-left: 347px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">TMM</div></div></div></foreignObject><text x="347" y="170" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">TMM</text></switch></g><rect x="227" y="27" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 67px; margin-left: 228px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Background sprite info</div></div></div></foreignObject><text x="267" y="71" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Background sp...</text></switch></g><path d="M 177 67 L 177 140.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 177 145.88 L 173.5 138.88 L 177 140.63 L 180.5 138.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 123px; margin-left: 177px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">sprite info</div></div></div></foreignObject><text x="177" y="126" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">sprite info</text></switch></g><path d="M 57.5 172 L 57.5 162 L 97 162 L 117.5 162 L 117.5 151.5 L 136.5 167 L 117.5 182.5 L 117.5 172 L 97 172 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" stroke-dasharray="3 3" pointer-events="all"/><path d="M 117.5 162 L 117.5 151.5 L 136.5 167 L 117.5 182.5 L 117.5 172" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 167px; margin-left: 97px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">TMM</div></div></div></foreignObject><text x="97" y="170" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">TMM</text></switch></g><rect x="137" y="27" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 47px; margin-left: 138px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Foreground sprite info</div></div></div></foreignObject><text x="177" y="51" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Foreground sp...</text></switch></g><path d="M 267 267 L 267 300.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267 305.88 L 263.5 298.88 L 267 300.63 L 270.5 298.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 287px; margin-left: 267px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">global palette index</div></div></div></foreignObject><text x="267" y="290" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">global palette index</text></switch></g><rect x="227" y="227" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 247px; margin-left: 228px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Compositor</div></div></div></foreignObject><text x="267" y="251" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Compositor</text></switch></g><path d="M 247 447 L 247 467 L 7 467 L 7 7 L 177 7 L 177 20.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 177 25.88 L 173.5 18.88 L 177 20.63 L 180.5 18.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 247 447 L 247 467 L 7 467 L 7 7 L 267 7 L 267 20.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267 25.88 L 263.5 18.88 L 267 20.63 L 270.5 18.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 287 447 L 287 487 L 287 490.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 287 495.88 L 283.5 488.88 L 287 490.63 L 290.5 488.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 472px; margin-left: 287px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">VGA signal</div></div></div></foreignObject><text x="287" y="475" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">VGA signal</text></switch></g><rect x="227" y="387" width="80" height="60" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 417px; margin-left: 228px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">tiny VGA signal generator</div></div></div></foreignObject><text x="267" y="421" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">tiny VGA sign...</text></switch></g><path d="M 267 347 L 267 380.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267 385.88 L 263.5 378.88 L 267 380.63 L 270.5 378.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 267 347 L 267 380.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267 385.88 L 263.5 378.88 L 267 380.63 L 270.5 378.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 367px; margin-left: 267px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">rgb value</div></div></div></foreignObject><text x="267" y="370" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">rgb value</text></switch></g><path d="M 326.5 332 L 326.5 342.5 L 307.5 327 L 326.5 311.5 L 326.5 322 L 347 322 L 367.5 322 L 367.5 311.5 L 386.5 327 L 367.5 342.5 L 367.5 332 L 347 332 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 326.5 332 L 326.5 342.5 L 307.5 327 L 326.5 311.5 L 326.5 322" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><path d="M 367.5 322 L 367.5 311.5 L 386.5 327 L 367.5 342.5 L 367.5 332" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 327px; margin-left: 347px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">PAL</div></div></div></foreignObject><text x="347" y="330" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">PAL</text></switch></g><rect x="227" y="307" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 327px; margin-left: 228px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Palette lookup</div></div></div></foreignObject><text x="267" y="331" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Palette lookup</text></switch></g><path d="M 267 187 L 267 220.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267 225.88 L 263.5 218.88 L 267 220.63 L 270.5 218.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 386.5 42 L 386.5 52 L 327 52 L 326.5 52 L 326.5 62.5 L 307.5 47 L 326.5 31.5 L 326.5 42 L 327 42 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 326.5 52 L 326.5 62.5 L 307.5 47 L 326.5 31.5 L 326.5 42" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 47px; margin-left: 347px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BAM</div></div></div></foreignObject><text x="347" y="50" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BAM</text></switch></g><path d="M 326.5 92 L 326.5 102.5 L 307.5 87 L 326.5 71.5 L 326.5 82 L 347 82 L 367.5 82 L 367.5 71.5 L 386.5 87 L 367.5 102.5 L 367.5 92 L 347 92 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 326.5 92 L 326.5 102.5 L 307.5 87 L 326.5 71.5 L 326.5 82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><path d="M 367.5 82 L 367.5 71.5 L 386.5 87 L 367.5 102.5 L 367.5 92" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 87px; margin-left: 347px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">AUX</div></div></div></foreignObject><text x="347" y="90" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">AUX</text></switch></g><rect x="227" y="147" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 167px; margin-left: 228px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Sprite render</div></div></div></foreignObject><text x="267" y="171" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Sprite render</text></switch></g><path d="M 207 187 L 207 207 L 267 207 L 267 220.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267 225.88 L 263.5 218.88 L 267 220.63 L 270.5 218.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 207px; margin-left: 237px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">pixel data</div></div></div></foreignObject><text x="237" y="210" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">pixel data</text></switch></g><path d="M 117.5 42 L 117.5 31.5 L 136.5 47 L 117.5 62.5 L 117.5 52 L 77 52 L 76.5 52 L 76.5 62.5 L 57.5 47 L 76.5 31.5 L 76.5 42 L 77 42 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 117.5 42 L 117.5 31.5 L 136.5 47 L 117.5 62.5 L 117.5 52" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><path d="M 76.5 52 L 76.5 62.5 L 57.5 47 L 76.5 31.5 L 76.5 42" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 47px; margin-left: 97px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">FAM</div></div></div></foreignObject><text x="97" y="50" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">FAM</text></switch></g><rect x="137" y="147" width="80" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 167px; margin-left: 138px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Sprite render</div></div></div></foreignObject><text x="177" y="171" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Sprite render</text></switch></g><path d="M 477.5 162 L 477.5 151.5 L 496.5 167 L 477.5 182.5 L 477.5 172 L 477 172 L 417.5 172 L 417.5 162 L 477 162 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 477.5 162 L 477.5 151.5 L 496.5 167 L 477.5 182.5 L 477.5 172" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 167px; margin-left: 457px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">TMM</div></div></div></foreignObject><text x="457" y="170" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">TMM</text></switch></g><rect x="497" y="147" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 167px; margin-left: 498px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Tilemap memory</div></div></div></foreignObject><text x="557" y="171" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tilemap memory</text></switch></g><path d="M 417.5 52 L 417.5 42 L 447 42 L 477.5 42 L 477.5 31.5 L 496.5 47 L 477.5 62.5 L 477.5 52 L 447 52 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" pointer-events="all"/><path d="M 477.5 42 L 477.5 31.5 L 496.5 47 L 477.5 62.5 L 477.5 52" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 47px; margin-left: 457px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">BAM</div></div></div></foreignObject><text x="457" y="50" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">BAM</text></switch></g><rect x="497" y="27" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 47px; margin-left: 498px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Background attribute memory</div></div></div></foreignObject><text x="557" y="51" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Background attribute...</text></switch></g><rect x="147" y="457" width="100" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 467px; margin-left: 148px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: normal; overflow-wrap: normal;">screen position</div></div></div></foreignObject><text x="197" y="471" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">screen position</text></switch></g><rect x="387" y="27" width="30" height="320" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" transform="rotate(180,402,187)" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 394 37)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-end; width: 310px; height: 1px; padding-top: 37px; margin-left: 84px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PPU RAM bus</div></div></div></foreignObject><text x="394" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">PPU RAM bus</text></switch></g><rect x="27" y="27" width="30" height="160" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" transform="rotate(180,42,107)" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 34 37)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-end; width: 150px; height: 1px; padding-top: 37px; margin-left: -116px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PPU RAM bus</div></div></div></foreignObject><text x="34" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">PPU RAM bus</text></switch></g><rect x="227" y="497" width="80" height="50" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 522px; margin-left: 228px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">native VGA signal generator</div></div></div></foreignObject><text x="267" y="526" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">native VGA si...</text></switch></g><path d="M 267 547 L 267 577 L 267 580.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 267 585.88 L 263.5 578.88 L 267 580.63 L 270.5 578.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 567px; margin-left: 267px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">VGA signal</div></div></div></foreignObject><text x="267" y="570" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">VGA signal</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="903px" height="152px" viewBox="-0.5 -0.5 903 152" style="background-color: rgb(255, 255, 255);"><defs/><g><path d="M 180 150 L 180 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 260 150 L 260 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 340 150 L 340 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 420 150 L 420 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 500 150 L 500 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 580 150 L 580 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 660 150 L 660 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 740 150 L 740 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 901 20 L 100 20" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><rect x="0" y="30" width="100" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 45px; margin-left: 0px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ppu_sprite_bg</div></div></div></foreignObject><text x="96" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">ppu_sprite_bg</text></switch></g><rect x="100" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">0</div></div></div></foreignObject><text x="140" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">0</text></switch></g><rect x="180" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 181px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">1</div></div></div></foreignObject><text x="220" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">1</text></switch></g><rect x="260" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 261px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">2</div></div></div></foreignObject><text x="300" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">2</text></switch></g><rect x="340" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 341px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">3</div></div></div></foreignObject><text x="380" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">3</text></switch></g><rect x="420" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 421px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">4</div></div></div></foreignObject><text x="460" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">4</text></switch></g><rect x="500" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 501px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">5</div></div></div></foreignObject><text x="540" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">5</text></switch></g><rect x="580" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 581px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">6</div></div></div></foreignObject><text x="620" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">6</text></switch></g><rect x="660" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 661px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">7</div></div></div></foreignObject><text x="700" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">7</text></switch></g><path d="M 190 30 L 330 30 L 340 45 L 330 60 L 190 60 L 180 45 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 45px; margin-left: 181px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; text-decoration: underline; white-space: normal; overflow-wrap: normal;">BAM address</div></div></div></foreignObject><text x="260" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle" text-decoration="underline">BAM address</text></switch></g><rect x="0" y="70" width="100" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 85px; margin-left: 0px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ppu_sprite_fg</div></div></div></foreignObject><text x="96" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">ppu_sprite_fg</text></switch></g><path d="M 190 70 L 330 70 L 340 85 L 330 100 L 190 100 L 180 85 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 85px; margin-left: 181px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; text-decoration: underline; white-space: normal; overflow-wrap: normal;">TMM address</div></div></div></foreignObject><text x="260" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle" text-decoration="underline">TMM address</text></switch></g><rect x="0" y="0" width="100" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 10px; margin-left: 0px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">clk</div></div></div></foreignObject><text x="96" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">clk</text></switch></g><rect x="0" y="110" width="100" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 125px; margin-left: 0px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ppu_pceg</div></div></div></foreignObject><text x="96" y="129" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">ppu_pceg</text></switch></g><path d="M 750 110 L 810 110 L 820 125 L 810 140 L 750 140 L 740 125 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 125px; margin-left: 741px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; text-decoration: underline; white-space: normal; overflow-wrap: normal;">pixel done</div></div></div></foreignObject><text x="780" y="129" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle" text-decoration="underline">pixel done</text></switch></g><path d="M 750 30 L 810 30 L 820 45 L 810 60 L 750 60 L 740 45 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 45px; margin-left: 741px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">TMM data</div></div></div></foreignObject><text x="780" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">TMM data</text></switch></g><path d="M 510 30 L 650 30 L 660 45 L 650 60 L 510 60 L 500 45 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 45px; margin-left: 501px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; text-decoration: underline; white-space: normal; overflow-wrap: normal;">TMM address</div></div></div></foreignObject><text x="580" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle" text-decoration="underline">TMM address</text></switch></g><path d="M 830 110 L 890 110 L 900 125 L 890 140 L 830 140 L 820 125 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 125px; margin-left: 821px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; text-decoration: underline; white-space: normal; overflow-wrap: normal;">pixel ready</div></div></div></foreignObject><text x="860" y="129" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle" text-decoration="underline">pixel ready</text></switch></g><path d="M 100 150 L 100 0" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 820 150 L 820 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 900 150 L 900 0" fill="none" stroke="rgb(0, 0, 0)" stroke-opacity="0.5" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><rect x="740" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 741px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">8</div></div></div></foreignObject><text x="780" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">8</text></switch></g><rect x="820" y="0" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 10px; margin-left: 821px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">9</div></div></div></foreignObject><text x="860" y="14" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">9</text></switch></g><path d="M 430 30 L 490 30 L 500 45 L 490 60 L 430 60 L 420 45 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 45px; margin-left: 421px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">BAM data</div></div></div></foreignObject><text x="460" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">BAM data</text></switch></g><path d="M 430 70 L 490 70 L 500 85 L 490 100 L 430 100 L 420 85 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 85px; margin-left: 421px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">TMM data</div></div></div></foreignObject><text x="460" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">TMM data</text></switch></g><path d="M 110 30 L 170 30 L 180 45 L 170 60 L 110 60 L 100 45 Z" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)" opacity="0.7"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 45px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><text x="140" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">idle</text></switch></g><path d="M 110 110 L 170 110 L 180 125 L 170 140 L 110 140 L 100 125 Z" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)" opacity="0.7"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 125px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">input<br />stability</div></div></div></foreignObject><text x="140" y="129" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">input...</text></switch></g><path d="M 110 70 L 170 70 L 180 85 L 170 100 L 110 100 L 100 85 Z" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)" opacity="0.7"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 85px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><text x="140" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">idle</text></switch></g><path d="M 350 30 L 410 30 L 420 45 L 410 60 L 350 60 L 340 45 Z" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)" opacity="0.7"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 45px; margin-left: 341px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><text x="380" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">idle</text></switch></g><path d="M 350 70 L 410 70 L 420 85 L 410 100 L 350 100 L 340 85 Z" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)" opacity="0.7"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 85px; margin-left: 341px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><text x="380" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">idle</text></switch></g><path d="M 670 30 L 730 30 L 740 45 L 730 60 L 670 60 L 660 45 Z" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)" opacity="0.7"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 45px; margin-left: 661px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><text x="700" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">idle</text></switch></g><path d="M 510 70 L 570 70 L 580 85 L 570 100 L 510 100 L 500 85 Z" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)" opacity="0.7"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 85px; margin-left: 501px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><text x="540" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">idle</text></switch></g><path d="M 830 30 L 890 30 L 900 45 L 890 60 L 830 60 L 820 45 Z" fill-opacity="0.7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-opacity="0.7" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)" opacity="0.7"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 45px; margin-left: 821px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><text x="860" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">idle</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ 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 @@
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="DSABoardId" Val="basys3"/>
- <Option Name="WTXSimLaunchSim" Val="33"/>
+ <Option Name="WTXSimLaunchSim" Val="62"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
@@ -98,6 +98,13 @@
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
+ <File Path="$PSRCDIR/ppu_pceg_consts.vhd">
+ <FileInfo SFType="VHDL2008">
+ <Attr Name="IsGlobalInclude" Val="1"/>
+ <Attr Name="UsedIn" Val="synthesis"/>
+ <Attr Name="UsedIn" Val="simulation"/>
+ </FileInfo>
+ </File>
<File Path="$PSRCDIR/er_ram.vhd">
<FileInfo SFType="VHDL2008">
<Attr Name="UsedIn" Val="synthesis"/>
@@ -222,6 +229,12 @@
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
+ <File Path="$PSRCDIR/ppu_pceg_tb.vhd">
+ <FileInfo>
+ <Attr Name="UsedIn" Val="synthesis"/>
+ <Attr Name="UsedIn" Val="simulation"/>
+ </FileInfo>
+ </File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="ppu_tb"/>
@@ -373,9 +386,7 @@
</Run>
<Run Id="synth_3" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="true" IncrementalCheckpoint="$PSRCDIR/utils_1/imports/synth_3/top.dcp" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_3" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_3" AutoRQSDir="$PSRCDIR/utils_1/imports/synth_3">
<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"/>
@@ -453,9 +464,7 @@
</Run>
<Run Id="impl_3" Type="Ft2:EntireDesign" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_3" SynthRun="synth_3" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_3" AutoRQSDir="$PSRCDIR/utils_1/imports/impl_3">
<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"/>
diff --git a/basys3/ppu_tb_behav.wcfg b/basys3/ppu_tb_behav.wcfg
new file mode 100644
index 0000000..085f335
--- /dev/null
+++ b/basys3/ppu_tb_behav.wcfg
@@ -0,0 +1,505 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wave_config>
+ <wave_state>
+ </wave_state>
+ <db_ref_list>
+ <db_ref path="ppu_tb_behav.wdb" id="1">
+ <top_modules>
+ <top_module name="glbl" />
+ <top_module name="ppu_consts" />
+ <top_module name="ppu_pceg_consts" />
+ <top_module name="ppu_tb" />
+ </top_modules>
+ </db_ref>
+ </db_ref_list>
+ <zoom_setting>
+ <ZoomStartTime time="924.298300 us"></ZoomStartTime>
+ <ZoomEndTime time="943.298301 us"></ZoomEndTime>
+ <Cursor1Time time="932.318300 us"></Cursor1Time>
+ </zoom_setting>
+ <column_width_setting>
+ <NameColumnWidth column_width="167"></NameColumnWidth>
+ <ValueColumnWidth column_width="149"></ValueColumnWidth>
+ </column_width_setting>
+ <WVObjectSize size="6" />
+ <wvobject type="group" fp_name="group136">
+ <obj_property name="label">clks</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/CLK100">
+ <obj_property name="ElementShortName">CLK100</obj_property>
+ <obj_property name="ObjectShortName">CLK100</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/NPIXCLK">
+ <obj_property name="ElementShortName">NPIXCLK</obj_property>
+ <obj_property name="ObjectShortName">NPIXCLK</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/TPIXCLK">
+ <obj_property name="ElementShortName">TPIXCLK</obj_property>
+ <obj_property name="ObjectShortName">TPIXCLK</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject type="group" fp_name="group150">
+ <obj_property name="label">ppu top</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/RESET">
+ <obj_property name="ElementShortName">RESET</obj_property>
+ <obj_property name="ObjectShortName">RESET</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/WEN">
+ <obj_property name="ElementShortName">WEN</obj_property>
+ <obj_property name="ObjectShortName">WEN</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/ADDR">
+ <obj_property name="ElementShortName">ADDR[15:0]</obj_property>
+ <obj_property name="ObjectShortName">ADDR[15:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/DATA">
+ <obj_property name="ElementShortName">DATA[15:0]</obj_property>
+ <obj_property name="ObjectShortName">DATA[15:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/R">
+ <obj_property name="ElementShortName">R[3:0]</obj_property>
+ <obj_property name="ObjectShortName">R[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/G">
+ <obj_property name="ElementShortName">G[3:0]</obj_property>
+ <obj_property name="ObjectShortName">G[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/B">
+ <obj_property name="ElementShortName">B[3:0]</obj_property>
+ <obj_property name="ObjectShortName">B[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/VSYNC">
+ <obj_property name="ElementShortName">VSYNC</obj_property>
+ <obj_property name="ObjectShortName">VSYNC</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/HSYNC">
+ <obj_property name="ElementShortName">HSYNC</obj_property>
+ <obj_property name="ObjectShortName">HSYNC</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/VBLANK">
+ <obj_property name="ElementShortName">VBLANK</obj_property>
+ <obj_property name="ObjectShortName">VBLANK</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/SYSCLK">
+ <obj_property name="ElementShortName">SYSCLK</obj_property>
+ <obj_property name="ObjectShortName">SYSCLK</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/SYSRST">
+ <obj_property name="ElementShortName">SYSRST</obj_property>
+ <obj_property name="ObjectShortName">SYSRST</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/PL_SPRITE_FG">
+ <obj_property name="ElementShortName">PL_SPRITE_FG</obj_property>
+ <obj_property name="ObjectShortName">PL_SPRITE_FG</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/PL_SPRITE_BG">
+ <obj_property name="ElementShortName">PL_SPRITE_BG</obj_property>
+ <obj_property name="ObjectShortName">PL_SPRITE_BG</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/PL_DONE">
+ <obj_property name="ElementShortName">PL_DONE</obj_property>
+ <obj_property name="ObjectShortName">PL_DONE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/PL_READY">
+ <obj_property name="ElementShortName">PL_READY</obj_property>
+ <obj_property name="ObjectShortName">PL_READY</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/TMM_WEN">
+ <obj_property name="ElementShortName">TMM_WEN</obj_property>
+ <obj_property name="ObjectShortName">TMM_WEN</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/BAM_WEN">
+ <obj_property name="ElementShortName">BAM_WEN</obj_property>
+ <obj_property name="ObjectShortName">BAM_WEN</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/FAM_WEN">
+ <obj_property name="ElementShortName">FAM_WEN</obj_property>
+ <obj_property name="ObjectShortName">FAM_WEN</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/PAL_WEN">
+ <obj_property name="ElementShortName">PAL_WEN</obj_property>
+ <obj_property name="ObjectShortName">PAL_WEN</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/AUX_WEN">
+ <obj_property name="ElementShortName">AUX_WEN</obj_property>
+ <obj_property name="ObjectShortName">AUX_WEN</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/TMM_W_ADDR">
+ <obj_property name="ElementShortName">TMM_W_ADDR[15:0]</obj_property>
+ <obj_property name="ObjectShortName">TMM_W_ADDR[15:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/TMM_R_ADDR">
+ <obj_property name="ElementShortName">TMM_R_ADDR[15:0]</obj_property>
+ <obj_property name="ObjectShortName">TMM_R_ADDR[15:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/BAM_W_ADDR">
+ <obj_property name="ElementShortName">BAM_W_ADDR[10:0]</obj_property>
+ <obj_property name="ObjectShortName">BAM_W_ADDR[10:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/BAM_R_ADDR">
+ <obj_property name="ElementShortName">BAM_R_ADDR[10:0]</obj_property>
+ <obj_property name="ObjectShortName">BAM_R_ADDR[10:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/TMM_R_DATA">
+ <obj_property name="ElementShortName">TMM_R_DATA[14:0]</obj_property>
+ <obj_property name="ObjectShortName">TMM_R_DATA[14:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/BAM_R_DATA">
+ <obj_property name="ElementShortName">BAM_R_DATA[14:0]</obj_property>
+ <obj_property name="ObjectShortName">BAM_R_DATA[14:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/FAM_W_ADDR">
+ <obj_property name="ElementShortName">FAM_W_ADDR[7:0]</obj_property>
+ <obj_property name="ObjectShortName">FAM_W_ADDR[7:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/PAL_W_ADDR">
+ <obj_property name="ElementShortName">PAL_W_ADDR[5:0]</obj_property>
+ <obj_property name="ObjectShortName">PAL_W_ADDR[5:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/AUX_W_ADDR">
+ <obj_property name="ElementShortName">AUX_W_ADDR[0:0]</obj_property>
+ <obj_property name="ObjectShortName">AUX_W_ADDR[0:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/CIDX">
+ <obj_property name="ElementShortName">CIDX[5:0]</obj_property>
+ <obj_property name="ObjectShortName">CIDX[5:0]</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/BG_EN">
+ <obj_property name="ElementShortName">BG_EN</obj_property>
+ <obj_property name="ObjectShortName">BG_EN</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/FG_EN">
+ <obj_property name="ElementShortName">FG_EN[127:0]</obj_property>
+ <obj_property name="ObjectShortName">FG_EN[127:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/FG_HIT">
+ <obj_property name="ElementShortName">FG_HIT[127:0]</obj_property>
+ <obj_property name="ObjectShortName">FG_HIT[127:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/X">
+ <obj_property name="ElementShortName">X[8:0]</obj_property>
+ <obj_property name="ObjectShortName">X[8:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/Y">
+ <obj_property name="ElementShortName">Y[7:0]</obj_property>
+ <obj_property name="ObjectShortName">Y[7:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/UR">
+ <obj_property name="ElementShortName">UR[3:0]</obj_property>
+ <obj_property name="ObjectShortName">UR[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/UG">
+ <obj_property name="ElementShortName">UG[3:0]</obj_property>
+ <obj_property name="ObjectShortName">UG[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/UB">
+ <obj_property name="ElementShortName">UB[3:0]</obj_property>
+ <obj_property name="ObjectShortName">UB[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/BG_SHIFT_X">
+ <obj_property name="ElementShortName">BG_SHIFT_X[8:0]</obj_property>
+ <obj_property name="ObjectShortName">BG_SHIFT_X[8:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/BG_SHIFT_Y">
+ <obj_property name="ElementShortName">BG_SHIFT_Y[7:0]</obj_property>
+ <obj_property name="ObjectShortName">BG_SHIFT_Y[7:0]</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/FG_FETCH">
+ <obj_property name="ElementShortName">FG_FETCH</obj_property>
+ <obj_property name="ObjectShortName">FG_FETCH</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/NVSYNC">
+ <obj_property name="ElementShortName">NVSYNC</obj_property>
+ <obj_property name="ObjectShortName">NVSYNC</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/NHSYNC">
+ <obj_property name="ElementShortName">NHSYNC</obj_property>
+ <obj_property name="ObjectShortName">NHSYNC</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/THBLANK">
+ <obj_property name="ElementShortName">THBLANK</obj_property>
+ <obj_property name="ObjectShortName">THBLANK</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/TVBLANK">
+ <obj_property name="ElementShortName">TVBLANK</obj_property>
+ <obj_property name="ObjectShortName">TVBLANK</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/PCEG_RESET">
+ <obj_property name="ElementShortName">PCEG_RESET</obj_property>
+ <obj_property name="ObjectShortName">PCEG_RESET</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject type="group" fp_name="group149">
+ <obj_property name="label">background sprite</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="isExpanded"></obj_property>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/background_sprite/CLK">
+ <obj_property name="ElementShortName">CLK</obj_property>
+ <obj_property name="ObjectShortName">CLK</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/background_sprite/RESET">
+ <obj_property name="ElementShortName">RESET</obj_property>
+ <obj_property name="ObjectShortName">RESET</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/background_sprite/PL_STAGE">
+ <obj_property name="ElementShortName">PL_STAGE</obj_property>
+ <obj_property name="ObjectShortName">PL_STAGE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/background_sprite/OE">
+ <obj_property name="ElementShortName">OE</obj_property>
+ <obj_property name="ObjectShortName">OE</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/X">
+ <obj_property name="ElementShortName">X[8:0]</obj_property>
+ <obj_property name="ObjectShortName">X[8:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/Y">
+ <obj_property name="ElementShortName">Y[7:0]</obj_property>
+ <obj_property name="ObjectShortName">Y[7:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/BG_SHIFT_X">
+ <obj_property name="ElementShortName">BG_SHIFT_X[8:0]</obj_property>
+ <obj_property name="ObjectShortName">BG_SHIFT_X[8:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/BG_SHIFT_Y">
+ <obj_property name="ElementShortName">BG_SHIFT_Y[7:0]</obj_property>
+ <obj_property name="ObjectShortName">BG_SHIFT_Y[7:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/BAM_ADDR">
+ <obj_property name="ElementShortName">BAM_ADDR[10:0]</obj_property>
+ <obj_property name="ObjectShortName">BAM_ADDR[10:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/BAM_DATA">
+ <obj_property name="ElementShortName">BAM_DATA[14:0]</obj_property>
+ <obj_property name="ObjectShortName">BAM_DATA[14:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/TMM_ADDR">
+ <obj_property name="ElementShortName">TMM_ADDR[15:0]</obj_property>
+ <obj_property name="ObjectShortName">TMM_ADDR[15:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/TMM_DATA">
+ <obj_property name="ElementShortName">TMM_DATA[14:0]</obj_property>
+ <obj_property name="ObjectShortName">TMM_DATA[14:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/CIDX">
+ <obj_property name="ElementShortName">CIDX[5:0]</obj_property>
+ <obj_property name="ObjectShortName">CIDX[5:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/T_BAM_ADDR">
+ <obj_property name="ElementShortName">T_BAM_ADDR[10:0]</obj_property>
+ <obj_property name="ObjectShortName">T_BAM_ADDR[10:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/R_BAM_ADDR">
+ <obj_property name="ElementShortName">R_BAM_ADDR[10:0]</obj_property>
+ <obj_property name="ObjectShortName">R_BAM_ADDR[10:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/T_BAM_DATA">
+ <obj_property name="ElementShortName">T_BAM_DATA[14:0]</obj_property>
+ <obj_property name="ObjectShortName">T_BAM_DATA[14:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/R_BAM_DATA">
+ <obj_property name="ElementShortName">R_BAM_DATA[14:0]</obj_property>
+ <obj_property name="ObjectShortName">R_BAM_DATA[14:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/T_TMM_ADDR">
+ <obj_property name="ElementShortName">T_TMM_ADDR[15:0]</obj_property>
+ <obj_property name="ObjectShortName">T_TMM_ADDR[15:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/R_TMM_ADDR">
+ <obj_property name="ElementShortName">R_TMM_ADDR[15:0]</obj_property>
+ <obj_property name="ObjectShortName">R_TMM_ADDR[15:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/T_TMM_DATA">
+ <obj_property name="ElementShortName">T_TMM_DATA[14:0]</obj_property>
+ <obj_property name="ObjectShortName">T_TMM_DATA[14:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/R_TMM_DATA">
+ <obj_property name="ElementShortName">R_TMM_DATA[14:0]</obj_property>
+ <obj_property name="ObjectShortName">R_TMM_DATA[14:0]</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/background_sprite/PIXEL_ABS_X">
+ <obj_property name="ElementShortName">PIXEL_ABS_X</obj_property>
+ <obj_property name="ObjectShortName">PIXEL_ABS_X</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/background_sprite/PIXEL_ABS_Y">
+ <obj_property name="ElementShortName">PIXEL_ABS_Y</obj_property>
+ <obj_property name="ObjectShortName">PIXEL_ABS_Y</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/background_sprite/TILE_IDX_X">
+ <obj_property name="ElementShortName">TILE_IDX_X</obj_property>
+ <obj_property name="ObjectShortName">TILE_IDX_X</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/background_sprite/TILE_IDX_Y">
+ <obj_property name="ElementShortName">TILE_IDX_Y</obj_property>
+ <obj_property name="ObjectShortName">TILE_IDX_Y</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/TILE_PIDX_X">
+ <obj_property name="ElementShortName">TILE_PIDX_X[3:0]</obj_property>
+ <obj_property name="ObjectShortName">TILE_PIDX_X[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/TRANS_TILE_PIDX_X">
+ <obj_property name="ElementShortName">TRANS_TILE_PIDX_X[3:0]</obj_property>
+ <obj_property name="ObjectShortName">TRANS_TILE_PIDX_X[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/TILE_PIDX_Y">
+ <obj_property name="ElementShortName">TILE_PIDX_Y[3:0]</obj_property>
+ <obj_property name="ObjectShortName">TILE_PIDX_Y[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/TRANS_TILE_PIDX_Y">
+ <obj_property name="ElementShortName">TRANS_TILE_PIDX_Y[3:0]</obj_property>
+ <obj_property name="ObjectShortName">TRANS_TILE_PIDX_Y[3:0]</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/background_sprite/TRANS_TILE_PIDX">
+ <obj_property name="ElementShortName">TRANS_TILE_PIDX</obj_property>
+ <obj_property name="ObjectShortName">TRANS_TILE_PIDX</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/background_sprite/TILEMAP_WORD_OFFSET">
+ <obj_property name="ElementShortName">TILEMAP_WORD_OFFSET</obj_property>
+ <obj_property name="ObjectShortName">TILEMAP_WORD_OFFSET</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/background_sprite/PIXEL_BIT_OFFSET">
+ <obj_property name="ElementShortName">PIXEL_BIT_OFFSET</obj_property>
+ <obj_property name="ObjectShortName">PIXEL_BIT_OFFSET</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/TMM_DATA_PAL_IDX">
+ <obj_property name="ElementShortName">TMM_DATA_PAL_IDX[2:0]</obj_property>
+ <obj_property name="ObjectShortName">TMM_DATA_PAL_IDX[2:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/background_sprite/T_CIDX">
+ <obj_property name="ElementShortName">T_CIDX[5:0]</obj_property>
+ <obj_property name="ObjectShortName">T_CIDX[5:0]</obj_property>
+ <obj_property name="isExpanded"></obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject type="group" fp_name="group142">
+ <obj_property name="label">display coordinates</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="isExpanded"></obj_property>
+ <wvobject type="array" fp_name="/ppu_tb/uut/display_controller/T_POS_X">
+ <obj_property name="ElementShortName">T_POS_X[8:0]</obj_property>
+ <obj_property name="ObjectShortName">T_POS_X[8:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/display_controller/T_POS_Y">
+ <obj_property name="ElementShortName">T_POS_Y[7:0]</obj_property>
+ <obj_property name="ObjectShortName">T_POS_Y[7:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/display_controller/U_POS_X">
+ <obj_property name="ElementShortName">U_POS_X[8:0]</obj_property>
+ <obj_property name="ObjectShortName">U_POS_X[8:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/display_controller/U_POS_Y">
+ <obj_property name="ElementShortName">U_POS_Y[7:0]</obj_property>
+ <obj_property name="ObjectShortName">U_POS_Y[7:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/display_controller/N_POS_X">
+ <obj_property name="ElementShortName">N_POS_X[9:0]</obj_property>
+ <obj_property name="ObjectShortName">N_POS_X[9:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/display_controller/N_POS_Y">
+ <obj_property name="ElementShortName">N_POS_Y[8:0]</obj_property>
+ <obj_property name="ObjectShortName">N_POS_Y[8:0]</obj_property>
+ </wvobject>
+ <wvobject type="group" fp_name="group276">
+ <obj_property name="label">active</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/NACTIVE">
+ <obj_property name="ElementShortName">NACTIVE</obj_property>
+ <obj_property name="ObjectShortName">NACTIVE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/NHACTIVE">
+ <obj_property name="ElementShortName">NHACTIVE</obj_property>
+ <obj_property name="ObjectShortName">NHACTIVE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/NVACTIVE">
+ <obj_property name="ElementShortName">NVACTIVE</obj_property>
+ <obj_property name="ObjectShortName">NVACTIVE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/TACTIVE">
+ <obj_property name="ElementShortName">TACTIVE</obj_property>
+ <obj_property name="ObjectShortName">TACTIVE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/THACTIVE">
+ <obj_property name="ElementShortName">THACTIVE</obj_property>
+ <obj_property name="ObjectShortName">THACTIVE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/TVACTIVE">
+ <obj_property name="ElementShortName">TVACTIVE</obj_property>
+ <obj_property name="ObjectShortName">TVACTIVE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/display_controller/ACTIVE">
+ <obj_property name="ElementShortName">ACTIVE</obj_property>
+ <obj_property name="ObjectShortName">ACTIVE</obj_property>
+ </wvobject>
+ </wvobject>
+ </wvobject>
+ <wvobject type="group" fp_name="group115">
+ <obj_property name="label">pipeline stages</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="isExpanded"></obj_property>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/pipeline_clock_edge_generator/CLK">
+ <obj_property name="ElementShortName">CLK</obj_property>
+ <obj_property name="ObjectShortName">CLK</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/pipeline_clock_edge_generator/RESET">
+ <obj_property name="ElementShortName">RESET</obj_property>
+ <obj_property name="ObjectShortName">RESET</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/pipeline_clock_edge_generator/SPRITE_BG">
+ <obj_property name="ElementShortName">SPRITE_BG</obj_property>
+ <obj_property name="ObjectShortName">SPRITE_BG</obj_property>
+ </wvobject>
+ <wvobject type="other" fp_name="/ppu_tb/uut/pipeline_clock_edge_generator/SPRITE_FG">
+ <obj_property name="ElementShortName">SPRITE_FG</obj_property>
+ <obj_property name="ObjectShortName">SPRITE_FG</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/pipeline_clock_edge_generator/DONE">
+ <obj_property name="ElementShortName">DONE</obj_property>
+ <obj_property name="ObjectShortName">DONE</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/pipeline_clock_edge_generator/READY">
+ <obj_property name="ElementShortName">READY</obj_property>
+ <obj_property name="ObjectShortName">READY</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject type="group" fp_name="group126">
+ <obj_property name="label">aux</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/aux/CLK">
+ <obj_property name="ElementShortName">CLK</obj_property>
+ <obj_property name="ObjectShortName">CLK</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/aux/RESET">
+ <obj_property name="ElementShortName">RESET</obj_property>
+ <obj_property name="ObjectShortName">RESET</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/aux/AUX_WEN">
+ <obj_property name="ElementShortName">AUX_WEN</obj_property>
+ <obj_property name="ObjectShortName">AUX_WEN</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/aux/AUX_ADDR">
+ <obj_property name="ElementShortName">AUX_ADDR[0:0]</obj_property>
+ <obj_property name="ObjectShortName">AUX_ADDR[0:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/aux/AUX_DATA">
+ <obj_property name="ElementShortName">AUX_DATA[15:0]</obj_property>
+ <obj_property name="ObjectShortName">AUX_DATA[15:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/aux/BG_SHIFT_X">
+ <obj_property name="ElementShortName">BG_SHIFT_X[8:0]</obj_property>
+ <obj_property name="ObjectShortName">BG_SHIFT_X[8:0]</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/aux/BG_SHIFT_Y">
+ <obj_property name="ElementShortName">BG_SHIFT_Y[7:0]</obj_property>
+ <obj_property name="ObjectShortName">BG_SHIFT_Y[7:0]</obj_property>
+ </wvobject>
+ <wvobject type="logic" fp_name="/ppu_tb/uut/aux/FG_FETCH">
+ <obj_property name="ElementShortName">FG_FETCH</obj_property>
+ <obj_property name="ObjectShortName">FG_FETCH</obj_property>
+ </wvobject>
+ <wvobject type="array" fp_name="/ppu_tb/uut/aux/INT_REG">
+ <obj_property name="ElementShortName">INT_REG[31:0]</obj_property>
+ <obj_property name="ObjectShortName">INT_REG[31:0]</obj_property>
+ </wvobject>
+ </wvobject>
+</wave_config>
diff --git a/docs/architecture.md b/docs/architecture.md
index 9a77e57..dd34426 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -235,20 +235,11 @@ Important notes:
## Pipeline stage reference
-This table describes which components use which lines during pipeline stages
-1-5. The pipeline stages happen for every pixel, and is run on the system clock
-(100 MHz).
-
-|Stage|Component|Action|To|Type|
-|-|-|-|-|-|
-|1|`ppu_sprite_bg`|write|BAM address|bus|
-|2|`ppu_sprite_bg`|read|BAM data|bus|
-|2|`ppu_sprite_fg`|write|TMM address|bus|
-|3|`ppu_sprite_bg`|write|TMM address|bus|
-|3|`ppu_sprite_fg`|read|TMM data|bus|
-|4|`ppu_sprite_bg`|read|TMM data|bus|
-|5|`ppu_pceg`|write|pixel done|flag|
-|6|`ppu_pceg`|write|pixel ready|flag|
+![Pipeline stage diagram](../assets/ppu-pipeline.svg)
+
+This diagram describes which components use which lines during pipeline stages
+0-9. The pipeline stage counter is reset after every pixel, and is run on the
+system clock (100 MHz).
## Registers
diff --git a/docs/ppu.drawio b/docs/ppu.drawio
index 7d4d400..52160c1 100644
--- a/docs/ppu.drawio
+++ b/docs/ppu.drawio
@@ -1 +1 @@
-<mxfile host="Electron" modified="2023-03-12T08:38:04.645Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.8.16 Chrome/106.0.5249.199 Electron/21.4.0 Safari/537.36" etag="52K4OrVv843H2dPzCX49" version="20.8.16" type="device" pages="4"><diagram name="level-1" id="DBE48RpXtx8JnoEt3ekA">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</diagram><diagram id="MdQQJuunD4ehtDpxKxax" name="level-2">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</diagram><diagram id="lj51MlK96fuJFRP7cw84" name="level-3">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</diagram><diagram id="1ySgP4OewCsUoPnmkRD4" name="display">7VhNc9owEP01zKSHdGwMDj3GQJNDmSFDkpKjsIWtIlseWWC7v74rW8YYy4RMPtrM9MJIT1pp973dRdCzxmF2w1EczJiHaa9veFnPmvT6/aFtw6cE8hKwBlcl4HPilZBZAwvyGyvQUOiWeDhpbBSMUUHiJuiyKMKuaGCIc5Y2t60Zbd4aIx+3gIWLaBv9STwRlOhoaNT4LSZ+UN1sGmolRNVmBSQB8lh6AFnTnjXmjIlyFGZjTCV3FS+l3feO1b1jHEfiHIMc3T49zCaLNLuZi4eZCB9v0GW/PGWH6FYFrJwVecWAz9k2VtswFzjT8Y5W1Xaj7Ze5jxayBLMQC57DlrTm07KUWXDAZb8iGSkN/b1tHSYMVKT6qKeDzdrYDl22/LYYJKPbu3v7ThO1g9yNDDTyZEwo2sGdfZuCJ86Kw8iXowt7YGSDkfGlxVFhieWVBuxLAyLwIkauXE2hLAALRAguTkwYShYJZNg1JX4E2IoJwUJYSMCERL7cJo9pE3lSwmNt2oRXq4rWvDk9lKOvk2PwXnKYGj2uZwBcwI1jDd1QSnHBLcpjRiQ7TrLBwg2UAGtC6UJtTxiVlztJ2VpsGBY2mE93QGyiRCmwIrCh0xtO1CFjRhkHMGIRGDscwykq1eU9nAkkDuYx5gQowdLExfKOeY04SYTiezYvHS4u9VASFFlzMi2QAihey0gpWmE6ZwkRhEmYlxLt7X8crYfE86SHB+l1efUe6XWQQNr8eYP00XpofkQP6+amu86OCs1uF5p5pSHKtN6t0FpMzecPADwSnMaMC03Lg1aQQeW/suVpaqmR+2fybXZI+IpWZ9o6Bd4iV/UKWC0JEpdjHP3vdv9Etzs/wz6g22kzqJ1A1w9LAJ5aeYM9eMmqKaYrlk5rwGmWL9R+wHwWAZ+MxUqiX1iIXL3I0VawZkkDjzxfSvuvw2r6pI4rJpOsMcvVrON5CJ6zLXfxqdpRlArEfSyeb3My/pMSckyRILvmS//tS77ddUvFln9NsYZetXwdihWewLgquVeJOPqUGo6ef2K86Puw0Qo1rTcRnG3wEdhJ+hnd6sQX4Mc+9Y3PzmTWyaT2V5P5ciZhWv8rUKwd/LViTf8A</diagram></mxfile> \ No newline at end of file
+<mxfile host="Electron" modified="2023-03-29T15:34:42.504Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.8.16 Chrome/106.0.5249.199 Electron/21.4.0 Safari/537.36" etag="y_Tz0g61eYKg321pPkIq" version="20.8.16" type="device" pages="5"><diagram name="level-1" id="DBE48RpXtx8JnoEt3ekA">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</diagram><diagram id="MdQQJuunD4ehtDpxKxax" name="level-2">7Vxbe6JIEP01eXQ+7uqjcXPZL8kkM0km+9pCi0wamm0aL/Prt5FGLk0QjChunJdIUdhQdapOdVHOhTp2lzcE+LMHbEF0oUjW8kL960JRZLk/YH8iySqW9BU1FtjEsbhSKnh2/kAulLg0dCwY5BQpxog6fl5oYs+DJs3JACF4kVebYpRf1Qc2FATPJkCi9M2x6CyWDnQpld9Cx54lK8sSP+OCRJkLghmw8CIjUq8u1DHBmMaf3OUYosh4iV3i664/OLu5MQI9WucCfTwdzm+1+Z/Hu/lKDxG5/X3fM/rx18wBCvkTBz5xKIwu9KaY3zpdJfaAFjMPP8SEzrCNPYCuUuklwaFnwWhRiR0F75CaM36QXnCPsc+EMhP+hpSuuONBSDETzaiL+NmN1dZfRgGho8irTOBhDyayawchrjOHhDrMfyPk2B6TuY5lre8r8IHpePYlphS77MSAyUQbcrMGOCQmrDCcloAREBvSCkWd4z0yXGYJ7qMbiF1IyYopEIgAdeZ53AEOX3ujt7n0CTvsplMVPJ0G7E4yEGAfMiukojUwGoCkrwsgeXl42AEazJl+dHaK4JK78WBwmSBsvpfgBXpWAVFMkjm/O0QSz2+FiCa1AhH2WGCVUfAjwAQlCOLJWk2SGk/V8qCQUJrpsw/xHRwcr0lsZvB6Ccx3ew21yHOVGS4PyMWMqT6z1BGdXTCOy+PtQ3REaQguK73Jzypa3ozJ4SJDN1w0yzBNIitzf86gTa1niNF+poRalFA33vV+zXjnCJG+cZd0mCLUPVHEkaFSxlAWCGbrO6oM+Cw8vpPV34rnuX0zZJBb6iG8s3p7R0e7bCDLzdhgi/5HbJBwST9/dU8ppLfYvPyqFihDxO81JrCjlCHrO1GG1hZlJM7LWM9GeALQ+kERC9HYdBZ7vJNLCZ8gBK1uAThoJeQPWnNpAgTG2PVx4FBMjh4wxRrrkBFD/u3rVjAEsvWo/lg++tri7r4nCyb5P8eBXjcO2tkrN6U+xSik1y3Up3xKvdi2KfLqsEo9T6s7BHMpOpUzOiu2lWd0ZrQHh0enuD/9dTOKPM12d1HJ8bWhO7z7cRO+fn8bTaX7y1er9/rLe+u1g1yxipfyaNClAn/GNypU8Y07VR+s82Gnqlr/iJ0qEcvU8SJT5CEt2dCDBHSxlNKkeqWU0drm42vVUoO6bKXvO+Y/5yVFQDqxJxvB2YOH8ODB89tA7MQ/je538HYX3xwdAgIdeTNUKDlVbQvfVut/uiysNGoWa5veE8L4PfQ7R56qUo88W+vcGcOvlHrrv5HVukWeQwHal6NTewG/fyKV6nqzGxt3tRD8xpYkWqneTg5Nck8GaKPXf04MaC3wdd1hn47ytbxtf1yt3w7WdPGV23Pylo25yILd2+vKxrHpWqxxfGcZj1wCCr4Ul/ePxuW7tW2LjdWmndWq1upBRz3EN33XJ1eMtMARJbVl1RzIkeE4bFSLVGo3He2Qa3aF90Y04oxz14imONBxdKLpG4LNziO/25OAcWKFolYI7G1DXlv02ykUDbGJ+OIg6LI4VCQXupjj/ZgBrBen30oCWFYOGsFiqXjuGdTvGRjdoGnNaMTT1eothae4j8tN2wNKiTMJ13Tb0WgtmQZrLVhLRxpEEwYmgdCLHjQaoXOwJxiNPSstxBEl+B2OMcIkjZ0pC5uCCPA5eJNZkBU/FQPyZa7IOwuBCUSpv5OVLDgFIaJ7qo6KEy/9En9JJf4qDhHvLbkmQMi+a3h6ZYKfUYqVJmHwOYwXHULxWgET5w/2KEjyoOUQaK7Bwb4EBjTjWxJbIfmJw8s6FUup4Ce3UuVPHuq7SJO2RpRa4iB1Hx6q2mWdHbTMO6SZf+R9TG1UTSRl/OPFNHpCoy8bGtmyS9PbMqIiGPELTMIdc8Ct2JQzWhpwK66jD5s1Cwv6zZuFJSN0w2/D7L/8esU8sfPPddhh+pP4WD39jwXUq/8A</diagram><diagram id="lj51MlK96fuJFRP7cw84" name="level-3">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</diagram><diagram id="1ySgP4OewCsUoPnmkRD4" name="display">7VhNc9owEP01zKSHdGwMhB5joMmhzJAhpOQobGGryF6PLLDdX9+VLccYG0ImH21meor0pNVq39tdK3SsUZDeCBL5U3Ap73QNN+1Y4063a/bMHv5RSFYgw8FVAXiCuXpTBczZb6pBQ6Nb5tK4tlECcMmiOuhAGFJH1jAiBCT1bWvgda8R8WgDmDuEN9GfzJW+jqJvVPgtZZ5fejYNvRKQcrMGYp+4kOxB1qRjjQSALEZBOqJckVfyUth9P7L6dDFBQ3mOQUZuHxfT8TxJb2ZyMZXBww257Ban7Ajf6oD1ZWVWMuAJ2EZNZ9r/jgpJ0zYpyKo8oYoW04RCQKXIcF9S8WlZmiR/j8tuSTLRGnpPtlWYONCRtkc96W3WxrbvwPLbvBcPb+/uB3ctUdvE2ahAQ1cFQMId+uwOON7EXgkceWp0MegZaW9ofGlwlFtS5dLAfYnPJJ1HxFGrCdYFYr4M8IpjE4eKMoYZds2ZFyK2AikhwIUYTVjoqW3qmCbnJyU8FKJJeLmqac3q0305um1y9N5LDrNFj+spAhfocdRCN5ZSlHNLsgiYYseON1Q6vhZgzTif6+0xcOXcjovWMsBhbkPFZIfExlqUHMsD69ud/lgfMgIOAsEQQjS2BcVTdF4rPwIkkXvziAqGlFBl4lDlY1YhdhyS6B5mxYVzpy6J/TxrTqYF0QCnaxUpJyvKZxAzyUDBopDoyf7HwXrAXFfdcC+9Lq/eI732Eqg1f94gfVpvaDay59we9qKAz29spdVBoQ2ahWZetRBlWu9WaA2mZrMFAg+MJhEI2dLysBWkWPmvbHkttVTL/TOlOfbNeUWrMwdtCrxFrrYrYDUkiB1Bafi/2/0T3e78DPuAbteaQc0Eul4sEXhs5A118SWrp5SvIJlUgF0vX6x9HzwIkU+ASEv0i0qZ6Rc52UqolzTyKLKlsv/aL6eP+rh8Mk5rs0zPjr4kY9gKh56qHU2pJMKj8vk2p+I/KaGgnEi2q7/0377km123UGz51xSr6VXJd0Sx/CY4LkvuVSIOP6WGw+efGC/6HtZaYUvrjaWADT0Aj5J+Rrc68QH82Ke+8dmZTI8y2fpfk/lyJnFa/SqQr+39tmJN/gA=</diagram><diagram id="xwm_nTvbWLU7bshfNvv3" name="pipeline">7Vxbc6M2FP41fswMl9jAY+ykSaeTbqbuzq6fMjLIQIMRI+QY768vMgIDR06TDRZb7JeMOIAkvk/nKjkjc7bO7ilKgkfi4WhkaF42Mm9HhuFY4/wvF+wKwdixC4FPQ68Q6QfBPPyBhVAT0k3o4bTxICMkYmHSFLokjrHLGjJEKdk2H1uRqDlqgnwMBHMXRVD6LfRYUEjtsXaQP+DQD8qRdU3cWaPyYSFIA+SRbU1k3o3MGSWEFa11NsMRx67EpXjvtyN3q4lRHLP3vBB/mz371CTzdDd7sJ2HH4G7uDKKXl5RtBEfLCbLdiUCOPZuOJD5VUziXDj1UBpg3queXwRsHYkmJZvY29/Q8iuSIDdknPYxv4TTFV+AvQYDYvL3mKwxo7v8ge0B9xL2oAZ5KaM4Qix8bfKGBP1+1V01whMJ85kYmlipui36EQtVL/stu0jJhrpYvFXH+VhH5YsMUR8z8GLeqH3mQbSn7QMUmhcKBfLGpCMKq44UUXh9oVAgb153RGHVkSIKxxcKBfLXRkcUVh0ponByoTAru+mIwqojRRRaFwpL5LsKZ8aKwxn7QqFAftJVODNRHM44FwoF8lZX4YylOJwpP/VjHB6l7VfnydH0Bk/tyOPduV/LcSqOYAwYwiTJ5jlNaMjw89IHFDKcsSZvKaPkBc9IROiB11UYRS0RikI/zi9pwcX0FVMWuii6EfJ16Hl8lOk2yMee52rLh9xSlIDFkXKdjv2/BKvGW+uFD4OzN1eMgN4U0NcWUMVOfQWZ2vHF0uDno2SUFawaGdoJCHBziDD9HAOfgbu98mt42xK42xrRHdwGgFsfMNx233DDshP0EIOBuyoI9QY3LBGZw4W7Kt70Bjcs51wPF+6q0NIb3DBuGQ8X7nHvrhKWSSYDhrt3VwlLGtZw4Z707SoNCPf05pGP5HkUpymAPg1QwpsBzpBPcsSmCaZhPhmOZil9KkXGESBrzK3CDJdb2XsmRVMTBM7F2GjDCMyGym3i/dMkZuXT112GjW8kSROVSZIJk6Raxro6q4zV6jtjNWEK9ffjRXOkmiMjS63mwIzAjV7OQl/+S0FO5lpM6Fq4tUpcfFaGStd7t1RwiyHJTcf+5BkHsV9D1bHpAZsIEvhlEVYX6O+W1p/W/SKZLbZfXlbudrL65+sV3Bso3ISHGOoX+hOgLQmRlIL9a/vkjpd6++CByvhUij6scpZ2hmLk7YaFvt0+uaPQ0MhTOZgdAMQHtAvZ3j38+SOopzt2o+nf083i9vfvcRYvrpzZH/Z8KXEI76BpkBv+QIV+lkL7dFvHUgqhmzlXCp2utNBRrIXQV9mAw8GUGS2FW0RStGH67QwXbbvvHSIDJnxFUXcQOUf7yLTCnEOeXkNTMqAMr422pJR3KrSllgRufoZctXuF+eCzLa3t6LlV+9K83wEr7eBXoQ7IY1p4BCCMk03uuScRN+pLmrd8trfpaBlGHI0zp0xlvhg4MY5u7/wlTZ5Sd5Xt5l/vJHnI/1STAAcSpt5Ni0L7JmUFphbnyEr7l20K7ZuUFejiL6z0ryswqzhHVtq/fOlbVyShwBmy0i7O960rg4mbP8VKu+J4Ol3JLw//raIoWh3+5Yd59y8=</diagram></mxfile> \ No newline at end of file