2

I have a VHDL testbench where I would like to write 32-bit binary words to a file for testing. Below is a minimal, complete, verifiable example.

When executed with GHDL (commands below) an overflow is generated at the indicated line. If the line is commented out execution completes successfully and writes the file. The overflow occurs anytime the high bit is set.

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;

I run the following GHDL commands to run the VHDL code (save as 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

With the line commented out, the corrected results are written to the file:

% od -tx4 out.bin
0000000 7fffffff

If the line is uncommented, an overflow is generated:

ghdl:error: overflow detected
    from: ieee.numeric_std.to_integer at numeric_std-body.vhdl:3040
ghdl:error: simulation failed

As noted above, the write will work with any value in the first 31-bits. The write will overflow with any value where the 32-bit is set.

The underlying problem is integer'high is 2^31-1. See:

The accepted answer here states to use an intermediate 'text' format a text processing language. Another answer shows a solution for reading using 'pos but that doesn't help me write.

Is there a simple rework/workaround that will allow me to write all 32-bits of data to a binary file?

4

2 回答 2

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;
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 个字符并在正确的字节序)。

这里的 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。过程调用的签名与隐式声明的文件类型写入的签名不匹配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) 和 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结果字节顺序)

于 2018-08-12T04:42:58.523 回答
1

如果您不是绝对需要二进制输出,您可以使用 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
于 2018-08-13T07:55:06.167 回答