Initialiser la RAM bloc FPGA depuis des fichiers texte avec la bibliothèque TEXTIO de VHDL
Peupler la RAM bloc avec des valeurs prédéfinies se fait le plus efficacement en lisant des littéraux binaires ou hexadécimaux depuis un fichier ASCII. Cette technique sert aussi à créer des ROM, car la ROM FPGA est simplement une RAM qu'on lit uniquement.
Pour les exemples ci-dessous, les constantes et le type RAM suivants sont déclarés dans la région déclarative du fichier VHDL :
constant ram_depth : natural := 256; constant ram_width : natural := 32; type ram_type is array (0 to ram_depth - 1) of std_logic_vector(ram_width - 1 downto 0);
Cet article fait partie d'une série sur la bibliothèque TEXTIO en VHDL. Lecture de fichier de stimulus dans le banc de test avec TEXTIO | Lecture d'image bitmap BMP avec TEXTIO
Lecture de lignes et de données avec TEXTIO
Le paquet TEXTIO, situé dans la bibliothèque standard std, fournit les sous-programmes requis pour les E/S de fichiers. Il est automatiquement disponible, vous n'avez qu'à l'importer :
use std.textio.all;
Nos données RAM seront stockées dans un fichier ASCII où chaque ligne représente un mot de mémoire. La procédure READLINE lit une ligne unique dans un objet LINE. Son prototype est :
procedure READLINE (file F: TEXT; L: inout LINE); type LINE is access STRING; -- pointeur vers une chaîne allouée dynamiquement
VHDL‑2008 introduit OREAD, HREAD, et BREAD pour extraire des valeurs octales, hexadécimales et binaires d'un objet LINE. Pour la brièveté, nous nous concentrerons sur les lectures hexadécimales et binaires. Les déclarations pertinentes sont :
procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; alias BREAD is READ [LINE, STD_ULOGIC_VECTOR];
Pour les versions VHDL legacy (pré‑2008), la procédure standard READ doit être utilisée, qui ne supporte pas l'hexadécimal directement. Dans ce cas, une routine de conversion personnalisée est requise.
Chargement de données hexadécimales
La notation hexadécimale est commode car chaque paire de chiffres hex correspond directement à un octet. L'exemple de fichier ram_content_hex.txt contient 256 lignes, chacune tenant une chaîne hex de 8 caractères de 00000001 à 00000100 :
| 1 2 … 255 256 | 0000000100000002…000000FF00000100 |
La fonction impure suivante lit le fichier et retourne un tableau ram_type entièrement initialisé. Elle fonctionne avec VHDL‑2008 et plus récent :
impure function init_ram_hex return ram_type is file text_file : text open read_mode is "ram_content_hex.txt"; variable text_line : line; variable ram_content : ram_type; begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); hread(text_line, ram_content(i)); end loop; return ram_content; end function;
Après avoir défini la fonction, le signal RAM est instancié avec le contenu initial :
signal ram_hex : ram_type := init_ram_hex;
VHDL Legacy : Implémenter HREAD manuellement
Quand HREAD n'est pas disponible (ex: VHDL‑93 ou VHDL‑2002), une routine de conversion manuelle peut être intégrée dans la fonction d'initialisation. L'exemple suivant démontre cette approche :
impure function init_ram_hex return ram_type is file text_file : text open read_mode is "ram_content_hex.txt"; variable text_line : line; variable ram_content : ram_type; variable c : character; variable offset : integer; variable hex_val : std_logic_vector(3 downto 0); begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); offset := 0; while offset < ram_content(i)'high loop read(text_line, c); case c is when '0' => hex_val := "0000"; when '1' => hex_val := "0001"; when '2' => hex_val := "0010"; when '3' => hex_val := "0011"; when '4' => hex_val := "0100"; when '5' => hex_val := "0101"; when '6' => hex_val := "0110"; when '7' => hex_val := "0111"; when '8' => hex_val := "1000"; when '9' => hex_val := "1001"; when 'A' | 'a' => hex_val := "1010"; when 'B' | 'b' => hex_val := "1011"; when 'C' | 'c' => hex_val := "1100"; when 'D' | 'd' => hex_val := "1101"; when 'E' | 'e' => hex_val := "1110"; when 'F' | 'f' => hex_val := "1111"; when others => hex_val := "XXXX"; assert false report "Found non-hex character '" & c & "'"; end case; ram_content(i)(ram_content(i)'high - offset downto ram_content(i)'high - offset - 3) := hex_val; offset := offset + 4; end loop; end loop; return ram_content; end function;
Bien qu'une procédure HREAD dédiée puisse être définie, la plupart des outils de synthèse (ex: Xilinx Vivado) ne supportent pas les procédures acceptant un argument LINE. L'erreur suivante illustre cette limitation :
Dans Vivado :
[Synth 8-27] Procedure argument of type ‘line’ is not supported [init_ram_tb.vhd:15]
Lecture de données binaires
Si la largeur de la RAM n'est pas un multiple de 8, les littéraux binaires peuvent être préférables. L'exemple de fichier ram_content_bin.txt contient 256 lignes, chacune avec une chaîne binaire de 32 bits :
| 1 2 … 255 256 | 0000000000000000000000000000000100000000000000000000000000000010…0000000000000000000000001111111100000000000000000000000100000000 |
En VHDL‑2008, la procédure BREAD peut être utilisée pour lire des valeurs binaires directement :
impure function init_ram_bin return ram_type is file text_file : text open read_mode is "ram_content_bin.txt"; variable text_line : line; variable ram_content : ram_type; begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); bread(text_line, ram_content(i)); end loop; return ram_content; end function;
Instanciez la RAM avec :
signal ram_bin : ram_type := init_ram_bin;
VHDL Legacy : Lectures binaires avec READ
Pour VHDL‑2002 ou VHDL‑93, la procédure READ doit être utilisée. Comme elle retourne un vecteur bit, le résultat est converti en std_logic_vector via To_StdLogicVector :
impure function init_ram_bin return ram_type is file text_file : text open read_mode is "ram_content_bin.txt"; variable text_line : line; variable ram_content : ram_type; variable bv : bit_vector(ram_content(0)'range); begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); read(text_line, bv); ram_content(i) := To_StdLogicVector(bv); end loop; return ram_content; end function;
Rétroportage des fonctionnalités TEXTIO modernes
Si vous préférez ne pas modifier le code legacy, vous pouvez importer le paquet tiers std_logic_1164_additions. Cette bibliothèque rétroportent les procédures HREAD et BREAD vers les versions VHDL plus anciennes, au coût d'une dépendance supplémentaire.
Pour des exemples plus détaillés et une lecture approfondie, consultez les articles accompagnants de cette série.
VHDL
- Protéger l'aluminium contre la corrosion : stratégies d'experts pour une durabilité à long terme
- Éléments métalliques vs non métalliques : différences clés expliquées
- Construire votre premier template AWS CloudFormation — Guide pratique
- Cloud Computing vs Informatique Traditionnelle : Comparaison Pratique
- Maîtriser les commentaires en C : Écrire des notes claires et efficaces
- Lecture de Fichiers en Java avec BufferedReader – Guide Pratique avec Exemples
- Calculer des Moyennes en Python : Guide Pratique
- Le micromètre expliqué : lecture et utilisation de cet instrument de mesure de précision
- Invoquer des blocs de fonction PLC via clients OPC UA : guide pratique