You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:59:39