Read from File in VHDL using TextIO Library

Read from File in VHDL using TextIO Library

When you need to simulate a design in VHDL it is very useful to have the possibility to read the stimuli to provide to your Design Under Test (DUT) reading from an input file.

This approach allows you to have different test bench input stimuli using the same VHDL test bench code.

Read from file in VHDL and generate test bench stimuli
Read from file in VHDL and generate test bench stimuli

In VHDL, there are predefined libraries that allow the user to read from an input ASCII file in a simple way. The TextIO library is the standard library that provides all the procedure to read from or write to a file.

It is clear that these procedures cannot be used in a synthesizable RTL VHDL code, I mean no file handling possibility is present into a silicon device using simple RTL VHDL code, but they are very useful in test bench design.

There are several different ways to open a file and read from it.

In VHDL, File are handled as array of line an example of VHDL syntax to read from file is:

-- Declare and Open file in read mode: 

file file_handler     : text open read_mode is “filename.dat”;
Variable row          : line;
Variable v_data_read  : integer;

-- in the concurrent or sequential section of the architecture

-- Read line from file
readline(file_handler, row);

-- Read value from line
read(row, v_data_read);

The last action is used to read the desired value from the line.

If v_data_read is an integer value, the “read” procedure will try to read an integer value from the input line, if it is a real value, the procedure will try to read a real number and so on.

In this bunch of VHDL code, the file is opened during the file declaration on row 3.

A complete example of a process that read from file two integer values is given below:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
.
.
.
.
p_read : process(rstb,clk)
--------------------------------------------------------------------------------------------------
constant NUM_COL                : integer := 2;   -- number of column of file

type t_integer_array		   is array(integer range <> )  of integer;
file test_vector                : text open read_mode is "file_name.txt";
variable row                    : line;
variable v_data_read            : t_integer_array(1 to NUM_COL);
variable v_data_row_counter     : integer := 0;


begin

  
  if(rstb='0') then

    v_data_row_counter     := 0;
    v_data_read            := (others=> -1);

    i_op1                  <= (others=>'0');
    i_op2                  <= (others=>'0');
  ------------------------------------
  elsif(rising_edge(clk)) then
    
    if(ena = '1') then  -- external enable signal
    
    -- read from input file in "row" variable
      if(not endfile(test_vector)) then
        v_data_row_counter := v_data_row_counter + 1;
        readline(test_vector,row);
      end if;
    
    -- read integer number from "row" variable in integer array
      for kk in 1 to NUM_COL loop
        read(row,v_data_read(kk));
      end loop;

      value1_std_logic_8_bit    <= conv_std_logic_vector(v_data_read(1),8);
      value2_std_logic_8_bit    <= conv_std_logic_vector(v_data_read(2),8);

    end if;
    
  end if;
end process p_read;

The code above implements a process that at each clock cycle read from an input file 2 integer values if the control signal “ena” is ‘1’.

This VHDL code is parametric, the number of columns in the file is configured using the constant NUM_COL. You can use this code to read from an input file the stimuli for your test bench.

The input file will have the following format:

1 2
3 4
5 6
...

Here below there are the procedures you can find in IEEE TextIO standard library to read from file different type of values:

-- changed for vhdl92 syntax (and now a built-in):
  procedure READLINE(file f: TEXT; L: out LINE);

  procedure READ(L:inout LINE; VALUE: out bit; GOOD : out BOOLEAN);
  procedure READ(L:inout LINE; VALUE: out bit);

  procedure READ(L:inout LINE; VALUE: out bit_vector; GOOD : out BOOLEAN);
  procedure READ(L:inout LINE; VALUE: out bit_vector);

  procedure READ(L:inout LINE; VALUE: out BOOLEAN; GOOD : out BOOLEAN);
  procedure READ(L:inout LINE; VALUE: out BOOLEAN);

  procedure READ(L:inout LINE; VALUE: out character; GOOD : out BOOLEAN);
  procedure READ(L:inout LINE; VALUE: out character);

  procedure READ(L:inout LINE; VALUE: out integer; GOOD : out BOOLEAN);
  procedure READ(L:inout LINE; VALUE: out integer);

  procedure READ(L:inout LINE; VALUE: out real; GOOD : out BOOLEAN);
  procedure READ(L:inout LINE; VALUE: out real);

  procedure READ(L:inout LINE; VALUE: out string; GOOD : out BOOLEAN);
  procedure READ(L:inout LINE; VALUE: out string);

  procedure READ(L:inout LINE; VALUE: out time; GOOD : out BOOLEAN);
  procedure READ(L:inout LINE; VALUE: out time);

  procedure SREAD (L    : inout LINE; VALUE : out STRING; STRLEN : out NATURAL);
  alias STRING_READ is SREAD [LINE, STRING, NATURAL];
  alias BREAD is READ [LINE, BIT_VECTOR, BOOLEAN];
  alias BREAD is READ [LINE, BIT_VECTOR];
  alias BINARY_READ is READ [LINE, BIT_VECTOR, BOOLEAN];
  alias BINARY_READ is READ [LINE, BIT_VECTOR];

  procedure OREAD (L    : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN);

  procedure OREAD (L    : inout LINE; VALUE : out BIT_VECTOR);
  alias OCTAL_READ is OREAD [LINE, BIT_VECTOR, BOOLEAN];
  alias OCTAL_READ is OREAD [LINE, BIT_VECTOR];

  procedure HREAD (L    : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN);

  procedure HREAD (L    : inout LINE; VALUE : out BIT_VECTOR);
  alias HEX_READ is HREAD [LINE, BIT_VECTOR, BOOLEAN];
  alias HEX_READ is HREAD [LINE, BIT_VECTOR];

 TextIO library READ function overload

If you appreciated this post, please help us to share it with your friend.

[social_sharing style=”style-7″ fb_like_url=” https://surf-vhdl.com/read-from-file-in-vhdl-using-textio-library?utm_source=POST&utm_medium=FB&utm_campaign=SHARE” fb_color=”light” fb_lang=”en_US” fb_text=”like” fb_button_text=”Share” tw_lang=”en” tw_url=” https://surf-vhdl.com/read-from-file-in-vhdl-using-textio-library?utm_source=POST&utm_medium=TW&utm_campaign=SHARE” tw_button_text=”Share” g_url=” https://surf-vhdl.com/read-from-file-in-vhdl-using-textio-library?utm_source=POST&utm_medium=GPLUS&utm_campaign=SHARE” g_lang=”en-US” g_button_text=”Share” linkedin_url=” https://surf-vhdl.com/read-from-file-in-vhdl-using-textio-library?utm_source=POST&utm_medium=LK&utm_campaign=SHARE” linkedin_lang=”en_US” alignment=”center”]

If you need to contact us, please write to: surf.vhdl@gmail.com

We appreciate any of your comment, please post below:

12 thoughts to “Read from File in VHDL using TextIO Library”

  1. Hi , Nice note. One question, if you have an array to read in one row and multiple columns once, like reading all the elements in just one clock cycle what do we do? another question, what about the space between the taps how do we ignore that? thank you.

  2. Its not reading for me and providing an error ‘ramtype’ already imposes an index constraint

  3. You don’t actually need for it to be clocked. You can have a sequential process in the simulator with while loops and ifs. Unless you have an FPGA with a filing system the code above is only for the simulator.

    Is there something like stdio in VHDL so you could report constants nicely formatted?
    or use

    variable buf: line;
    lprintf(buf, “hello %d”, 10);
    write(output, buf)

    1. Hi Francis,
      the statement in the example should help to read from file and feed your synchronous design.
      Of course, you can use different strategies. For instance use the “wait” statement into a process.
      Regarding the formatting, VHDL is not so “smart” 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *