Problem z dekoderem adresów

Apr 16, 2025 Last reply: 1 year ago 12 Replies

Jakiś czas temu zacząłem pracować nad projektem komputera na 8085, pierwotnie przyjmując następujące założenia co do organizacji pamięci.


0x0000-0x7FFF - RAM1 (62256)
0x8000-0xBFFF - RAM2 (62256 podzielony na dwa banki)
0xC000-0xFFFF - EPROM

Takie podejście całkiem fajnie sprawdzało się w przypadku BASIC-a, ale okazało się beznadziejne, gdy zabrałem się za uruchamiania CP/M - brakowało pamięci żeby uruchomić niektóre programy.



Przygotowałem więc jeszcze jedną wersję płyty procesorowej, ze zmodyfikowanym dekoderem adresów (pierwotna wersja używała układów



74HCT, tym razem użyłem GAL-a). Złożyłem to, zmodyfikowałem system, wszystkie zadziałało.

Tym razem organizacja pamięci wygląda następująco:


0x0000-0x7FFF - EPROM lub RAM1 w zależności od stanu linii ROM_SHADOW ustawianej na rejestrze 74273. Po resecie domyślnie startuje EPROM, potem można to zmienić.
0x8000-0xFFFF - RAM2, dostępny cały czas.

Przyszło mi jednak do głowy, żeby dwa wcześniej złożone wcześniej prototypy też zmodyfikować w ten sposób, aby pracowały z taką organizacją pamięci. Ujednolicenie tego z nową wersją przez wciśnięcie GAL-a wymagałoby zbyt dużych przeróbek, więc zastosowałem inne podejście. Usunąłem układ 74HCT139 i na jego miejsce wlutowałem nowy moduł dekodera adresów, zbudowany na elementach SMD (74HCT139 + pojedyncza bramka AND).



Połączenia wyglądają następująco: Wejście A połówki 74HCT139 - sygnał SHADOW_ROM Wejście B połówki 74HCT139 - linia adresowa A15 Wejście G połówki 74HCT139 - sygnał MEM_EN (z istniejącej logiki, która interpretuje sytuację na magistrali, stary dekoder tez z niego korzystał) Wyjście Y0 połówki 74HCT139 - CS_EPROM Wyjście Y2 połówki 74HCT139 - CSRAM1 Wyjścia Y1 i Y3 połówki 74HCT139 - do wejść bramki AND, której wyjście stanowi sygnał CS_RAM2.



Wejścia niewykorzystanej połówki 74HCT139 są połączone z masą.



Konieczne było też wprowadzenie paru innych modyfikacji (m.in. wywalenie istniejącego układu do tymczasowego ustawiania linii A14 i A15 po resecie (żeby kod wykonywał się z EPROM-u w górnej części przestrzeni adresowej) oraz doprowadzenie A14 do RAM2.



Generalnie przyglądałem się schematowi dziesiątki razy i nie widzę powodu, dla którego miałoby to nie działać. Połączenia odpowiadają logice, którą zaimplementowałem w GAL-u we wspomnianej wersji, która działa. Sprawdziłem też połączenia multimetrem aby upewnić się, że wszystkie sygnały dochodzą tam, gdzie trzeba.



Co dzieje się w rzeczywistości? Po resecie kod zaczyna wykonywać kod z EPROM-u, posiada też dostęp do RAM2 (bo tam trzyma stos i niektóre zmienne). Uruchamia się bootloader, który ładuje CP/M z karty pamięci do pewnego obszaru w RAM2. Operacja kończy się powodzeniem i wykonany zostaje skok do tej lokalizacji. Tutaj też jeszcze kod działa, bo kolejne instrukcje są wykonywane. Aż do momentu, kiedy próbuję przestawić stan linii ROM_SHADOW, aby mieć dostęp do RAM1. Wtedy wszystko się zawiesza. Jak wspominałem, w przypadku rozwiązania z GAL-em wszystko działało, więc problem nie leży po stronie kodu.



Ktoś ma pomysł co może być przyczyną takiego zachowania? Sytuacja objawia się tak samo w przypadku obydwu zmodyfikowanych egzemplarzy. Jakiś problem z timingami zastosowanych elementów SMD?


Dodam jeszcze, że jedyny pomysł jaki w tej chwili mi przychodzi to jakieś problemy z timingami i propagacją sygnałów. Może nowy 74HCT273 w wersji SMD jest za wolny? Może montaż na module dodaje dodatkowe opóźnienia ze względu na pojemności montażowe? Spróbuję chyba wymienić rejest 74HCT273 na wersję HC (albo jeszcze lepiej AC) i zobaczę czy to w czymś pomoże.

W dniu 16.04.2025 o 10:14, Atlantis pisze: [cut]

Czyżby problem z odpowiednim zwalnianiem linii A14? Nie widzę co prawda schematu, ale ewidentnie sprawa programowa.

Adresy powinny być chyba kodowane i dekodowane bajtowo w jednym układzie (dla danego bajtu). Podobne numery robił mi kiedyś zamierzchły 80C552 na przełączaniu banków pamięci zewnętrznej.

Oscyloskop Twoim przyjacielem. A jeszcze lepiej analizator stanów (bajtowy).

Też może być...

Po wprowadzeniu przeróbek linia A14 (podobnie jak wszystkie inne linie) jest sterowana bezpośrednio przez procesor. No, może nie tyle bezpośrednio, co za pośrednictwem bufora 74HCT245. Obecnie w układzie nie ma już żadnych mechanizmów przełączania banków i tymczasowego ustawiania adresów, zostały zastąpione przez ROM shadowing.

W każdym razie... Przyjrzałem się jeszcze raz kodowi z GAL-a, rzuciłem okiem na dokumentację układów i przez chwilę byłem pewien, że już znalazłem przyczynę. Mianowicie w oryginalnej wersji sygnał zatrzaskujący wartość z magistrali danych w porcie 74HCT273 był zdefiniowany następująco:

/LOCPTCS = /LOCIOCS * /A4 * /WR

Tymczasem zatrzaśnięcie wartości w 273 następuje na zboczu rosnącym. Innymi słowy moment ten był opóźniany do samego końca operacji OUT. W takim przypadku sygnał SHADOW_ROM byłby ustawiany tuż przed operacją pobrania kolejnej instrukcji i mógłbym faktycznie mieć problem z timingami na dekoderze adresów, prowadzący do konfliktu na magistrali.

Spróbowałem więc najbardziej oczywistego rozwiązania:

LOCPTCS = /LOCIOCS * /A4 * /WR

Niestety, pudło - nie działa. Nie dosyć, że urządzenie nadal się zawiesza, to jeszcze do rejestru trafia błedna wartość (widzę to, bo nie świeci się jedna z diod podpiętych do tego rejestru, która powinna się świecić).

Kolejnym krokiem była próba zsynchronizowania sygnału zatrzaskującego

74273 z zegarem systemowym. W GAL-u mogę to uzyskać w prosty sposób:

LOCPTCS.R = /LOCIOCS * /A4 * /WR

Teraz wartość nie trafia na wyjście bezpośrednio, ale przez flip-flopa sterowanego zegarem systemowym. Niestety - też nie pomogło. Do portu trafia błędna wartość, system się zawiesza.

Jednak co ciekawe:

/LOCPTCS.R = /LOCIOCS * /A4 * /WR

Daje częściowy sukces. W tej wersji system nie zawiesza się po ustawieniu SHADOW_ROM i przechodzi dalej. Co prawda bootowanie CP/M wywala się nieco później, ale nie jestem pewien czy to nie jest jakiś niezależny błąd...

Co więcej - mam podobny projekt na Z80. Tam cała logika dekodera adresów siedzi już w jednym GAL-u, jednak tam także przez pomyłkę użyłem zanegowanej wartości sygnału LOCPTCS. Pomimo tego działał. Spróbowałem też wersji niezanegowanej oraz zatrzaskiwanej - nie robiło mu to najmniejszej różnicy, działał poprawnie w każdej wersji.

Czekam jeszcze na paczki z układami 74*273 w wersjach HC i AC. Zobaczymy, czy to w czymś pomoże.

... wygląda to tak, jakby Twój CS potrzebował więcej "czasu" na wygenerowanie swojego stanu względem RW... może "po drodze" wstaw jeszcze jakiś jeden lub dwa "noop'y" ?

Tego już próbowałem, na samym początku - nie pomogło. Generalnie spróbowałem jeszcze:

- wymienić 74HCT138 (generuje LOCIOCS) na 74HC138.

- wymienić 74HCT273 na 74HC273.

Nie zmieniło to niczego.

Jeszcze z rzeczy, które przychodzą mi do głowy:

- Wymiana 74HCT74 na 74HC74. Układ generuje sygnał IOM synchronizowany z /ALE, który odblokowuje dekodery adresów dopiero wtedy, gdy mamy na magistrali czysty adres.

- Wymiana tego 74HCT139 w wersji SMD na 74HC139.

Tutaj będę musiał jednak poczekać na przyjście paczki z częściami.

Nic to nie da, różnice czasowe i progów są kosmetyczne. Masz gdzieś drobny błąd z tym dekodowaniem czy przydzielaniem adresów.

Wygląda na to, że masz rację. Wymiana dekodera na HC139 niczego nie zmieniła. Po raz kolejny sprawdzam połączenia, ale nie widzę niczego podejrzanego.

No to pozostaje ci tylko podłączyć jakiś analizator stanów i analizować to adresowanie i na czym się wiesza, może potem na tej podstawie napisać kawałek programu żeby sie w kółko kręcił i dał możliwość dokładnego zbadania zależności oscylem. Sam tak kiedyś naprawiałem komputery wielkości lodówki gdzie procesor to była płyta z ponad 160 scalakami a alu była zrobiona na 74181 i 182, 16 bit. Uszkodzenie było takie że przekłamywał na jednej operacji jeden bit, w zależności jak się płytę włożyło to działał lub nie. Napisałem na niego program i szukałem oscylem aż znalazłem nogę od 74181 która jak się wygięło płytę miała pełny kontakt albo niepełny w środku scalaka, tworzył się dodatkowy opornik szeregowy około 300om, to wystarczyło żeby zrobić opóźnienie sygnału na tyle że kiedy był zatrzaskiwany w rejestrze wpisywało '0' zamiast '1'.

W dniu 16.04.2025 o 10:14, Atlantis pisze:

Ja bym próbował na początek zwolnić zegar. Jak timingi to się powinno poprawić.

Ok, kilka prób z użyciem oscyloskopu faktycznie wyjaśniło sprawę. Okazuje się, że miałem do czynienia z mieszanką dwóch przyczyn. Pierwsza była banalna - zamieniłem miejscami sygnały A15 i SHADOW_ROM na wejściach 74139, przez do dekoder generował niewłaściwe sekwencje sygnałów CS dla pamięci, co prowadziło do konfliktu po ustawieniu SHADOW_ROM w stanie wysokim.

Jednak samo to nie rozwiązało problemu, bo jak się okazuje była jeszcze druga przyczyna, faktycznie związana z timingami. Układ zaczął działać dopiero wtedy, gdy zsynchronizowałem sygnał CS portu 74273 (generującego SHADOW_ROM) z zegarem systemowym, zatrzaskując go w flip-flopie. Było to relatywnie proste do realizacji, bo tę część logiki miałem zaimplementowaną w GAL-u.

Teraz zabrałem się za wprowadzanie podobnej modyfikacji w starszej wersji projektu na 8080. Tym razem wejścia 74139 są podłączone prawidłowo (sprawdzone wizualnie i za pomocą oscyloskopu) ale układ również nie działa, wywalając się po skoku do załadowanego CP/M-a. Podejrzewam, że to też jakaś wersja problemów z timingiem przy pisaniu do portu. Tym razem port jest zrealizowany na 74S412 (polski klon 8212).

Sterowanie portem odbywa się w następujący sposób:

  1. Pin MD podciągnięty do VCC
  2. Wejście DS1 podłączone do IO_WR
  3. Wejście DS2 podłączone do zanegowanego wyjścia dekodera adresów I/O (74138)
  4. Wejścia DI0..DI7 do magistrali systemowej.
  5. Wyjścia DO0..DO7 tam, gdzie są potrzebne. ;)

Zastanawiam się czy i tym razem nie opóźnić trochę sygnału DS2, przez zatrzaśnięcie go w 7474 sygnałem zegara systemowego.

Tylko dlaczego w ogóle mam ten problem? Czy przypadkiem w 8080 nie powinienem mieć już stabilnej nowej wartości na liniach danych, gdy na szynie adresowej pojawia się adres, a linia IO_WR przechodzi w stan niski?

W dniu 23.04.2025 o 20:51, Atlantis pisze:

Myślę że dopiero po ustawieniu io_wr na niski będzie stabilna wartość na data, wcześniej może być różnie, opóźnij ten DS2 i zobacz co sie stanie.

czekaj ... 74273 nie ma CS.

373 ?

O ile pamietam, to tak powinno być.

Oscyloskop nie pokazuje?

J.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required