Come è possibile pilotare display VGA con frequenze di clock pixel così elevate?


12

Sto lavorando su un circuito digitale utilizzando componenti discreti per pilotare un display VGA 640x480 in modalità testo 80x30.

Per un display 640x480, il pixel clock è 25.175MHz, che ha un periodo di circa 40 ns. Non capisco come dovrei essere in grado di fornire un nuovo pixel al display così spesso.

L'architettura di base per il mio circuito è la seguente:

  1. Il contatore binario per pixel orizzontali conta da 25.175 MHz a 800 (640 pixel visibili + 160 per portico anteriore, sincronizzazione, portico posteriore). A 800, incrementa il contatore di linee verticali (e resetta a 525 linee)

  2. Usando la posizione orizzontale e verticale, ricava la coordinata x, y del carattere corrente.

  3. Utilizzando le coordinate x, y del carattere, indicizzalo nella memoria video per recuperare il carattere ASCII.

  4. Utilizzare il carattere ASCII per indicizzare nella ROM dei caratteri per ottenere un modello di bit per il carattere

  5. Utilizzare il registro a scorrimento parallelo al seriale per convertire la linea di caratteri a 8 pixel in singoli bit alla frequenza di clock dei pixel

Se segui la catena, va: Counter -> RAM -> ROM -> Parallel to Serial Shift Register

Utilizzando i componenti più veloci che riesco a trovare, i ritardi di propagazione e i tempi di accesso si sommano a circa 15 ns + 20 ns + 70 ns + 15 ns = 120 ns, molto più grandi del periodo di 40 ns per 25 MHz.

Con risoluzioni e frequenze di aggiornamento ancora più elevate, puoi avere pixel clock ben al di sopra di 100 MHz che sarà un periodo di 10 ns.

Come è possibile fornire nuovi pixel al display ogni 10 ns quando solo il tempo di accesso per RAM / ROM è già ben al di sopra di esso, nemmeno considerando tutti gli altri segnali nel sistema?


7
Si utilizza la RAM video dedicata e si esegue il clock direttamente nel segnale video. Lavori a capire cosa visualizzare molto prima di visualizzarlo effettivamente.
Hearth

2
Vai a leggere su Maximite . Utilizza solo l'hardware periferico di una MCU e alcune resistenze per pilotare una porta VGA. Inizia esaminando la periferica PIC32 che utilizza. Funziona bene. (Ho un Maximite qui.)
Jon

"The Cheap Video Cookbook" di "Don Lancaster"
Jasen

Risposte:


17

Ci sono due ragioni principali per le quali trovi questa sfida.

In primo luogo, stai usando parti più vecchie e più discrete (integrazione su scala inferiore) di quanto sarebbe stato usato per fare questo nell'era di VGA.

Ma poi li stai usando in modo atipico. In particolare, il tuo approccio non pipelinedsignifica che devi sommare più ritardi nel determinare il tuo intervallo e quindi valutare.

Al contrario, i progetti digitali sincroni che tentano di raggiungere la velocità provano a fare il meno possibile tra i registri.

Mentre i dettagli probabilmente differirebbero un po ', parlando rozzamente funzionerebbe qualcosa del genere:

  • Si incrementa o reimposta l'indirizzo, quindi quello va in un registro.
  • Si blocca l'indirizzo nella memoria sincrona
  • È possibile bloccare l'output della memoria sincrona
  • Lo agganci all'indirizzo del generatore di caratteri sincrono
  • Agganci l'output del generatore di caratteri nel registro di output
  • applica la ricerca tavolozza ...
  • nel DAC sincrono ...

Quando si interrompe un'attività in questo modo, si ottiene solo un ritardo combinatorio più un certo ritardo di propagazione e la registrazione del registro e i tempi di attesa che devono rientrare tra i clock.

Un design costruito in questo modo richiederà molti clock per produrre un output: la latenza sarà effettivamente superiore a un design puramente combinatorio. Ma produce un nuovo output corretto su ogni ciclo di un clock molto più veloce.

Ehi, è un video, non importa se il CRT sta disegnando una dozzina di pixel dietro il contatore dei pixel - ovviamente tieni conto di ciò nella tempistica dei segnali di sincronizzazione in modo che siano corretti rispetto a quando i dati effettivamente esce dal DAC.

In pratica, quasi tutti i sistemi digitali complessi funzionano in questo modo, dato che è un'ottima idea - fino a quando una CPU pipeline non dipende da un risultato computazionale precedente o da un ramo condizionale ... Quindi le cose diventano interessanti, mentre ne parlano nella prossima lezione di una classe di sistemi digitali - ma per fortuna la tua situazione VGA è molto più semplice, specialmente se non ti preoccupi ancora di strappare gli effetti se il buffer dei personaggi cambia mentre viene disegnato lo schermo.

In pratica, se vuoi costruirlo, fallo in un FPGA. Ciò costringerà praticamente le memorie sincrone su di te se usi quelle interne, o i registri IO sincroni se usi la memoria esterna. Avrai un sacco di spintoni verso un design adeguato, il tessuto stesso sarà più veloce delle tue parti discrete e, naturalmente, se commetti un errore devi solo aggiustare i pollici mentre si ricompila piuttosto che passare una lunga giornata a ricablare .


"specialmente se non ti preoccupi ancora di strappare gli effetti se il buffer dei caratteri cambia mentre viene disegnato lo schermo" - ecco perché fin dai primi giorni dei coprocessori video, i coprocessori avevano un modo per informare il processo principale che non lo sono attualmente scaricando la memoria sullo schermo e se vogliono cambiare il buffer video, dovrebbero farlo ora.
John Dvorak,

Penso che tu stia complicando troppo questo. Ha già affermato di utilizzare un registro a scorrimento a 8 bit che emette un bit per clock di pixel. Presumibilmente si tratta di un registro a scorrimento a 8 bit con fermo. Ciò significa che deve recuperare un nuovo byte una volta ogni 8 clock di pixel, quindi una frequenza di 3,125 MHz. Questo ti dà tutti i 320 ns per ottenere i dati sul latch del registro a scorrimento, che è molto più lungo dei 120 ns che ha detto che ci vorrebbe.
Chris_F,

Per un caso monocromatico molto semplice a bassa risoluzione, sì, la tempistica dei byte non sarebbe troppo impegnativa, ma una parte fondamentale della domanda era che il richiedente stava cercando di capire come le prestazioni dei tipici sistemi "reali" di risoluzione non banale è possibile. E la risposta è la stessa di tutti gli altri utili sistemi digitali: tecnologia più veloce e progettazione sincrona pipeline.
Chris Stratton,

2

Utilizzando i componenti più veloci che riesco a trovare, i ritardi di propagazione e i tempi di accesso si sommano a circa 15 ns + 20 ns + 70 ns + 15 ns = 120 ns, molto più grandi del periodo di 40 ns per 25 MHz.

Dimentichi che una scheda grafica non disegnerebbe solo un singolo pixel, ma almeno una linea di scansione completa. Quindi, questo sarebbe un problema completamente pipelineable.

Inoltre, non dimenticare che finora ci sono stati cinque decenni di produzione di hardware video. Il tuo problema verrebbe di solito risolto con un tipo speciale di RAM, in cui esegui il rendering delle tue lettere su una porta e che viene letto in sequenza in un DAC del segnale video. Quell'hardware è molto più veloce di quello che stai guardando.

L'architettura di base per il mio circuito è la seguente:

  1. Il contatore binario per pixel orizzontali conta da 25.175 MHz a 800 (640 pixel visibili + 160 per portico anteriore, sincronizzazione, portico posteriore). A 800, incrementa il contatore di linee verticali (e resetta a 525 linee)

  2. Usando la posizione orizzontale e verticale, ricava la coordinata x, y del carattere corrente.

No, perché dovresti farlo? Metti semplicemente il tuo pixel di riga in un'area contigua di memoria e lo metti in modo lineare al tuo DAC - se si tratta di un'implementazione CPU / MCU, non lasceresti nemmeno che la tua CPU lo faccia, ma un'unità DMA, programmata non fare altro che prendere un valore dopo l'altro e metterlo ad esempio su una porta dati parallela, senza alcuna interazione del core della CPU.

  1. Utilizzando le coordinate x, y del carattere, indicizzalo nella memoria video per recuperare il carattere ASCII.

Ah, vuoi renderizzare al volo - buona scelta, ma insolito a costi moderni di RAM. Invece, dovresti semplicemente rendere il personaggio in un frame buffer in anticipo, o se il tuo dispositivo è estremamente sottile, reindirizza direttamente (vedi la mia spiegazione DMA sopra) la riga di caratteri al DAC.


1
Mentre le cose moderne tendono a preferire i framebuffer pre-renderizzati, sono ovviamente una cattiva scelta se stai cercando di lavorare senza molta RAM. Se lo stai facendo in un FPGA, puoi semplicemente fare in modo che la macchina a stati DMA prenda gli indirizzi dalla mappa delle celle dei caratteri e poi legga dai corrispondenti glifi dei caratteri.
R .. GitHub smette di aiutare ICE il

pienamente d'accordo qui! quindi, la mia sezione di risposta sulla terza domanda.
Marcus Müller,

2

A parte il pipelining (che è molto quello che dovresti fare), ti stai perdendo qualcosa di importante ...

Il registro a scorrimento in ingresso seriale, parallelo in uscita segna un punto a 25 Mhz dispari, certo, ma se i tuoi personaggi hanno una larghezza di 8 pixel, il loro input è a soli ~ 3.2MHz che è facilmente raggiungibile per la serie LS dell'era VGA, per tutto ciò è necessario disporre del byte successivo pronto quando il registro a scorrimento è terminato con quello corrente (qui entra in gioco la pipeline).

Genera un pixel clock a ~ 25MHz e un memory clock a 1/8 di quello per guidare il buffer di testo e la ROM CG, quindi condividi la memoria e l'accesso alla ROM CG.

Un ulteriore trucco, l'output del buffer di testo verrà ripetuto per ogni riga all'interno di una determinata riga di testo, quindi forse potresti sincronizzare gli 80 byte di testo in un buffer ad anello e quindi interrompere la lettura della ram per le successive 7 righe (supponendo un 8 carattere di linea), questo ti consente di liberare memoria da usare per la CPU, al costo di 80 byte di RAM appesi sul lato della cosa.


1

Quindi ovviamente non funziona; hai bisogno di una pipeline.

1) Conservare i personaggi contigui in memoria. Inizia in alto a sinistra.

2) Recupera un personaggio durante l'intervallo di cancellazione. Continua a recuperare i caratteri in ordine di memoria.

3) Pipeline ogni carattere decodificato più indice di linea nella ROM.

4) Pipeline dell'output ROM in un buffer.

5) Pipettare il buffer in un registro a scorrimento. Leggi i pixel continuamente a intervalli di 40 ns da questo.

(Ciò implica che è necessario caricare un nuovo carattere nel registro a scorrimento ogni 320 ns, il che potrebbe anche essere fattibile senza pipeline su tutto il resto del sistema.)

6) Durante il blanking orizzontale, tornare all'inizio della riga o passare al carattere successivo (ovvero l'inizio della riga successiva).

Caratteristica bonus: poiché hai bisogno di un personaggio ogni 320 ns, puoi anche leggere una coppia carattere + colore ed eseguire caratteri di colore stile MSDOS o stile spettro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.