Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Reading from a TXT file to a 2d array in vhdl

Status
Not open for further replies.

yashjain

Junior Member level 1
Joined
Jul 28, 2019
Messages
15
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
164
Hi,

I wanna read my text file to initialise an array of 2d.
Iḿ using this in my test bench.


Code:
signal stream_data             : a2_std_logic_vector_type(39 downto 0)(6 downto 0)(9 downto 0);

    signal din_anc                 : std_logic_vector(9 downto 0);

create_SDI_stream : process
  variable anc_line  : line;
  variable anc_data  : std_logic_vector(9 downto 0);
 
    begin 
    file_open(file_anc,"file_anc.txt", read_mode); 
    
   if not endfile(file_anc) then
      
      for i in 0 to 39 loop
        readline(file_anc,anc_line);
        for j in anc_line'range loop
          hread(anc_line,anc_data);
          stream_data(to_integer(anc_line))(j) <= anc_data;
         wait for 1 ps;
        end loop;
      end loop;
    end if;               
    file_close(file_anc);
end process;


000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1
000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1

Model sim error :-

# HDL call sequence:
# Stopped at /home/yash/workspace/video_anc_generic/sim/tb_generic_anc_extractor.vhd 118 ForLoop loop

how can I solve it?
 

# Stopped at /home/yash/workspace/video_anc_generic/sim/tb_generic_anc_extractor.vhd 118 ForLoop loop

how can I solve it?
I'm not a VHDL expert so I can't be sure what the error means. But I do notice the if statement isn't doing anything as opening the file then checking for end of file is a rather useless check. The first for loop will run out of data as the file has less lines than the number of times through the loop.

You could try starting with an example that works https://www.nandland.com/vhdl/examples/example-file-io.html and modifying to your needs.

I don't get why you have the wait 1 ps; statement usually file reading routines just read the data into an array with no delays.
 

read text file to make a serial output data vhdl

HI,

I'm trying to read data from a text file and ouput every hex value in the line serially for my test bench.
The output waveform is very weird and it's skipping some values of the line. Also the data is not generated
at the clock edge.
Can someone help in this regard?

Code:
file file_anc : text;

signal din_anc;
signal video_clk;

constant video_clk_period : time := 7 ns; -- frequncy of 3g sdi / 1 sec

begin

create clock: process
begin
video_clk <='0';
    wait for video_clk_period/2;
    video_clk <='1';
    wait for video_clk_period/2;
  end process;

create serial data: process

variable anc_line : line;
variable anc_data : std_logic_vector(9 downto 0);

begin 

file_open(file_anc,"file_anc.txt", read_mode);

	if not endfile(file_anc) then
		for j in anc_line'range loop
          hread(anc_line,anc_data);
			 din_anc<= anc_data;
			 wait until rising_edge(video_clk);
		end loop;
	end if;
file_close(file_anc);
end process;

## file_anc.txt

000 FF1 3F0 3F1 001 CD0 CF0 FD0 DC1

Or is there any other way to generate a serial data by reading text io file.
I have to generate serial data by reading the text file in this format itself.
 

Your loop only assigns the din_anc each clock cycle with a new value, there is nothing in the code to serialize the din_anc data.

Did you even look at the example at the link I posted?

You are still using an if statement to check for end of the file, which is NOT going to work. You should use a while loop if you want to check for end of file (as is done in the example).
 

anc_line is just a pointer to a string. When you read the line the 'range will be (1 to LINE_LENGTH) where LINE_LENGTH is the length of the line in chars, not words. In your example, it means the loop will unroll into 35 iterations (because there are 35 characters on the line).
There is a version of hread that tells you whether the read you did was good or not.
And you should also have wait. at the end of the process, otherwise you're just going to open it again


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
create serial data: process
  variable anc_line : line;
  variable anc_data : std_logic_vector(9 downto 0);
  variable good     : boolean;
 
begin 
 
  file_open(file_anc,"file_anc.txt", read_mode);
  
  while not ENDFILE(file_anc) loop
    readline(file_anc, anc_line);
    hread(anc_line,anc_data, good);
    while good loop    
      din_anc<= anc_data;
      wait until rising_edge(video_clk);
      
      hread(anc_line,anc_data, good);
    end loop;
  end loop;
  
  file_close(file_anc);
  wait;
end process;



I dont quite understand your problem now though. Are you asking for help with code in #1 or #3?
 
I dont quite understand your problem now though. Are you asking for help with code in #1 or #3?

I merged two separate threads. It's obvious the first post was about trying to read the data file. The second post (which was in a new thread) was how they wanted to read the file but also serialize the output data.
 

HI, it worked.
But, further down the code, Iḿ encountering an error relating to array.

Iḿ trying to read one TEXT file line one by one at a particular point. So, I have made an array which would load all the data from the text file and then output the data at specific event. I'm using this approach since, Every line in my text file can conatin different amount of data.

Code:
architecture behav of tb is 
signal array : a_std_logic_vector_type (data_counter downto 0)(9 downto 0);  -- POINT 1
    signal dout  : std_logic_vector(9 downto 0);

begin

create_enable: process (video_clk)
begin 
  if rising_edge(video_clk) then
    if  vcount = true and hcount = 0 then 
      read_line_enable <= '1';
    else 
      read_line_enable <= '0';
    end if;    

    -- insert data 
    if hcount <= data_counter then
        dout <=  array(data_counter);  -- POINT 2
        din_anc <= dout;
    else  
       dout <= "00"&x"20";
       din_anc <= dout;
        -- hcount_d <= hcount;--for data synchornisation
    end if; 
  end if; 
end process;   

data_count: process

variable anc_line       : line;
variable anc_data       : std_logic_vector(9 downto 0);
variable data_available : boolean;
  begin

    file_open(file_anc, "file_anc.txt", read_mode);
    
    if read_line_enable = '1' then
      readline(file_anc, anc_line);
      hread(anc_line, anc_data, data_available);

      while (data_available = true) loop
        hread(anc_line, anc_data, data_available);
        data_counter <= data_counter + 1;
        array(data_counter) <= anc_data;  -- POINT 3
      end loop;
      data_counter <= 0; 
    end if;   
    file_close(file_anc);
    wait;
  end process;

But, whenever Iḿ trying to compile it, it gives an error.

near "array": expecting IDENTIFIER :: POINT 1
near "array": syntax error :: POINT 2,3

How to solve this error
 

array is a reserved word for the creation of a type. So it cannot be used as an object name.
 
Thanks! saw that later.

Bit more debugging and the testbench would be complete. For some reason my file doesn't open in the code. Spent countless iterations but it doesn't seem to open.

Code:
architecture behaviour of tb_generic_anc_extractor is 

file  file_anc                 : text;
----------------------- other code
signal din_anc                 : std_logic_vector(9 downto 0);
    signal hcount                  : integer := 0;
    signal data_counter            : integer := 0;
    signal vcount                  : boolean := false;
    signal read_line_enable        : std_logic := '0';

    type anc_array is array (0 to data_counter) of std_logic_vector(9 downto 0);
    signal arr : anc_array;
    signal dout  : std_logic_vector(9 downto 0);

begin

create_enable: process (video_clk)
begin 
  if rising_edge(video_clk) then
    if  vcount = true and hcount = 0 then 
      read_line_enable <= '1';
    else 
      read_line_enable <= '0';
    end if;    

    -- insert data 
    if hcount <= data_counter then
           
        din_anc <= arr(data_counter);
    else  
        
       din_anc <= "00"&x"20";
        -- hcount_d <= hcount;--for data synchornisation
    end if; 
  end if; 
end process;   

data_count: process

variable anc_line       : line;
variable anc_data       : std_logic_vector(9 downto 0);
variable data_available : boolean;
variable result         : anc_array(others=>(others=>'0'));
  begin
  
    file_open(file_anc, "file_anc.txt", read_mode);
    if read_line_enable = '1' then
      readline(file_anc, anc_line);
      hread(anc_line, anc_data, data_available);

      while (data_available = true) loop
        hread(anc_line, anc_data, data_available);
        result(data_counter) := anc_data; -- arr(data_counter) <= anc_data; or using this
        data_counter <= data_counter + 1;
       
        wait until rising_edge(video_clk);
      end loop;
      -- data_counter <= 0; 
    end if;
     
    file_close(file_anc);
    wait;
  end process;

create_hcount : process(video_clk)
begin
if falling_edge(video_clk) then
  if fw_dvalid = '1' then                        --when data is valid
    hcount <= to_integer(unsigned(fw_hcount))+1; -- create a integer pointer for fw_hcount to compare later
  end if;                                        -- +1 for timing synchronisation
end if;                                          -- fw :- framework
end process;


create_vcount : process(video_clk)    -- will create a case statement for later addition of vcount select
begin
if rising_edge(video_clk) then        -- checking at falling edge
  if fw_vcount <= "00000000000"  then -- checking if vcount reach 0

    vcount <= true;                   -- assigning boolean value true.
  else 
    vcount <= false;  
  end if;
  
end if;
end process;



end architecture;

Can spot the issue?
 

What do you mean by "doesnt seem to open"? Does it throw an error about the file not existing? Is there no stimulus? Please explain the problem or show the error.
 

What do you mean by "doesnt seem to open"? Does it throw an error about the file not existing? Is there no stimulus? Please explain the problem or show the error.

If I use this process :-

Code:
data_count: process

variable anc_line       : line;
variable anc_data       : std_logic_vector(9 downto 0);
variable data_available : boolean;
-- variable result         : anc_array(others=>(others=>'0'));
  begin
  
    file_open(file_anc, "file_anc.txt", read_mode);
    if read_line_enable = '1' then
      readline(file_anc, anc_line);
      hread(anc_line, anc_data, data_available);

      while (data_available = true) loop
        hread(anc_line, anc_data, data_available);
        -- result(data_counter) := anc_data;
        data_counter <= data_counter + 1;
        arr(data_counter) <= anc_data;
        wait until rising_edge(video_clk);
      end loop;
      -- data_counter <= 0; 
    end if;
     
    file_close(file_anc);
    wait;
  end process;

then it compiles succesfully. but with warnings :-
(vcom-1013) Type "anc_array" depends on value of signal "data_counter"

And if I use this process :-

Code:
data_count: process

variable anc_line       : line;
variable anc_data       : std_logic_vector(9 downto 0);
variable data_available : boolean;
variable result         : anc_array;
  begin
  
    file_open(file_anc, "file_anc.txt", read_mode);
    if read_line_enable = '1' then
      readline(file_anc, anc_line);
      hread(anc_line, anc_data, data_available);

      while (data_available = true) loop
        hread(anc_line, anc_data, data_available);
        result(data_counter) := anc_data;
        data_counter <= data_counter + 1;
       
        wait until rising_edge(video_clk);
      end loop;
      data_counter <= 0; 
    end if;
     
    file_close(file_anc);
    wait;
  end process;

Then it compiles with warnings:-
(vcom-1013) Type "anc_array" depends on value of signal "data_counter".

In both the cases, the file_anc remains closed and there is no data is read from text file. Also data_available signal is False.
 

You should not create a type from a signal. Your array is only length 1 (0 downto 0). You should use some constant value to set the length of the type
 

You should not create a type from a signal. Your array is only length 1 (0 downto 0). You should use some constant value to set the length of the type

Yup, already did it, but same result. result array is formed of size 10. But, the flie remains close. Or even If I add a enf file loop, it doesn´t read values.

Code:
type anc_array is array (0 to 9) of std_logic_vector(9 downto 0);
begin 

data_count: process

variable anc_line       : line;
variable anc_data       : std_logic_vector(9 downto 0);
variable data_available : boolean;
variable result         : anc_array;
variable count          : integer := 0;
  begin
  
    file_open(file_anc, "file_anc.txt", read_mode);
    if read_line_enable = '1' then
      readline(file_anc, anc_line);
      hread(anc_line, result(0), data_available);

      while (data_available = true) loop
        for result'range loop
          hread(anc_line, anc_data, data_available);
          result(i) := anc_data;
          data_counter <= count + 1;
        end loop;
        wait until rising_edge(video_clk);
      end loop;
    end if;
     
    file_close(file_anc);
    wait;
  end process;
 

You should not create a type from a signal. Your array is only length 1 (0 downto 0). You should use some constant value to set the length of the type

Maybe not a good solution, but it should be possible to initialize the constant from a function that makes a separate "pre-read" of the file to check how much data there is.
 

Maybe not a good solution, but it should be possible to initialize the constant from a function that makes a separate "pre-read" of the file to check how much data there is.

Yes, thats what Iḿ trying to do. Pre read in the text data into an array and output it in another process.

If you refer to above codes, create_enable process is used for outputting the data. And data_count process is basically counting the no. of data in one line along with making an array to pre read the data.
But, this way doesn't seam to work somehow.
 

The problem is you're trying to create an array before you know the size. So if you need to read the whole file into an array you can do one of the following:
1. Read the file to see how big it is, create the array type and then read the file again
2. Read the file into an access type and increase the size of the array dynamically

I would suggest 1, as you are unlikely to find examples of 2 online. It is perfectly possible but you need a good understanding of VHDL.

But why do you need to store the whole file as an array?
 

HI,

Thanks TrickyDicky for the help!
your 1st option is what I have implemented.
ANd now it all works. MY text file character format wasn't right, thus it wasn't reading right. When I debugged the code to output the data is string that is when I got to know it.

So, If anyone who wants to read space seperated text file and out the contents of one line serially and wait till your other other for reading next line is high. You can use my code!
Here is the final code for the job !
Code:
type anc_array is array (0 to 2000) of std_logic_vector(9 downto 0);
  signal arr : anc_array;
file  file_anc                 : text;
signal data_counter            : integer := 0;


data_count: process

variable anc_line       : line;
variable anc_data       : std_logic_vector(9 downto 0);
variable data_available : boolean := true;
variable count          : integer := 0;

  begin
  
    file_open(file_anc, "file_anc.txt", read_mode);  -- open file
    while not endfile(file_anc) loop
      wait until read_line_enable = '1'; -- Reading one line condition
          if data_available = true then --cheching if there is any more data on your line
            count:= 0;                  -- return false when no more data on line
            data_counter <= 0;          -- this makes your conter wrap back to 0 
          end if;  
            while (data_available = true) and data_counter<arr'length loop              -- LOops till the last data in one line is reached
              hread(anc_line, anc_data, data_available);  -- redaing one data from the line
              arr(count) <= anc_data;                      -- text file data being fed to the array.
              count := count+1;
              data_counter <= count; -- counting the no. of data values in one line. Will be used later
              wait for 1 ns;            -- exit when no data is present in the text line                                     
            end loop;
    end loop; 
    file_close(file_anc);
    wait for 1 ps;
  end process;
 

You did not implement option #1. Your array is already defined in the first line with the type declaration and it is set to 2001 entries.

If your file is 5000 lines then your filling of the array will get an index outside the range and will fail in simulation.

Tricky's option #1 suggestion was to read the entire file first to find out how many lines are in it and then create the array (with the correct number of entries) and read the file a second time to fill the array.

If you don't care about files with more than 2001 lines then put the assignment to the array arr(count) inside an if statement that checks for a count greater than 2001, which will just allow the code to read the reset of the file without assigning the values read to the array.

I also don't get the reason for having the wait for 1ns; statement, reading files shouldn't have any time control statements if you are reading them into an array anyway that just makes the simulation run a bunch of cycles for no good reason.
 

Hi,
Nope you are getting it all wrong. The code reads all the data in one line. That is

TEXT FILE:-
000 3FF 311 322
3FF 000 111 222

Then the code would put all the values of first line in the array. And reads next line when your condition is true. I have declared size of my array cause thats the max amount of data I want to output serially. Remember this is simulation, so your array size can very large. Then you read the array out by index. Then read again to over write the array. This way we don't have to either care about the size of line or no. of lines. Its fully automated.

I have used 1 ns delay, because without it was not working correctly. So you can always see if you can do away with 1 ns statements in your code if it works good.
 

Hi,
Nope you are getting it all wrong.
I'm more inclined to believe you didn't follow what I wrote about above.

The code reads all the data in one line. That is

TEXT FILE:-
000 3FF 311 322
3FF 000 111 222

Then the code would put all the values of first line in the array. And reads next line when your condition is true. I have declared size of my array cause thats the max amount of data I want to output serially. Remember this is simulation, so your array size can very large. Then you read the array out by index. Then read again to over write the array. This way we don't have to either care about the size of line or no. of lines. Its fully automated.

I have used 1 ns delay, because without it was not working correctly. So you can always see if you can do away with 1 ns statements in your code if it works good.
I've used VHDL for decades and I've never needed to add a 1ns delay into a file reading process that loaded an array. Yes I've used time control or wait for clock edges or other signals when I didn't use an array and read the data directly into the testbench when it was needed for excessively large sets of data vectors.

It looks to me like you have a somewhat overly complicated testbench architecture and are restricted by the handshake between the file read and the rest of the the testbench code. If I read a file in I just read the data and stick it in the array at time 0ns and then release reset sometime later like normal and the data is in the array before the simulation of the UUT even starts.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top