.. vim: noexpandtab fileencoding=utf-8 nomodified wrap textwidth=270 foldmethod=marker foldmarker={{{,}}} foldcolumn=4 ruler showcmd lcs=tab\:|- list tabstop=8 noexpandtab nosmarttab softtabstop=0 shiftwidth=0 :date: 2026.06.26 02:20:12 :_modified: 1970.01.01 00:00:00 :tags: HW :authors: Gilhad :summary: CPLD ATF2 :title: CPLD ATF2 :nice_title: |logo| %title% |logo| %HEADER% CPLD ATF2 -------------------------------------------------------------------------------- * Dokud je !A_HALT aktivní, je aktivní i !HALT (následkem toho CPU "zanedlouho" (=pár taktů E) nastaví BA=1 jako potvrzení, že je HALT režim) * Pokud je HALT režim (tedy platí BA=1), karta MHF_A má plný přístup k RAM a nic jiného (registry, devices, EMS ...) se nepoužívá (každá adresa je v RAM) (a MR=0000 díky ATF1) * Když je nastaveno dekóduje pouze Rw a E na Read a Write a MR nastaví na 0000 (native RAM), jinak nemá výstupy * Pokud není HALT režim (tedy platí BA=0), ATF1 dekóduje adresy, stará se o jednoduchá zařízení na adresách A020..A0FF a o RAM a ROM signály mimo EMS oblasti * !Read = E & Rw * !Write = E & !Rw * podle jumperu BootFrom (BootSrc) při restartu nastaví, zda bude ROM defaultně připojená na horních adresách * podle registru A006 rozhoduje, zda bude ROM aktuálně připojená na horních adresách - **xxx xxBR** (B readonly BootSrc, R RomMapped) * podle registru A007 rozhoduje, kolik ROM bude zabírat prostoru - **xxxx xVAL** (VAL default 000 ( = 24.75kB), dále viz kód) * default po resetu je RomMapped nastaven podle BootFrom a velikost ROM maximální - VAL=000, tedy ROM je 24.75 kB (A100..FFFF) * MR je nastavováno i s ohledem na tyto registry * v EMS1 a EMS2 oblastech NEgeneruje ROM ani RAM signaly a přepne je do HiZ CODE -------------------------------------------------------------------------------- .. code:: Name ATF2_GLUE; PartNo 0002; Date 2026-06-26; Revision 0.1; Designer Gilhad and ChatGPT; Company None ; Assembly None ; Location ; Device f1504isptqfp100; /* Skutecna jmena signalu a cisla pinu, pokud je pred jmenem !, je signal aktivni v LOW: */ /************************************************************/ /* I is Input, O is output, H is 3state HiZ */ /************************************************************/ /* IOH Data for everything */ PIN 6 = D0; PIN 8 = D1; PIN 9 = D2; PIN 10 = D3; PIN 12 = D4; PIN 13 = D5; PIN 14 = D6; PIN 16 = D7; PIN 17 = Rw; /* OH CPU Rw, also used in HALT mode by MHF */ PIN 19 = !HALT; /* O CPU HALT */ /* I CA12..15 is connected to CPU.A12..15 */ PIN 20 = CA12; PIN 21 = CA13; PIN 23 = CA14; PIN 25 = CA15; /* PIN 29 = unused */ PIN 30 = !ROM; /* O CS for ROM */ PIN 31 = !RAM; /* O CS for RAM */ /* pokud CPU vlastni shared RAM, je to Output a ovlada jeji A16 */ /* pokud je HALT a BA a MHF vybral SystemRAM, je to input a ovlada GA16 */ PIN 32 = B_S_16; /* IO connected to SharedRAM.A16 and MHF MCU */ PIN 33 = !B_HALT; /* I MHF request 0=HALT active */ PIN 35 = B_READ; /* I MHF request 1=Read, 0=Write */ PIN 36 = B_SHARE_DIRTY; PIN 37 = B_SHARE_GRANTED; PIN 40 = B_SHARE_REQUEST; PIN 41 = B_S_SELECT; PIN 42 = B_S_READ; PIN 44 = B_S_WRITE; PIN 45 = B_G_ENABLE; PIN 46 = B_G_A_DIR; PIN 47 = B_G_D_DIR; PIN 48 = B_SHARE_SELECT; PIN 52 = A_SHARE_SELECT; PIN 54 = A_G_D_DIR; PIN 56 = A_G_A_DIR; PIN 57 = A_G_ENABLE; PIN 58 = A_S_WRITE; PIN 60 = A_S_READ; PIN 61 = A_S_SELECT; PIN 63 = A_SHARE_REQUEST; PIN 64 = A_SHARE_GRANTED; PIN 65 = A_SHARE_DIRTY; PIN 67 = A_READ; /* I MHF request 1=Read, 0=Write */ PIN 68 = !A_HALT; /* I MHF request 0=HALT active */ PIN 69 = A_S_16; /* IO connected to SharedRAM.A16 and MHF MCU */ /* pokud CPU vlastni shared RAM, je to Output a ovlada jeji A16 */ /* pokud je HALT a BA a MHF vybral SystemRAM, je to input a ovlada GA16 */ /* I HD6309 CPU signals {{{ */ PIN 71 = BS; PIN 75 = MRDY; PIN 76 = DMA_BREQ; PIN 79 = Dev_FIRQ; PIN 80 = Dev_IRQ; PIN 81 = Dev_NMI; PIN 83 = BA; /* }}} */ /* I Memory Regions {{{ */ PIN 84 = MR3; PIN 92 = MR2; PIN 93 = MR1; PIN 94 = MR0; /* }}} */ /* OH GA12..16 is connected to SystemRAM.A12..16 and SysBus.A12..15 {{{ */ PIN 96 = GA16; PIN 97 = GA15; PIN 98 = GA14; PIN 99 = GA13; PIN 100 = GA12; /* }}} */ /***** Input Only {{{ ****/ /* Pin 85 = IO_52; /* INPUT/GCLK3 */ Pin 87 = E; /* INPUT/GCLK1 */ Pin 88 = xIO_62; /* INPUT/OE1 - 12V Vpp */ Pin 89 = !Reset; /* INPUT/GCLR */ Pin 90 = Q; /* INPUT/OE2/GCLK2 */ /* }}} */ /* {{{ HD6309 Memory Regions +-------------------------------------------------------------------------+ | HD6309 Memory Regions | +---------------+---------------+-----------------------------------------+ | TYP | RANGE | CONTENT | +---------------+---------------+-----------------------------------------+ | 0000 | 0000..7FFF | Native RAM 32K (or more) | +---------------+---------------+-----------------------------------------+ | 0001 | 8000..8FFF | EMS1 4K | +---------------+---------------+-----------------------------------------+ | 0010 | 9000..9FFF | EMS2 4K | +---------------+---------------+-----------------------------------------+ | 1rrr | A000..A005 | 6 GLUE registers ( rrr = regnum ) | +---------------+---------------+-----------------------------------------+ | 1000 | A000 | GLUE register 000 EMS1.Page AAxBBBBB | +---------------+---------------+-----------------------------------------+ | 1001 | A001 | GLUE register 001 EMS1.Status xxxxxWxC | +---------------+---------------+-----------------------------------------+ | 1002 | A002 | GLUE register 002 EMS2.Page AAxBBBBB | +---------------+---------------+-----------------------------------------+ | 1003 | A003 | GLUE register 003 EMS2.Status xxxxxWxC | +---------------+---------------+-----------------------------------------+ | 1004 | A004 | GLUE register 004 ChipA.Status xxxxDWAC | +---------------+---------------+-----------------------------------------+ | 1005 | A005 | GLUE register 005 ChipB.Status xxxxDWAC | +---------------+---------------+-----------------------------------------+ | 1111 | A006..A01F | GLUE registers mirrored /reserved | +---------------+---------------+-----------------------------------------+ | 0100 | A020..A0FF | Memory mapped devices [1..7] x 32 B | +---------------+---------------+-----------------------------------------+ | 0011 | A100..FFFF | Native ROM 23.75K (or less) | +---------------+---------------+-----------------------------------------+ }}} */ TRUE = E # !E; FALSE = E & !E; /************************************************************/ /* HALT mode */ /************************************************************/ HALT = A_HALT # B_HALT; /************************************************************/ /* FIELDS */ /************************************************************/ FIELD MR = [MR3..MR0]; FIELD EMS1_PAGE = [EMS1_A1, EMS1_A0, EMS1_B4, EMS1_B3, EMS1_B2, EMS1_B1, EMS1_B0]; FIELD EMS2_PAGE = [EMS2_A1, EMS2_A0, EMS2_B4, EMS2_B3, EMS2_B2, EMS2_B1, EMS2_B0]; /* data from CPU */ FIELD DATA = [D7..D0]; /************************************************************/ /* INTERNAL NODES */ /************************************************************/ /* EMS1 mapping */ NODE EMS1_A1; NODE EMS1_A0; NODE EMS1_B4; NODE EMS1_B3; NODE EMS1_B2; NODE EMS1_B1; NODE EMS1_B0; /* EMS2 mapping */ NODE EMS2_A1; NODE EMS2_A0; NODE EMS2_B4; NODE EMS2_B3; NODE EMS2_B2; NODE EMS2_B1; NODE EMS2_B0; /************************************************************/ /* Chip ownership/state */ /************************************************************/ /* A = owned by MHF C = owned by CPU D = dirty */ NODE CHIPA_A; NODE CHIPA_C; NODE CHIPA_D; NODE CHIPB_A; NODE CHIPB_C; NODE CHIPB_D; /************************************************************/ /* Derived signals */ /************************************************************/ NODE EMS1_SYS; NODE EMS1_MHFA; NODE EMS1_MHFB; NODE EMS1_ROM; NODE EMS2_SYS; NODE EMS2_MHFA; NODE EMS2_MHFB; NODE EMS2_ROM; NODE CHIPA_W; NODE CHIPB_W; NODE CPU_WANTS_A; NODE CPU_WANTS_B; NODE CPU_USES_A; NODE CPU_USES_B; NODE HALT_MODE; NODE REG_ACCESS; NODE REG_READ; NODE REG_WRITE; NODE EMS_WINDOW; NODE ROM_WINDOW; NODE RAM_WINDOW; NODE ACTIVE_PAGE_A1; NODE ACTIVE_PAGE_A0; NODE ACTIVE_B4; NODE ACTIVE_B3; NODE ACTIVE_B2; NODE ACTIVE_B1; NODE ACTIVE_B0; /************************************************************/ /* CONSTANT DECODE */ /************************************************************/ EMS_WINDOW = (MR:1) # (MR:2); RAM_WINDOW = (MR:0); ROM_WINDOW = (MR:3); REG_ACCESS = MR3; REG_READ = REG_ACCESS & E & Rw & !BA; REG_WRITE = REG_ACCESS & E & !Rw & !BA; HALT_MODE = !HALT & BA; CPU_MODE = !HALT_MODE; BUS_MODE = HALT_MODE; /************************************************************/ /* Decode current mapping */ /************************************************************/ EMS1_SYS = !EMS1_A1 & !EMS1_A0; EMS1_MHFA = !EMS1_A1 & EMS1_A0; EMS1_MHFB = EMS1_A1 & !EMS1_A0; EMS2_SYS = !EMS2_A1 & !EMS2_A0; EMS2_MHFA = !EMS2_A1 & EMS2_A0; EMS2_MHFB = EMS2_A1 & !EMS2_A0; /* 11 = reserved/invalid */ EMS1_VALID = !(EMS1_A1 & EMS1_A0); EMS2_VALID = !(EMS2_A1 & EMS2_A0); /************************************************************/ /* REG0 EMS1 PAGE */ /************************************************************/ /* D7 D6 = AA D5 = reserved D4..D0 = BBBBB */ EMS1_A1.D = D7; EMS1_A0.D = D6; EMS1_B4.D = D4; EMS1_B3.D = D3; EMS1_B2.D = D2; EMS1_B1.D = D1; EMS1_B0.D = D0; /* AA: 00 System RAM 01 MHF_A 10 MHF_B 11 invalid/ROM TODO */ /* spolecne rizeni */ EMS1_A1.CK = !Q; EMS1_A0.CK = !Q; EMS1_B4.CK = !Q; EMS1_B3.CK = !Q; EMS1_B2.CK = !Q; EMS1_B1.CK = !Q; EMS1_B0.CK = !Q; EMS1_A1.AR = Reset; EMS1_A0.AR = Reset; EMS1_B4.AR = Reset; /* TODO default $8000 */ EMS1_B3.AR = Reset; EMS1_B2.AR = Reset; EMS1_B1.AR = Reset; EMS1_B0.AR = Reset; EMS1_A1.CE = REG_WRITE & (MR:8); EMS1_A0.CE = REG_WRITE & (MR:8); EMS1_B4.CE = REG_WRITE & (MR:8); EMS1_B3.CE = REG_WRITE & (MR:8); EMS1_B2.CE = REG_WRITE & (MR:8); EMS1_B1.CE = REG_WRITE & (MR:8); EMS1_B0.CE = REG_WRITE & (MR:8); /************************************************************/ /* REG2 EMS2 PAGE */ /************************************************************/ /* D7 D6 = AA D5 = reserved D4..D0 = BBBBB */ EMS2_A1.D = D7; EMS2_A0.D = D6; EMS2_B4.D = D4; EMS2_B3.D = D3; EMS2_B2.D = D2; EMS2_B1.D = D1; EMS2_B0.D = D0; /* AA: 00 System RAM 01 MHF_A 10 MHF_B 11 invalid/ROM TODO */ EMS2_A1.CK = !Q; EMS2_A0.CK = !Q; EMS2_B4.CK = !Q; EMS2_B3.CK = !Q; EMS2_B2.CK = !Q; EMS2_B1.CK = !Q; EMS2_B0.CK = !Q; EMS2_A1.AR = Reset; EMS2_A0.AR = Reset; EMS2_B4.AR = Reset; /* TODO default $9000 */ EMS2_B3.AR = Reset; EMS2_B2.AR = Reset; EMS2_B1.AR = Reset; EMS2_B0.AR = Reset; EMS2_A1.CE = REG_WRITE & (MR:10); EMS2_A0.CE = REG_WRITE & (MR:10); EMS2_B4.CE = REG_WRITE & (MR:10); EMS2_B3.CE = REG_WRITE & (MR:10); EMS2_B2.CE = REG_WRITE & (MR:10); EMS2_B1.CE = REG_WRITE & (MR:10); EMS2_B0.CE = REG_WRITE & (MR:10); /************************************************************/ /* CPU wants which chip */ /************************************************************/ CHIPA_W = A_SHARE_REQUEST; CHIPB_W = B_SHARE_REQUEST; /************************************************************/ /* CPU / MHF requests */ /************************************************************/ CPU_REQ_A = EMS1_MHFA # EMS2_MHFA; CPU_REQ_B = EMS1_MHFB # EMS2_MHFB; MHF_REQ_A = A_SHARE_REQUEST; MHF_REQ_B = B_SHARE_REQUEST; /************************************************************/ /* CHIP A ownership */ /************************************************************/ /* Pravidla: 00 -> nikdo 10 -> CPU 01 -> MHF 11 -> zakazany stav Pokud chteji oba: - vlastnik zustava - pokud nebyl zadny -> CPU */ CHIPA_C.D = ( CPU_REQ_A & !MHF_REQ_A ) # ( CPU_REQ_A & MHF_REQ_A & CHIPA_C ) # ( CPU_REQ_A & MHF_REQ_A & !CHIPA_C & !CHIPA_A ); CHIPA_A.D = ( MHF_REQ_A & !CPU_REQ_A ) # ( CPU_REQ_A & MHF_REQ_A & CHIPA_A ); CHIPA_C.CK = !Q; CHIPA_C.AR = Reset; CHIPA_C.CE = E # !E; CHIPA_A.CK = !Q; CHIPA_A.AR = Reset; CHIPA_A.CE = E # !E; /************************************************************/ /* CHIP B ownership */ /************************************************************/ CHIPB_C.D = ( CPU_REQ_B & !MHF_REQ_B ) # ( CPU_REQ_B & MHF_REQ_B & CHIPB_C ) # ( CPU_REQ_B & MHF_REQ_B & !CHIPB_C & !CHIPB_A ); CHIPB_A.D = ( MHF_REQ_B & !CPU_REQ_B ) # ( CPU_REQ_B & MHF_REQ_B & CHIPB_A ); CHIPB_C.CK = !Q; CHIPB_C.AR = Reset; CHIPB_C.CE = E # !E; CHIPB_A.CK = !Q; CHIPB_A.AR = Reset; CHIPB_A.CE = E # !E; /* SHARE_GRANTED */ A_SHARE_GRANTED = CHIPA_A; B_SHARE_GRANTED = CHIPB_A; /* Dirty A */ CHIPA_D.D = CHIPA_A.D; CHIPA_D.CK = !Q; CHIPA_D.AR = Reset; CHIPA_D.CE = (CHIPA_A.D $ CHIPA_A) # (CHIPA_C.D $ CHIPA_C); /* Dirty B */ CHIPB_D.D = CHIPB_A.D; CHIPB_D.CK = !Q; CHIPB_D.AR = Reset; CHIPB_D.CE = (CHIPB_A.D $ CHIPB_A) # (CHIPB_C.D $ CHIPB_C); /* SHARE_DIRTY */ /************************************************************/ /* SHARE_DIRTY */ /************************************************************/ A_SHARE_DIRTY = !CHIPA_A & CHIPA_D # CHIPA_A & CPU_REQ_A; B_SHARE_DIRTY = !CHIPB_A & CHIPB_D # CHIPB_A & CPU_REQ_B; /* ############################################################# */ ACTIVE_PAGE_A1 = (MR:1 & EMS1_A1) # (MR:2 & EMS2_A1); ACTIVE_PAGE_A0 = (MR:1 & EMS1_A0) # (MR:2 & EMS2_A0); ACTIVE_B4 = (MR:1 & EMS1_B4) # (MR:2 & EMS2_B4); ACTIVE_B3 = (MR:1 & EMS1_B3) # (MR:2 & EMS2_B3); ACTIVE_B2 = (MR:1 & EMS1_B2) # (MR:2 & EMS2_B2); ACTIVE_B1 = (MR:1 & EMS1_B1) # (MR:2 & EMS2_B1); ACTIVE_B0 = (MR:1 & EMS1_B0) # (MR:2 & EMS2_B0); /* Vyhodnoceni typu stranky */ /************************************************************/ /* ACTIVE SOURCE */ /************************************************************/ ACTIVE_SYS = !ACTIVE_PAGE_A1 & !ACTIVE_PAGE_A0; ACTIVE_MHFA = !ACTIVE_PAGE_A1 & ACTIVE_PAGE_A0; ACTIVE_MHFB = ACTIVE_PAGE_A1 & !ACTIVE_PAGE_A0; ACTIVE_VALID = !(ACTIVE_PAGE_A1 & ACTIVE_PAGE_A0); /* #branch */ /* EMS valid */ /* Tohle uz mas skoro hotove. */ EMS_OK = ACTIVE_SYS # (ACTIVE_MHFA & CHIPA_C) # (ACTIVE_MHFB & CHIPB_C); /* #end branch */ /************************************************************/ /* EMS ACCESS */ /************************************************************/ EMS_ACCESS = ACTIVE_SYS # (ACTIVE_MHFA & CHIPA_C) # (ACTIVE_MHFB & CHIPB_C); /************************************************************/ /* EMS ADDRESS */ /************************************************************/ GA16 = ACTIVE_B4; GA15 = ACTIVE_B3; GA14 = ACTIVE_B2; GA13 = ACTIVE_B1; GA12 = ACTIVE_B0; /* pouze pri EMS */ GA16.OE = EMS_WINDOW; GA15.OE = EMS_WINDOW; GA14.OE = EMS_WINDOW; GA13.OE = EMS_WINDOW; GA12.OE = EMS_WINDOW; /************************************************************/ /* SYSTEM RAM SELECT */ /************************************************************/ RAM = EMS_WINDOW & ACTIVE_SYS; RAM.OE = EMS_WINDOW & !BA; /************************************************************/ /* SHARED CHIP SELECT */ /************************************************************/ A_S_SELECT = EMS_WINDOW & ACTIVE_MHFA & CHIPA_C; B_S_SELECT = EMS_WINDOW & ACTIVE_MHFB & CHIPB_C; /************************************************************/ /* SHARED READ */ /************************************************************/ A_S_READ = EMS_WINDOW & ACTIVE_MHFA & CHIPA_C & E & Rw; B_S_READ = EMS_WINDOW & ACTIVE_MHFB & CHIPB_C & E & Rw; /************************************************************/ /* SHARED WRITE */ /************************************************************/ A_S_WRITE = EMS_WINDOW & ACTIVE_MHFA & CHIPA_C & E & !Rw; B_S_WRITE = EMS_WINDOW & ACTIVE_MHFB & CHIPB_C & E & !Rw; /************************************************************/ /* GATE ADDRESS DIRECTION */ /************************************************************/ A_G_A_DIR = FALSE; /* FIXME Pokud bezi CPU. V HALT rezimu se prepne. */ B_G_A_DIR = FALSE; /************************************************************/ /* DATA DIRECTION */ /************************************************************/ A_G_D_DIR = EMS_WINDOW & ACTIVE_MHFA & CHIPA_C & Rw; B_G_D_DIR = EMS_WINDOW & ACTIVE_MHFB & CHIPB_C & Rw; /************************************************************/ /* ENABLE GATES */ /************************************************************/ A_G_ENABLE = EMS_WINDOW & ACTIVE_MHFA & CHIPA_C & E; B_G_ENABLE = EMS_WINDOW & ACTIVE_MHFB & CHIPB_C & E; /************************************************************/ /* EMS STATUS */ /************************************************************/ EMS1_C = EMS1_SYS # (EMS1_MHFA & CHIPA_C) # (EMS1_MHFB & CHIPB_C); EMS2_C = EMS2_SYS # (EMS2_MHFA & CHIPA_C) # (EMS2_MHFB & CHIPB_C); EMS1_W = EMS1_MHFA & CHIPA_W # EMS1_MHFB & CHIPB_W; EMS2_W = EMS2_MHFA & CHIPA_W # EMS2_MHFB & CHIPB_W; /************************************************************/ /* REGISTERS READ */ /************************************************************/ /* REG0 */ [D7..D0].OE = REG_READ; D7 = REG_READ & ( (MR:8) & EMS1_A1 # (MR:10) & EMS2_A1 ); D6 = REG_READ & ( (MR:8) & EMS1_A0 # (MR:10) & EMS2_A0 ); D5 = REG_READ & ( /* (MR:8) & FALSE ) */ FALSE ); D4 = REG_READ & ( (MR:8) & EMS1_B4 # (MR:10) & EMS2_B4 ); D3 = REG_READ & ( (MR:8) & EMS1_B3 # (MR:10) & EMS2_B3 # (MR:12) & CHIPA_D # (MR:13) & CHIPB_D ); D2 = REG_READ & ( (MR:8) & EMS1_B2 # (MR:9) & EMS1_W # (MR:10) & EMS2_B2 # (MR:11) & EMS2_W # (MR:12) & CHIPA_W # (MR:13) & CHIPB_W ); D1 = REG_READ & ( (MR:8) & EMS1_B1 # (MR:10) & EMS2_B1 # (MR:12) & CHIPA_A # (MR:13) & CHIPB_A ); D0 = REG_READ & ( (MR:8) & EMS1_B0 # (MR:9) & EMS1_C # (MR:10) & EMS2_B0 # (MR:11) & EMS2_C # (MR:12) & CHIPA_C # (MR:13) & CHIPB_C ); /* Jedna optimalizace, kterou bych udelal V navrhu mas nekolik vyrazu typu EMS_WINDOW & ACTIVE_MHFA & CHIPA_C ktere se opakuji prakticky vsude. To je presne pripad, kdy se vyplati vytvorit pomocne uzly: NODE A_CPU_ACTIVE; NODE B_CPU_ACTIVE; A_CPU_ACTIVE = EMS_WINDOW & ACTIVE_MHFA & CHIPA_C; B_CPU_ACTIVE = EMS_WINDOW & ACTIVE_MHFB & CHIPB_C; Pak se vetsina rovnic zkrati na: A_S_SELECT = A_CPU_ACTIVE; A_S_READ = A_CPU_ACTIVE & E & Rw; A_S_WRITE = A_CPU_ACTIVE & E & !Rw; A_G_ENABLE = A_CPU_ACTIVE & E; A_G_D_DIR = A_CPU_ACTIVE & Rw; To je nejen citelnejsi, ale na ATF1504 casto vede i k mensimu poctu product termu, protoze fitter muze A_CPU_ACTIVE fyzicky sdilet mezi vice makrobunkami. Myslim, ze prave timto smerem se da dostat navrh pod limit bunek. */