# for Loop Through String in VHDL

I'm trying to write a loop in VHDL that will print a certain message on an LCD screen.

I have predefined the following:

constant LCDHP  :integer range 0 to 1056:=  1056;--horizontal period
constant LCDHPW :integer range 0 to 30  :=  30  ;--horizontal pulse-width
constant LCDHBP :integer range 0 to 16  :=  16  ;--horizontal back-porch
constant LCDHFP :integer range 0 to 210 :=  210 ;--horizontal front-porch
constant LCDVP  :integer range 0 to 525 :=  525 ;--vertical period
constant LCDVPW :integer range 0 to 13  :=  13  ;--vertical pulse-width
constant LCDVBP :integer range 0 to 10  :=  10  ;--vertical back-porch
constant LCDVFP :integer range 0 to 22  :=  22  ;--vertical front-porch
type coordinate is record
H:integer range LCDHP'range;
V:integer range LCDVP'range;
end record;
constant TP:coordinate:=(H=>LCDHP-LCDHFP,V=>LCDVP-LCDVFP);--text-position
function char2ascii(char:character)return std_logic_vector is
begin
case char is
when'0'=>return conv_std_logic_vector(16,7);
when'1'=>return conv_std_logic_vector(17,7);
when'2'=>return conv_std_logic_vector(18,7);
when'3'=>return conv_std_logic_vector(19,7);
...
end function char2ascii;
constant message0:string(1 to 60):=   "Hello, I'm Doron Behar and I'm the developer of this project";


I will not deliver all the content of this file because it's very long and most of it is not relevant. Yet, I have managed to print text on the screen with a different method:

The standard (and simple) method is to write a asynchronous process. (It could also be written in a parallel way without a process and using when else) I'll show an example for the standard method:

process(pixel_row,pixel_column)
begin
if pixel_row>TP.H - 16 and pixel_row <= TP.H then
if pixel_column <= TP.V - 0 * 8 and pixel_column > TP.V - 1 * 8 then
char_code <= char2ascii(message0(1));
elsif pixel_column <= TP.V - 1 * 8 and pixel_column > TP.V - 2 * 8 then
char_code <= char2ascii(message0(2));
elsif pixel_column <= TP.V - 2 * 8 and pixel_column > TP.V - 3 * 8 then
char_code <= char2ascii(message0(3));
elsif--well you get the idea..
char_code <= ...;
else
char_code <= char2ascii(' ');
end if;
else
char_code <= char2ascii(' ');
end if;
end process;


This is not a smart way to print the text, it's good if the string is not long and it's working but in the case of a full sentence it's not very efficient because it requires to write 2*message'length (which is 120 in my example) lines for 1 message.

The solution I thought of was using a loop:

process(pixel_row,pixel_column)
begin
for i in message0 'range loop
if pixel_row>TP.H-16 and pixel_row<=TP.H then
if pixel_column<=TP.V-(i-1)*8 and pixel_column>TP.V-i*8 then
char_code<=char2ascii(message0(i));
else
char_code<=char2ascii(' ');
end if;
else
char_code<=char2ascii(' ');
end if;
end loop;
end process;


From some reason it just doesn't work! I'm not sure what is the reason why I see nothing on the screen while I can print text with the 1st method.

I've also tried using for generate:

txt:for i in message0'range generate
char_code<= char2ascii(message0(i)) when
pixel_row>TP.H-16 and pixel_row<=TP.H and pixel_column<=TP.V-(i-1)*8 and pixel_column>TP.V-i*8
else        char2ascii(' ');
end generate txt;


But I got the following errors:

Error (10028): Can't resolve multiple constant drivers for net "char_code[6]" at display-control.vhd(339)
Error (10029): Constant driver at display-control.vhd(339)
Error (10028): Can't resolve multiple constant drivers for net "char_code[5]" at display-control.vhd(339)
Error (10028): Can't resolve multiple constant drivers for net "char_code[3]" at display-control.vhd(339)
Error (10028): Can't resolve multiple constant drivers for net "char_code[2]" at display-control.vhd(339)
Error (10028): Can't resolve multiple constant drivers for net "char_code[1]" at display-control.vhd(339)
Error (10028): Can't resolve multiple constant drivers for net "char_code[0]" at display-control.vhd(339)


Is there something wrong with the way I treat the string's range? Is it even possible to do what I'm trying to do or should I think of a totally different method?

Any Help Appreciated :)

• You are saying your design is working, but how? Processes without sensitivity lists are not allowed in synthesis and driving a LC-Display bus without a clock won't work either... – Paebbels Feb 7 '16 at 18:00
• you are right @Paebbels, I've made an edit. I dropped off the sensitivity list originally in order to spare some of the content from the post. – Doron Behar Feb 8 '16 at 16:35

You don't want a loop here. But your process does need to generate i (the index into the message) from TP.V, probably through division by 8.

Something like:

process()
variable i : natural range 0 to LCDVP/8;
begin
if pixel_row>TP.H - 16 and pixel_row <= TP.H then
i := pixel_column / 8;
if i <= message0'high then
char_code <= char2ascii(message0(i));
else
char_code <= char2ascii(' ');
end if;
else
char_code <= char2ascii(' ');
end if;
end process;


You may object to the use of division in synthesis, but I've never seen a synthesis tool out there (this century at least) that can't make the obvious optimisation for a fixed division by 8.

I'll note the you are also making life unnecessarily hard for yourself with the declaration of char2ascii : its body should be pretty much a one-liner too.

• TP.V is constant. It doesn't make sense to write i:=TP.V/8 because it's just gonna make i equal to a certain number and that's it. – Doron Behar Feb 7 '16 at 17:49
• Details, details.... (Edited) – Brian Drummond Feb 7 '16 at 18:02