# How to easily resize strings in VHDL?

I have declared a string in the testbench code. However, I find that it is not simple to assign value to it. Here is the test code:

process
variable str : string(1 to 64);
begin
str := "hello world";
report str;
wait;
end process;


Why can't string contain index 0 in it? Also, how can I assign a string of any length to this variable since it won't be easy to make every string I assign to it, equal 64 characters by putting in white spaces.

EDIT:

This is what I came up with at the end, is there a simpler way to do this in VHDL?

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_misc.all;
use IEEE.numeric_std.all;

entity experiment_4 is
end entity;

architecture beh of experiment_4 is
procedure write_string(strout: out string; constant strin: in string) is
variable str : string(strout'range);
variable l,r: integer;
begin
if strin'length > strout'length then
assert false report "the specified string cannot fit into the specified variable" severity failure;
else
for i in strout'range loop
strout(i) := ' ';
end loop;
strout(strin'range) := strin;
end if;
end procedure;
begin

process
variable str : string(1 to 64);
begin
write_string(str, "hello world");
report str;
wait;
end process;

end architecture;


I'm not quite certain to understand what you are trying to do here. Maybe there is a bit of a XY problem in the first place. Nonetheless, I'll try to answer questions we have so far.

Strings are defined by standard as:

  type STRING is array (POSITIVE range <>) of CHARACTER;


and positive is defined as:

  subtype POSITIVE is INTEGER range 1 to INTEGER'HIGH;


That's why you cannot use index 0: by definition, string indices are from 1 onwards. When declaring variables/signals/subtypes, you may only be more restrictive than the original range.

In VHDL, strings are no more than arrays, the very same way std_logic_vectors are arrays. You should think about assign strings the same way you do when assigning (part of) logic arrays.

Here in your example code, you seem to want to assign a variable-length string literal to a (constrained) string variable. You do it with a procedure that pads the input argument. You could as well create a function, which may be clearer:

function padded(s: string; len: positive := 64; p: character := ' ') return string
is
alias xs: string(1 to s'length) is s;
variable ret : string(1 to len) := (others => p);
begin
if xs'length >= len then
ret := xs(1 to len);
else
ret(1 to xs'length) := xs;
end if;
return ret;
end function;


Then:

process
variable str : string(1 to 64);
begin
str := padded("hello world", str'length);
report str;
wait;
end process;


Another option is to use access to a string. Access is VHDL equivalent of pointers, with the nice feature that actual array constraints are attached to the targetted instance, so they may change.

It happens standard defines such thing in std.textio, line, which is defined as:

type LINE is access STRING;


Line type definition comes with procedures that are able to append text to it, called write.

procedure WRITE (L: inout LINE; VALUE: in STRING;
JUSTIFIED: in SIDE:= RIGHT; FIELD: in WIDTH := 0);


Note write is overloaded for many other value types, but I wont include them here, see standard for more.

Notice write L argument is inout. It is actually modified by the procedure. Behind the scenes, write reallocates the targetted string object to new size.

Typical usage is for constructing variable-length message:

use std.textio.all;

-- ...

function describe_number(v: in integer) return string is
variable ret: line := new string'("");
begin
write(ret, string'("Passed argument is: "));
write(ret, v);
if v >= 1000 then
write(ret, string'(", this is a lot !"));
end if;
return ret.all;
end function describe_number;

-- ...

process
begin
report describe_number(1);
report describe_number(1000);
wait;
end process;


All right, this is the final solution, I don't think there is a better way but let me know if there is one.

  procedure write_string(strout: out string; constant strin: in string) is
begin
assert strin'length <= strout'length
report "the specified string size " & integer'image(strin'length) & " cannot fit into the specified variable size " & integer'image(strout'length)
severity failure;
for i in strout'range loop
strout(i) := ' ';
end loop;
strout(strin'range) := strin;
end procedure;