Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> VHDL

FPGA Block RAM initialiseren vanuit tekstbestanden met VHDL's TEXTIO-bibliotheek

Block RAM vullen met vooraf gedefinieerde waarden wordt het efficiëntst gedaan door binaire of hexadecimale literalen uit een ASCII-bestand te lezen. Deze techniek dient ook om ROM's te creëren, aangezien FPGA-ROM simpelweg een RAM is die alleen gelezen wordt.

Voor de onderstaande voorbeelden worden de volgende constanten en RAM-type gedeclareerd in het declaratieve gebied van het VHDL-bestand:

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

Dit artikel is onderdeel van een serie over de TEXTIO-bibliotheek in VHDL. Stimulus-bestand lezen in testbench met TEXTIO | BMP-bitmapafbeelding lezen met TEXTIO

Regels en Data Lezen met TEXTIO

Het TEXTIO-pakket, gelegen in de standaard std bibliotheek, voorziet in de subprogramma's die nodig zijn voor bestands-I/O. Het is automatisch beschikbaar, dus je hoeft het alleen te importeren:

use std.textio.all;

Onze RAM-data wordt opgeslagen in een ASCII-bestand waar elke regel één geheugenwoord voorstelt. De READLINE procedure leest een enkele regel in een LINE object. De prototype is:

procedure READLINE (file F: TEXT; L: inout LINE); type LINE is access STRING; -- pointer naar een dynamisch toegewezen string

VHDL-2008 introduceert OREAD, HREAD en BREAD voor het extraheren van octale, hexadecimale en binaire waarden uit een LINE object. Voor beknoptheid focussen we op hexadecimale en binaire leesoperaties. De relevante declaraties zijn:

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

Voor legacy VHDL-versies (pre-2008) moet de standaard READ procedure gebruikt worden, die geen hexadecimaal direct ondersteunt. In dat geval is een aangepaste conversieroutine vereist.

Hexadecimale Data Laden

Hexadecimale notatie is handig omdat elk paar hex-cijfers direct op een byte mappt. Het voorbeeld ram_content_hex.txt bestand bevat 256 regels, elk met een 8-karakter hex-string van 00000001 tot 00000100:

1
2
…
255
256
00000001
00000002
…
000000FF
00000100

De volgende impure functie leest het bestand en retourneert een volledig geïnitialiseerd ram_type array. Het werkt met VHDL-2008 en nieuwer:

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;

Na het definiëren van de functie, wordt het RAM-signaal geïnstantieerd met de initiële inhoud:

signal ram_hex : ram_type := init_ram_hex;

Legacy VHDL: HREAD Handmatig Implementeren

Wanneer HREAD niet beschikbaar is (bijv. VHDL-93 of VHDL-2002), kan een handmatige conversieroutine in de initialisatiefunctie worden ingebouwd. Het volgende voorbeeld demonstreert deze aanpak:

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;

Hoewel een speciale HREAD procedure gedefinieerd kan worden, ondersteunen de meeste synthese-tools (bijv. Xilinx Vivado) geen procedures die een LINE argument accepteren. De volgende fout illustreert deze beperking:

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

Binaire Data Lezen

Als de RAM-breedte geen veelvoud is van 8, kunnen binaire literalen preferabel zijn. Het voorbeeld ram_content_bin.txt bestand bevat 256 regels, elk met een 32-bit binaire string:

1
2
…
255
256
00000000000000000000000000000001
00000000000000000000000000000010
…
00000000000000000000000011111111
00000000000000000000000100000000

In VHDL-2008 kan de BREAD procedure gebruikt worden om binaire waarden direct te lezen:

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;

Instantieer de RAM met:

signal ram_bin : ram_type := init_ram_bin;

Legacy VHDL: Binaire Leesoperaties met READ

Voor VHDL-2002 of VHDL-93 moet de READ procedure gebruikt worden. Aangezien het een bit vector retourneert, wordt het resultaat geconverteerd naar 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;

Moderne TEXTIO-functies Backporten

Als je liever de legacy-code niet wilt wijzigen, kun je het derde-partij-pakket std_logic_1164_additions importeren. Deze bibliotheek backport de HREAD en BREAD procedures naar oudere VHDL-versies, ten koste van een extra afhankelijkheid.

Voor meer gedetailleerde voorbeelden en verder lezen, zie de bijbehorende artikelen in deze serie.

VHDL

  1. Micrometer Uitgelegd: Hoe te Lezen en Gebruiken Deze Precisie Meetinstrument
  2. PLC-functieblokken Aanroepen via OPC UA-clients: Een Praktische Gids
  3. Aluminium Beschermen Tegen Corrosie: Expertstrategieen voor Lange Levensduur
  4. Metaal vs. Niet-metaal Elementen: Belangrijkste Verschillen Uitgelegd
  5. CNC Blauwdruk Lezen Beheersen: Essentiële Vaardigheden Voor Moderne Machinisten
  6. Bouw Uw Eerste AWS CloudFormation Template – Een Praktische Gids
  7. Cloud Computing vs. Traditionele Computing: Een Praktische Vergelijking
  8. Commentaar in C Beheersen: Duidelijke, Effectieve Notities Schrijven
  9. FPGA-gebaseerde RC Servo-controller ontwerpen met nauwkeurige PWM
  10. Gemiddeldes Berekenen in Python: Een Praktische Gids
  11. Bestanden Lezen in Java met BufferedReader – Een Praktische Gids met Voorbeelden