如何读取图像文件并将其转换为vhdl

时间:2017-03-28 12:05:35

标签: image io vhdl

我正在尝试使用vhdl中的textio包读取图像文件。 如果我用记事本打开一个.jpg,我会得到一些垃圾数据,但实际上它是ASCII数据。在这里,我试图读取这些ascii数据并将它们转换为字节。

下面是我的代码:

library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
use ieee.std_logic_textio.all;

entity file_io is

 port (
     clk:             in  std_logic;
     Data:            out std_logic_vector(7 downto 0)
 );
 end entity;

 architecture behav of file_io is

signal test_data : std_logic_vector(7 downto 0);
use ieee.numeric_std.all; 
use std.textio.all;
use ieee.std_logic_textio.all;
begin

File_reader:process(clk)
    file f    : text open read_mode is "C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg";
    variable L:   line;
    variable var_int:   integer:= 0;
    variable var_char:   character;  

begin

if rising_edge(clk) then
        while not endfile(f) loop
                 readline(f, L);
         read(L, var_char);
         var_int := character'pos(var_char);
         test_data  <= std_logic_vector(to_unsigned(var_int, test_data'length));  
        end loop;
     end if;
    Data <= test_data;
  end process;
end architecture behav;

测试平台:

LIBRARY ieee;
use ieee.std_logic_1164.ALL;
use std.textio.all;

ENTITY file_io_test IS 
END file_io_test;

ARCHITECTURE behavior OF file_io_test IS
use work.io.all;
    signal clk:         std_logic := '0';
    signal Data: std_logic_vector(7 downto 0);

    -- Clock period definitions
    constant clk_period : time := 10 ns;

    BEGIN
      -- Instantiate the Unit Under Test (UUT)
    UUT:
     entity work.file_io(behav)
    port map (
           clk => clk,
        Data => Data
          );

    -- Clock process definitions( clock with 50% duty cycle is generated here.
     clk_process :process
       begin
         clk <= '1';
         wait for clk_period/2;  --for 5 ns signal is '1'.
          clk <= '0';
         wait for clk_period/2;  --for next 5 ns signal is '0'.

     end process;
    end behavior;  

我只获得波形中的一个字节。预期结果是:每个时钟周期新字符应该是rread并且应该获得新字节。

下面是波形: enter image description here

下面是我想要阅读的图片: enter image description here

2 个答案:

答案 0 :(得分:1)

您在流程的while部分内放置了rising_edge循环。发生的情况是,当第一个时钟边沿发生时,while循环将迭代直到文件末尾,并为您提供输入图像的最后一个字节。

删除while循环语句可以解决您的问题。

答案 1 :(得分:1)

这个问题有一个根本性的缺陷。您不能使用textio来读取二进制值,而是用于文本。

参见IEEE Std 1076-2008 16.4包TEXTIO第3段(部分)和4:

  

程序包TEXTIO中声明的READLINE,WRITELINE和TEE读取和写入TEXT类型文件的整行。过程READLINE导致从文件中读取下一行,并返回参数L的值作为指定表示该行的对象的访问值。如果参数L在调用开始时包含非空访问值,则该过程可以解除分配该值指定的对象。 该行的表示不包含行尾的表示 。 ...

     

该语言未定义行尾的表示形式。实现应允许将CHARACTER和STRING类型的所有可能值写入文件。但是,由于允许实现使用CHARACTER和STRING类型的某些值作为行分隔符,因此可能无法从TEXT文件中读取这些值。

这可以用你的Chrysanthemum.jpg来证明:

Chrsanthemum read failure

VHDL可以一次读取一个原始字符(符合您的需要)。

请参阅IEEE Std 1076-2008 5.5文件类型: 5.5.jpg 5.5 cont.jpg

所以我们要做的就是声明一个文件类型,然后我们隐式定义这些过程。

我们可以使用它们来调用原始读取,而不会因textio引起任何行结束问题:

library ieee;
use ieee.std_logic_1164.all;

entity file_io is
    port (
        clk:    in  std_logic;
        Data:   out std_logic_vector(7 downto 0);
        done:   out boolean
 );
 end entity;

architecture foo of file_io is
    use ieee.numeric_std.all;
begin

File_reader:
    process (clk)
        -- "C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg";
        constant filename:  string := "Chrysanthemum.jpg"; -- local to sim
        variable char_val:  character;
        variable status: FILE_OPEN_STATUS;
        variable openfile:  boolean;  -- FALSE by default
        type f is file of character;
        file ffile: f;
        variable char_count:    natural := 0;
    begin
        if rising_edge (clk) then
            if not openfile then
                file_open (status, ffile, filename, READ_MODE);
                if status /= OPEN_OK then
                    report "FILE_OPEN_STATUS = " & 
                            FILE_OPEN_STATUS'IMAGE(status)
                    severity FAILURE;
                end if;
                report "FILE_OPEN_STATUS = " & FILE_OPEN_STATUS'IMAGE(status);
                openfile := TRUE;
            else 
                if not endfile(ffile) then
                    read(ffile, char_val);
                    -- report "char_val = " & character'image(char_val);
                    char_count := char_count + 1;
                    Data  <= std_logic_vector (
                             to_unsigned(character'pos(char_val),
                             Data'length) );
                 end if;
                 if endfile(ffile) then  -- can occur after last character
                    report "ENDFILE, read " & 
                          integer'image(char_count) & "characters";
                    done <= TRUE;
                    FILE_CLOSE(ffile);
                end if;
            end if;
        end if;
    end process;
end architecture foo;

library ieee;
use ieee.std_logic_1164.all;

entity file_io_test is 
end file_io_test;

architecture behavior of file_io_test is
    signal clk:         std_logic := '0';
    signal data:        std_logic_vector(7 downto 0);
    signal done:        boolean;
    constant clk_period: time := 10 ns;
begin
uut:
    entity work.file_io(foo)
        port map (
           clk => clk,
           data => data,
           done => done
        );

clk_process:
    process
    begin
        if not done then
             clk <= '1';
             wait for clk_period/2;
              clk <= '0';
             wait for clk_period/2;
         else
             wait;
         end if;
     end process;
end architecture behavior;  

现在我们可以拥有所有字符,而不是可以在我们的阅读中界定一行:

file_io_test_char_raw.png

请注意,包std.textio不会通过任何上下文项显示。