0
\$\begingroup\$

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;
\$\endgroup\$
2
  • \$\begingroup\$ Why do you write the and-gate results to a file? Shouldn't you compare the unit under test (uut) results with your output file? And if all inputs match there outputs, shouldn't you write a "TEST PASSED" to the console? \$\endgroup\$
    – Paebbels
    Commented Jul 28, 2015 at 16:38
  • \$\begingroup\$ Just trying to use the IO vhdl library, i'm not interested in other stuff for the moment. Just something to do practice... \$\endgroup\$ Commented Jul 28, 2015 at 19:00

1 Answer 1

0
\$\begingroup\$

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'.

\$\endgroup\$
7
  • \$\begingroup\$ Why did you add two wait statements? one with 5 ns and one with 0 ns? \$\endgroup\$ Commented Jul 29, 2015 at 9:12
  • \$\begingroup\$ "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." after 0 ns will cause a delta cycle delay. \$\endgroup\$
    – user8352
    Commented Jul 29, 2015 at 10:22
  • \$\begingroup\$ I understood the problem... now i have the same problem with a sequential circuit. I'm not sure of what the problem is. \$\endgroup\$ Commented Jul 29, 2015 at 16:15
  • \$\begingroup\$ Hi i'm sorry to bother you again, you said the the two consecutive statemtents <code> wait for 5 ns;</code> and <code>wait for 0 ns</code> can be collpsed in a single one, how such collapse should be written? i've tried with simply <code> wait for 5 ns;</code> since 5 + 0 = 5, but it doesn't work, so probably i'm missing something... \$\endgroup\$ Commented Sep 7, 2015 at 12:58
  • \$\begingroup\$ The problem is that the my_and sees the prior values of x_tb and y_tb in the same delta cycle z_bit is assigned. The wait for 0.0 ns adds a one delta cycle delay so my_and assigns z (z_tb) with most recently read values. When eliminating the wait for 0.0 ns, set the delays for assigning x_tb and y_tb to a value slightly smaller than 5.0 ns or increase the wait for 5.0 ns slightly. The assignments to x_tb and y_tb and sampling z (z_tb) shouldn't occur in the same delta cycle. \$\endgroup\$
    – user8352
    Commented Sep 7, 2015 at 20:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.