strings and tasks

Guest
Hi,

How do I use string constants with tasks, concatenating strings to print a message? My efforts so far have been unsuccessful. I currently have something like:

task mytask(input [1024 * 8:1] a_string);
begin
$display("String: %s", a_string);
end
endtask

mytask("a string for display");
mytask("another string for display");

I put the 1024 in the mytask prototype, becuase I thought this is what I'd need to do, but maybe there is a better way as this solution is not quite working. What gets displayed is "String: " followed by a big gap then the constant string I've passed. What I want printed is the two strings together, e.g. "String: a string for display"

Thx
 
On 7/4/2013 8:00 AM, crunchy.buscuits@gmail.com wrote:
Hi,

How do I use string constants with tasks, concatenating strings to print a message? My efforts so far have been unsuccessful. I currently have something like:

task mytask(input [1024 * 8:1] a_string);
begin
$display("String: %s", a_string);
end
endtask

mytask("a string for display");
mytask("another string for display");

I put the 1024 in the mytask prototype, becuase I thought this is what I'd need to do, but maybe there is a better way as this solution is not quite working. What gets displayed is "String: " followed by a big gap then the constant string I've passed. What I want printed is the two strings together, e.g. "String: a string for display"

Thx

I suspect there is an easier way to do this, but one workaround
is to pass the string's length as a second argument so then
you can do something like:

$display ("String: %s", a_string[str_len*8:1]);

--
Gabor
 
On 7/4/2013 8:56 AM, Gabor wrote:
On 7/4/2013 8:00 AM, crunchy.buscuits@gmail.com wrote:
Hi,

How do I use string constants with tasks, concatenating strings to
print a message? My efforts so far have been unsuccessful. I currently
have something like:

task mytask(input [1024 * 8:1] a_string);
begin
$display("String: %s", a_string);
end
endtask

mytask("a string for display");
mytask("another string for display");

I put the 1024 in the mytask prototype, becuase I thought this is what
I'd need to do, but maybe there is a better way as this solution is
not quite working. What gets displayed is "String: " followed by a big
gap then the constant string I've passed. What I want printed is the
two strings together, e.g. "String: a string for display"

Thx

I suspect there is an easier way to do this, but one workaround
is to pass the string's length as a second argument so then
you can do something like:

$display ("String: %s", a_string[str_len*8:1]);

It just occured to me that when the the string is shorter than the
input length (< 1024 characters in your case) the upper bits would
all be zero. So you don't actually have to pass the string length
to the function, you can find it by searching for a full byte of
zero in the input string. Something like:

reg str_len = 1024;
for (i = 1023;i > 0;i = i - 1)
if (a_string[i*8+1 +: 8]==0)
str_len = i;

--
Gabor
 
It just occured to me that when the the string is shorter than the

input length (< 1024 characters in your case) the upper bits would

all be zero. So you don't actually have to pass the string length

to the function, you can find it by searching for a full byte of

zero in the input string. Something like:



reg str_len = 1024;

for (i = 1023;i > 0;i = i - 1)

if (a_string[i*8+1 +: 8]==0)

str_len = i;



--

Gabor
Great stuff, thanks for the help.
 
On 05/07/13 08:11, crunchy.buscuits@gmail.com wrote:
It just occured to me that when the the string is shorter than the

input length (< 1024 characters in your case) the upper bits would

all be zero. So you don't actually have to pass the string length

to the function, you can find it by searching for a full byte of

zero in the input string. Something like:



reg str_len = 1024;

for (i = 1023;i > 0;i = i - 1)

if (a_string[i*8+1 +: 8]==0)

str_len = i;



--

Gabor

Great stuff, thanks for the help.
The other thing that might help is you can use $write, which doesn't put
a line feed on the end. Then add a '\n' to the last string you print,

regards
Alan

--
Alan Fitch
 
That gives me another idea. I don't know if $clog2() works for big numbers, but if it does, you could do something like this:


$display ("String: %s", a_string[$clog2(a_string):1]);
 
unfrostedpoptart wrote:
On Monday, July 8, 2013 11:08:29 AM UTC-7, Kevin Neilson wrote:
That gives me another idea. I don't know if $clog2() works for big numbers, but if it does, you could do something like this:
$display ("String: %s", a_string[$clog2(a_string):1]);

Kevin,

$clog2 is part of System Verilog. If you're using that, then you can use real string types and not have to mess with the 8*N:1 hack for putting ASCII in regs. Then you don't need all the work-arounds.

Here's some info online: http://testbench.in/SV_04_STRINGS.html

One problem I've run into with this, though, is displaying them in waveform viewers. The problem is that SV strings are dynamic and waveform viewers generally don't deal well with displaying things that can change size! I know there's been some progress on this but don't remember that latest word from Cadence or Synopsys. For just printing ($display/write), it's fine.

David
Actually $clog2 is in Verilog 2001 also, although synthesis support is
"spotty." Xilinx got it wrong in ISE 13.x using a natural log (base e)
instead of log base 2, then offering a workaraound function. However I
seem to recall that it operates on integers, which would be a problem in
this case. Still might be worth a try...

I assumed that SV would have real strings, but like many of us, my tools
at hand just don't support SV yet...

--
Gabor
 
On Monday, July 8, 2013 11:08:29 AM UTC-7, Kevin Neilson wrote:
That gives me another idea. I don't know if $clog2() works for big numbers, but if it does, you could do something like this:
$display ("String: %s", a_string[$clog2(a_string):1]);
Kevin,

$clog2 is part of System Verilog. If you're using that, then you can use real string types and not have to mess with the 8*N:1 hack for putting ASCII in regs. Then you don't need all the work-arounds.

Here's some info online: http://testbench.in/SV_04_STRINGS.html

One problem I've run into with this, though, is displaying them in waveform viewers. The problem is that SV strings are dynamic and waveform viewers generally don't deal well with displaying things that can change size! I know there's been some progress on this but don't remember that latest word from Cadence or Synopsys. For just printing ($display/write), it's fine.

David
 
Ah....

I thought the method of scanning the string for length was going to work for me, but I had some teething troubles with iverilog so didn't get round to finally properly trying it until today, with ModelSim.

However, ModelSim complains of the problem:

Range must be bounded by constant expressions.

So selecting part of a string with a variable seems to have its problems as well.
 
On Tuesday, July 9, 2013 9:48:26 AM UTC+1, crunchy....@gmail.com wrote:
Ah....



I thought the method of scanning the string for length was going to work for me, but I had some teething troubles with iverilog so didn't get round to finally properly trying it until today, with ModelSim.



However, ModelSim complains of the problem:



Range must be bounded by constant expressions.



So selecting part of a string with a variable seems to have its problems as well.
And this doesn't work either:

task mytask(input [1024 * 8:1] a_string, input integer len);
begin
$display("String: %s", a_string[len:1]);
end
endtask

i.e. providing string length as a task parameter.

ModelSim complains about the a_string[len:1] line as follows:

"Range must be bounded by constant expressions"
 
And this doesn't work either:



task mytask(input [1024 * 8:1] a_string, input integer len);

begin

$display("String: %s", a_string[len:1]);

end

endtask



i.e. providing string length as a task parameter.



ModelSim complains about the a_string[len:1] line as follows:



"Range must be bounded by constant expressions"
It's beginning to look like I'll have to live with gaps between my strings. Although not pretty, it's not a huge problem either, function is more important.

Thx
 
crunchy.buscuits@gmail.com wrote:
And this doesn't work either:



task mytask(input [1024 * 8:1] a_string, input integer len);

begin

$display("String: %s", a_string[len:1]);

end

endtask



i.e. providing string length as a task parameter.



ModelSim complains about the a_string[len:1] line as follows:



"Range must be bounded by constant expressions"

It's beginning to look like I'll have to live with gaps between my strings. Although not pretty, it's not a huge problem either, function is more important.

Thx
Since you seem to have an issue with the requirement of using a constant
string length, the usual way out of this mess is to write a loop. i.e.
instead of using a loop to find the string length (which should work)
you would instead use a loop to _print the string_ itself. This is
where $write comes in handy because it doesn't append a line-end.

for (i = 1023;i >= 0;i = i - 1)
if (a_string[i*8+1 +: 8]!=0) $write ("%s", a_string[i*8+1 +: 8]);

This will also strip out any nulls within the string, but you
wouldn't normally have those.

--
Gabor
 
ModelSim complains about the a_string[len:1] line as follows:

"Range must be bounded by constant expressions"
The alternate syntax may work:

a_string[1+:len]
 
$clog2 has worked in Synplify for years, but it's not surprising that it still doesn't work in XST, even though it's something you want in about every parameterizable module or anything with a RAM. The authors of XST assume every user loves to hard-code every number and instantiate all primitives using CoreGen. Before XST supported constant functions which allowed you to write your own clog2 function (or does it even now?), I had to make a really long kludgey `ifdef to do it.

Synplify supports quite a few SV constructs now.
 
That's cool; I didn't know about the string types. You may still want to use regs though if you want it to be synthesizable. (No, $display isn't synthesizable, but you may need to store strings in a ROM or something.) I haven't tried the string types with Modelsim but it seems to do well with enumerated types which have descriptors of different lengths.

Another SV construct which is synthesizable is the 'char' data type, which is essentially an 8-bit reg:

char [15:0] str = "My string";
 
On Tuesday, July 9, 2013 3:16:41 PM UTC+1, gabor wrote:

Thx

Since you seem to have an issue with the requirement of using a constant

string length, the usual way out of this mess is to write a loop. i.e.

instead of using a loop to find the string length (which should work)

you would instead use a loop to _print the string_ itself. This is

where $write comes in handy because it doesn't append a line-end.



for (i = 1023;i >= 0;i = i - 1)

if (a_string[i*8+1 +: 8]!=0) $write ("%s", a_string[i*8+1 +: 8]);



This will also strip out any nulls within the string, but you

wouldn't normally have those.



--

Gabor
It's now working, thanks.
 
On 09/07/13 18:20, Kevin Neilson wrote:
That's cool; I didn't know about the string types. You may still want to use regs though if you want it to be synthesizable. (No, $display isn't synthesizable, but you may need to store strings in a ROM or something.) I haven't tried the string types with Modelsim but it seems to do well with enumerated types which have descriptors of different lengths.

Another SV construct which is synthesizable is the 'char' data type, which is essentially an 8-bit reg:

char [15:0] str = "My string";
char, although present in the Accellera draft, was removed from the
final IEEE standard. It was replaced by byte, which is equivalent to

bit signed [7:0]

regards
Alan

P.S. of course if you want char back, just do

typedef byte char;



--
Alan Fitch
 
On 7/4/2013 5:00 AM, crunchy.buscuits@gmail.com wrote:
Hi,

How do I use string constants with tasks, concatenating strings to print
a message? My efforts so far have been unsuccessful. I currently have
something like:

task mytask(input [1024 * 8:1] a_string);
begin
$display("String: %s", a_string);
end
endtask

mytask("a string for display");
mytask("another string for display");


I put the 1024 in the mytask prototype, becuase I thought this is
what I'd need to do, but maybe there is a better way as this solution is
not quite working. What gets displayed is "String: " followed by a big gap
then the constant string I've passed. What I want printed is the two
strings together, e.g. "String: a string for display"
I normally use "%0s" for this, but I don't know how portable it is.

Cary
 
On Wednesday, July 10, 2013 3:42:01 AM UTC+1, Cary R. wrote:

I normally use "%0s" for this, but I don't know how portable it is.
Cool, that works. Tried it with ModelSim and Icarus Verilog and it works with both of those.
 
Use $display("String: %0s", a_string);

The "0" in there does what you want, I think.

On 07/04/2013 05:00 AM, crunchy.buscuits@gmail.com wrote:
Hi,

How do I use string constants with tasks, concatenating strings to print a message? My efforts so far have been unsuccessful. I currently have something like:

task mytask(input [1024 * 8:1] a_string);
begin
$display("String: %s", a_string);
end
endtask

mytask("a string for display");
mytask("another string for display");

I put the 1024 in the mytask prototype, becuase I thought this is what I'd need to do, but maybe there is a better way as this solution is not quite working. What gets displayed is "String: " followed by a big gap then the constant string I've passed. What I want printed is the two strings together, e.g. "String: a string for display"

Thx

--
Steve Williams "The woods are lovely, dark and deep.
steve at icarus.com But I have promises to keep,
http://www.icarus.com and lines to code before I sleep,
http://www.picturel.com And lines to code before I sleep."
 

Welcome to EDABoard.com

Sponsor

Back
Top