I am trying to read data from a text file in VHDL which includes two vectors and single character. While reading, white spaces are not detected for the numbers but are detected for the character. Why is that?
VHDL CODE:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
library STD;
use STD.TEXTIO.ALL;
entity sample_tb is
end sample_tb;
architecture Behavioral of sample_tb is
begin
stim : process
file F_in : TEXT open READ_MODE is "input_sample.txt";
variable current_read_line : line;
variable input_number1 : std_logic_vector(1 downto 0);
variable input_number2 : std_logic_vector(1 downto 0);
variable input_field : string(1 to 1);
variable current_write_line : line;
begin
while( not endfile(F_in)) loop
readline(F_in, current_read_line);
read(current_read_line, input_number1);
read(current_read_line, input_number2);
read(current_read_line, input_field);
wait for 100 ns;
write(current_write_line, input_number1);
write(current_write_line, input_number2);
write(current_write_line, input_field);
writeline(OUTPUT, current_write_line);
end loop;
wait;
end process;
end Behavioral;
input_sample.txt
:
00 00 A
00 00 B
00 00 C
00 00 D
00 00 E
Output when I declare variable input_field : string(1 to 1);
(keep in mind that there is an extra space after 0000)
0000
0000
0000
0000
0000
Output when I declare variable input_field : string(1 to 2);
0000 A
0000 B
0000 C
0000 D
0000 E
I have understood that the code detects the white space before the letters and considers it to be a string. But, why doesn't that happen when reading the two std_logic_vectors? Why is the white space between 00 and 00 ignored?
Also, is the way to ensure that the code disregards the white space before the letters as well?
2 Answers 2
Space characters are not a legal std_logic character, hence, reads for std_logic_vector throw away leading white space and fail if there is a non-white space character that is not a std_logic value. In fact, all reads except for type string behave this way. The string read OTOH, returns the next characters in the line and expects to read exactly the number of characters in the argument - if there are not at least argument length characters in the line, then it is an error.
Sread is designed to read tokens - white space separated words - hence, it only keeps the non-space characters in a similar fashion to what read does for std_logic_vector. Sread reads up to the number of characters in the argument string and also returns the length. Sread returns 0 as the length if no characters were available to read. I should also note that Sread is VHDL-2008 so make sure to turn on the appropriate switch in your simulator.
Hence, the following code segment will strip out all leading white space.
variable str_len : integer ;
. . .
readline(F_in, current_read_line);
read(current_read_line, input_number1);
read(current_read_line, input_number2);
sread(current_read_line, input_field, str_len);
If you want the white space when writing, simply add it back:
write(current_write_line, to_string(input_number1) & ' ' &
to_string(input_number2) & ' ' & input_field);
writeline(OUTPUT, current_write_line);
-
\$\begingroup\$ It's meant for the OP \$\endgroup\$user16145658– user161456582024年05月21日 02:03:51 +00:00Commented May 21, 2024 at 2:03
-
\$\begingroup\$ @user16145658 Anyone can make careless editing mistakes. I certainly appreciate anything that is on-point and corrects something I may have missed. \$\endgroup\$Jim Lewis– Jim Lewis2024年05月21日 22:15:30 +00:00Commented May 21, 2024 at 22:15
This will reproduce input_sample.txt on OUTPUT by writing input_number1, input_number2 and input_field. Note the two writes of a space (" ") interposed between the values written.
This is a specific solution for the code presented in the question:
stim : process
file F_in : TEXT open READ_MODE is "input_sample.txt";
variable current_read_line : line;
variable input_number1 : std_logic_vector(1 downto 0);
variable input_number2 : std_logic_vector(1 downto 0);
variable input_field : string(1 to 1);
variable current_write_line : line;
variable substr : line; -- ADDED
begin
while( not endfile(F_in)) loop
readline(F_in, current_read_line);
read(current_read_line, input_number1);
read(current_read_line, input_number2);
for i in current_read_line'range loop -- ADDED FOR LOOP
if current_read_line(i) /= ' ' then -- First non space
write(substr, current_read_line(i to current_read_line'high));
deallocate (current_read_line);
write(current_read_line, substr.all);
deallocate (substr);
exit; -- after first non space element
end if;
end loop;
read(current_read_line, input_field);
wait for 100 ns;
write(current_write_line, input_number1);
write(current_write_line, string'(" ")); -- SPACE
write(current_write_line, input_number2);
write(current_write_line, string'(" ")); -- SPACE
write(current_write_line, input_field);
writeline(OUTPUT, current_write_line);
end loop;
wait;
end process;
A read for a std_logic_vector will eat white space up until the first character belonging to the element base type std_ulogic value and read until the first non element value.
After the second std_logic_vector read there's a for loop that eats leading spaces. This is analogous to what a read for a non-string type will do, and it's also what occurs in sread mentioned in Jim's answer.
(The while loop iteration scheme condition does not require parentheses. Conditions are boolean expressions delimited by reserved words.)
%: ghdl -a -fsynopsys sample_tb.vhdl
%: ghdl -e -fsynopsys sample_tb
%: ghdl -r sample_tb
00 00 A
00 00 B
00 00 C
00 00 D
00 00 E
%:
where the writeline operations duplicate the contents of input_sample.txt to OUTPUT.
The description of the read behavior can be found in IEEE std 1076-2008 16.4 Package TEXTIO pages 273 and 274 or IEEE Std 1076-1993/2002 14.3 Package TEXTIO.
The basic distinction is string read procedure calls use an end of line indication comprised of one or more characters where CHARACTER is the element type of STRING to delimit a readline operation, leaving other CHARACTER values in the read[1] string. Trying to read[2] a string from from a line will result in those characters being extracted into the string.
[1] read verb 4 his remark could be read as a dig at Forsyth. INTERPRET, take, take to mean, construe, see, explain, understand.
[2] noun I settled down for a read of "The Irish Press". perusal, study, scan, scrutiny; look (at), browse (through), glance (through), leaf (through), flick (through), skim (through).
-
\$\begingroup\$ That is obscenely complex given that VHDL-2008 supports sread and all simulators except Xilinx xsim support it. \$\endgroup\$Jim Lewis– Jim Lewis2024年05月21日 03:30:37 +00:00Commented May 21, 2024 at 3:30
-
\$\begingroup\$ A declaration and a 9 line for loop is obscenely complex because hyperbole? How's the weather in the Pacific Northwest or is the political news getting you down? \$\endgroup\$user16145658– user161456582024年05月21日 04:58:43 +00:00Commented May 21, 2024 at 4:58
-
\$\begingroup\$ Considering that sread gets the job done in one simple statement and that you are suggesting pointer manipulations to a person just getting started. \$\endgroup\$Jim Lewis– Jim Lewis2024年05月21日 14:01:20 +00:00Commented May 21, 2024 at 14:01
-
\$\begingroup\$ Also note a read operation should never see an end of line character. From 16.4, "Procedure READLINE causes the next line to be read from the file and returns as the value of parameter L an access value that designates an object representing that line. If parameter L contains a non-null access value at the start of the call, the procedure may deallocate the object designated by that value. The representation of the line does not contain the representation of the end of the line." Most simulators are compliant in this regard, however, there are a few that are not - Xilinx xsim. \$\endgroup\$Jim Lewis– Jim Lewis2024年05月21日 14:25:42 +00:00Commented May 21, 2024 at 14:25
-
\$\begingroup\$ @Jim You've already down voted. Consider putting some of that effort into your own posts. \$\endgroup\$user16145658– user161456582024年05月21日 18:30:34 +00:00Commented May 21, 2024 at 18:30
std_logic_vector
to store the white space? Coming from a software background, it is clear to me thatread()
ignores leading white space and stops at the first non-std_logic
character. \$\endgroup\$