Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> VHDL

FPGA Block RAM aus Textdateien mit VHDLs TEXTIO-Bibliothek initialisieren

Das Befüllen von Block RAM mit vordefinierten Werten gelingt am effizientesten durch Einlesen binärer oder hexadezimaler Literale aus einer ASCII-Datei. Diese Technik eignet sich auch zur Erstellung von ROMs, da FPGA-ROM schlicht ein RAM ist, das nur gelesen wird.

Für die folgenden Beispiele sind die untenstehenden Konstanten und der RAM-Typ im deklarativen Bereich der VHDL-Datei deklariert:

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);

Dieser Artikel ist Teil einer Serie zur TEXTIO-Bibliothek in VHDL. Stimulus-Datei in Testbench mit TEXTIO einlesen | BMP-Bitmap-Bild mit TEXTIO einlesen

Zeilen und Daten mit TEXTIO einlesen

Das TEXTIO-Paket in der Standard-std-Bibliothek stellt die für Datei-I/O benötigten Subprogramme bereit. Es ist automatisch verfügbar, Sie müssen es nur importieren:

use std.textio.all;

Unsere RAM-Daten werden in einer ASCII-Datei gespeichert, wo jede Zeile ein Speicherwort repräsentiert. Die READLINE-Prozedur liest eine einzelne Zeile in ein LINE-Objekt. Ihr Prototyp lautet:

procedure READLINE (file F: TEXT; L: inout LINE); type LINE is access STRING; -- Zeiger auf dynamisch allozierten String

VHDL-2008 führt OREAD, HREAD und BREAD ein, um oktale, hexadezimale und binäre Werte aus einem LINE-Objekt zu extrahieren. Der Übersichtlichkeit halber fokussieren wir uns auf hexadezimale und binäre Reads. Die relevanten Deklarationen sind:

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];

Für legacy VHDL-Versionen (vor 2008) muss die Standard-READ-Prozedur verwendet werden, die Hexadezimal nicht direkt unterstützt. In diesem Fall ist eine benutzerdefinierte Konvertierungsroutine nötig.

Hexadezimale Daten laden

Hexadezimale Notation ist praktisch, da jedes Hex-Ziffernpaar direkt auf ein Byte abbildet. Die Beispiel-ram_content_hex.txt-Datei enthält 256 Zeilen, jeweils einen 8-stelligen Hex-String von 00000001 bis 00000100:

1
2
…
255
256
00000001
00000002
…
000000FF
00000100

Die folgende impure Funktion liest die Datei und gibt ein vollständig initialisiertes ram_type-Array zurück. Sie funktioniert mit VHDL-2008 und neuer:

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;

Nach Definition der Funktion wird das RAM-Signal mit dem Initialinhalt instanziiert:

signal ram_hex : ram_type := init_ram_hex;

Legacy VHDL: HREAD manuell implementieren

Wenn HREAD nicht verfügbar ist (z. B. VHDL-93 oder VHDL-2002), kann eine manuelle Konvertierungsroutine in die Initialisierungsfunktion eingebettet werden. Das folgende Beispiel demonstriert diesen Ansatz:

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;

Zwar könnte eine dedizierte HREAD-Prozedur definiert werden, aber die meisten Synthese-Tools (z. B. Xilinx Vivado) unterstützen keine Prozeduren, die ein LINE-Argument akzeptieren. Der folgende Fehler illustriert diese Einschränkung:

In Vivado:
[Synth 8-27] Procedure argument of type 'line' is not supported [init_ram_tb.vhd:15]

Binäre Daten einlesen

Wenn die RAM-Breite kein Vielfaches von 8 ist, können binäre Literale vorzuziehen sein. Die Beispiel-ram_content_bin.txt-Datei enthält 256 Zeilen, jeweils einen 32-Bit-Binärstring:

1
2
…
255
256
00000000000000000000000000000001
00000000000000000000000000000010
…
00000000000000000000000011111111
00000000000000000000000100000000

In VHDL-2008 kann die BREAD-Prozedur genutzt werden, um binäre Werte direkt einzulesen:

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;

Instanziieren Sie den RAM mit:

signal ram_bin : ram_type := init_ram_bin;

Legacy VHDL: Binäre Reads mit READ

Für VHDL-2002 oder VHDL-93 muss die READ-Prozedur verwendet werden. Da sie einen bit-Vektor zurückgibt, wird das Ergebnis via To_StdLogicVector in std_logic_vector konvertiert:

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;

Moderne TEXTIO-Features zurückportieren

Wenn Sie den Legacy-Code nicht ändern möchten, können Sie das Drittanbieter-Paket std_logic_1164_additions importieren. Diese Bibliothek portiert HREAD und BREAD auf ältere VHDL-Versionen zurück, auf Kosten einer zusätzlichen Abhängigkeit.

Für detailliertere Beispiele und weiterführende Literatur siehe die begleitenden Artikel dieser Serie.

VHDL

  1. Aluminium vor Korrosion schützen: Expertenstrategien für langfristige Haltbarkeit
  2. Metall vs. Nichtmetall-Elemente: Wesentliche Unterschiede erklärt
  3. Ihr erstes AWS CloudFormation Template erstellen – Ein praktischer Leitfaden
  4. Cloud Computing vs. Traditional Computing: Praktischer Vergleich
  5. Kommentare in C meistern: Klare, effektive Notizen schreiben
  6. Dateien in Java mit BufferedReader lesen – Praktischer Leitfaden mit Beispielen
  7. Durchschnitt berechnen in Python: Praktischer Leitfaden
  8. Mikrometer: Präzises Messen, Ablesen & Richtige Anwendung
  9. PLC-Funktionsbausteine über OPC UA-Clients aufrufen: Praktischer Leitfaden
  10. Technische Zeichnungen (Blueprints) lesen: Essenzielle Skill für CNC-Fachkräfte