Tento dokument popisuje časování propagace změny obsahu VRAM do generovaneho obrazu v MZ-800 grafických režimech (DMD bit 3 = 0). Pro MZ-700 textový režim viz 09-mz700-fetch-pipeline.md.
Klíčová otazka: Jak daleko před paprskem musí byt CPU zápis do VRAM, aby se změna projevila na aktualnim řádku?
Každý ze 40 sloupců na řádku vyžaduje přesně 2 DRAM čtení v page-mode (společný RAS, 2 ČAS cykly):
| Čtení | CLK0 offset | Účel |
|---|---|---|
| 1 | +0 | Plane I data (VA bus) |
| 2 | +4 | Plane II data (VA bus), případně VC bus |
Každý sloupec trvá 16 CLK0. Dve čtení jsou rozlozena s mezerou 4 CLK0 v prvních 8 CLK0 sloupce. Zbylych 8 CLK0 slouzi pro interspersed DRAM operace (viz nize).
Pozn.: Dokument 11 uvadel 160 čtení/řádek (40×4). Správný počet je 80 video čtení (40×2). Dodatecna DRAM čtení během viditelné oblasti nejsou video data fetch — viz sekce Mystery reads.
| Režim | RAS | ČAS 1 (plane I) | ČAS 2 (plane II) |
|---|---|---|---|
| 320x200/4c | 0xB0+N | 0x88/0x89 | 0xC8/0xC9 |
| 640x200/2c | 0xB0+N | 0x92/0x93 | 0xD2/0xD3 |
| 320x200/16c | 0xB0+N | 0x9C/0x9D | 0xDC/0xDD |
Pozn.: RAS = 0xB0+N plati pro konkrétní řádek (raster line). Na jiných radcich ma RAS jinou základní hodnotu, ale vždy +1 za každý sloupec.
Kazde čtení produkuje 8 bitu na VA bus (roviny I+II) a současně 8 bitu na VC bus (roviny III+IV). Jedno čtení = 8 pixelů jedne roviny. Pro 4-barevný režim (2 roviny) staci 2 čtení na kompletní sloupec dat.
V režimu 320x200 (DMD=0x00, 0x02) jsou mezi každý video sloupec vlozena další DRAM čtení na adrese DRAM 0x0040 (RAS=0x00, ČAS=0x40). Časování: CLK0 +12 od zacatku sloupce.
| Fáze v ramci sloupce | CLK0 offset | Operace |
|---|---|---|
| Video read 1 | +0 | Plane I data |
| Video read 2 | +4 | Plane II data |
| (mezera) | +8 | — |
| Mystery read | +12 | DRAM 0x0040 |
V režimu 640x200 (DMD=0x04) tyto mystery reads nenastávají.
Prakticky dopad: mystery reads obsazuji DRAM sbernici, cimz prodluzuji dobu od CPU zápisu do DRAM aktualizace v režimu 320x200 oproti 640x200 (38 vs 22 CLK0 pro free write).
CLK0: 0 329 340 957 1135
| | | | |
| refresh | | 40 sloupcu x 16 CLK0 | |
| + mystery | = 640 CLK0 | |
| | | | |
| prefetch | canvas start prefetch |
| col 0 | col 39 end |
| Udalost | CLK0 | Poznámka |
|---|---|---|
| Prefetch col 0 | 329 | První DRAM čtení |
| HBLN visible | 335 | Status Register bit 7 = 1 |
| Canvas start | 340 | První pixel na výstupu |
| Col N prefetch | 329 + N×16 | První DRAM čtení pro sloupec N |
| Col 39 prefetch | 953 | Poslední video sloupec |
| Col 39 konec | 957 | Poslední DRAM čtení |
| HBLN blank | 975 | Status Register bit 7 = 0 |
Od prvniho DRAM čtení (CLK0 329+N×16) k prvnimu pixelů na výstupu = ~8 CLK0 (~0.45 us).
To odpovídá situaci: - CLK0 +0: čtení plane I (8 pixelů) - CLK0 +4: čtení plane II (8 pixelů) - CLK0 +8: první pixel na výstupu
Pipeline tedy zpracovava data za 4 CLK0 od posledniho čtení. To je vyrazne méně než v MZ-700 textovém režimu (19 CLK0), protože není třeba CG lookup.
Dokument 11 uvaděl pipeline latenci 3 CLK0 pro MZ-800 režimy. Toto číslo odpovidalo rozdílu HBLN visible (CLK0 335) a canvas start (CLK0 340), ne skutečně latenci pipeline od DRAM čtení.
Správná hodnota: 8 CLK0 od prvniho DRAM čtení k prvnimu pixelů na výstupu (ověřeno přímo změnou VRAM v presnem CLK0 a sledovanim IGRB přechodu).
GDG používá late write (read-modify-write) pro CPU zápisy. DRAM bunka se aktualizuje až po skonceni CPU cyklů — GDG provede DRAM zápis v dalším volnem slotu.
| Situace | CPU cyklus | DRAM latence | Celkem | WAIT |
|---|---|---|---|---|
| Blanking, 320x200 | 19 CLK0 | +10 CLK0 | 29 CLK0 | 0 TW |
| Blanking, 640x200 | 18 CLK0 | +11 CLK0 | 29 CLK0 | 0 TW |
| Visible free, 320x200 | 18 CLK0 | +20 CLK0 | 38 CLK0 | 0 TW |
| Visible free, 640x200 | 17 CLK0 | +5 CLK0 | 22 CLK0 | 0 TW |
| Visible WAIT, 320x200 | 30 CLK0 | +1 CLK0 | 31 CLK0 | 3 TW |
| Visible WAIT, 640x200 | 30 CLK0 | +1 CLK0 | 31 CLK0 | 3 TW |
Vysvětlení sloupců: - CPU cyklus: délka Z80 write cyklů (T1-T3 + WAIT) - DRAM latence: doba od konce CPU cyklů do aktualizace DRAM bunky - Celkem: doba od zahajeni CPU zápisu do DRAM aktualizace - WAIT: počet wait T-stavu (0 pro free write, 3+ pro penalizovany)
V režimu 320x200 jsou mystery reads vlozeny mezi video sloupce a obsazuji DRAM sbernici. GDG musí cekat na volný slot pro CPU zápis, což prodluzuje DRAM latenci: - 320x200: 20 CLK0 navíc (musí cekat na mezeru po mystery read) - 640x200: 5 CLK0 navíc (žádné mystery reads, vice volnych slotu)
Pro změnu sloupce N na aktualnim řádku musí byt DRAM aktualizace dokoncena před CLK0 329 + N×16 (zacatek video fetch).
Minimalni před-start CPU zápisu:
| Režim | Během blanking | Během visible (free) |
|---|---|---|
| 320x200 | CLK0 300+N×16 | CLK0 291+N×16 |
| 640x200 | CLK0 300+N×16 | CLK0 307+N×16 |
Příklad pro sloupec 20 (stred obrazovky): - Blanking: CPU musí zahajit zápis před CLK0 620 - Visible 320x200: před CLK0 611 - Visible 640x200: před CLK0 627
Změny VRAM během HBLN blanking se VŽDY projeví na následujícím řádku. Ověřeno simulací v obou režimech (640/640 pixelů).
Bezpečné okno pro blanking zápisy: CLK0 957 až 329 = 508 CLK0 (~28.6 us, ~101 T-stavu CPU).
První CPU zápis do VRAM během visible oblasti neobdrzi WAIT. Druhý a další zápisy dostavaji WAIT (3-6 TW).
Pro jediný zápis ("painting ahead of beam"): 1. CPU zahaji zápis během visible oblasti 2. Zápis trvá 38 CLK0 (320x200) nebo 22 CLK0 (640x200) celkem 3. Pokud cilovy sloupec ještě nebyl precten, změna se projeví
Ale: po tomto jednom zápisu následuje "horka fáze" (32 CLK0 v 320x200, 17 CLK0 v 640x200). Další zápis dostane WAIT.
LDIR provádí střídavě READ + WRITE. READ v MZ-800 režimu nepenalizuje (viz dokument 15). Mezi WRITE a následujícím READ další iterace uplyne ~70 CLK0, což je za hranici horke fáze. LDIR do VRAM tedy běží bez WAITu — ale každý zápis produkuje DRAM aktualizaci se zpozdenim.
| Vlastnost | 320x200/4c | 640x200/2c | 320x200/16c | 0x03 (nedok.) | 0x07 (nedok.) |
|---|---|---|---|---|---|
| Video čtení/řádek | 80 (40×2) | 80 (40×2) | 80 (40×2) | 284 | 182 (81×2) |
| Mystery čtení/řádek | 39 | 0 | 39 | 0 | 0 |
| Prefetch CLK0 | 329 | 329 | 329 | 329 | 329 |
| Pipeline latence | ~8 CLK0 | ~8 CLK0 | ~8 CLK0 | ~8 CLK0 | ~8 CLK0 |
| Visible free latence | 38 CLK0 | 22 CLK0 | 38 CLK0 | ~22 CLK0* | 22 CLK0 |
| Bezpečné blanking okno | 508 CLK0 | 508 CLK0 | 508 CLK0 | 508 CLK0 | 508 CLK0 |
(*) DMD=0x03 nemá mystery reads (na rozdíl od 0x00/0x02), proto ma kratsí visible free latenci priblizne odpovídající 640x200.
16-barevný režim (DMD=0x02) ma stejně časování jako 4-barevný (DMD=0x00), včetně mystery reads. Jediný rozdíl: ČAS adresy (0x9C/0xDC místo 0x88/0xC8).
DMD=0x03 (320x200, bits[1:0]=11): Hybridni režim s 284 video ctenimi (jako Frame B), ČAS zaklady 0x0A, 0x4A, 0xBE, 0xFE. Používá VC bus (roviny III+IV), VA bus je ignorovan. Na rozdíl od 0x00/0x02 nemá mystery reads, což znamená vice volnych slotu pro CPU DRAM zápisy během viditelné oblasti.
DMD=0x07 (640x200, bits[1:0]=11): Identický DRAM fetch pattern jako 0x06 (182 čtení, ČAS 0x0A/0x4A/0xFE). Používá VC bus (plane III) pro oba bity paletoveho indexu, plane I (VA) je ignorovan. Z hlediska propagace VRAM zápisu se chova identický jako ostatní 640x200 režimy.
Simulace (HDL): Všechny hodnoty pochází z gate-level simulace
(GDG_core.vhd + cocotb testbenche test_mz800_propagation.py
a test_dmd_undocumented.py).
Ověřeno: - Fetch timing: 2 video čtení/sloupec, 16 CLK0/sloupec, start CLK0 329 - Pipeline latence: ~8 CLK0 (přímo měření VRAM flip + IGRB) - DRAM adresy: 3 režimy (4c, 2c, 16c), ČAS rozlišení dle režimu - Mystery reads: 39/řádek v 320x200 (DMD=0x00, 0x02), 0 v 640x200 - Blanking propagace: 640/640 pixelů (320x200), 638/640 (640x200) - CPU write timing: blanking 29 CLK0, visible 22-38 CLK0, WAIT 31 CLK0 - Nedokumentované režimy (test_all_dmd_overview, test_vram_plane_usage): - DMD=0x03: 284 vid čtení, 0 mystery, ČAS 0x0A/0x4A/0xBE/0xFE, VC only - DMD=0x07: 182 vid čtení, 0 mystery, ČAS 0x0A/0x4A/0xFE (= 0x06)
Reálně HW: Ještě neověřeno.