Jak można obsługiwać wyświetlacze VGA przy tak wysokich częstotliwościach taktowania pikseli?

12

Pracuję na obwodzie cyfrowym, używając dyskretnych komponentów do sterowania wyświetlaczem VGA 640x480 w trybie tekstowym 80x30.

W przypadku wyświetlacza 640x480 zegar pikseli wynosi 25,175 MHz, a jego okres wynosi około 40ns. Nie rozumiem, jak często powinienem zapewniać nowy piksel na wyświetlaczu.

Podstawowa architektura mojego obwodu jest następująca:

  1. Licznik binarny dla poziomych pikseli zlicza od 25,175 MHz do 800 (640 widocznych pikseli + 160 dla ganku frontowego, synchronizacji, ganku tylnego). Przy 800 przyrostowy licznik linii pionowej (i resetowany przy 525 liniach)

  2. Używając pozycji poziomej i pionowej, uzyskaj współrzędną x, y bieżącego znaku.

  3. Używając współrzędnej x, y znaku, indeksuj do pamięci wideo, aby pobrać znak ASCII.

  4. Użyj znaku ASCII, aby zindeksować pamięć ROM w celu uzyskania wzorca bitowego dla znaku

  5. Użyj równoległego do szeregowego rejestru przesuwnego, aby przekonwertować 8-znakową linię znaku na poszczególne bity przy częstotliwości zegara pikseli

Jeśli podążasz za łańcuchem, to idzie: Licznik -> RAM -> ROM -> Rejestr równoległy do ​​szeregowego przesunięcia

Używając najszybszych komponentów, jakie mogę znaleźć, opóźnienia propagacji i czas dostępu sumują się do około 15ns + 20ns + 70ns + 15ns = 120ns, znacznie dłużej niż okres 40ns dla 25MHz.

Przy jeszcze wyższych rozdzielczościach i częstotliwościach odświeżania możesz mieć zegary pikselowe znacznie powyżej 100 MHz, co będzie okresem 10ns.

Jak to możliwe, aby zapewnić nowe piksele na wyświetlaczu co 10ns, kiedy czas dostępu do pamięci RAM / ROM jest już znacznie powyżej, nawet biorąc pod uwagę wszystkie inne sygnały w twoim systemie?

supershirobon
źródło
7
Używasz dedykowanej pamięci RAM wideo i taktujesz ją bezpośrednio do sygnału wideo. Zastanawiasz się, co wyświetlić na długo przed jego wyświetleniem.
Hearth
2
Przeczytaj o Maximite . Po prostu używa urządzenia peryferyjnego MCU i kilku rezystorów do sterowania portem VGA. Zacznij od zbadania używanego urządzenia peryferyjnego PIC32. Działa w porządku. (Mam tutaj Maximite.)
Jonk
„The Cheap Video Cookbook” „Don Lancaster”
Jasen,

Odpowiedzi:

17

Są dwa główne powody, dla których uważasz to za trudne.

Po pierwsze, używasz starszych i bardziej dyskretnych części (integracja na niższą skalę), niż byłoby to możliwe w erze VGA.

Ale następnie używasz ich w nietypowy sposób. W szczególności twoje podejście nie jest takie, pipelinedco oznacza, że ​​musisz zsumować wiele opóźnień przy określaniu odstępu, a tym samym oceń.

Natomiast synchroniczne projekty cyfrowe, które próbują osiągnąć prędkość, starają się robić jak najmniej między rejestrami.

Chociaż szczegóły prawdopodobnie by się nieco różniły, z grubsza mówiąc, działałoby to mniej więcej tak:

  • Zwiększasz lub resetujesz adres, a następnie trafia on do rejestru.
  • Zatrzaskujesz adres w pamięci synchronicznej
  • Zatrzaskujesz wyjście pamięci synchronicznej
  • Zatrzaskujesz to na adres synchronicznego generatora znaków
  • Zatrzaskujesz wyjście generatora znaków do rejestru wyjściowego
  • zastosuj wyszukiwanie palety ...
  • do synchronicznego DAC ...

Kiedy rozbijesz takie zadanie, otrzymujesz tylko jedno opóźnienie kombinatoryczne plus pewne opóźnienie propagacji oraz konfigurację rejestru i czasy wstrzymania, które muszą mieścić się między zegarami.

Konstrukcja zbudowana w ten sposób zajmie wiele zegarów, aby uzyskać wynik - opóźnienie będzie w rzeczywistości wyższe niż projekt wyłącznie kombinatoryczny. Ale generuje nową prawidłową moc wyjściową w każdym cyklu znacznie szybszego zegara.

I hej, to wideo, nie ma znaczenia, czy CRT rysuje kilkanaście pikseli za licznikiem pikseli - oczywiście bierzesz to pod uwagę przy synchronizacji sygnałów synchronizacji, aby były poprawne w porównaniu z faktycznymi danymi wychodzi z DAC-a.

W praktyce prawie wszystkie złożone systemy cyfrowe działają w ten sposób, ponieważ jest to świetny pomysł - aż do momentu, gdy procesor potokowy natrafi na zależność od wcześniejszego wyniku obliczeniowego lub gałęzi warunkowej ... Wtedy sprawy stają się interesujące, jak by to mówili w następnym wykładzie z klasy systemów cyfrowych - ale na szczęście twoja sytuacja w VGA jest o wiele prostsza, szczególnie jeśli nie martwisz się jeszcze efektami łzy, jeśli bufor postaci zmieni się podczas rysowania ekranu.

Jeśli chcesz to zbudować, zrób to w FPGA. To wymusi na tobie synchroniczne wspomnienia, jeśli używasz pamięci wewnętrznej lub synchronicznych rejestrów IO, jeśli używasz pamięci zewnętrznej. Będziesz musiał dużo popychać w kierunku odpowiedniego projektu, sama tkanina będzie szybsza niż twoje dyskretne części, i oczywiście, jeśli popełnisz błąd, wystarczy tylko przekręcić kciuki, gdy rekompiluje się, zamiast spędzać cały dzień na okablowaniu .

Chris Stratton
źródło
„zwłaszcza jeśli nie martwisz się jeszcze efektami rozdzierania, jeśli bufor postaci zmienia się podczas rysowania ekranu” - dlatego od najwcześniejszych dni koprocesorów wideo koprocesory miały sposób poinformować główny proces, że nie są obecnie zrzucają swoją pamięć na ekran i jeśli chcą zmienić bufor wideo, powinni to zrobić teraz.
John Dvorak,
Myślę, że nadmiernie to komplikujesz. Stwierdził już, że używa 8-bitowego rejestru przesuwnego, który wyprowadza jeden bit na zegar pikselowy. Prawdopodobnie jest to 8-bitowy rejestr przesuwny z zatrzaskiem. Oznacza to, że musi pobrać nowy bajt tylko raz na zegary 8-pikselowe, a więc częstotliwość 3,125 MHz. To daje ci wszystkie 320ns na przesłanie danych do zatrzasku rejestru przesuwnego, co jest znacznie dłuższe niż 120ns, które według niego zajmie.
Chris_F,
W przypadku bardzo prostej monochromatycznej obudowy o niskiej rozdzielczości tak tak, czas bajtów nie byłby zbyt trudny, ale kluczową częścią pytania było to, że pytający próbował zrozumieć, w jaki sposób wydajność typowych „prawdziwych” systemów o nietrywialnej rozdzielczości jest możliwe. Odpowiedź jest taka sama, jak we wszystkich innych przydatnych systemach cyfrowych: szybsza technologia i synchroniczny projekt potokowy.
Chris Stratton
2

Używając najszybszych komponentów, jakie mogę znaleźć, opóźnienia propagacji i czas dostępu sumują się do około 15ns + 20ns + 70ns + 15ns = 120ns, znacznie dłużej niż okres 40ns dla 25MHz.

Zapominasz, że karta graficzna nigdy nie rysuje tylko jednego piksela - ale przynajmniej pełną linię skanowania. Byłby to zatem problem całkowicie możliwy do rozwiązania.

Nie zapominaj też, że do tej pory istniało pięć dekad produkcji sprzętu wideo. Twój problem zwykle rozwiązuje się za pomocą specjalnego rodzaju pamięci RAM, w której renderujesz litery na jednym porcie i która jest kolejno odczytywana do przetwornika DAC sygnału wideo. Ten sprzęt jest znacznie szybszy niż to, na co patrzysz.

Podstawowa architektura mojego obwodu jest następująca:

  1. Licznik binarny dla poziomych pikseli zlicza od 25,175 MHz do 800 (640 widocznych pikseli + 160 dla ganku frontowego, synchronizacji, ganku tylnego). Przy 800 przyrostowy licznik linii pionowej (i resetowany przy 525 liniach)

  2. Używając pozycji poziomej i pionowej, uzyskaj współrzędną x, y bieżącego znaku.

Nie, dlaczego miałbyś to zrobić? Po prostu umieściłeś piksel rzędu w ciągłym obszarze pamięci i liniowo wyłożyłeś go na swój przetwornik cyfrowo-analogowy - jeśli chodzi o implementację CPU / MCU, nie pozwoliłbyś nawet procesorowi na to, ale zaprogramowaną jednostkę DMA aby nic nie robić, tylko przyjmować jedną wartość po drugiej i podawać ją np. do równoległego portu danych, bez interakcji rdzenia procesora.

  1. Używając współrzędnej x, y znaku, indeksuj do pamięci wideo, aby pobrać znak ASCII.

Ach, chcesz renderować w locie - dobry wybór, ale niezwykły przy współczesnych kosztach pamięci RAM. Zamiast tego po prostu wyrenderujesz znak w buforze ramek lub, jeśli twoje urządzenie jest wyjątkowo wąskie, bezpośrednio wyrzuć (patrz moje wyjaśnienie DMA powyżej) wiersz znaków do DAC.

Marcus Müller
źródło
1
Podczas gdy nowoczesne rzeczy preferują wstępnie renderowane bufory klatek, są one oczywiście złym wyborem, jeśli próbujesz pracować bez większego wysiłku. Jeśli robisz to w FPGA, możesz po prostu zmusić maszynę stanu DMA do pobierania adresów z mapy komórek postaci, a następnie odczytywania z odpowiednich glifów znaków.
R .. GitHub ZATRZYMAJ LÓD
w pełni się zgadzam tutaj! stąd moja sekcja odpowiedzi na trzecie pytanie.
Marcus Müller,
2

Oprócz tworzenia potoków (co jest bardzo ważne, co należy zrobić) brakuje czegoś ważnego ....

Rejestrowane równolegle, szeregowe zegary przesuwne rejestrują kropki przy 25 dziwnych MHz, oczywiście, ale jeśli twoje postacie mają szerokość 8 pikseli, to ich wejście wynosi tylko ~ 3,2 MHz, co jest łatwo dostępne dla serii LS z ery VGA, mimo wszystko musisz przygotować następny bajt, gdy rejestr przesuwny zakończy się bieżącym (w tym momencie przychodzi potok).

Wygeneruj zegar pikselowy przy ~ 25 MHz i zegar pamięci na 1/8 tego, aby sterować buforem tekstowym i CG ROM, a następnie potokuj tę pamięć i dostęp do CG ROM.

Kolejna sztuczka, wyjście bufora tekstu będzie powtarzane dla każdego wiersza w danym wierszu tekstu, więc być może możesz taktować 80 bajtów tekstu w buforze pierścieniowym, a następnie przestać czytać ram dla kolejnych 7 wierszy (zakładając, że 8 znak linii), pozwala to zwolnić pamięć, z której procesor może korzystać, kosztem konieczności zawieszenia 80 bajtów pamięci RAM z boku urządzenia.

Dan Mills
źródło
1

Więc to oczywiście nie działa; potrzebujesz rurociągu.

1) Zachowaj ciągłe znaki w pamięci. Zacznij od lewego górnego rogu.

2) Pobierz znak podczas przerwy wygaszania. Kontynuuj pobieranie znaków w kolejności pamięci.

3) Potokuj każdy zdekodowany znak plus indeks linii do ROM.

4) Potokuj wyjście ROM do bufora.

5) Potokuj bufor do rejestru przesuwnego. Odczytuj z tego stale piksele w odstępach 40ns.

(Oznacza to, że musisz ładować nową postać do rejestru przesuwnego co 320ns, co może być nawet wykonalne bez potokowania całej reszty systemu.)

6) Podczas wygaszania w poziomie powróć na początek linii lub przejdź do następnego znaku (tj. Początek następnej linii).

Funkcja bonusowa: ponieważ potrzebujesz tylko znaku co 320 ns, możesz także odczytać parę znak + kolor i wykonać znaki w stylu MSDOS lub Spectrum.

pjc50
źródło