VHDL textio,从文件中读取图像

VHDL textio, reading image from file

我正在尝试学习如何在 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;

我的代码有什么问题?

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

L.all

因此,要获得角色,您可以这样做:

L.all(1) = ','

作为 shorthand,您还可以:

L(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:(report note): data_read = 1
prueba.vhdl:33:17:@15ns:(report note): data_read = 1
prueba.vhdl:33:17:@25ns:(report note): data_read = 0
prueba.vhdl:33:17:@35ns:(report note): data_read = 0
prueba.vhdl:33:17:@45ns:(report note): data_read = 0
prueba.vhdl:33:17:@55ns:(report note): data_read = 0
prueba.vhdl:33:17:@65ns:(report note): data_read = 1
prueba.vhdl:33:17:@75ns:(report note): data_read = 1
prueba.vhdl:33:17:@85ns:(report note): data_read = 1
prueba.vhdl:33:17:@95ns:(report note): data_read = 1
prueba.vhdl:33:17:@105ns:(report note): data_read = 1
prueba.vhdl:33:17:@115ns:(report note): data_read = 0
prueba.vhdl:33:17:@125ns:(report note): data_read = 0
prueba.vhdl:33:17:@135ns:(report note): data_read = 0
prueba.vhdl:33:17:@145ns:(report note): data_read = 0
prueba.vhdl:33:17:@155ns:(report note): data_read = 0
prueba.vhdl:33:17:@165ns:(report note): data_read = 0
prueba.vhdl:33:17:@175ns:(report note): data_read = 1
prueba.vhdl:33:17:@185ns:(report note): data_read = 1
prueba.vhdl:33:17:@195ns:(report note): data_read = 0
prueba.vhdl:33:17:@205ns:(report note): data_read = 1
prueba.vhdl:33:17:@215ns:(report note): data_read = 1
prueba.vhdl:33:17:@225ns:(report note): data_read = 1
prueba.vhdl:33:17:@235ns:(report note): data_read = 1
prueba.vhdl:33:17:@245ns:(report note): 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;

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

您可以研究这个包,它包含最多 3 个维度的动态大小数组类型,可以 load/save from/to csv 和原始文件。

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

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