VHDL/GHDL 设置高位时二进制 32 位写入溢出
VHDL/GHDL Binary 32-bit Write Overflow When High Bit Set
我有一个 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;
我运行以下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 位的任何值。
潜在的问题是整数'high是2^31-1。参见:
- How to represent Integer greater than integer'high
此处接受的答案声明使用中间 'text' 格式文本处理语言。另一个答案显示了使用 'pos 阅读的解决方案,但这对我写作没有帮助。
- How can I read binary data in VHDL/modelsim whithout using special binary formats
有没有简单的 rework/workaround 可以让我将所有 32 位数据写入二进制文件?
将您的文件类型更改为字符。一次将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
请注意,由于 stop
,此处所需的命令(-a、-e、-r)之外的唯一命令行参数是 --std-08。没有 Synopsys 包依赖项,也不需要 -fexplicit(两者都不依赖)。
od -tx4 out.bin
0000000 7fffffff ffffffff
0000010
主机的文件系统包含由 8 位字符数组组成的文件。约定(格式)叠加了更大的东西的想法。
VHDL 将类型叠加在文件事务上,不幸的是,无法声明大于 2 ** 31 -1 的自然范围值,如果您的整数更大,它们将不可移植。
上述方法将文件视为字符文件,允许按照约定叠加内容元素的大小(在主机系统中,如果要读取 32 位无符号,则需要读取 4 个字符和 assemble 正确字节顺序的 32 位值)。
此处的unsigned_int是一个32位无符号值。请注意,由于隐式子类型转换(形式元素和实际元素在这里以从左到右的顺序关联),子程序调用中不需要匹配升序或降序。
原作者post遇到评论中反映的问题:
The write() above generates an error during analysis:
u32_file_write.vhd:23:14:error: cannot resolve overloading for
subprogram call.
The error repeats four times, once for each write().
I've not found a way to get GHDL to write raw bytes other than an
integer.
注释中的第 23 行似乎对应于上面的第 18 行,其中字符 14 是第一个 write 过程调用的参数列表 write[file IntFileType, character]
,它建议类型 IntFileType
的类型声明定义的类型标记尚未更改为类型 character
。过程调用的签名与文件类型 IntFileType
隐式声明的写入不匹配,还注意到行号不匹配。
此答案中提供了完整的代码,以允许从问题中完整复制,这是通过使用 .vhdl 后缀命名设计文件并使用上面的命令行完成的。
使用的 ghdl 版本是最新版本 (GHDL 0.36-dev (v0.35-259-g4b16ef4)),使用 AdaCore 2015 GPL gnat (GPL 2015 (20150428-49)) 构建,并使用MacOS 上的 llvm 后端代码生成器 (clang+llvm-3.8.0) 和 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 写入的字符的字节顺序已反转以匹配 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
我有一个 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;
我运行以下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 位的任何值。
潜在的问题是整数'high是2^31-1。参见:
- How to represent Integer greater than integer'high
此处接受的答案声明使用中间 'text' 格式文本处理语言。另一个答案显示了使用 'pos 阅读的解决方案,但这对我写作没有帮助。
- How can I read binary data in VHDL/modelsim whithout using special binary formats
有没有简单的 rework/workaround 可以让我将所有 32 位数据写入二进制文件?
将您的文件类型更改为字符。一次将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
请注意,由于 stop
,此处所需的命令(-a、-e、-r)之外的唯一命令行参数是 --std-08。没有 Synopsys 包依赖项,也不需要 -fexplicit(两者都不依赖)。
od -tx4 out.bin 0000000 7fffffff ffffffff 0000010
主机的文件系统包含由 8 位字符数组组成的文件。约定(格式)叠加了更大的东西的想法。
VHDL 将类型叠加在文件事务上,不幸的是,无法声明大于 2 ** 31 -1 的自然范围值,如果您的整数更大,它们将不可移植。
上述方法将文件视为字符文件,允许按照约定叠加内容元素的大小(在主机系统中,如果要读取 32 位无符号,则需要读取 4 个字符和 assemble 正确字节顺序的 32 位值)。
此处的unsigned_int是一个32位无符号值。请注意,由于隐式子类型转换(形式元素和实际元素在这里以从左到右的顺序关联),子程序调用中不需要匹配升序或降序。
原作者post遇到评论中反映的问题:
The write() above generates an error during analysis:
u32_file_write.vhd:23:14:error: cannot resolve overloading for subprogram call.The error repeats four times, once for each write(). I've not found a way to get GHDL to write raw bytes other than an integer.
注释中的第 23 行似乎对应于上面的第 18 行,其中字符 14 是第一个 write 过程调用的参数列表 write[file IntFileType, character]
,它建议类型 IntFileType
的类型声明定义的类型标记尚未更改为类型 character
。过程调用的签名与文件类型 IntFileType
隐式声明的写入不匹配,还注意到行号不匹配。
此答案中提供了完整的代码,以允许从问题中完整复制,这是通过使用 .vhdl 后缀命名设计文件并使用上面的命令行完成的。
使用的 ghdl 版本是最新版本 (GHDL 0.36-dev (v0.35-259-g4b16ef4)),使用 AdaCore 2015 GPL gnat (GPL 2015 (20150428-49)) 构建,并使用MacOS 上的 llvm 后端代码生成器 (clang+llvm-3.8.0) 和 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 写入的字符的字节顺序已反转以匹配 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