Test bench with IO file vhdl

vhdl

Is the following test bench correct?
I tried to use a text file with the content

00
01
10
11

to test an architecture of an and port.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
use std.textio.all;

entity my_and_tb is
end entity my_and_tb;

architecture tb_arch of my_and_tb is
    component my_and is
    port  ( x, y : in std_ulogic;
           z : out std_ulogic);
end component;
signal x_tb, y_tb, z_tb : std_ulogic;
begin
my_and_inst : my_and port map( x => x_tb, y => y_tb, z => z_tb);

tb_process : process
    file my_input : TEXT open READ_MODE is "my_input.txt";
    file my_output : TEXT open WRITE_MODE is "my_output.txt";
    variable my_line : LINE;
    variable my_input_line : LINE;
    variable my_output_line : LINE;
    variable x_bit : bit;
    variable y_bit : bit;
    variable z_bit : bit;
begin
    while not endfile(my_input) loop
        readline(my_input,my_line);
        read(my_line,x_bit);
        read(my_line,y_bit);
        x_tb <= to_stdulogic(x_bit) after 5 ns;
        y_tb <= to_stdulogic(y_bit) after 5 ns;
        z_bit := to_bit(z_tb);
        write(my_output_line,z_bit);
        writeline(my_output,my_output_line);
        wait for 10 ns;
    end loop;
end process;
end architecture tb_arch;

Basically the simulation with ncsim is blocked…
Update…

Same problem for this example (is a flip flop d, and basically the clock make me confuse, i thought it was ok but it isn't… could you help me?)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;

entity ff_d_tb is
end entity ff_d_tb;

architecture ff_d_tb_arch of ff_d_tb is
component ff_d is
port(clk, d : in std_logic;
     q : out std_logic);
end component;

signal clk_tb, d_tb, q_tb : std_logic;
begin

ff_d_comp : ff_d
port map(clk => clk_tb, d => d_tb, q => q_tb);  

clk_process : process
begin
    clk_tb <= '0','1' after 5 ns;
    wait for 10 ns;
end process;

ff_process : process
    file in_file : text open READ_MODE is "input.txt";
    file out_file : text open WRITE_MODE is "output.txt";
    variable l_in : line;
    variable l_out : line;
    variable q_loc, d_loc : std_logic;
begin
    while not endfile(in_file) loop
        readline(in_file,l_in);
        read(l_in,d_loc);
        d_tb <= d_loc after 5 ns;
        wait until falling_edge(clk_tb);
        q_loc := q_tb;
        write(l_out,q_loc);
        writeline(out_file,l_out);
    end loop;
    wait;
end process;
end architecture ff_d_tb_arch;

Best Answer

No. Your testbench isn't correct.

You have two superfluous use clauses:

-- use ieee.numeric_std.all;
-- use ieee.std_logic_misc.all;

Your process tb_process should have wait; end loop; allowing the simulation to complete when you've finished processing input stimulus from my_input.txt.

About then you'll notice all your results in my_output.txt are all 0, which is caused by delta cycle delay in assignment to signal z_tb in entity my_and. Your process also has delayed assignments to x_tb and y_tb which need to be taken into account.

No signal update occurs during the execution of any process (and all signal updates occur within processes, concurrent statements are elaborated into process statements or process statements and block statements). Essentially you need to suspend the process before any of these assignments take effect.

The cure is one or more wait statements which will suspend execution. The following shows two, a wait for 5 ns; and a wait for 0 ns;. They can be collapsed in to one wait statement. The purpose is to show that you need at least a delta cycle delay following assignments to x_tb and y_tb taking effect for z_tb to be updated. If there were a delayed signal assignment for z (z_tb) in entity my_and that delay would also be added to the first wait statement.

tb_process:  
    process
        file my_input:  TEXT open READ_MODE is "my_input.txt";
        file my_output:  TEXT open WRITE_MODE is "my_output.txt";
        variable my_line:  LINE;
        variable my_input_line:  LINE;
        variable my_output_line:  LINE;
        variable x_bit:  bit;
        variable y_bit:  bit;
        variable z_bit:  bit;
    begin
        while not endfile(my_input) loop
            readline(my_input,my_line);
            read(my_line,x_bit);
            read(my_line,y_bit);
            x_tb <= to_stdulogic(x_bit) after 5 ns;
            y_tb <= to_stdulogic(y_bit) after 5 ns;
            wait for 5 ns;  -- added
            wait for 0 ns;  -- added
            z_bit := to_bit(z_tb);
            -- report "x_bit = " & bit'image(x_bit);
            -- report "y_bit = " & bit'image(y_bit);
            -- report "z_tb = "  & std_ulogic'image(z_tb);
            write(my_output_line,z_bit);
            writeline(my_output,my_output_line);
            -- wait for 10 ns;  -- removed
        end loop;
        wait;
    end process;

Note the wait for 10 ns; is commented out, it's not needed when your process has a linear model of time allowing signal assignments to take affect (has (an) other wait statement(s)).

The above modification to your process statement with a zero delay model for my_and gives:

more my_output.txt
0
0
0
1

Which is the expected output.

Notice the commented report statements which can be used to debug the process statement. If you don't have enough delay the first report for z_tb will show a 'U'.

Related Topic