Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> VHDL

Инициализация блочной памяти FPGA из текстовых файлов с помощью библиотеки TEXTIO в VHDL

Наполнение блочной памяти предопределенными значениями наиболее эффективно делается чтением бинарных или шестнадцатеричных литералов из ASCII-файла. Эта техника также служит для создания ROM, так как FPGA ROM — это просто RAM, из которого только читают.

Для примеров ниже в декларативной области VHDL-файла объявлены следующие константы и тип RAM:

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

Эта статья часть серии о библиотеке TEXTIO в VHDL. Чтение файла стимулов в тестбенче с помощью TEXTIO | Чтение битового изображения BMP с помощью TEXTIO

Чтение строк и данных с TEXTIO

Пакет TEXTIO, находящийся в стандартной библиотеке std, предоставляет подпрограммы, необходимые для файлового ввода-вывода. Он автоматически доступен, нужно только импортировать его:

use std.textio.all;

Наши данные RAM будут храниться в ASCII-файле, где каждая строка представляет одно слово памяти. Процедура READLINE читает одну строку в объект LINE. Её прототип:

procedure READLINE (file F: TEXT; L: inout LINE); type LINE is access STRING; -- указатель на динамически выделенную строку

VHDL‑2008 вводит OREAD, HREAD и BREAD для извлечения восьмеричных, шестнадцатеричных и двоичных значений из объекта LINE. Для краткости сфокусируемся на чтении шестнадцатеричных и двоичных значений. Соответствующие объявления:

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

Для старых версий VHDL (до 2008) должна использоваться стандартная процедура READ, которая не поддерживает шестнадцатеричный формат напрямую. В этом случае требуется собственная рутина конвертации.

Загрузка шестнадцатеричных данных

Шестнадцатеричная нотация удобна, потому что каждая пара шестнадцатеричных цифр напрямую отображается в байт. Пример файла ram_content_hex.txt содержит 256 строк, каждая с 8-символьной шестнадцатеричной строкой от 00000001 до 00000100:

1
2
…
255
256
00000001
00000002
…
000000FF
00000100

Следующая нечистая функция читает файл и возвращает полностью инициализированный массив ram_type. Она работает с VHDL‑2008 и новее:

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;

После определения функции сигнал RAM инстанцируется с начальным содержимым:

signal ram_hex : ram_type := init_ram_hex;

Устаревший VHDL: ручная реализация HREAD

Когда HREAD недоступен (например, VHDL‑93 или VHDL‑2002), рутину ручной конвертации можно встроить в функцию инициализации. Следующий пример демонстрирует этот подход:

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;

Хотя можно определить выделенную процедуру HREAD, большинство инструментов синтеза (например, Xilinx Vivado) не поддерживают процедуры, принимающие аргумент типа LINE. Следующая ошибка иллюстрирует это ограничение:

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

Чтение двоичных данных

Если ширина RAM не кратна 8, двоичные литералы могут быть предпочтительнее. Пример файла ram_content_bin.txt содержит 256 строк, каждая с 32-битной двоичной строкой:

1
2
…
255
256
00000000000000000000000000000001
00000000000000000000000000000010
…
00000000000000000000000011111111
00000000000000000000000100000000

В VHDL‑2008 процедура BREAD может использоваться для прямого чтения двоичных значений:

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;

Инстанцируйте RAM так:

signal ram_bin : ram_type := init_ram_bin;

Устаревший VHDL: двоичное чтение с READ

Для VHDL‑2002 или VHDL‑93 должна использоваться процедура READ. Поскольку она возвращает вектор bit, результат конвертируется в std_logic_vector через 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;

Перенос современных возможностей TEXTIO

Если вы предпочитаете не менять устаревший код, можно импортировать сторонний пакет std_logic_1164_additions. Эта библиотека переносит процедуры HREAD и BREAD на старые версии VHDL ценой дополнительной зависимости.

Для более детальных примеров и дальнейшего чтения см. сопровождающие статьи в этой серии.

VHDL

  1. Защита алюминия от коррозии: экспертные стратегии для долговечности
  2. Металлы против неметаллов: ключевые различия объяснены
  3. Создайте свой первый шаблон AWS CloudFormation — практическое руководство
  4. Облачные вычисления против традиционных: практическое сравнение
  5. Комментарии в C: пишем понятные и эффективные заметки
  6. Чтение файлов в Java с BufferedReader — Практическое руководство с примерами
  7. Вычисление среднего значения в Python: практическое руководство
  8. Микрометр: как читать и использовать этот точное измерительный инструмент
  9. Вызов функциональных блоков ПЛК через OPC UA клиентов: Практическое руководство
  10. Освоение чтения чертежей для ЧПУ: ключевые навыки современного машиниста