« Very High Speed Integrated Circuit Hardware Description Language/Interfaces VGA et PS2 » : différence entre les versions

Contenu supprimé Contenu ajouté
m Robot : Remplacement de texte automatisé (-(<|</)source([ \t>]) +\1syntaxhighlight\2)
Ligne 31 :
{{Solution|contenu=
Les valeurs que l’on donne dans le programme sont légèrement différentes de celles du dessin, mais cela n'a pas beaucoup d'importance. Si vous voulez comprendre d'où viennent ces valeurs, je vous conseille de lire [[b:TD3_VHDL_Compteurs_et_registres#Exercice_4_:_réalisation_des_signaux_de_synchronisation_d.27un_écran_VGA|cet exercice]] et sa solution.
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 96 :
vert_sync_out <= vert_sync;
END aVGA_SYNC;
</syntaxhighlight>
</source>
On a donné ici que les '''quatre "process"''' qui réalisent nos '''quatre blocs'''.
 
Ligne 117 :
==== Exercice 2 ====
On dispose d'un composant [[w:Logique_combinatoire_(Electronique)|combinatoire]] rect capable de dessiner un rectangle décrit en VHDL par son entité :
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 127 :
red1,green1,blue1 : out std_logic);
END rect;
</syntaxhighlight>
</source>
Sa couleur est fixée par son entrée coloRGB, sa position par x_rect et y_rect. Sa taille est fixée par delta_x et delta_y. Le code correspondant à son architecture est :
<sourcesyntaxhighlight lang="VHDL">
ARCHITECTURE arect of rect is begin
PROCESS(row,col,x_rec,y_rec) BEGIN
Ligne 149 :
end process;
end arect;
</syntaxhighlight>
</source>
1°) Écrire le programme VHDL qui permet de dessiner un rectangle de taille 100x100 aux coordonnées 100 suivant x et 100 suivant y. On dispose pour cela d'une horloge à 50 MHz appelée clk_50. On réalise donc l'assemblage de la figure ci-dessus pour donner l'entité :
<sourcesyntaxhighlight lang="VHDL">
ENTITY VGAtop IS
PORT (clk_50 : in STD_LOGIC;
hsynch,vsynch,red,green,blue : out STD_LOGIC);
END VGAtop;
</syntaxhighlight>
</source>
2°) Modifier le programme précédant pour qu’il dessine une balle et deux raquettes. La position de la balle sera donnée par des entrées externes mais les positions X des raquettes seront fixées.
<sourcesyntaxhighlight lang="VHDL">
ENTITY VGAtop IS
PORT (clk_50 : in STD_LOGIC;
Ligne 165 :
hsynch,vsynch,red,green,blue : out STD_LOGIC);
END VGAtop;
</syntaxhighlight>
</source>
Remarquez par la même occasion que l’on a choisi les positions verticales des raquettes sur seulement {{Unité|8|bits}}. Économie économie !
{{Solution|contenu=
Pour éviter des solutions trop longues, on commence par donner la partie VHDL commune aux deux questions :
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 193 :
 
end atop;
</syntaxhighlight>
</source>
Remarquez qu’il faut retirer des commentaires pour la question 2°)
 
Ligne 200 :
1°) Puisque 100 est notre chiffre pour la question, il nous faut d’abord le convertir en binaire soit : 0001100100
Mettez la partie VHDL ci-dessous dans la partie à compléter et vous aurez votre rectangle.
<sourcesyntaxhighlight lang="VHDL">
signal clk_25 : std_logic;
signal srow,scol : STD_LOGIC_VECTOR(9 DOWNTO 0);
Ligne 217 :
delta_x=>"0001100100",delta_y=>"0001100100", -- 100 et 100
x_rec => "0001100100", y_rec => "0001100100");
</syntaxhighlight>
</source>
 
2°) C'est un peu plus complexe pour la balle et les deux raquettes. Il faut en effet utiliser des signaux intermédiaire pour chaque composant rectangle et faire un OU final.
 
N'oubliez pas de retirer les commentaires de l'entité VGATop avant d'y insérer ce code :
<sourcesyntaxhighlight lang="VHDL">
signal clk_25,sred,sgreen,sblue,sred1,sgreen1,sblue1,sred2,sgreen2,sblue2 : std_logic;
signal srow,scol : STD_LOGIC_VECTOR(9 DOWNTO 0);
Ligne 250 :
green <= sgreen or sgreen1 or sgreen2;
blue <= sblue or sblue1 or sblue2;
</syntaxhighlight>
</source>
}}
 
Ligne 257 :
Voici un exemple de tracé de rectangle destiné à la carte DE2-115 d'Altera. La grande différence avec ce qui a été fait jusqu'à présent est l'apparition des signaux VGA_BLANK, VGA_SYNC et VGA_CLK en sortie. Ils sont liés d'une manière ou une autre au fait que cette carte utilise des convertisseurs numériques analogiques pour les signaux de couleur.
{{Boîte déroulante|titre=Code de tracé d'un rectangle (spécifique à carte Altera DE2-115)|contenu=
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 428 :
end process;
end arect;
</syntaxhighlight>
</source>
}}
Les contraintes pour la carte DE2-115 sont présentées sous forme de fichier csv. Ce genre de fichier peut facilement s'importer dans Quartus.
Ligne 454 :
 
Soit le programme VHDL suivant :
<sourcesyntaxhighlight lang="VHDL">
ENTITY rect_generic is
generic(x,y,dx,dy : natural); --c'est ici qu’il y a du nouveau
Ligne 490 :
END PROCESS;
END arect_gen;
</syntaxhighlight>
</source>
Ses seules grandes différences sont l'apparition dans l'entité de quatre valeurs generic : x, et y pour la position et dx, dy pour la taille ainsi que l'entrée "e_rect" destinée à choisir un affichage ou non du rectangle. L'utilisation d'un tel rectangle se fera toujours par un "port map", mais il faudra lui ajouter un "generic map".
 
Ligne 498 :
{{solution|contenu=
La solution présentée a été réalisée par des étudiants. Ainsi l’ordre choisi pour les segments est un peu étrange, mais cette solution a été testée avec succès.
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 559 :
end a_aff;
</syntaxhighlight>
</source>
Tous les calculs réalisés dans les "generic map" (multiplications et divisions) ne sont pas réalisés par les ressources du {{Abréviation|FPGA|Field Programmable Gate Array|en}} mais par les ressources de votre PC : c’est le compilateur VHDL qui fait le travail.
}}
Ligne 573 :
Les sorties sont les 5 signaux VGA non représentés qui en final vont faire le dessin ci-dessus, c'est-à-dire deux raquettes, une balle et quatre afficheurs de scores. Pour cadencer tout cela il faut une horloge, encore une fois non présentée. Toutes les entrées sont pour changer les positions, de la balle et des raquettes, et pour fournir des nombres à afficher sur les scores.
{{Solution|contenu=
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 826 :
end a_aff;
</syntaxhighlight>
</source>
}}
 
Ligne 838 :
 
Le code donné dessine les murs de briques légèrement sur la droite (c'est volontaire) et les briques sont bleues.
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 993 :
end a_ligne8briques;
</syntaxhighlight>
</source>
}}
 
Ligne 1 017 :
 
{{Boîte déroulante|titre=Notre RAMB16_S9 de caractères (spécifique à Xilinx)|contenu=
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 1 130 :
-- End of RAMB16_S9_inst instantiation
end arch;
</syntaxhighlight>
</source>
}}
Ce code nécessite la remarque suivante :
Ligne 1 141 :
 
{{Boîte déroulante|titre=Notre RAMB16_S1 de caractères (spécifique à Xilinx)|contenu=
<sourcesyntaxhighlight lang="VHDL">
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Ligne 1 244 :
-- End of RAMB16_S1_inst instantiation
end arch;
</syntaxhighlight>
</source>
}}
Cette RAM sera modifiée lorsque l’on s'intéressera au jeu du pacman un peu plus loin.
Ligne 1 280 :
{{Boîte déroulante|titre=Notre dessin de caractères (spécifique à Xilinx)|contenu=
Ce programme ne respecte pas tout à fait le cahier des charges initial car il multiplie par 4=2x2 la taille des caractères. Nous avons laissé en commentaire une version sans ce "zoom" dans le code ci-dessous.
<sourcesyntaxhighlight lang="VHDL">
library ieee;
use ieee.std_logic_1164.all;
Ligne 1 386 :
architecture arch of font_rom is
-- ******** voir RAM1B6_S1 plus haut
</syntaxhighlight>
</source>
}}
Vous avez trois lignes (utilisez les commentaires pour cela) à changer pour retirer le zoom :
Ligne 1 409 :
{{Solution|contenu=
Nous nous sommes aperçu après coup que si l’on continue à paver l'écran les numéros des pavés tombent justement sur 64, 65, 66, ... pour la ligne du bas. Ainsi la génération des numéros de pavés à partir de pixel_x et pixel_y reste identique à ce que l’on a déjà fait. Par contre pour ne garder que l’affichage de cette ligne du bas, il faut changer la génération de "text_bit_on" qui, rappelons-le, est responsable de l'extinction des caractères non voulus.
<sourcesyntaxhighlight lang="VHDL">
-- partie VHDL a changer
text_bit_on <=
'1' when (pixel_x(9)='0') and (pixel_y(9 downto 7)="000") else
'0';
</syntaxhighlight>
</source>
en
<sourcesyntaxhighlight lang="VHDL">
-- partie VHDL changée
text_bit_on <=
'1' when (pixel_x(9)='0') and (pixel_y(9 downto 6)="0111") else -- pour exo4
'0';
</syntaxhighlight>
</source>
}}
 
Ligne 1 434 :
 
Nous allons donc commencer par essayer de générer des pavés numérotés à partir de 0. Ils formeront les adresses de la RAM des caractères à afficher. Si l'adresse se nomme addr_pave (pour adresse pavé ou numéro pavé) on réalise simplement :
<sourcesyntaxhighlight lang="VHDL">
addr_pave <= pixel_y(6) & pixel_x(9 downto 4);
</syntaxhighlight>
</source>
Quand pixel_x et pixel_y s'incrémentent addr_pave donne le numéro de chaque pavé. Voyez-vous correctement que la dernière ligne (de caractères sur l'écran VGA) commence par le numéro 64 et s'arrête à 103 ?
 
Ligne 1 456 :
{{Solution| contenu=
Nous donnons sans plus de commentaire le programme complet. Essayez de trouver comment est géré le retard de la recherche évoqué en remarque ci-dessus.
<sourcesyntaxhighlight lang="VHDL">
library ieee;
use ieee.std_logic_1164.all;
Ligne 1 644 :
end arch;
</syntaxhighlight>
</source>
}}
 
Ligne 1 650 :
{{Solution|contenu=
Le minimum de changement est :
<sourcesyntaxhighlight lang="VHDL">
addr_pave <= '0' & pixel_x(9 downto 4);
</syntaxhighlight>
</source>
Remarquez qu'avec cette modification toute la colonne gauche contient un ensemble de pavés numéro 0... et qu'en fait toutes les colonnes contiennent le même numéro de pavé ! C'est
<sourcesyntaxhighlight lang="VHDL">
text_bit_on <=
'1' when (pixel_y(9 downto 6)="0111") else
'0';
</syntaxhighlight>
</source>
qui gère la zone d'affichage : ici la dernière ligne.
}}
Ligne 1 674 :
{{Solution|contenu=
Nous donnons en vrac une solution qui fonctionne mais qui mériterait d’être commentée et épurée.
<sourcesyntaxhighlight lang="VHDL">
library ieee;
use ieee.std_logic_1164.all;
Ligne 2 202 :
end a_ligne8briques;
</syntaxhighlight>
</source>
}}
Nous allons mettre toutes ces connaissances acquises à la lecture de ces sections à profit pour réaliser un pacman. Cela nous permettra de changer un peu de domaine de jeu pour laisser tomber les raquettes.
Ligne 2 236 :
 
Cette figure permet de comprendre le début de l'initialisation de la mémoire :
<sourcesyntaxhighlight lang="VHDL">
--*********** début du contenu de la RAMB16_S1
-- rien d'intéressant / Noir complet
Ligne 2 246 :
--brique / rien d'intéressant
INIT_03=>X"FFD5ABD5ABD5ABD5ABD5ABD5ABD5ABFF00005555555555555555555555550000",
</syntaxhighlight>
</source>
 
Cette mémoire est commandée par une RAMB16_S9 qui sera destinée à réaliser le labyrinthe complet.
Ligne 2 252 :
===== Exercice 7 =====
À partir du contenu de la RAMB16_S9, pouvez-vous dessiner ce qui sera reproduit sur votre écran VGA ?
<sourcesyntaxhighlight lang="VHDL">
-- Address 0 to 4095
INIT_00=>X"0000000000000000000000000000000000000000000000000000000000000000",
Ligne 2 287 :
INIT_1e=>X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1f=>X"0000000000000000000000000000000000000000000000000000000000000000",
</syntaxhighlight>
</source>
Une chaîne de caractères est écrite en bas de l'écran. Pouvez-vous la donner en vous aidant des codes ASCII contenu dans cette mémoire.
{{remarque|contenu=Le contenu de la ROM se lit ici de la droite vers la gauche !!!}}
Ligne 2 296 :
===== Exercice 8 =====
Nous donnons le contenu de la RAMB16_S1 qui gère les sprites :
<sourcesyntaxhighlight lang="VHDL">
-- Address 0 to 4095
--??/blanc
Ligne 2 316 :
-- ennemi fantome/ennemi esprit
INIT_08=>X"000000003C243C007E5A7E0000000000000000AAFFC3C3FF7E5A7E3C00000000",
</syntaxhighlight>
</source>
Pouvez-vous dessiner sur une feuille ce que cela donnera sur un écran VGA ?
 
===== Affichage des sprites =====
Pour gérer les sprites il nous faut prévoir les entrées correspondantes dans l'entité. La voici présentée :
<sourcesyntaxhighlight lang="VHDL">
entity pacman is
port(
Ligne 2 337 :
);
end pacman;
</syntaxhighlight>
</source>
On y voit apparaître les coordonnées du [[w:Pac-Man|pacman]] sur {{Unité|10|bits}} et le numéro du sprite car le pacman est représenté bouche ouverte ou fermée et allant vers la droite, la gauche, le haut et le bas. Cela fait en tout 8 sprites différents d'où les trois bits "pacman_sprite_number". Le fait que les coordonnées soient sur {{Unité|10|bits}} indique qu’il peut être affiché n’importe où sur l'écran. Si l’on désire interfacer ces coordonnées avec un processeur {{Unité|8|bits}}, on peut se limiter à {{Unité|8|bits}} et relier directement les deux bits de poids faibles à 0.
 
Ligne 2 343 :
Voici le programme complet avec sprite et décor.
{{Boîte déroulante|titre=Notre pacman avec décor de fond et sprite (spécifique à Xilinx)|contenu=
<sourcesyntaxhighlight lang="VHDL">
library ieee;
use ieee.std_logic_1164.all;
Ligne 2 792 :
-- End of RAMB16_S1_inst instantiation
end arch;
</syntaxhighlight>
</source>
}}
Ce programme est un peu long, mais nous sommes obligé de le donner quasiment complètement puisque le contenu de la RAMB16_S1 a changé et en plus elle a été transformée en RAMB16_S1_S1.