String contains hex value that can fit within 32 bits. There is no "0x" or "x" at the start, just the hex value.
Does VHDL have a built in method to convert this into an integer or I need to write my own custom function to do this?
EDIT:
A file contains data that is read into a line and then part of it is assigned to a VHDL string data type. Here is an example:
variable my_string : string(1 to 8);
Now assume that the my_string contains the hex value that has been read from file which could be something like e.g "A57E01AC". It could be upper or lower case, I cannot guarantee the case. It is also possible that instead of 8 characters in the string there be less but it will still fit into 32 bit integer anyway. And yes, the value is signed. The file is generated by some other program. The data in the file is not uniform since it contains ASCII form of packets of data and a data has different fields inside it. However, I will know when the characters 13 to 18 (for example) contain the hex string that must be converted to integer.
Now, with the my_string containing "A57E01AC", how do I convert this into an integer? I could write a function myself but am wondering if VHDL has built in functions for this sort of thing.
And yes, this is for testbench only.
-
1\$\begingroup\$ We need to know what value you are converting, is this a wire or a variable in a test bench \$\endgroup\$Voltage Spike– Voltage Spike ♦2024年12月17日 02:02:23 +00:00Commented Dec 17, 2024 at 2:02
-
3\$\begingroup\$ Beside the feeling that this is the wrong SE site (you might want to ask this on Stack Overflow), what does your research of the widely available VHDL common libraries' documentation reveal? What did you find, and why does it not help you? \$\endgroup\$the busybee– the busybee2024年12月17日 08:10:32 +00:00Commented Dec 17, 2024 at 8:10
-
\$\begingroup\$ see also: this post \$\endgroup\$SnappyRiffs– SnappyRiffs2024年12月17日 14:56:35 +00:00Commented Dec 17, 2024 at 14:56
-
\$\begingroup\$ @SnappyRiffs Sadly I looked at your referenced post - had to fix the errors in it. \$\endgroup\$Jim Lewis– Jim Lewis2024年12月17日 22:27:16 +00:00Commented Dec 17, 2024 at 22:27
-
\$\begingroup\$ I have added details so it should now be possible to open the question again. \$\endgroup\$gyuunyuu– gyuunyuu2024年12月19日 02:04:29 +00:00Commented Dec 19, 2024 at 2:04
2 Answers 2
You cannot currently read integers as hex. You can read signed, unsigned, and std_logic_vector as hex and convert them to integer. If you can, read the characters using hread. With VHDL-2008, hread for signed and unsigned is in package numeric_std - similarly hread for std_logic_vector is in std_logic_1164.
library IEEE ;
use std.textio.all ;
use ieee.numeric_std.all ; -- with VHDL-2008 has hread for signed and unsigned
. . .
hread(buf, b_signed) ;
b_int := to_integer(b_signed) ;
If you are parsing an input and as a result, you have an 8 bit hex value in a string, it gets more interesting. The easiest thing you can do is put it back into an object of type line and read it. You can do this by doing:
process
variable StrPtr: line ;
variable b_signed : signed(31 downto 0) ;
variable b_int : integer ;
begin
. . .
StrPtr := new string'(my_string) ;
hread(StrPtr , b_signed) ;
b_int := to_integer(b_signed) ;
-- at this point StrPtr is null, but you can deallocate it if you want
deallocate(StrPtr) ;
If you poke around in std_logic_1164 you will find a Char2QuadBits in the package body. This will character by character convert your string to std_logic_vector. Unfortunately it is not visible so you would have to copy it. There may also be some open source utilities the provide this capability.
-
\$\begingroup\$ VHDL seems quite weak in its string capabilities. Often the stimulus and expected results are stored in an external file that has been generated through some other C program or Python or TCL script. VHDL is severly lagging behind in basic string processing capabilities it seems. There are workarounds for many things and some open source packages but it does beg the question why these things are not part of the language itself yet so they can be optimized by the simulation tools. \$\endgroup\$gyuunyuu– gyuunyuu2024年12月19日 21:43:03 +00:00Commented Dec 19, 2024 at 21:43
-
\$\begingroup\$ I do get somewhat confused why the functions that work with line type are not defined for string type as well when line is basically a pointer to a string. \$\endgroup\$gyuunyuu– gyuunyuu2024年12月20日 00:13:21 +00:00Commented Dec 20, 2024 at 0:13
-
\$\begingroup\$ I have posted an answer, this is the code that I intend to use as given in the answer \$\endgroup\$gyuunyuu– gyuunyuu2024年12月20日 02:34:12 +00:00Commented Dec 20, 2024 at 2:34
-
\$\begingroup\$ Perhaps even more frustrating that the language implements Char2QuadBits, but does not make it visible. It would be appropriate to add them to the IEEE VHDL standard. See gitlab.com/IEEE-P1076/VHDL-Issues/-/issues to add an issue. It is volunteer based, so you can come and do the implementations too. That will insure the work gets done. \$\endgroup\$Jim Lewis– Jim Lewis2024年12月20日 17:11:17 +00:00Commented Dec 20, 2024 at 17:11
Here is the code that I eventually wrote myself and it works:
function hchar_to_slv(c : character) return std_logic_vector is
variable slv : std_logic_vector(3 downto 0);
begin
case c is
when '0' => slv := "0000";
when '1' => slv := "0001";
when '2' => slv := "0010";
when '3' => slv := "0011";
when '4' => slv := "0100";
when '5' => slv := "0101";
when '6' => slv := "0110";
when '7' => slv := "0111";
when '8' => slv := "1000";
when '9' => slv := "1001";
when 'A' | 'a' => slv := "1010";
when 'B' | 'b' => slv := "1011";
when 'C' | 'c' => slv := "1100";
when 'D' | 'd' => slv := "1101";
when 'E' | 'e' => slv := "1110";
when 'F' | 'f' => slv := "1111";
when others =>
slv := "XXXX";
report "Invalid value passed into hchar_to_slv: " & c
severity failure;
end case;
return slv;
end function hchar_to_slv;
function hstring_to_integer(str : string; is_signed : boolean := FALSE) return integer is
constant STR_T : string(1 to str'length) := str;
variable slv : std_logic_vector(4*str'length-1 downto 0) := (others=>'0');
variable hchar_slv : std_logic_vector(3 downto 0) := (others=>'0');
begin
-- validate input parameter
assert str'length <= 8
report "Input to hstring_to_integer too large: " & str
severity failure;
-- conversion from string to slv
for i in 0 to STR_T'length - 1 loop
hchar_slv := hchar_to_slv(STR_T(STR_T'length - i));
slv(4*i+3 downto 4*i) := hchar_slv;
end loop;
-- conversion from slv to integer
if (is_signed = TRUE) then
return to_integer(signed(slv));
else
if str'length = 8 and slv(slv'left) = '1' then
report "The input string value is 32 bits " &
"while its MSb is '1'; Conversion to unsigned " &
"is not possible so expect warning: NUMERIC_STD.TO_INTEGER not in bounds of subtype NATURAL"
severity warning;
end if;
return to_integer(unsigned(slv));
end if;
end function hstring_to_integer;
Going from string to std_logic_vector and then to integer is the simplest route. The code implies that the input parameter has number of bits that are multiple of 4. This is very important for conversion from string to signed integer.
-
\$\begingroup\$ Some day you may wish to support Z as generating "ZZZZ", and likewise for U, X, W, -, L, H. Char2QuadBits has some of these but not all. Other than missing these, your code appears to be identical to Char2QuadBits. \$\endgroup\$Jim Lewis– Jim Lewis2024年12月20日 17:09:08 +00:00Commented Dec 20, 2024 at 17:09
-
1\$\begingroup\$ Your
hstring_to_integer
has a bug. Integers are 32 bits when they are signed. Hence, your conversion in the return needs to be to_integer(signed(slv)). Using unsigned will overflow when the left most bit of the slv is a 1. \$\endgroup\$Jim Lewis– Jim Lewis2024年12月23日 03:38:57 +00:00Commented Dec 23, 2024 at 3:38 -
1\$\begingroup\$ Following on from my comment above, when using type unsigned, you only get 31 bits of integer \$\endgroup\$Jim Lewis– Jim Lewis2024年12月24日 19:00:42 +00:00Commented Dec 24, 2024 at 19:00
-
\$\begingroup\$ Yes, when doing unsigned with 8 character string, the result will become a negative number when put into an integer; that is, when the MSb is '1'. This is why a severity warning; message is issued. I thought if it should be a fatal instead. I shall look into the bug you have pointed out. \$\endgroup\$gyuunyuu– gyuunyuu2024年12月26日 13:48:22 +00:00Commented Dec 26, 2024 at 13:48