Published:

This article shows how to work with strings containing line breaks in VHDL. Read on to learn how to split long lines in your VHDL code, print text containing newline characters, and how VHDL differs from regular programming languages regarding non-printing control characters in strings.

Splitting string literals in the VHDL code

Sometimes you want to define a long line of text as a string constant or variable while keeping your VHDL code lines short, and that’s easy to do. You can split long and unruly text lines by using the ampersand & concatenation operator:

constant quote : string := "VHDLwhiz helps you understand " &
  "advanced concepts within FPGA design without being overly technical.";

When printing the quote constant during simulation, the two string literals appear as one long line:

# VHDLwhiz helps you understand advanced concepts within FPGA design without being overly technical.

Adding a newline character to a string

This section shows how to add a line feed character in your string to produce a line break once you print the string during simulation.

Line breaks are made up of control characters that differ between systems. Fortunately, VHDL makes it easy to do with its dedicated LF line feed character:

constant banner : string :=
  "__      ___    _ _____  _             _     _     " & LF &
  "\ \    / / |  | |  __ \| |           | |   (_)    " & LF &
  " \ \  / /| |__| | |  | | |  __      _| |__  _ ____" & LF &
  "  \ \/ / |  __  | |  | | |  \ \ /\ / / '_ \| |_  /" & LF &
  "   \  /  | |  | | |__| | |___\ V  V /| | | | |/ / " & LF &
  "    \/   |_|  |_|_____/|______\_/\_/ |_| |_|_/___|";

When printed to the simulator console, the LF characters translate into line breaks:

# __      ___    _ _____  _             _     _     
# \ \    / / |  | |  __ \| |           | |   (_)    
#  \ \  / /| |__| | |  | | |  __      _| |__  _ ____
#   \ \/ / |  __  | |  | | |  \ \ /\ / / '_ \| |_  /
#    \  /  | |  | | |__| | |___\ V  V /| | | | |/ / 
#     \/   |_|  |_|_____/|______\_/\_/ |_| |_|_/___|

According to the VHDL Language Reference Manual, the LF character shall translate into the representation of the end of a line on whatever system you are running. Thus, the LF character may produce slightly different log files between operating systems.

For completeness, let’s see what happens if we use the "\r\n" sequence instead, which means carriage return + line feed (CR+LF) in many programming languages:

constant banner_not_working : string :=
  "__      ___    _ _____  _             _     _     \r\n" &
  "\ \    / / |  | |  __ \| |           | |   (_)    \r\n" &
  " \ \  / /| |__| | |  | | |  __      _| |__  _ ____\r\n" &
  "  \ \/ / |  __  | |  | | |  \ \ /\ / / '_ \| |_  /\r\n" &
  "   \  /  | |  | | |__| | |___\ V  V /| | | | |/ / \r\n" &
  "    \/   |_|  |_|_____/|______\_/\_/ |_| |_|_/___|";

It doesn’t work because VHDL doesn’t treat the backslash as an escape sequence. Instead, they are printed literally to the simulator console:

# __      ___    _ _____  _             _     _     \r\n\ \    / / |  | |  __ \| |           | |   (_)    \r\n \ \  / /| |__| | |  | | |  __      _| |__  _ ____\r\n  \ \/ / |  __  | |  | | |  \ \ /\ / / '_ \| |_  /\r\n   \  /  | |  | | |__| | |___\ V  V /| | | | |/ / \r\n    \/   |_|  |_|_____/|______\_/\_/ |_| |_|_/___|

Printing a single line in VHDL

And finally, when printing using the report statement or the writeline procedure, a newline always follows the printed text. For example, after importing use std.textio.all; at the top of the VHDL file, we can define this procedure that prints a string to the simulator console:

procedure print(msg : string) is
  variable l : line;
begin
  write(l, msg);
  writeline(output, l);
end procedure;

Then we could call the new print procedure once for each string we want to print on an individual line:

print("__      ___    _ _____  _             _     _     ");
print("\ \    / / |  | |  __ \| |           | |   (_)    ");
print(" \ \  / /| |__| | |  | | |  __      _| |__  _ ____");
print("  \ \/ / |  __  | |  | | |  \ \ /\ / / '_ \| |_  /");
print("   \  /  | |  | | |__| | |___\ V  V /| | | | |/ / ");
print("    \/   |_|  |_|_____/|______\_/\_/ |_| |_|_/___|");

That would have the same effect as calling print on the banner constant we defined earlier, containing the LF line breaks:

print(banner);

The output to the simulator console in both cases is:

# __      ___    _ _____  _             _     _     
# \ \    / / |  | |  __ \| |           | |   (_)    
#  \ \  / /| |__| | |  | | |  __      _| |__  _ ____
#   \ \/ / |  __  | |  | | |  \ \ /\ / / '_ \| |_  /
#    \  /  | |  | | |__| | |___\ V  V /| | | | |/ / 
#     \/   |_|  |_|_____/|______\_/\_/ |_| |_|_/___|

Summary

  • Ampersand & is the string concatenation operator in VHDL
  • LF is VHDL’s line feed/newline/end of line/EOL character
  • The backslash “\” character has no special meaning in string literals
  • The report statement and TEXTIO’s writeline procedure produce a newline after the printed text

Author: Jonas Julian Jensen

I’m from Norway, but I live in Bangkok, Thailand. Before I started VHDLwhiz, I worked as an FPGA engineer in the defense industry. I earned my master’s degree in informatics at the University of Oslo.

Leave a Reply

Your email address will not be published.