Search code examples
vhdl

How to read text file line by line in vhdl by clk?


I am trying read a text file line by line in clock event to output. But my code just reads the first element in every clock! Where is the problem?

entity filter_tb is
PORT( clk : IN std_logic;   
     filter_out : OUT real 
     );
end filter_tb;

architecture filter_tb of filter_tb is
begin

process(clk) 
    file file_pointer : text;
    variable line_content : real;
    variable line_num : line; 
begin
    file_open(file_pointer,"myFile.txt",READ_MODE);
    readline(file_pointer, line_num); 
    read(line_num, line_content);
    filter_out <= line_content;
    file_close(file_pointer);
end process;

end filter_tb;

myFile.txt:

0.0000000e+00
5.8778525e-01
9.5105652e-01
9.5105652e-01
5.8778525e-01
1.2246468e-16

Solution

  • There are some context clause elements in the root declarative region missing as well as the means to exercise the design model:

    library ieee;
    use ieee.std_logic_1164.all;
    use std.textio.all;
    
    entity filter_tb is
    

    You need to only open and close the file once. This of it as phases: open the file, read data once per clock, when no more data close the file and suspend the process until the end of simulation.

    architecture filter_tb of filter_tb is
    begin
    
        process -- (clk)            -- process now contains wait statement
            constant filename:      string := "myFile.txt"; -- use more than once
            file file_pointer:      text;
            variable line_content:  real;
            variable line_num:      line; 
            variable filestatus:    file_open_status;
        begin
            file_open (filestatus, file_pointer, filename, READ_MODE);
            report filename & LF & HT & "file_open_status = " & 
                        file_open_status'image(filestatus);
            assert filestatus = OPEN_OK 
                report "file_open_status /= file_ok"
                severity FAILURE;    -- end simulation
    
            while not ENDFILE (file_pointer) loop
                wait until falling_edge(clk);  -- once per clock
                readline (file_pointer, line_num); 
                read (line_num, line_content);
                filter_out <= line_content;
            end loop;
    
            wait until falling_edge(clk); -- the last datum can be used first
            file_close (file_pointer);
            report filename & " closed.";
            wait;
    
        end process;
    
    end architecture filter_tb;
    

    This uses a different file_open procedure call that also assigns a file_open_status variable when when reported would make it obvious you were opening the file repetitively.

    After there are no more lines to be read the file will be closed. Note the wait statement waiting on a clock edge event in the loop statement, which will read one datum per clock.

    The final wait statement suspends the process for the remainder of the simulation.

    With top level ports we can add an enclosing testbench:

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity tb_filter_tb is
    end entity;
    
    architecture foo of tb_filter_tb is
        signal clk:         std_logic := '0';
        signal filter_out:  real;
    begin
    DUT:
        entity work.filter_tb
            port map (
                clk => clk,
                filter_out => filter_out
            );
        
    CLOCK:
        process
        begin
            wait for 5 ns;
            clk <= not clk;
            if now > 90 ns then
                wait;
            end if;
        end process;
    MONITOR:
        process
        begin
            wait until falling_edge(clk);
            wait for 0 ns;
            report "filter_out = " & real'image(filter_out);
        end process;
    end architecture;
    

    The monitor process can report the values of filter_out on every active clock edge:

    ghdl -r tb_filter_tb
    filter_tb.vhdl:25:13:@0ms:(report note): myFile.txt
      file_open_status = open_ok
    filter_tb.vhdl:80:9:@10ns:(report note): filter_out = 0.0
    filter_tb.vhdl:80:9:@20ns:(report note): filter_out = 5.8778525e-1
    filter_tb.vhdl:80:9:@30ns:(report note): filter_out = 9.5105652e-1
    filter_tb.vhdl:80:9:@40ns:(report note): filter_out = 9.5105652e-1
    filter_tb.vhdl:80:9:@50ns:(report note): filter_out = 5.8778525e-1
    filter_tb.vhdl:80:9:@60ns:(report note): filter_out = 1.2246468e-16
    filter_tb.vhdl:42:9:@70ns:(report note): myFile.txt closed.
    filter_tb.vhdl:80:9:@70ns:(report note): filter_out = 1.2246468e-16
    filter_tb.vhdl:80:9:@80ns:(report note): filter_out = 1.2246468e-16
    filter_tb.vhdl:80:9:@90ns:(report note): filter_out = 1.2246468e-16
    

    until simulation ends.