基于VHDL读取ENVI生成的100×100、16位编码的图像二进制文件
在VHDL中读取ENVI生成的100×100 16位像素二进制文件的实现方案
嘿,这个需求我熟!ENVI导出的.raw格式二进制图像本质就是无文件头的原始像素流,按行优先顺序存储,100×100的16位像素总共对应20000个字节(每个像素占2字节)。下面给你一套可落地的VHDL实现思路、代码示例,还有容易踩的坑:
核心逻辑梳理
ENVI的原始二进制文件没有额外的元数据,直接就是像素的二进制数据,默认是大端字节序(高字节在前,低字节在后)。我们要做的就是:
- 用VHDL的文件IO接口逐字节读取文件
- 把每两个字节拼接成一个16位像素
- 输出有效像素数据,或者存储到RAM里供后续处理
完整VHDL代码实现
模块定义与信号声明
首先搭建基础的模块框架,引入必要的库:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use std.textio.all; -- VHDL处理文件依赖这个库 entity envi_image_reader is Port ( clk : in STD_LOGIC; rst_n : in STD_LOGIC; start_read : in STD_LOGIC; -- 触发读取的控制信号 pixel_data : out STD_LOGIC_VECTOR(15 downto 0); -- 输出16位像素值 pixel_valid : out STD_LOGIC; -- 标记当前pixel_data有效 read_done : out STD_LOGIC -- 标记所有像素读取完成 ); end envi_image_reader; architecture Behavioral of envi_image_reader is -- 定义二进制文件类型 type file_type is file of character; file envi_image_file : file_type; -- 内部信号:跟踪读取进度、缓存字节数据 signal byte_counter : integer range 0 to 19999 := 0; -- 总字节数100*100*2=20000 signal pixel_buffer : STD_LOGIC_VECTOR(15 downto 0); signal is_high_byte_read : BOOLEAN := FALSE; -- 标记是否已经读取了像素的高字节 begin
文件读取与像素拼接进程
在时钟驱动的进程里实现核心的读取逻辑,逐字节读取并拼接成16位像素:
process(clk, rst_n) variable temp_char : character; variable temp_byte : std_logic_vector(7 downto 0); begin if rst_n = '0' then -- 复位时初始化所有状态 byte_counter <= 0; pixel_valid <= '0'; read_done <= '0'; is_high_byte_read <= FALSE; pixel_buffer <= (others => '0'); file_close(envi_image_file); elsif rising_edge(clk) then pixel_valid <= '0'; -- 默认无效,只有拼接完成后置高 if start_read = '1' and read_done = '0' then -- 首次启动时打开文件 if byte_counter = 0 then -- 替换成你的图像文件路径,仿真时建议放在工程根目录 file_open(envi_image_file, "your_envi_image.raw", READ_MODE); end if; -- 确保文件成功打开后再读取 if file_open(envi_image_file) then -- 读取一个字节,转成8位逻辑向量 read(envi_image_file, temp_char); temp_byte := std_logic_vector(to_unsigned(character'pos(temp_char), 8)); -- 拼接16位像素:先读高字节,再读低字节 if not is_high_byte_read then pixel_buffer(15 downto 8) <= temp_byte; is_high_byte_read <= TRUE; else pixel_buffer(7 downto 0) <= temp_byte; pixel_data <= pixel_buffer; pixel_valid <= '1'; -- 输出有效像素 is_high_byte_read <= FALSE; byte_counter <= byte_counter + 2; -- 每处理2字节算一个像素 -- 检查是否读取完所有像素 if byte_counter = 19998 then -- 最后一组字节处理完成 read_done <= '1'; file_close(envi_image_file); end if; end if; end if; elsif start_read = '0' then -- 停止读取时重置状态 read_done <= '0'; byte_counter <= 0; is_high_byte_read <= FALSE; end if; end if; end process; end Behavioral;
关键注意事项
- 字节序问题:ENVI默认生成的16位像素是大端格式,如果你的目标硬件是小端架构(比如大部分x86系统),需要把拼接的字节顺序调换——也就是把
pixel_buffer(7 downto 0)和pixel_buffer(15 downto 8)互换后再输出。 - 文件路径:仿真时要确保VHDL工具能找到你的.raw文件,最好把文件放在工程目录下,或者使用绝对路径。
- 像素存储扩展:如果需要把所有10000个像素都存起来,可以在模块里添加一个100×100的双端口RAM,当
pixel_valid为高时,把pixel_data写入RAM的对应地址(地址可以用行号*100 + 列号生成)。 - 仿真验证:可以用ENVI把像素值导出成文本格式,然后在ModelSim等仿真工具里对比输出的
pixel_data,确保读取正确。
内容的提问来源于stack exchange,提问作者elmakhloufi assaad
相关产品推荐
相关产品推荐

