Read from File in VHDL using TextIO Library

Why Read Testbench Stimuli from an Input File?

When you need to simulate a design in VHDL, it is very useful to read the stimuli provided to your Design Under Test (DUT) directly from an input file. This approach allows you to use different testbench input stimuli with the same VHDL testbench code.

Read from file in VHDL and generate test bench stimuli

In VHDL, predefined libraries allow the user to read from an input ASCII file. The TextIO library is the standard library that provides all the procedures to read from or write to a file.

These procedures cannot be used in synthesizable RTL VHDL code—since no file handling capability is present in a silicon device—but they are extremely useful in testbench design.

VHDL Syntax: How readline and read Work

There are several different ways to open a file and read from it. In VHDL, files are handled as arrays of lines. An example of VHDL syntax to read from a 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);

It is important to understand the difference between the two main procedures:
– readline reads an entire line from the input file and stores it into a temporary buffer (the line variable).
– read extracts the desired value from that buffer line.

If v_data_read is an integer, the read procedure will try to extract an integer value from the input line; if it is a real value, the procedure will read a real number, and so on. A very useful feature of the read procedure is that it automatically ignores white spaces (spaces or tabs) between values in the file.

In this VHDL snippet, the file is opened during the file declaration on line 3.

Interactive TextIO Flow

Click "Step" to simulate the VHDL process.

file_name.txt (Disk)
24 56
12 98
07 42
EOF
variable row : line
readline(file, row)
v_data_read array
read(row, v_data_read(1))
?
read(row, v_data_read(2))
?
Ready to simulate.

Complete VHDL Process Example

A complete example of a process that reads two integer values from a file 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, reads 2 integer values from an input file if the control signal ena is '1'.

Notice the use of the endfile() function. It checks if the end of the file has been reached, preventing the simulator from crashing when trying to read beyond the available data.

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 the stimuli for your testbench from an input file.

The input file will have the following format:

1 2
3 4
5 6
...

TextIO Library READ Function Overloads

Below are the procedures available in the IEEE TextIO standard library to read different types of values from a file:

-- 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];

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