string データタイプ
 
stringは、新しいデータタイプで文字列を表します。文字列の長さを、シミュレーション中ダイナミックに変化させることができます。
stringは、変数を定義するときの"型"になります.。詳しく見る前に、文字列定数について見ていきます。

ストリングリテラル(文字列定数

クオート"" で挟まれた文字列を指します。
1)クオート""中のバックスラッシュ改行は、改行が無視されます
module string_literal_test;
 
 
         initial begin
		$display("今日は天気がよいので\
外で泳ぎましょう。");
		$display("今日は天気がよいので\n\
外で泳ぎましょう。");
 
	end
  
endmodule
 

実行結果です。最初の$displayでは、バックスラッシュ+改行になっており、ソースコードのディスプレイ上では、改行されますが、実行表示としては、
無視されます。実行上で改行させたいときは、\nと書きます。
***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

今日は天気がよいので外で泳ぎましょう。
今日は天気がよいので
外で泳ぎましょう。

---------- シミュレーションを終了します。time=0ns

2) 8ビットASCII文字単位で、変数に代入することが出来ます。
module string_literal_test;
 
	byte c = "A"; // assigns to c "A"
	integer c1 = "A";
 
	bit [5:0][7:0] d="ABCD";
	logic [2:0][7:0] e="ABCDE";
 
 
         initial begin
		$display("c=%s",c);
		$display("c=%s",c1);
		$display("d=%s %x",d,d);
		$display("e=%s %x",e,e);
	end
 
 
 
endmodule
 
 

結果です。
***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

c=A
c=   A
d=  ABCD 000041424344
e=CDE 434445

---------- シミュレーションを終了します。time=0ns
変数への代入は、右詰され、左側は、ゼロPAD、もしくは切捨てられます。

module string_test;
	logic [8*14:1] stringvar;
 
         initial begin
		stringvar = "Hello world";
		$display("%s is stored as %h", stringvar, stringvar);
		stringvar = {stringvar,"!!!"};
		$display("%s is stored as %h", stringvar, stringvar);
        
         end
endmodule
 
 
***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

   Hello world is stored as 00000048656c6c6f20776f726c64
Hello world!!! is stored as 48656c6c6f20776f726c64212121

---------- シミュレーションを終了します。time=0ns

3)ストリングリテラルの連接についての注意点

次のコードでは、結果は、等しくなりません。

module string_literal_concat;
	bit [8*10:1] s1, s2;
 
         initial begin
		s1 = "Hello";
		s2 = " world!";
		if ({s1,s2} == "Hello world!")
			$display("strings are equal");
		else $display("strings are not equal because  s1=%x s2=%x {s1,s2}=%x",s1,s2,{s1,s2});
        end
endmodule
***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

strings are not equal because  s1=000000000048656c6c6f s2=00000020776f726c6421 {s1,s2}=000000000048656c6c6f00000020776f726c6421

---------- シミュレーションを終了します。time=0ns

これは、ゼロパッドしているが故です。bit 幅は、コンパイル時に決定され固定していることに起因する問題です。このような場合は、string変数を使うとよいでしょう。

4)ストリングリテラルの16進直接指定

バックスラッシュxYY (YYは、16進二桁)で直接ASCIIコードを指定できます

module string_literal_test;
 
	byte c = "A"; // assigns to c "A"
	byte c1 = "\x41";
 
	bit [7:0][7:0] d="ABC\x00DEFG";
	string s1;
         initial begin
		$display("c=%s",c);
		$display("c=%s",c1);
		$display("d=%x",d);
 
		s1=string'(d);
		$display("s1=%s",s1);	
 
 
	end
 
 
 
endmodule
 
***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

c=A
c=A
d=4142430044454647
s1=ABCDEFG

---------- シミュレーションを終了します。time=0ns

string タイプ

1)stringは、regと違い、ゼロパッドされることはないので、直感的に自然な結果になります

module string_literal_concat;
	string s1, s2;
 
         initial begin
		s1 = "Hello";
		s2 = " world!";
		if ({s1,s2} == "Hello world!")
			$display("strings are equal %s",{s1,s2});
         end
endmodule
 


***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

strings are equal Hello world!

---------- シミュレーションを終了します。time=0ns

2)string 代入前初期値は、""空(長さ0の)のストリング,0の書き込みは、常に無視されます。

言語の内部実装には、Cのchar* になっていると思います。(DPIでのインターフェース仕様からの類推) しかし、Cのポインタの生存管理は、言語内でクローズしており,ユーザは意識する必要はありません。

module string_literal_test;
 
	byte c = "A"; // assigns to c "A"
	byte c1 = "\x41";
 
	bit [7:0][7:0] d="ABC\x00DEFG";
	string s1;
         initial begin
		$display("c=%s",c);
		$display("c=%s",c1);
		$display("d=%x",d);
 
                s1=string'(d);
		$display("s1=%s",s1);	
 
 
	end
 
 
 
endmodule
 


3) string以外の変数->string変換では、キャストが必要です

  ストリングリテラル -> string キャスト不要
  string         -> string キャスト不要

  を除いて、キャストが必要となります。ストリングへのキャストは、string'( ) です。
  
  ストリングへのキャスト操作は、次のようになります。
 

  1. ビット幅が8ビットの倍数でない場合は、8ビット倍数となるように左側が0パッドされます。
  2. ゼロバイナリのバイトは、スキップされます。(結果として空のストリングになる場合もあります。)
module cast_test;
 
 
	bit [7:0] a;
	byte b;
	shortint c;
	int		d;
	integer e;
	longint f;
	shortreal	g;
	real	h;
	realtime i;
	time	j;
	logic [131:0] l;
 
	string s="abcdefghijk";
 
         initial begin
		a=s;
		$display("a=%s",a);
		b=s;
		$display("b=%s",b);
		c=s;
		$display("c=%s",c);
		d=s;
		$display("d=%s",d);
		e=s;
		$display("e=%s",e);
		f=s;
		$display("f=%s",f);
 
		j=s;
		$display("j=%s",j);
		l=s;
		$display("l=%s",l);


//              g=s;//Compile Error//              h=s;//Compile Error//              i=s;//Compile Error
		$display("");
 
		s=string'(a);
		$display("s=%s",s);
		s=string'(b);
		$display("s=%s",s);
		s=string'(c);
		$display("s=%s",s);
		s=string'(d);
		$display("s=%s",s);
		s=string'(e);
		$display("s=%s",s);
		s=string'(f);
		$display("s=%s",s);
 
		s=string'(j);
		$display("s=%s",s);
		s=string'(l);
		$display("s=%s",s);
 
	end
 
 
 
endmodule


***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

a=k
b=k
c=jk
d=hijk
e=hijk
f=defghijk
j=defghijk
l=      abcdefghijk

s=k
s=k
s=jk
s=hijk
s=hijk
s=defghijk
s=defghijk
s=abcdefghijk

---------- シミュレーションを終了します。time=0ns

3) stringに関するオペレータ

使用可能なオペレータは、それほど多くありません。以下に限定されます。

オペレータ 意味
Str1 == Str2 二つのstringが一致するなら1、一致しないなら0を返します。オペランドのどちらかがストリング変数ならば、比較は、ストリングタイプとして、行われます。どちらもストリングリテラルであるなら、reg variable変数同士の比較と同じように行われます。
Str1 != Str2 不一致のときに1、一致のとき0が返ります。
Str1 < Str2
Str1 <= Str2
Str1 > Str2
Str1 >= Str2
c言語のstrcmpに同じです。条件が成立して==のときは、0が返ります。==でない条件成立のときは、正数が返ります。
不成立のときは、負数が返ります。 正数、負数は、かならずしも+1、-1ではありません。
{Str1,Str2,...,Strn} オペランドのどれかひとつでも、stringタイプなら stringに変換されて演算が行われます。
{multiplier{Str}} multiplierが定数でないか、Strがstringタイプであるときは、stringに変換されて演算が行われます。
Str[index] string は、内部的にインデクスが振られ0からNが振られています。(Nは、Str.len()-1)
str[0]は、最初の文字、 str[N]は最後の文字になります。
Str.method(...) string メンバー関数です。
module string_compare_and_concat_test;
 
 
	bit [7:0] a;
	byte b;
	shortint c;
	int		d;
	integer e;
	longint f;
	shortreal	g;
	real	h;
	realtime i;
	time	j;
	logic [131:0] l;
 
	string s="abcdefghijk";
 
 
         initial begin
		a=s;
		if (a==s) $display("Equal  %s %s",a,s);
		else $display("Not equal %s %s",a,s);
 
		if (a <s) $display("a<s");
                else if (a<=s) $display("a<=s");
                else if (a>s) $display("a>s");
                else if (a>=s) $display("a>=s");
 
		b=s;
		if (b==s)$display("Equal  %s %s",b,s);
		else $display("Not equal %s %s",b,s);
 
 
		c=s;
		if (c==s)$display("Equal  %s %s",c,s);
		else $display("Not equal %s %s",c,s);
 
 
		d=s;
		if (d==s)$display("Equal  %s %s",d,s);
		else $display("Not equal %s %s",d,s);
 
 
		e=s;
		if (e==s)$display("Equal  %s %s",e,s);
		else $display("Not equal %s %s",e,s);
 
 
		f=s;
		if (f==s)$display("Equal  %s %s",f,s);
		else $display("Not equal %s %s",f,s);
 
 
		j=s;
		if (j==s)$display("Equal  %s %s",j,s);
		else $display("Not equal %s %s",j,s);
 
 
		l=s;
		if (l==s)$display("Equal  %s %s",l,s);
		else $display("Not equal %s %s",l,s);
 
		if (l <s) $display("l<s");
                else if (l<=s) $display("l<=s");
                else if (l>s) $display("l>s");
                else if (l>=s) $display("l>=s");
 
 
		s="AB";
		$display("{s,a}=%s",{s,a});
		$display("{s,b}=%s",{s,b});
		$display("{s,c}=%s",{s,c});
		$display("{s,d}=%s",{s,d});
 
		$display("{s,e}=%s",{s,e});
		$display("{s,f}=%s",{s,f});
		$display("{s,j}=%s",{s,j});
		$display("{s,l}=%s",{s,l});
 
		repeat_f(0);	
 
	end
 
		function  automatic void repeat_f(int c);
			if (c==4) return;
			$display("%1d{s,a}=%s",c,{c{s,a}});
			repeat_f(c+1);
		endfunction
 
endmodule


上のベンチの結果です。

***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

Not equal k abcdefghijk
a>s
Not equal k abcdefghijk
Not equal jk abcdefghijk
Not equal hijk abcdefghijk
Not equal hijk abcdefghijk
Not equal defghijk abcdefghijk
Not equal defghijk abcdefghijk
Equal        abcdefghijk abcdefghijk
l<=s
{s,a}=ABk
{s,b}=ABk
{s,c}=ABjk
{s,d}=ABhijk
{s,e}=ABhijk
{s,f}=ABdefghijk
{s,j}=ABdefghijk
{s,l}=ABabcdefghijk
0{s,a}= 
1{s,a}=ABk
2{s,a}=ABkABk
3{s,a}=ABkABkABk

---------- シミュレーションを終了します。time=0ns


少し、注意する点を挙げます。

module cast_test;
	string a,b;
	reg [31:0] r;
	int i=3;
 
 initial begin
 
	b = {2{"H"}}; // OK
	$display("b=%s",b);
 
        a = {i{"H"}}; // OK (non-constant replication)
	$display("a=%s",a);
 
	//r = {i{"Hi"}}; // Compile Error
 
	a = {i{b}}; // OK
	$display("{i{b}}=%s",a);
	a = {a,b}; // OK
	$display("a=%s",a);
	a = {"ABC",b}; 
	$display("a=%s",a);
	r = {"H",""}; // ""は、8'b0に変換される。
	$display("r=%h",r);
 
	b = {"H",""}; // "" は、空ストリング
	$display("b=%s",b);
	a[0] = "i"; 
	$display("a=%s",a);
	a[0] =byte'(b); // キャストが必要
	$display("a=%s",a);
	a[1] = "\0"; // バイナリゼロの書き込みは、無視される。
	$display("a=%s",a);
end
 
 
endmodule
 

string に代入する場合は、

a = {i{"H"}};

のように、変数repeatが可能になります。これに対して、regに代入する場合は、コンパイル時にビット幅が確定しないので、コンパイルエラーとなります。

r = {i{"Hi"}}; // Compile Error

***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

b=HH
a=HHH
{i{b}}=HHHHHH
a=HHHHHHHH
a=ABCHH
r=00004800
b=H
a=iBCHH
a=HBCHH
a=HBCHH

---------- シミュレーションを終了します。time=0ns



4)stringのメンバー関数

メソッド 意味
function int len(); 長さを返します。stringが空(="")のときは、0が返ります。
function void putc(int i, byte c); str[i]=c;を実行します。 i < 0 または、 i >= str.len()のときは、strは、書き込まれません。.
また、c==0のときも、書き込まれません。
function byte getc(int i); str[i] を返します。 i < 0 または、 i >= str.len(),のときは、 0が返ります。
function string toupper(); 大文字に変換します。
function string tolower(); 小文字に変換します。
function int compare(string s); C言語のstrcmpに同じです。
function int icompare(string s); 大文字、小文字を無視したcompareです。
function string substr(int i, int j); str.substr(i, j) は、str[i:j]を返します。
i < 0, j < i, or j >= str.len(), のときは、""空stringが返ります。
function integer atoi();
function integer atohex();
function integer atooct();
function integer atobin();
atoi:ASCIIデシマルストリングをintegerl型に変換した結果を返します。
atohex:ASCIIHexストリングをintegerl型に変換した結果を返します。
atooct:ASCIIHexストリングをintegerl型に変換した結果を返します。
atobin:ASCIIBinaryストリングをintegerl型に変換した結果を返します。

これらの関数は、32ビットで打ち切りになります。32ビットより大きいときは、$sscanfを使ってください。
function real atoreal(); ASCIIデシマルストリングをreal型に変換した結果を返します。
function void itoa(integer i); integer型iをDecimalストリング(0-9)に変換します。
function void hextoa(integer i); integer型iをHexストリング(0-f)に変換します。
function void octtoa(integer i); integer型iをOctalストリング(0-7)に変換します。
function void bintoa(integer i); integer型iを0/1ストリングに変換します。
function void realtoa(real r); real型rをストリングに変換します。


上記のビルトイン関数を使って、パターンマッチングする例2種です。下記を参照しました。
http://www.testbench.in/SV_04_STRINGS.html
http://hitorilife.com/match.php

C言語並に手軽に書けることが分かります。

 
 
module string_match;
 
    string str1,str2;
 
 
    
    initial begin
	 //include pattern matching
        str1 = "今日は、晴れ です。";
        str2 = "今日";
        if(match(str1,str2))
            $display(" str2 : %s : found in :%s:",str2,str1);
 
        str1 = "今日は、晴れ です。";
        str2 = "晴れ";
        if(match(str1,str2))
            $display(" str2 : %s : found in :%s:",str2,str1);
 
        str1 = "今日は、晴れ です。";
        str2 = "です。";
        if(match(str1,str2))
            $display(" str2 : %s : found in :%s:",str2,str1);
 
        str1 = "今日は、晴れ です。";
        str2 = "今日は、";
        if(match(str1,str2))
            $display(" str2 : %s : found in :%s:",str2,str1);
 
        str1 = "今日は、晴れ です。";
        str2 = "晴れ です。";
        if(match(str1,str2))
            $display(" str2 : %s : found in :%s:",str2,str1);
 
	//*? pattern matching
	 $display("");
 
       str1="abcde.tx";
	 str2="abcde.txt";
	 match_check(str1,str2);
 
 
   	 str1="*";
	 str2="abcde.txt";
	 match_check(str1,str2);
 
 	 str1="*.*";
	 str2="abcde.txt";
	 match_check(str1,str2);
 
 
	 str1="abcde.??";
	 str2="abcde.txt";
	 match_check(str1,str2);
 
	 str1="abcde.???";
	 str2="abcde.txt";
	 match_check(str1,str2);
 
    end
 
    function  automatic bit match(string s1,s2);
       int l1,l2;
       l1 = s1.len();
       l2 = s2.len();
 
 
       match = 0 ;
       if( l2 > l1 )
           return 0;
       for(int i = 0;i < l1 - l2 + 1; i ++)
           if( s1.substr(i,i+l2 -1) == s2)
               return 1;
   endfunction
 
	function   automatic void match_check( ref string s1,s2);
		if (match2(str1,str2))  $display(" マッチしました。  str1=%s : str2=%s:",str1,str2);
	  	else $display("マッチしません。 str1=%s  : str2=%s",str1,str2);        
	endfunction
 
	function  automatic bit match2(string s1,s2);
		//For Debug $display("%s %s",s1,s2);
		if (!s1.len()  &&!s2.len()) return 1;
		//?
		if (s1.getc(0)=="?") 	if (!s2.len()) return 0;
		else begin
			return match2(s1.substr(1,s1.len()-1),s2.substr(1,s2.len()-1));
		end
		//* 
		if (s1.getc(0)=="*") begin
			if (!s2.len()) 	return match2(s1.substr(1,s1.len()-1),s2);	
			else begin
				if (match2(s1.substr(1,s1.len()-1),	s2)) return 1;
                                else return match2(s1,s2.substr(1,s2.len()-1));
                             
                endend
		if (s1.getc(0)==s2.getc(0 )) return match2(s1.substr(1,s1.len()-1),s2.substr(1,s2.len()-1));
		return 0;
        
endfunction
endmodule
 
 
***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

 str2 : 今日 : found in :今日は、晴れ です。:
 str2 : 晴れ : found in :今日は、晴れ です。:
 str2 : です。 : found in :今日は、晴れ です。:
 str2 : 今日は、 : found in :今日は、晴れ です。:
 str2 : 晴れ です。 : found in :今日は、晴れ です。:

マッチしません。 str1=abcde.tx  : str2=abcde.txt
 マッチしました。  str1=* : str2=abcde.txt:
 マッチしました。  str1=*.* : str2=abcde.txt:
マッチしません。 str1=abcde.??  : str2=abcde.txt
 マッチしました。  str1=abcde.??? : str2=abcde.txt:

---------- シミュレーションを終了します。time=0ns

5)システムタスク

システムタスク名 task/function 意味
$swrite(output_str, list_of_arguments );
$swriteb(output_str, list_of_arguments );
$swriteo(output_str, list_of_arguments );
$swriteh(output_str, list_of_arguments );
task output_strに指定フォーマットで読み取ります。フォーマット指定は、どこにあってもよいのですが、"%d %s"等の定数フォーマットでなければなりません。
$sformat ( output_str , format_string , list_of_arguments ) ; task output_strにformat_string(2ndパラメータに限定されます。)で指定されるフォーマットで書き込みます。format_strは、"%d %s"等の定数に限定されず、stringも使用することが出来ます。
$sformatf ( format_string , list_of_arguments ) ; function $sformatのfunction版で戻り値がstring になります。
$psprintfは、LRM(P1800-2009)では定義されておらずvendor uniqueです。$sformatfを使ってください。
$sscanf ( str , format , args ) function format指定で、strをスキャンします。読み込みに成功した個数が戻り値として返ります。
module string_literal_test;
 
	logic [79:0] a;
	parameter pformat="S/N%h %b %3d %s";
	string format=pformat;
	string str,result;
	logic [8*13:1] r1;
	byte b;
	int c;
	string comment;
 
         initial begin
 
 
		str="S/Nbeafdeadabcd1234 01001010 100 コメントなし";
 
 
		$sscanf(str,"S/N%h %b %3d %s",a,b,c,comment);
		$display(     "S/N%h %b %3d %s",a,b,c,comment);
 
		$sscanf(str,format,a,b,c,comment);
		$display("S/N%h %b %3d %s",a,b,c,comment);
 
		$sformat(result,format,a,b,c,comment);
		$display("%s",result);
 
		$swrite(result,pformat,a,b,c,comment);
		$display("%s",result);
 
 
		my_log($sformatf(format,a,b,c,comment));
		my_log( convert2string(c,c+1));
 
 
	end
 
	function void my_log( inputstring s);
		$display("time=%0t %s",$time,s);
 
	endfunction
 
	function    automatic string convert2string( inputint address, int data);
		return $sformatf("%3d :%3d",address,data);
	endfunction
 
 
endmodule
 
***** Veritak SV Engine Version 0.423 Build Jul.7.2011 *****

S/N0000beafdeadabcd1234 01001010 100 コメントなし
S/N0000beafdeadabcd1234 01001010 100 コメントなし
S/N0000beafdeadabcd1234 01001010 100 コメントなし
S/N0000beafdeadabcd1234 01001010 100 コメントなし
time=0 S/N0000beafdeadabcd1234 01001010 100 コメントなし
time=0 100 :101

---------- シミュレーションを終了します。time=0ns