【问题标题】:VHDL textio, reading image from fileVHDL textio,从文件中读取图像
【发布时间】:2015-06-27 15:35:06
【问题描述】:

我正在尝试学习如何在 FPGA 中实现图像处理算法,为此我正在使用包含 bmp 图像(使用 MATLAB 转换)的 txt 文件。

我在使用 textio 包时遇到问题,所以现在我只能读取第一列数据(但不能读取整行数据)。

txt文件有这个方面:

    1,1,0,0,0
    0,1,1,1,1
    1,0,0,0,0
    0,0,1,1,0
    1,1,1,1,1

以逗号分隔的 5x5 矩阵。 我现在在模拟中拥有的实体的输出是

    1 0 1 0 1 

对应于第一列。 我不明白为什么代码没有读完所有行,当它结束时跳转到下一行。

这是读取文件的过程(我添加了一个名为逗号的变量,因此我可以检测到逗号并跳过它但仍然不起作用):

reading : process 

    constant filename : string := "C:\DOCUMENTACION\PROYECTOS\Envio_salida_VGA_atraves_FPGA\MatLab\Procesado de imagen con Toolbox\prueba.txt";
    file f : text open read_mode is filename;
    variable L : line;
    variable data_read : integer;
    variable comma : character;
begin
    while not endfile(f) loop
        wait until rising_edge(clk); 
            readline(f, L);
            read(L, data_read);

            while L = ',' loop
                read(L, comma);
            end loop;

            d_out <= data_read;
    end loop;

我的代码有什么问题?

【问题讨论】:

  • 您是否考虑过直接从软件驱动刺激进入模拟,而不是通过文件?这个基于 Python 的示例处理位图、jpeg、tiff 等,并自动比较输出的相似性:github.com/chiggs/oc_jpegencode

标签: image file vhdl fpga


【解决方案1】:

我不明白为什么代码没有读完所有行以及何时结束跳转到下一行。

您只是尝试读取一个整数,然后在下一个 readline 之前读取一个逗号。

还请注意,只要您可以依靠一个字符来分隔一行上的连续整数,您就不必关心该字符是什么(而且您不必看comma)。

要读取一行中的每个整数,您需要注意您的read 调用是否已消耗所有行缓冲区。

在将您的示例数据保存到名为 prueba.txt 的文件后,我修改了您的代码以进行演示:

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

entity prueba is
end entity;

architecture foo of prueba is
    signal d_out:   integer;
    signal clk:     std_logic := '0';
begin
reading:
    process
        constant filename:  string := "prueba.txt";
        file f:              text open read_mode is filename;
        variable L:          line;
        variable data_read:  integer;
        variable char:      character;  
        variable len:       integer;  
    begin
        while not endfile(f) loop
            readline(f, L);

            len := L'length;
            while len > 0 loop
                read (L, data_read);
                len := L'length;
                if len > 0 then
                    read (L, char);
                    len := L'length;
                end if;
                wait until rising_edge(clk); 
                d_out <= data_read;
                report "data_read = " & integer'image(data_read);
            end loop;
        end loop;
        wait until rising_edge(clk);
        wait;                   
    end process;
CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if Now > 250 ns then -- picked by prueba.txt number of elements
            wait;
        end if;
    end process;

end architecture;

因为生成的波形需要您计算时钟或时间而不是数据,所以我添加了一个报告语句,它给出:

prueba.vhdl:33:17:@5ns:(报告说明):data_read = 1
prueba.vhdl:33:17:@15ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@25ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@35ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@45ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@55ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@65ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@75ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@85ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@95ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@105ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@115ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@125ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@135ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@145ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@155ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@165ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@175ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@185ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@195ns:(报告说明): data_read = 0
prueba.vhdl:33:17:@205ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@215ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@225ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@235ns:(报告说明): data_read = 1
prueba.vhdl:33:17:@245ns:(报告说明): data_read = 1

我们发现 prueba.txt 中的所有整数都被读取。

注意我添加了一个名为len 的变量来保存L 中可用的字符数。每个read 或每个readline len 都会更新。如果行上没有更多字符,我们不会尝试读取。

CLOCK 过程中对Now 的评估以及在reading 过程中额外的wait until rising_edge(clk); 和后续wait 只是为了在波形有用的地方停止模拟。


我们使用L'length 告诉我们一行上是否还有更多数据,或者我们是否应该进入外部while loop,如果不在文件末尾则调用readline

您还可以注意到,仅使用 'length 属性可以重写该过程:

reading:
    process
        constant filename:  string := "prueba.txt";
        file f:              text open read_mode is filename;
        variable L:          line;
        variable data_read:  integer;
        variable char:      character;  
    begin
        while not endfile(f) loop
            readline(f, L);
            while L'length > 0 loop
                read (L, data_read);
                if L'length > 0 then
                    read (L, char);
                end if;
                wait until rising_edge(clk); 
                d_out <= data_read;
                report "data_read = " & integer'image(data_read);
            end loop;
        end loop;
        wait until rising_edge(clk);
        wait;                   
    end process;

这给出了相同的答案。如果我们要做一些聪明的事情,比如扔掉 cmets,我们会使用 len 变量,这也需要我们扫描 L 并修剪尾随空白。我们可以给len赋值,但不能给L'length赋值。因为在您的 prueba.txt 中最后一个数据后面没有任何内容,我们可以简单地使用 length 属性。

【讨论】:

  • 我尝试运行此代码 sn-p 并且它工作正常(如您所示)但我仍然不明白某些部分:为什么必须在每个 if 和 while 中再次定义“len”部分?我试图避免这种情况,但它不起作用,我不确定为什么会发生这种情况。
【解决方案2】:

L 是一个指向字符串的指针。要取消引用指针,您需要:

L.all

因此,要获得一个角色,你可以这样做:

L.all(1) = ','

作为简写,你也可以这样做:

L(1) = ','

【讨论】:

    【解决方案3】:

    你可以研究这个包,它包含一个动态大小的数组类型,最多 3 维,可以从/到 csv 和原始文件加载/保存。

    https://github.com/LarsAsplund/vunit/blob/master/vhdl/array/src/array_pkg.vhd

    它是 VUnit VHDL 测试框架的一部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-29
      相关资源
      最近更新 更多