VHDL/GHDL Двоичное 32-битное переполнение записи при установке старшего бита
У меня есть VHDL testbench, где я хотел бы записать 32-битные двоичные слова в файл для тестирования. Ниже приведен минимальный, полный, проверяемый пример.
При выполнении с GHDL (команды ниже) в указанной строке генерируется переполнение. Если строка закомментирована, выполнение завершается успешно и записывает файл. Переполнение происходит всякий раз, когда установлен старший бит.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
use std.env.stop;
entity u32_file_write is
end entity;
architecture rtl of u32_file_write is
type intFileType is file of natural;
file fh : intFileType;
begin
run: process
variable no_high_bit : std_logic_vector(31 downto 0) := x"7FFFFFFF";
variable with_high_bit : std_logic_vector(31 downto 0) := x"FFFFFFFF";
begin
file_open(fh, "out.bin", write_mode);
write(fh, to_integer(unsigned(no_high_bit)));
write(fh, to_integer(unsigned(with_high_bit))); -- Overflow here.
file_close(fh);
stop;
end process;
end architecture;
Я запускаю следующие команды GHDL для запуска кода VHDL (сохранить как u32_file_write.vhd
):
ghdl -a -fexplicit --std=08 --ieee=synopsys u32_file_write.vhd
ghdl -e -fexplicit --std=08 --ieee=synopsys u32_file_write
ghdl -r -fexplicit --std=08 --ieee=synopsys u32_file_write
С закомментированной строкой исправленные результаты записываются в файл:
% od -tx4 out.bin
0000000 7fffffff
Если строка не закомментирована, генерируется переполнение:
ghdl:error: overflow detected
from: ieee.numeric_std.to_integer at numeric_std-body.vhdl:3040
ghdl:error: simulation failed
Как отмечалось выше, запись будет работать с любым значением в первых 31-битах. Запись будет переполнена любым значением, для которого установлено 32-разрядное значение.
Основная проблема - целое число, высокое - 2^31-1. Увидеть:
В принятом ответе здесь говорится об использовании промежуточного "текстового" формата в текстовом языке обработки. Другой ответ показывает решение для чтения с использованием 'pos, но это не помогает мне писать.
Существует ли простая переделка / обходной путь, который позволит мне записать все 32-битные данные в двоичный файл?
2 ответа
Измените тип файла на символ. Преобразовать 8 бит за раз в символ и записать все четыре символа в файл,
С 8-битными записями вы несете ответственность за правильность порядка байтов.
Вы можете сделать это с помощью процедуры записи, предназначенной для записи 32-битных значений без знака в файл символов:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
use std.env.stop;
entity u32_file_write is
end entity;
architecture foo of u32_file_write is
-- type intFileType is file of natural;
type intFileType is file of character; -- CHANGED type mark
file fh : intFileType;
procedure write (file cf: intFileType; val: unsigned (31 downto 0)) is
begin
write (cf, character'val(to_integer(val( 7 downto 0))));
write (cf, character'val(to_integer(val(15 downto 8))));
write (cf, character'val(to_integer(val(23 downto 16))));
write (cf, character'val(to_integer(val(31 downto 24))));
end procedure;
begin
run: process
variable no_high_bit : std_logic_vector(31 downto 0) := x"7FFFFFFF";
variable with_high_bit : std_logic_vector(31 downto 0) := x"FFFFFFFF";
begin
file_open(fh, "out.bin", write_mode);
-- write(fh, to_integer(unsigned(no_high_bit)));
-- write(fh, to_integer(unsigned(with_high_bit))); -- Overflow here.
write (fh, unsigned(no_high_bit));
write (fh, unsigned(with_high_bit));
file_close(fh);
stop;
end process;
end architecture;
ghdl -a -fexplicit --std=08 --ieee=synopsys u32_file_write.vhdl ghdl -e -fexplicit --std=08 --ieee=synopsys u32_file_write ghdl -r -fexplicit --std=08 --ieee=synopsys u32_file_write
Обратите внимание, что единственным аргументом командной строки, кроме требуемой здесь команды (-a, -e, -r), является --std-08 из-за stop
, Здесь нет ни зависимостей пакета Synopsys, ни требования для -fexplicit (от которого также не зависит).
od -tx4 out.bin 0000000 7fffffff ffffffff 0000010
Файловая система хоста содержит файлы, которые состоят из массива 8-битных символов. Это соглашение (формат), которое накладывает идею чего-то большего.
VHDL накладывает тип на файловые транзакции, к сожалению, нет способа объявить натуральное значение диапазона больше 2 ** 31 -1, если бы ваши целые были больше, они не были бы переносимы.
Вышеупомянутый метод обрабатывает файлы как символьные файлы, позволяя накладывать размер элементов содержимого в соответствии с соглашениями (здесь, в хост-системе, если вы хотите прочитать 32-битный без знака, вы хотите прочитать 4 символа и собрать 32-битное значение в правильный порядок байтов).
Здесь unsigned_int является 32-битным значением без знака. Обратите внимание, что возрастающий или нисходящий порядок не обязательно должен совпадать при вызове подпрограммы из-за неявного преобразования подтипа (элементы формул и фактов здесь связаны в порядке слева направо).
Автор исходного сообщения столкнулся с проблемой, о которой сообщается в комментарии:
Приведенная выше запись () генерирует ошибку во время анализа:
u32_file_write.vhd: 23: 14: ошибка: не удается разрешить перегрузку для вызова подпрограммы.Ошибка повторяется четыре раза, один раз для каждой записи (). Я не нашел способ заставить GHDL писать необработанные байты, кроме целых.
Строка 23 в комментарии соответствует 18-й строке выше, где символ 14 - список параметров первого вызова процедуры записи write[file IntFileType, character]
который предлагает объявление для типа IntFileType
тип определения типа не был изменен на тип character
, Подпись вызовов процедуры не будет совпадать с сигнатурой неявно объявленной записи для типа файла IntFileType
также отмечая, что номера строк не совпадают.
В этом ответе приведен полный код, позволяющий полностью копировать его из вопроса, что было сделано вместе с именованием файла дизайна с суффиксом.vhdl и использованием приведенных выше командных строк.
Используемой версией ghdl является недавняя сборка (GHDL 0.36-dev (v0.35-259-g4b16ef4)), созданная с помощью мошенника AdaCore 2015 GPL (GPL 2015 (20150428-49)) и протестированная с помощью генератора внутреннего кода llvm (clang+llvm-3.8.0) и генератор кода mcode как в MacOS (10.11.6, gnat-gpl-2015-x86_64-darwin-bin и clang+llvm-3.8.0-x86_64-apple-darwin, с использованием Xcode 8.2. 1).
(Порядковый порядок записи символов из val в новой процедуре записи был изменен, чтобы соответствовать OP od -xt out.bin
порядок следования байтов)
Если вам абсолютно не нужен вывод в двоичном виде, вы можете использовать стандартные процедуры VHDL2008 для прямой записи ваших векторов без преобразования:
$ ghdl --version
GHDL 0.36-dev (v0.35-259-g4b16ef4c-dirty) [Dunoon edition]
Compiled with GNAT Version: GPL 2017 (20170515-63)
llvm code generator
Written by Tristan Gingold.
Copyright (C) 2003 - 2015 Tristan Gingold.
GHDL is free software, covered by the GNU General Public License. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ cat u32_file_write.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
use std.env.stop;
entity u32_file_write is
end entity;
architecture rtl of u32_file_write is
begin
run: process
variable no_high_bit : std_logic_vector(31 downto 0) := x"7FFFFFFF";
variable with_high_bit : std_logic_vector(31 downto 0) := x"FFFFFFFF";
variable l: line;
file fh: text open write_mode is "out.txt";
begin
hwrite(l, no_high_bit);
writeline(fh, l);
hwrite(l, with_high_bit);
writeline(fh, l);
file_close(fh);
stop;
end process;
end architecture;
$ ghdl -a -fexplicit --std=08 u32_file_write.vhd
$ ghdl -e -fexplicit --std=08 u32_file_write
$ ghdl -r -fexplicit --std=08 u32_file_write
simulation stopped @0ms
$ cat out.txt
7FFFFFFF
FFFFFFFF