在vhdl中读取二进制文件
Reading binary file in vhdl
我想从 ENVI logiciel 访问图像的二进制文件内容像素:大小 (100*100) 像素在 vhdl 中以 16 位对每个像素进行编码。
library IEEE;
USE ieee.std_logic_1164.ALL;
Use ieee.numeric_bit.ALL;
library std;
use std.textio.all;
entity image_bin is
end entity;
architecture behavioral of image_bin is
type image is array(0 to 99,0 to 99) of std_logic_vector(15 downto 0);
signal image(i,j):bit_vector(15 downto 0);
begin
process
type t_file is file of bit_vector;
file infile: text is in "C:\Users\hp\Desktop\file\T4.bin";
variable pixel_image:bit_vector(15 downto 0);
begin
IF start'EVENT AND start = '1' THEN
for i in to 99 loop
for j in to 99 loop
read(infile,pixel_image);
image(i,j)<=pixel_image;
end loop;
end loop;
file_close (infile);
end if;
end process;
问题太不具体,但这里有几点建议。
二进制文件I/O 在 VHDL 中工作,但只保证与其自身兼容,即您可以读取您的模拟最初编写的文件。除此之外,您可能需要进行试验。
我在 Modelsim 中阅读了第 3 方文件,几乎没有什么惊喜,(可能是意想不到的 endian-ness,我不记得了)我希望 GHDL 也能正常工作。
但是,Xilinx ISIM(在 ISE10.1 时代)坚持要在每个文件上看到特定的二进制文件 header,即使明确询问其格式,Xilinx 也拒绝记录。
我从 ISIM 写了一个文件,检查了它的内容,并将该文件的 header 黑化到我需要读取的图像文件中,并使用 Linux 将其从任何进一步的输出文件中删除head
和 tail
命令,所以我可以与世界其他地方交换二进制文件。 ISIM 对此非常满意,但这很痛苦。
编辑现在我们有一些代码...
首先,与 Python 相比,在 VHDL 中这样做并没有错;将涉及更多的打字(在打字的两种意义上)但是无论你使用哪种语言,你都必须理解你在写什么。
而且你将不得不完成代码(其中一些缺失)并修复琐碎的错误(你有一个类型和一个同名的信号......任何语言的草率练习)和其他琐碎的语法错误。
所以下一步是完成它,编译它,并修复那些错误。如果您在根据 VHDL 教科书仔细检查错误行后不理解错误,post 错误消息并询问它的含义以及如何处理它 - 至少,这将是一个实际问题。
你也在使用VHDL-1987文件声明,声明的是文本类型的文件;你必须升级到 VHDL-1993 文件处理。通过通常的方法找到 "VHDL-1993 binary file I/O" 的例子应该不难 - 试试吧。
在开始为 FPGA 编写 VHDL 代码之前,尤其是复杂的算法,您应该做两件事:
- 学习基本的 VHDL
- 了解 FPGA 的功能
您可以在 VHDL 中使用 file-I/O 来初始化 FPGA 存储器 (RAM/ROM) 或在模拟构造中。但不在 real-time 数据处理应用程序中。正如我在评论中所说:普通的 FPGA 在硬连线块中没有 file-I/O 功能。如果您想要这样的东西,最好使用 microcontroller/CPU 或我们的 SOC FPGA,它有一个 hard-wired ARM 内核并在软件中执行。但是当你在那里时,为什么还要使用 FPGA?
你的代码有错误
您的代码中有几个编程错误,如果您遵循一些教程,这些错误很容易避免。
第一个错误,我想问问你有没有编程经验。您定义了一个类型,接下来您可能想要定义一个新类型的对象。但是你输入了一些非法代码:
signal image(i,j) : bit_vector(15 downto 0);
解析器如何知道 i
和 j
是什么?在代码的声明部分之前,您不会定义它们。其次,你为什么突然使用bit_vector
,而你之前正在使用std_logic_vector
?
示例:
type [type name] is [type details];
signal [object name] : [type name] := [optional initialization details];
下一个错误:进程没有敏感列表。 process
语句是顺序处理块的开始。没有任何敏感列表,它自动启动。这是一个问题:没有什么能阻止它,因此该过程将尝试在无限小的时间内无限循环。这当然会引起问题。解决方法:使用敏感度列表。
[label:] process ([trigger signal names])
begin
end process;
进程内部实际上有一个触发条件:start'event and start='1'
...这个start
是从哪里来的?可能缺少实体上的输入端口?但是这个 start
应该是您流程的触发器。
那怎么办?
您可以做的是读取文件和初始化数组。 (请注意,综合中不支持 multi-dimensional 数组,因为没有 multi-dimensional RAM 之类的东西,因此您必须展平数组并执行一些索引算法)。对于下一个示例,我创建了一个文件 "test.bin" 并用字符串“12345678”填充它 = 8 个字符 = 8*8 位 = 256 位 = 2*2*16 位 -> 适用于 2 x 2 数组.
那你应该意识到 textio
包只能读取文本!所以最简单的就是每8位读取一个字符,然后将两个拼接成一个16位的值。
示例代码:
entity read_bin is end entity;
library ieee;
architecture behavioral of read_bin is
use ieee.std_logic_1164.all;
subtype data_type is std_logic_vector(15 downto 0);
type two_dim_array_type is array(0 to 1, 0 to 1) of data_type;
impure function init_two_dim_array return two_dim_array_type is
use std.textio.all;
type character_file is file of character;
file file_pointer : character_file;
variable upper : character;
variable lower : character;
variable output : two_dim_array_type;
use ieee.numeric_std.all;
begin
file_open(file_pointer, "test.bin", READ_MODE);
for i in 0 to 1 loop
for j in 0 to 1 loop
read(file_pointer, upper); -- first 8 bits
read(file_pointer, lower); -- second 8 bits
output(i, j) :=
std_logic_vector(to_unsigned(character'pos(upper),8))&
std_logic_vector(to_unsigned(character'pos(lower),8));
end loop;
end loop;
file_close(file_pointer);
return output;
end function;
signal two_dim_array : two_dim_array_type := init_two_dim_array;
begin
end architecture;
瞧:
大问题
对我来说最大的问题是:当你犯了这些编程错误时,你怎么能获得电信和嵌入式系统的博士学位?或者对 FPGA 的功能缺乏了解。我本人是电气工程博士候选人,这是我们教 first-year 本科生的东西。当我想获得博士学位时,我经历了几轮评估,对我的知识进行了广泛测试。这些职位竞争激烈。
我的建议:请获得一些本地支持以实现这一点。您不想在接下来的 3 年博士期间试图将 VHDL 学习到足够的水平,然后发现您只有 1 年的时间进行一些实际研究才能发布结果...
我想从 ENVI logiciel 访问图像的二进制文件内容像素:大小 (100*100) 像素在 vhdl 中以 16 位对每个像素进行编码。
library IEEE;
USE ieee.std_logic_1164.ALL;
Use ieee.numeric_bit.ALL;
library std;
use std.textio.all;
entity image_bin is
end entity;
architecture behavioral of image_bin is
type image is array(0 to 99,0 to 99) of std_logic_vector(15 downto 0);
signal image(i,j):bit_vector(15 downto 0);
begin
process
type t_file is file of bit_vector;
file infile: text is in "C:\Users\hp\Desktop\file\T4.bin";
variable pixel_image:bit_vector(15 downto 0);
begin
IF start'EVENT AND start = '1' THEN
for i in to 99 loop
for j in to 99 loop
read(infile,pixel_image);
image(i,j)<=pixel_image;
end loop;
end loop;
file_close (infile);
end if;
end process;
问题太不具体,但这里有几点建议。
二进制文件I/O 在 VHDL 中工作,但只保证与其自身兼容,即您可以读取您的模拟最初编写的文件。除此之外,您可能需要进行试验。
我在 Modelsim 中阅读了第 3 方文件,几乎没有什么惊喜,(可能是意想不到的 endian-ness,我不记得了)我希望 GHDL 也能正常工作。
但是,Xilinx ISIM(在 ISE10.1 时代)坚持要在每个文件上看到特定的二进制文件 header,即使明确询问其格式,Xilinx 也拒绝记录。
我从 ISIM 写了一个文件,检查了它的内容,并将该文件的 header 黑化到我需要读取的图像文件中,并使用 Linux 将其从任何进一步的输出文件中删除head
和 tail
命令,所以我可以与世界其他地方交换二进制文件。 ISIM 对此非常满意,但这很痛苦。
编辑现在我们有一些代码...
首先,与 Python 相比,在 VHDL 中这样做并没有错;将涉及更多的打字(在打字的两种意义上)但是无论你使用哪种语言,你都必须理解你在写什么。
而且你将不得不完成代码(其中一些缺失)并修复琐碎的错误(你有一个类型和一个同名的信号......任何语言的草率练习)和其他琐碎的语法错误。
所以下一步是完成它,编译它,并修复那些错误。如果您在根据 VHDL 教科书仔细检查错误行后不理解错误,post 错误消息并询问它的含义以及如何处理它 - 至少,这将是一个实际问题。
你也在使用VHDL-1987文件声明,声明的是文本类型的文件;你必须升级到 VHDL-1993 文件处理。通过通常的方法找到 "VHDL-1993 binary file I/O" 的例子应该不难 - 试试吧。
在开始为 FPGA 编写 VHDL 代码之前,尤其是复杂的算法,您应该做两件事:
- 学习基本的 VHDL
- 了解 FPGA 的功能
您可以在 VHDL 中使用 file-I/O 来初始化 FPGA 存储器 (RAM/ROM) 或在模拟构造中。但不在 real-time 数据处理应用程序中。正如我在评论中所说:普通的 FPGA 在硬连线块中没有 file-I/O 功能。如果您想要这样的东西,最好使用 microcontroller/CPU 或我们的 SOC FPGA,它有一个 hard-wired ARM 内核并在软件中执行。但是当你在那里时,为什么还要使用 FPGA?
你的代码有错误
您的代码中有几个编程错误,如果您遵循一些教程,这些错误很容易避免。
第一个错误,我想问问你有没有编程经验。您定义了一个类型,接下来您可能想要定义一个新类型的对象。但是你输入了一些非法代码:
signal image(i,j) : bit_vector(15 downto 0);
解析器如何知道 i
和 j
是什么?在代码的声明部分之前,您不会定义它们。其次,你为什么突然使用bit_vector
,而你之前正在使用std_logic_vector
?
示例:
type [type name] is [type details];
signal [object name] : [type name] := [optional initialization details];
下一个错误:进程没有敏感列表。 process
语句是顺序处理块的开始。没有任何敏感列表,它自动启动。这是一个问题:没有什么能阻止它,因此该过程将尝试在无限小的时间内无限循环。这当然会引起问题。解决方法:使用敏感度列表。
[label:] process ([trigger signal names])
begin
end process;
进程内部实际上有一个触发条件:start'event and start='1'
...这个start
是从哪里来的?可能缺少实体上的输入端口?但是这个 start
应该是您流程的触发器。
那怎么办?
您可以做的是读取文件和初始化数组。 (请注意,综合中不支持 multi-dimensional 数组,因为没有 multi-dimensional RAM 之类的东西,因此您必须展平数组并执行一些索引算法)。对于下一个示例,我创建了一个文件 "test.bin" 并用字符串“12345678”填充它 = 8 个字符 = 8*8 位 = 256 位 = 2*2*16 位 -> 适用于 2 x 2 数组.
那你应该意识到 textio
包只能读取文本!所以最简单的就是每8位读取一个字符,然后将两个拼接成一个16位的值。
示例代码:
entity read_bin is end entity;
library ieee;
architecture behavioral of read_bin is
use ieee.std_logic_1164.all;
subtype data_type is std_logic_vector(15 downto 0);
type two_dim_array_type is array(0 to 1, 0 to 1) of data_type;
impure function init_two_dim_array return two_dim_array_type is
use std.textio.all;
type character_file is file of character;
file file_pointer : character_file;
variable upper : character;
variable lower : character;
variable output : two_dim_array_type;
use ieee.numeric_std.all;
begin
file_open(file_pointer, "test.bin", READ_MODE);
for i in 0 to 1 loop
for j in 0 to 1 loop
read(file_pointer, upper); -- first 8 bits
read(file_pointer, lower); -- second 8 bits
output(i, j) :=
std_logic_vector(to_unsigned(character'pos(upper),8))&
std_logic_vector(to_unsigned(character'pos(lower),8));
end loop;
end loop;
file_close(file_pointer);
return output;
end function;
signal two_dim_array : two_dim_array_type := init_two_dim_array;
begin
end architecture;
瞧:
大问题
对我来说最大的问题是:当你犯了这些编程错误时,你怎么能获得电信和嵌入式系统的博士学位?或者对 FPGA 的功能缺乏了解。我本人是电气工程博士候选人,这是我们教 first-year 本科生的东西。当我想获得博士学位时,我经历了几轮评估,对我的知识进行了广泛测试。这些职位竞争激烈。
我的建议:请获得一些本地支持以实现这一点。您不想在接下来的 3 年博士期间试图将 VHDL 学习到足够的水平,然后发现您只有 1 年的时间进行一些实际研究才能发布结果...