Comment est-il possible de piloter des écrans VGA à des fréquences d'horloge aussi élevées?

12

Je travaille sur un circuit numérique utilisant des composants discrets pour piloter un écran VGA 640x480 en mode texte 80x30.

Pour un affichage 640x480, l'horloge pixel est de 25,175 MHz, qui a une période d'environ 40 ns. Je ne comprends pas comment je suis censé pouvoir fournir un nouveau pixel à l'affichage aussi souvent.

L'architecture de base de mon circuit est la suivante:

  1. Le compteur binaire pour les pixels horizontaux compte de 25,175 MHz à 800 (640 pixels visibles + 160 pour le porche avant, la synchronisation, le porche arrière). À 800, incrémenter le compteur de lignes verticales (et réinitialiser à 525 lignes)

  2. En utilisant la position horizontale et verticale, dérivez les coordonnées x, y du caractère actuel.

  3. En utilisant les coordonnées x, y du caractère, indexez dans la mémoire vidéo pour récupérer le caractère ASCII.

  4. Utilisez le caractère ASCII pour indexer dans la ROM de caractères pour obtenir le modèle de bits pour le caractère

  5. Utilisez un registre à décalage parallèle à série pour convertir une ligne de caractères de 8 pixels en bits individuels à une fréquence d'horloge de pixels

Si vous suivez la chaîne, cela va: Compteur -> RAM -> ROM -> Parallel to Serial Shift Register

En utilisant les composants les plus rapides que je puisse trouver, les délais de propagation et le temps d'accès totalisent environ 15 ns + 20 ns + 70 ns + 15 ns = 120 ns, bien plus que la période de 40 ns pour 25 MHz.

À des résolutions et des taux de rafraîchissement encore plus élevés, vous pouvez avoir des horloges de pixels bien au-dessus de 100 MHz, ce qui représente une période de 10 ns.

Comment est-il possible de fournir de nouveaux pixels à l'affichage toutes les 10 ns alors que le temps d'accès à la RAM / ROM est déjà bien supérieur, sans même prendre en compte tous les autres signaux de votre système?

supershirobon
la source
7
Vous utilisez la RAM vidéo dédiée et l'horloge directement dans votre signal vidéo. Vous travaillez à déterminer ce qu'il faut afficher bien avant de l'afficher.
Hearth
2
Allez lire sur Maximite . Il utilise simplement le matériel périphérique d'un MCU et quelques résistances pour piloter un port VGA. Commencez par examiner le périphérique PIC32 qu'il utilise. Fonctionne bien. (J'ai un Maximite ici.)
jonk
"The Cheap Video Cookbook" par "Don Lancaster"
Jasen

Réponses:

17

Il y a deux raisons principales pour lesquelles vous trouvez cela difficile.

Tout d'abord, vous utilisez des pièces plus anciennes et plus discrètes (intégration à plus petite échelle) que celles qui auraient été utilisées à cette époque à l'ère du VGA.

Mais ensuite, vous les utilisez de manière atypique. Plus précisément, votre approche n'est pas pipelinedce qui signifie que vous devez additionner plusieurs retards pour déterminer votre intervalle, et donc votre taux.

En revanche, les conceptions numériques synchrones qui tentent d'atteindre la vitesse essaient d'en faire le moins possible entre les registres.

Bien que les détails diffèrent probablement un peu, grossièrement, cela fonctionnerait comme ceci:

  • Vous incrémentez ou réinitialisez l'adresse, puis cela va dans un registre.
  • Vous verrouillez l'adresse dans la mémoire synchrone
  • Vous verrouillez la sortie de la mémoire synchrone
  • Vous le verrouillez dans l'adresse du générateur de caractères synchrone
  • Vous verrouillez la sortie du générateur de caractères dans le registre de sortie
  • appliquer la recherche de palette ...
  • dans le DAC synchrone ...

Lorsque vous décomposez une tâche comme celle-ci, vous n'obtenez qu'un seul délai combinatoire plus un certain délai de propagation et enregistrez les temps de configuration et de maintien devant s'adapter entre les horloges.

Une conception construite de cette façon nécessitera de nombreuses horloges pour produire une sortie - la latence sera en fait plus élevée qu'une conception purement combinatoire. Mais il produit une nouvelle sortie correcte à chaque cycle d'une horloge beaucoup plus rapide.

Et bon, c'est de la vidéo, cela n'a pas vraiment d'importance si le CRT dessine une douzaine de pixels derrière le compteur de pixels - vous en tenez bien sûr compte dans le timing des signaux de synchronisation afin qu'ils soient corrects par rapport au moment où les données réellement sort du CAD.

Dans la pratique, presque tous les systèmes numériques complexes fonctionnent de cette façon, car c'est une excellente idée - jusqu'à ce qu'un processeur pipeliné atteigne une dépendance par rapport à un résultat de calcul antérieur ou à une branche conditionnelle ... Ensuite, les choses deviennent intéressantes, comme ils en parleraient dans la prochaine conférence d'une classe de systèmes numériques - mais heureusement, votre situation VGA est beaucoup plus simple, surtout si vous ne vous inquiétez pas encore des effets de déchirement si le tampon de caractères change pendant que l'écran est en cours de dessin.

En pratique, si vous voulez construire cela, faites-le dans un FPGA. Cela vous imposera des mémoires synchrones si vous utilisez des mémoires internes ou des registres d'E / S synchrones si vous utilisez de la mémoire externe. Vous obtiendrez beaucoup de coup de pouce vers une conception appropriée, le tissu lui-même sera plus rapide que vos pièces discrètes, et bien sûr, si vous faites une erreur, vous n'avez qu'à tourner les pouces pendant qu'il recompile plutôt que de passer une longue journée à recâbler .

Chris Stratton
la source
"surtout si vous ne vous inquiétez pas encore des effets de déchirement si le tampon de caractères change pendant que l'écran est dessiné" - c'est pourquoi depuis les premiers jours des coprocesseurs vidéo, les coprocesseurs avaient un moyen d'informer le processus principal qu'ils ne le sont pas vidant actuellement leur mémoire sur l'écran et s'ils veulent changer le tampon vidéo, ils devraient le faire maintenant.
John Dvorak
Je pense que vous compliquez trop cela. Il a déjà déclaré qu'il utilisait un registre à décalage de 8 bits qui émet un bit par pixel d'horloge. Il s'agit vraisemblablement d'un registre à décalage de 8 bits avec verrouillage. Cela signifie qu'il n'a qu'à récupérer un nouvel octet une fois les horloges de 8 pixels, pour un taux de 3,125 MHz. Cela vous donne tous les 320 ns pour obtenir les données sur le verrou du registre à décalage, ce qui est beaucoup plus long que les 120 ns qu'il a dit qu'il faudrait.
Chris_F
Pour un cas monochrome très simple à faible résolution, oui, le timing des octets ne serait pas trop difficile, mais une partie clé de la question était que le demandeur essayait de comprendre comment les performances des systèmes "réels" typiques de résolution non triviale est possible. Et la réponse est la même que pour tous les autres systèmes numériques utiles: technologie plus rapide et conception synchrone en pipeline.
Chris Stratton
2

En utilisant les composants les plus rapides que je puisse trouver, les délais de propagation et le temps d'accès totalisent environ 15 ns + 20 ns + 70 ns + 15 ns = 120 ns, bien plus que la période de 40 ns pour 25 MHz.

Vous oubliez qu'un adaptateur graphique ne dessinerait jamais qu'un seul pixel, mais au moins une ligne de balayage complète. Ainsi, ce serait un problème complètement pipelineable.

N'oubliez pas non plus qu'il y a déjà eu cinq décennies de matériel de production vidéo. Votre problème serait généralement résolu avec un type spécial de RAM, dans lequel vous restituez vos lettres sur un port, et qui est lu séquentiellement sur un signal vidéo DAC. Ce matériel est bien plus rapide que ce que vous regardez.

L'architecture de base de mon circuit est la suivante:

  1. Le compteur binaire pour les pixels horizontaux compte de 25,175 MHz à 800 (640 pixels visibles + 160 pour le porche avant, la synchronisation, le porche arrière). À 800, incrémenter le compteur de lignes verticales (et réinitialiser à 525 lignes)

  2. En utilisant la position horizontale et verticale, dérivez les coordonnées x, y du caractère actuel.

Non, pourquoi feriez-vous ça? Vous mettriez simplement votre pixel de ligne dans une zone de mémoire contiguë et le mettriez linéairement sur votre DAC - s'il s'agit d'une implémentation CPU / MCU, vous ne laisseriez même pas votre CPU faire cela, mais une unité DMA, programmée pour ne rien faire mais prendre une valeur après l'autre et la mettre par exemple sur un port de données parallèle, sans aucune interaction avec le cœur du processeur.

  1. En utilisant les coordonnées x, y du caractère, indexez dans la mémoire vidéo pour récupérer le caractère ASCII.

Ah, vous voulez rendre à la volée - bon choix, mais inhabituel aux coûts modernes de RAM. Au lieu de cela, vous devez simplement rendre le caractère dans un tampon de trame au préalable, ou si votre appareil est extrêmement mince, dirigez directement (voir mon explication DMA ci-dessus) la ligne de caractères vers le DAC.

Marcus Müller
la source
1
Alors que les trucs modernes ont tendance à préférer les tampons d'images pré-rendus, ils sont évidemment un mauvais choix si vous essayez de travailler sans trop de RAM. Si vous faites cela dans un FPGA, vous pouvez simplement faire en sorte que la machine à états DMA prenne des adresses dans la mappe de cellules de caractères, puis les lise dans les glyphes de caractères correspondants.
R .. GitHub STOP HELPING ICE
entièrement d'accord ici! par conséquent, ma section de réponse sur la troisième question.
Marcus Müller
2

Mis à part le pipelining (qui est vraiment ce que vous devez faire), il vous manque quelque chose de majeur ...

Les horloges du registre à décalage d'entrée parallèle et de sortie série pointent à 25 Mhz impairs, bien sûr, mais si vos personnages ont une largeur de 8 pixels, leur entrée est à seulement ~ 3,2 MHz, ce qui est facilement accessible pour la série LS de l'ère VGA, pour autant que cela vous devez avoir l'octet suivant prêt lorsque le registre à décalage se termine avec l'actuel (c'est là que le pipeline entre).

Générez une horloge de pixels à ~ 25 MHz et une horloge de mémoire à 1/8 de celle-ci pour piloter le tampon de texte et la ROM CG, puis canalisez cette mémoire et les trucs d'accès à la ROM CG.

Une autre astuce, la sortie du tampon de texte sera répétée pour chaque ligne dans une ligne de texte donnée, donc vous pourriez peut-être synchroniser les 80 octets de texte dans un tampon en anneau puis arrêter de lire le ram pour les 7 lignes suivantes (en supposant un 8 caractère de ligne), cela vous permet de libérer de la mémoire pour le CPU à utiliser, au prix d'avoir besoin de 80 octets de RAM accroché sur le côté de la chose.

Dan Mills
la source
1

Alors, évidemment, cela ne fonctionne pas; vous avez besoin d'un pipeline.

1) Stockez les caractères de façon contiguë dans la mémoire. Commencez en haut à gauche.

2) Récupérez un caractère pendant l'intervalle de suppression. Continuez à récupérer les caractères dans l'ordre de la mémoire.

3) Pipeline chaque caractère décodé plus index de ligne dans la ROM.

4) Pipeline la sortie ROM dans un tampon.

5) Pipeline le tampon dans un registre à décalage. Lisez les pixels en continu à des intervalles de 40ns.

(Cela implique que vous devez charger un nouveau caractère dans le registre à décalage toutes les 320ns, ce qui pourrait même être faisable sans pipeliner le reste du système.)

6) Pendant la suppression horizontale, revenez au début de la ligne ou avancez au caractère suivant (c.-à-d. Début de la ligne suivante).

Bonus: comme vous n'avez besoin que d'un caractère toutes les 320ns, vous pouvez également lire une paire caractère + couleur et créer des caractères de couleur de style MSDOS ou de style spectre.

pjc50
la source