我有一个 VHDL 测试平台,我想将 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;
Run Code Online (Sandbox Code Playgroud)
我运行以下 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
Run Code Online (Sandbox Code Playgroud)
注释掉该行后,将更正的结果写入文件:
% od -tx4 out.bin
0000000 7fffffff
Run Code Online (Sandbox Code Playgroud)
如果该行未注释,则会生成溢出:
ghdl:error: overflow detected
from: ieee.numeric_std.to_integer at numeric_std-body.vhdl:3040
ghdl:error: simulation failed
Run Code Online (Sandbox Code Playgroud)
如上所述,写入将使用前 31 位中的任何值。写入将溢出任何设置 32 位的值。
潜在的问题是 integer'high 是 2^31-1。看:
此处接受的答案声明使用中间“文本”格式文本处理语言。另一个答案显示了使用 'pos 阅读的解决方案,但这并不能帮助我写作。
是否有一个简单的返工/解决方法可以让我将所有 32 位数据写入二进制文件?
小智 5
将您的文件类型更改为字符。一次将 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;
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)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(两者都不依赖)。
Run Code Online (Sandbox Code Playgroud)od -tx4 out.bin 0000000 7fffffff ffffffff 0000010
主机的文件系统包含由 8 位字符数组组成的文件。惯例(格式)叠加了更大的想法。
VHDL 在文件事务上叠加类型,不幸的是,无法声明大于 2 ** 31 -1 的自然范围值,如果您的整数更大,它们将无法移植。
上述方法将文件视为字符文件,允许按约定叠加内容元素的大小(在主机系统中,如果您想读取 32 位无符号,您需要读取 4 个字符并在正确的字节序)。
这里的 unsigned_int 是一个 32 位无符号值。请注意,由于隐式子类型转换(形式元素和实际元素在此处按从左到右的顺序关联),因此在子程序调用中不需要匹配升序或降序。
原帖作者在评论中遇到了一个问题:
上面的 write() 在分析过程中产生一个错误:
u32_file_write.vhd:23:14:error: cannot resolve Overloading for subprogram call。该错误重复四次,每次 write() 一次。我还没有找到让 GHDL 写入整数以外的原始字节的方法。
注释中的第 23 行似乎对应于上面的第 18 行,其中字符 14 是第一个 write 过程调用的参数列表,write[file IntFileType, character]
这表明 typeIntFileType
的类型定义的类型标记的声明尚未更改为 type character
。过程调用的签名与隐式声明的文件类型 write 的签名不匹配IntFileType
,还注意到行号不匹配。
此答案中提供了完整的代码,以允许从问题中完整复制,这是与使用 .vhdl 后缀命名设计文件并使用上面的命令行一起完成的。
使用的 ghdl 版本是使用 AdaCore 2015 GPL gnat (GPL 2015 (20150428-49)) 构建的最新版本 (GHDL 0.36-dev (v0.35-259-g4b16ef4)) 并使用 llvm 后端代码生成器 ( clang+llvm-3.8.0) 和 MacOS 上的 mcode 代码生成器(10.11.6,gnat-gpl-2015-x86_64-darwin-bin 和 clang+llvm-3.8.0-x86_64-apple-darwin,使用 Xcode 8.2。 1)。
(新写入过程中从 val 写入的字符的od -xt out.bin
字节序已颠倒,以匹配 OP 的结果字节顺序)