I'm trying to create a simple cache to use in simulation with my processor design.
I want to populate the cache with instructions that are stored in a file, .bin or .txt.
The file has no more than 1023 lines, and each line has the following format:
addr[tab]instruction
Adr is the address of the instruction, and the instruction is the instruction code, and [tab] is a tab (space between addr and instruction).
Here's the problem:
Addr is written as a hex value, has 32 bits, and instruction is written as a binary value and also has 32 bits. So one line looks like, for example, this
0000000A[tab]00001000000100001110000000000011
My idea was to create an array of std logic vectors and each line was one std logic vector where elem(63 downto 32) would be the address and elem (31 downto 0) would be the instruction code.
How do I read each line and at the same time convert hex value into binary, ignore tab, read the instruction and store everything into one std logic vector?
Thanks in advance for your help.
EDIT:
Would something like this work:
while not endfile(load_file) loop
readline(load_file, rdline);
hread(rdline, address);
read(rdline, data);
memory(index) := data;
index := index + 1;
end loop;
My question is: does hread move the cursor when reading the line? Also, how would I go about skipping the tab character?
-
\$\begingroup\$ Why do you store the instruction in binary format? It's easier to store both words in the same format. What do you have so for? \$\endgroup\$Paebbels– Paebbels2015年08月24日 12:19:04 +00:00Commented Aug 24, 2015 at 12:19
-
\$\begingroup\$ It's a requirement of the project I'm working on, and I can't change that. \$\endgroup\$idjuradj– idjuradj2015年08月24日 21:57:46 +00:00Commented Aug 24, 2015 at 21:57
-
\$\begingroup\$ @Paebbels I updated my question with the function I tried. \$\endgroup\$idjuradj– idjuradj2015年08月24日 22:03:16 +00:00Commented Aug 24, 2015 at 22:03
2 Answers 2
The basic process is to
- Open the file for reading using
file_open()
. - Loop over each line until end-of-file is encountered:
- Read the line to a variable of type
line
usingreadline()
. - Read the line as a
string
usingread()
. - Separate the string into the two parts you're interst using indeces.
- Convert the strings character-by-character to
std_logic_vector
s using a conversion function (I can't find a built in one - I might be missing the obvious - but it's just a simple case statement with cases for all of the characters you're interesed in and a flag or assert for any unexpected ones).
- Read the line to a variable of type
There's plenty of examples for the file IO part:
-
\$\begingroup\$ Sorry there's no code - I don't have an environment to try it out here. \$\endgroup\$Xcodo– Xcodo2015年08月24日 12:50:30 +00:00Commented Aug 24, 2015 at 12:50
-
\$\begingroup\$ Thanks for your suggestion. When I read the line, can I select the first eight characters and convert them from hex to binary using hread? Is there a way to automatically read the binary part into std_logic_vector (maybe using some default or built-in conversion?) \$\endgroup\$idjuradj– idjuradj2015年08月24日 14:28:18 +00:00Commented Aug 24, 2015 at 14:28
-
\$\begingroup\$ I'm not familiar with one for binary, but it is just a very simple case statement. You could look at the code of the textio package HREAD procedure and simplify it to only accept
1
or0
. \$\endgroup\$Xcodo– Xcodo2015年08月24日 14:36:23 +00:00Commented Aug 24, 2015 at 14:36 -
\$\begingroup\$ Since the hex and binary parts are separated by whitespace, you can use
hread()
to read from theline
directly into your address, then useread()
from the sameline
to read characters1
and0
into anstd_logic_vector
. This is usingstd_logic_textio
. \$\endgroup\$scary_jeff– scary_jeff2015年08月25日 07:49:59 +00:00Commented Aug 25, 2015 at 7:49
This is more of a comment, but I'll post it here for the sake of formatting. As mentioned elsewhere, this utility function might help.
FUNCTION hex2bin (hex: character) RETURN std_logic_vector IS
VARIABLE result : std_logic_vector (3 downto 0);
BEGIN
CASE hex IS
WHEN '0' => result := "0000";
WHEN '1' => result := "0001";
WHEN '2' => result := "0010";
WHEN '3' => result := "0011";
WHEN '4' => result := "0100";
WHEN '5' => result := "0101";
WHEN '6' => result := "0110";
WHEN '7' => result := "0111";
WHEN '8' => result := "1000";
WHEN '9' => result := "1001";
WHEN 'A'|'a' => result := "1010";
WHEN 'B'|'b' => result := "1011";
WHEN 'C'|'c' => result := "1100";
WHEN 'D'|'d' => result := "1101";
WHEN 'E'|'e' => result := "1110";
WHEN 'F'|'f' => result := "1111";
WHEN 'X'|'x' => result := "XXXX";
WHEN others => NULL;
END CASE;
RETURN result;
END;
-
\$\begingroup\$ Thanks for the manual implementation, I'm sure others will find it useful. Just curious, is this, in terms of functionality, in any way different than hread? \$\endgroup\$idjuradj– idjuradj2015年08月24日 21:58:39 +00:00Commented Aug 24, 2015 at 21:58
-
\$\begingroup\$
hread
reads from a line. His function converts a CHARACTER to a 4-bit SLV. \$\endgroup\$Paebbels– Paebbels2015年08月24日 22:16:31 +00:00Commented Aug 24, 2015 at 22:16 -
\$\begingroup\$ For simulation I would probably make the others case throw an assert to warn you on case of a badly formatted text file. \$\endgroup\$Xcodo– Xcodo2015年08月25日 07:52:36 +00:00Commented Aug 25, 2015 at 7:52