There's no printf() equivalent in VHDL that works with all types, and I think it would be quite hard to create as it is a strongly typed language. Here are some examples of what can be done in VHDL 2008, and a couple of extensions.
For reference the print() function definitions I am using is:
Of course you could use VHDL report statement instead and include the simulation time.
Real Numbers
Okay, so there's a printf() like formatting string here, but that only applies to real numbers.
Some quick examples for illustration:
Engineering Format
Two of these three functions rely on using a normalised scientific format. This is not helpful when printing reals in an engineering format. I've had a go at creating an alternative printing function that is more helpful with scientific units, i.e. exponents where the power of 10 is a multiple of 3.
Examples to illustrate, using powers of 10 not limited to multiples of 3 since this function is more general.
Complex Numbers
There's nothing specific for converting complex numbers to strings even though they are part of an IEEE standard library. They are just a pair of real values, but for convenience I offer these functions to mirror the to_string(real) ones.
Some quick examples for illustration:
Fixed Point Numbers
A couple of examples for ufixed and sfixed which fall back to using to_string(real). The point here is that by converting to the real type you have the printing options already, so the fixed point functions concentrate on printing the bit patterns. Note the discrepancy in the conversion of real to u/sfixed back to real caused by the limited resolution.
Time Values
Some quick examples for illustration:
Justification
Justifying text is limit to left or right, there is no center option. The justification function defaults to right justified, as quite simply there's limited point using it for right justification unless you want the padding of spaces to the right. Justification is also build into the write() functions too.
An example used in the Github source code is given here. The function right justifies the first string argument and left justifies the second.
This could also be written using the justify() function to concatenate strings to a single write() call:
The former feels more succinct in this case, but the justify() function has more general utility as it is not tied to writing to a line type. Examples to illustrate:
Conclusions
VHDL 2008 has improved the options available for formatting strings by providing for more types and more options for their formatting. Real values remain a pain for any sensible formatting as they are the ones requiring the most control, and the complex type was omitted. The justify() function is a welcome addition.