In previous post I explained in 5 steps how looks communication with files in VHDL. I presented some basic codes, which do simple write/read operations. Today I wanted to focus on that codes. If anyone tried to simulate them probably noticed that result are different from expectations. Below hopefully you will find an answer why…
Test 1: read -> write
I tested example 1 and simulated the code in Modelsim with the following input vector:
1000
2000
3000
4000
5000
6000
7000
8000
9000
And got results (for better view I depicted only the first values):
1000
2000
3000
4000
5000
6000
7000
8000
9000
00
It is not what I would expect. The output file is almost copy of the input one (beside two zeros in the last line), but data signal (shown in dec) in the simulation has totally different values.
Test 2: write -> read
To find out what is going on, I made the next test, but with reverse order of the operations. First I write data to the file, and then read it back.
... entity WriteIntToFile is end WriteIntToFile; architecture WriteIntToFile_rtl of WriteIntToFile is constant C_FILE_NAME_RD :string := "./dat/WriteIntToFile.dat"; constant C_FILE_NAME_WR :string := "./dat/WriteIntToFile.dat"; constant C_CLK :time := 10 ns; signal clk :std_logic := '0'; signal rst :std_logic := '0'; signal data :integer := 1; signal eowr :std_logic := '0'; signal eord :std_logic := '0'; ... begin ... GetData_proc: process variable statrd : FILE_OPEN_STATUS; variable statwr : FILE_OPEN_STATUS; variable varint_datawr :integer := 1; variable varint_datard :integer := 1; begin data <= 1; eowr <= '0'; eord <= '0'; wait until rst = '0'; -- write to file file_open(statwr, fptrwr, C_FILE_NAME_WR, write_mode); while varint_datawr < 100 loop wait until clk = '1'; varint_datawr := varint_datawr + 10; write(fptrwr, varint_datawr); end loop; file_close(fptrwr); wait until rising_edge(clk); eowr <= '1'; -- read from file file_open(statrd, fptrrd, C_FILE_NAME_RD, read_mode); while (not endfile(fptrrd)) loop wait until clk = '1'; read(fptrrd, varint_datard); data <= varint_datard; end loop; file_close(fptrrd); wait until rising_edge(clk); eord <= '1'; wait; end process; end WriteIntToFile_rtl;
This time, the file with data looks bad, but values in the simulation are OK.
After two tests, I can write that, if both operations are used, final results are almost OK, but intermediate step is always wrong. For read -> write operations, data in the simulator after reading is bad, and for write -> read operations data in the file after writing is bad.
HEX values
I did the next step in the investigation and displayed data in HEX values:
Test 1 – simulator:
Test 2 – file:
And lastly, when I compared it with ASCII code tables, the problem became more understandable.
Explanation
For test 1, in the input file, first value to read is 1000, then 2000, 3000… In HEX editor these values are not treated as integers, but as independent characters (as in binary file):
And now it can be seen that HEX values of the characters in the input file are identical to HEX values of data signal in the simulation.
For test 2, again, simulator does not see integers, which I would like to write to the file: 11, 21, 31… but see characters from ASCII tables, hidden under position 11 (0xB in HEX), 21 (0x15), 31 (0x1F)…
Modelsim does not treat data in the files as specified type (like integer), but always as characters. When it reads 1000, it does not see decimal number 1000, but characters 1, 0, 0, 0 which in ASCII code are represented by HEX values 0x31, 0x30, 0x30, 0x30. Then 0x0D and 0x0A, means New Line character (for Windows), but Modelsim also those bytes treats as regular data. This behaviour also explains why for test 1 in the output file are two zeros more at the end. Modelsim stores integers on 4 bytes. When you look back again at binary representation of the input file, will see that it contains 54 bytes (3×16 + 6). This number is not divisible by 4, so Modelsim adds two next bytes to get integer value. Why did it add “00”? This is not a standard, default value. I encourage you to make some tests and see how Modelsim add bytes.
The same is in opposite direction in test 2. I want to write number 11, but for Modelsim it is not 11, but the character under that position in ASCII table: VT. Then decimal 21 is 0x15 in HEX, and look again into ASCII table, it gives NAK character…
It seems that Modelsim is not an exception here. How various simulators treats data in files depends on many things – simulator, system, PC architecture. Working on that post I was looking for any information about similar issues, but found only that interesting discussion on comp.lang.vhd.
Hopefully that information will help to understand how looks low level communication with files in the simulation and how to debug it in case of any problems. If you still want to use those procedures and work on various data types, you will need to write your own functions and libraries. Fortunately, if you don’t want to do that, you don’t have to. Very useful is TextIO package, which I will describe in nest post.
*** *** ***
All source codes used in that post you can find on gitlab.com.
*** *** ***