简体   繁体   中英

Read file line of unknown size as string in VHDL

What I have

I'm trying to make a Test Bench where a file of one single line, where posible characters are "1" and "0". I've to read them all, and use one by one as input in my DUT.

So, in my TB, I've defined a process like the following, in order to read the file an pass it values to my DUT.

stim_proc: process

 file input_file: TEXT is in "DatosEntrada.dat";

 variable rdline : LINE;
 variable line_content : string ( 1 to 4);
 variable readed_char : character;

 variable j : integer := 0;

begin       

 while not endfile(input_file) loop

   readline(input_file, rdline);

   --read(rdline, line_content);

   for j in 1 to rdline'length-1 loop

     readed_char := line_content(j);

     if (readed_char = '1') then
       input <= '1';
     else
       input <= '0'; 
     end if;

     wait for clk_period;

   end loop;

 end loop;

end process;

What I think it's happening

I'm reading the first (and only) line of my file with the first readline execution. After this, this loop shouldn't execute again.

Then, data from file should be inside rdline . So I've to process it. In order to do it, I've tried to loop over rdline length, but this loop doesn't execute.

for j in 1 to rdline'length-1 loop

So I thought I need to read this line in order to loop over it, and tried to move its data to a string var. The problem is that vector var like string need to have a defined size, and I don't know the file line size .

What have I tried

I've tried different ways to accomplish it, like reading each time 4 chars from rdline into a string, process it, then repeat. However, I couldn't make it work.

I've found quite lot examples on Google about reading files with VHDL, but they're all pretty the same, and all have defined line formats, like columns or expected integers, where I just have an unknown text of one line.

I guess it could be achieved by reading from rdline var in some way, but I can't achieve it. Could you help me to code it?

Thank you in advance

Your example isn't an MCVE .

This readed_char := line_content(j); doesn't work when line_content isn't loaded. Otherwise your attempt to read values is basically sound.

The end of line is not contained in a read LINE buffer, there's no reason to not read the last character of rdline. An end of line is signaled by one or more format effectors other than horizontal tab, and just the line contents are present.

There's also this inference that you have some relationship to a clock edge and not just a clock period. The following example shows that. Note you can also supply an offset from an edge using a wait for time_value .

A loop constant is declared in the loop statement. The variable j you declared is not the same j the loop uses. The loop statement hides the j in the outer declarative region (the variable declaration in the process statement).

Your code treats any other character in the string buffer than '1' as a '0'. I didn't change that, do demonstrate it. You should be aware of the impact.

A LINE is an allocated string of some length dependent on the length of a line in your read file. Every time you call readline the string rdline points to is updated. It doesn't leak memory, the previous buffer rdline pointed to released. You can read the length by using the 'RIGHT attribute or as in this case simply consume all the characters.

There may be line length limits in a VHDL tool implementation. There are none defined in the standard other than the maximum length of a string (POSITIVE'RIGHT).

An MCVE:

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

entity foo is
end entity;

architecture fum of foo is
    signal input:           std_logic ;
    signal clk:             std_logic := '0';
    constant clk_period:    time := 10 ns;
begin

stim_proc: 
    process
        file input_file: TEXT is in "DatosEntrada.dat";
            variable rdline:    LINE;
            -- variable line_content : string ( 1 to 4);
            -- variable readed_char : character;
            -- variable j:         integer := 0;
    begin       
        while not endfile(input_file) loop
            readline(input_file, rdline);
            --read(rdline, line_content);
            -- for j in 1 to rdline'length - 1 loop -- EOL not in rdline
            for j in rdline'range loop
                -- readed_char := line_content(j);
                -- if readed_char = '1' then
                if rdline(j) = '1' then   -- changed
                    input <= '1';
                else
                    input <= '0'; 
                end if;
                -- wait for clk_period;  -- sync to edge instead
                wait until falling_edge(clk); -- input related to clk edge
            end loop;
        end loop;
        wait;     -- added prevents needless loops
    end process;

CLOCK:
    process
    begin
        wait for clk_period/2;
        clk <= not clk;
        if now > 32 * clk_period then
            wait;
        end if;
    end process;

end architecture;

And for DatosEntrada.dat containing:

11011110001HELLO11230000

That produces:

foo.png

Where you can see all non '1' characters are interpreted as '0'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM