I am trying to learn how to implement image processing algorithms in an FPGA and to do this I am working with a txt file that contains a bmp image (converted using MATLAB).
I am havin problems using the textio package, so by now I am only able to read the first column of data (but not the entire row of data).
The txt file have this aspect:
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
a 5x5 matrix separated by commas. The output of the entity I have now in my simulations is
1 0 1 0 1
that corresponds to the first column. I don't understand why the code doesn't read all the line and when it ends jump to the next line.
Here is the process for read the file (I have add a variable named comma so I could detect the comma and skip it but still doesn't work ):
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;
what is wrong with my code?
I don't understand why the code doesn't read all the line and when it ends jump to the next line.
You're only trying to read one integer then one comma before the next readline
.
Also note as long as you can count on one character separating consecutive integers on a line you don't have to care what the character is (and you don't so much as look at comma
).
To read every integer on a line you need to pay attention to whether your read
calls have consumed all the line buffer.
I modified your code to demonstrate after saving your example data to a file named 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;
Because a resulting waveform requires you count clocks or time instead of datums I added a report statement which gives:
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
Where we find all the integers in prueba.txt are read.
Note I added a variable named len
to hold the number of characters available in L
. Every read
or every readline
len
gets updated. If there are no more characters on the line we don't try to read.
The evaluation of Now
in the CLOCK
process and the extra wait until rising_edge(clk);
and following wait
in the reading
process are just to stop the simulation where a waveform would be useful.
L'length
to tell us if there are any more datums on a line or whether we should fall out into the outer while loop
and call readline
if not at the end of the file.
You could also note the process can be re-written using only the 'length
attribute:
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;
And this gives the same answer. We'd use a len
variable if we were to do something clever like throw away comments, which would also require we scan L
and trim trailing white space. We can assign values to len
but not L'length
. Because there is nothing trailing the last datum in your prueba.txt we can simply use the length
attribute.