12.システムタスク
$xxxで、シミュレータに組み込み済みのタスクまたは、ファンクションをシステムタスク/システムファンクションといいます。Verilog2001になって、「こういうのが欲しい」というのは、大抵あります。
システムタスクの呼び出しはstatementに属します。
<system_task_enable>
::= <name_of_system_task> ;
||= <name_of_system_task> ( <expression> <,<expression>>* ) ;
一方、システムファンクションの呼び出しは、expressionに属します。
<function_call> ::= <name_of_function> ( <expression> <,<expression>>* ) ||= <name_of_system_function> ( <expression> <,<expression>>* ) ||= <name_of_system_function>
12.1 Conversion Function
12.1.1 real 系の変換ファンクションとして次があります。
ファンクション名 | 戻り値 | 機能 |
$realtobits | [63:0] | real 型を引数にして、ビットベクタに変換します。ビットベクタイメージは、IEEE
Std 754-1985で、C言語のdoubleと等価です。 Verilogでは、REAL型のままポート宣言で渡すことはできません。REAL変数を他のmodule、funciton,task等に引き渡したいときにこのFunctionで変換してやります。 (下記サンプル参照) |
$bitstoreal | real | 上記の反対です。 |
$itor | real | ビットベクタをREALに変換します。 |
$rtoi | [31:0] | REALをビットベクタに変換します。変換はC言語と同様、小数点以下は、切捨てです。 |
Note1:Veritak実装では、32ビットIntegerより大きい数の変換は不定となります。
Note2:Veritak実装では、32ビットIntegerより大きい数の変換は不定です。
<例>
module driver (net_r);
output net_r;
real r;
wire [63:0] net_r = $realtobits (r);
endmodule
module receiver (net_r);
input net_r;
wire [63:0] net_r;
real r;
always @* r = $bitstoreal (net_r);
endmodule
12.1.2 符号の変換(Verilog2001)
$signed 戻り値は、signedになります。
$unsigned 戻り値は、 unsignedになります。
<例>
reg [7:0] regA;
reg signed [7:0] regS;
regA = $unsigned (-4); // regA は 4'b1100になります。
regS = $signed (4'b1100); // regS は -4になります。
12.2 Debug Use task($display,$fdisplay,$strobe,$monitor,$fmonitor)
12.2.1 $display
12.2.2 $write
次の例は、EXCEL読み込み用に、2次元メモリの内容を、コンマセパレートの10進符号付テキストファイルを書く例です。
$writeは、$dsiplayから改行コードを除いたものです。
task save_data_to_file; begin fi=$fopen(Eye_Save_Data_File); for (i=0;i<samples_per_scan;i=i+1) begin for (j=0;j< max_columns;j=j+1) begin if (j==0) $fwrite(fi,"%d ",$signed(saved_wave[i][j])); else if (j==max_columns-1) $fdisplay(fi,", %d ",$signed(saved_wave[i][j])); else $fwrite(fi,",%d",$signed(saved_wave[i][j])); end end $fclose(fi); end endtask |
12.2.3 $strobe
$strobe は、その時刻の最終的な確定値(つまり、次の時刻に移る直前に値をサンプル)をモニタします。
例
forever @(negedge clock) $strobe ("At time %d, data is %h",time ,data); |
module strobe_test; reg a; wire b=~a; initial begin $strobe("strobing a=%b b=%b time=%t",a,b,$time); a=0; #0; a=1; $display("displaying a=%b b=%b",a,b); end endmodule |
実行結果です。
displaying a=1 b=1 strobing a=1 b=0 time= 0 |
この性質は、継続代入文のモニタや、ASICでの提出パターンを作るときに重宝します。
12.2.4 $monitor
変化点を$displayと同じように出力します。
例です。
//Nov.16.2004 realtime variable delay regression test //Nov.19.2004 real parameter net delay //Feb.3.2005 `timescale 1ns/1ps module real_delay_test; parameter net_real_delay=3.1;//3.345; real tp; reg [7:0] a,b; integer i; integer a_addr=2022,b_addr=222; real rdelay; wire [7:0] #(net_real_delay) wb=a; reg [7:0] mem [0:2035][0:223]; initial begin rdelay=1.1; $monitor("a=%b wb=%b time=%f ",a,wb,$realtime); tp=10.11; i=tp; b=5; a<=#(tp) b; #(10.110); #(0.002); a=8'hff; #(10); a=8'h00; //new monitor for memory word #100; $monitor("new monitor1 :mem[%d][%d]=%b time=%f",a_addr,b_addr,mem[a_addr][b_addr],$realtime); for (i=0;i<8; i=i+2) begin mem[a_addr][b_addr][i +:2]=2'b11; #10; end //new monitor for memory bit on certain word #100; $monitor("new monitor 2 :mem[%d][%d][7]=%b time=%f",a_addr,b_addr,mem[a_addr][b_addr][7],$realtime); for (i=0;i<8; i=i+1) begin mem[a_addr][b_addr][i ]=0; #10; end //monitor off for moment $display("monitor off"); $monitoroff; for (i=0;i<8; i=i+2) begin mem[a_addr][b_addr][i +:2]=2'b11; #10; end //monitor on again $monitoron; $display("monitor on again"); for (i=0;i<8; i=i+1) begin mem[a_addr][b_addr][i ]=0; #10; end end endmodule |
実行結果です。$monitorが発行された時刻と、その後の変化点で、出力している様子がわかります。
$monitorは、新しい$monitorが発行されるとそれまでのモニタは破棄されて、新しいmonitorのみに対応します。
$monitoroffでお休みし$monitoronで再開します。
例にあるように、メモリのあるワードのあるビットをモニタすることもできるので、便利かつ強力なデバッグ機能です。
F:\regression_test\monitor_test.v(5)::real_delay_test Verilogのシミュレーションの準備が完了しました。スタートは,Goボタンを押してください。 ------------- シミュレーションを開始します。-------------------- a=xxxxxxxx wb=xxxxxxxx time=0.000000 a=00000101 wb=xxxxxxxx time=10.110000 a=11111111 wb=xxxxxxxx time=10.112000 a=11111111 wb=xxxxx1x1 time=13.210000 a=11111111 wb=11111111 time=13.212000 a=00000000 wb=11111111 time=20.112000 a=00000000 wb=00000000 time=23.212000 new monitor1 :mem[ 2022][ 222]=xxxxxx11 time=120.112000 new monitor1 :mem[ 2022][ 222]=xxxx1111 time=130.112000 new monitor1 :mem[ 2022][ 222]=xx111111 time=140.112000 new monitor1 :mem[ 2022][ 222]=11111111 time=150.112000 new monitor 2 :mem[ 2022][ 222][7]=1 time=260.112000 new monitor 2 :mem[ 2022][ 222][7]=0 time=330.112000 monitor off monitor on again new monitor 2 :mem[ 2022][ 222][7]=1 time=380.112000 new monitor 2 :mem[ 2022][ 222][7]=0 time=450.112000 ---------- シミュレーションを終了します。time=460---------- |
ファイルに出力させる例です。$fmonitorは、古いmonitorは、破棄されません。$monitoron、$monitoroffは利かないので、$fmonitorを止めたいときは、$fcloseしてしまいます。
次の例は、monitorの結果をファイル(monitor.txt)にアペンドしていく例です。
//Nov.16.2004 realtime variable delay regression test //Nov.19.2004 real parameter net delay //Feb.3.2005 `timescale 1ns/1ps module real_delay_test; parameter net_real_delay=3.1;//3.345; real tp; reg [7:0] a,b; integer i; integer a_addr=2022,b_addr=222; real rdelay; wire [7:0] #(net_real_delay) wb=a; reg [7:0] mem [0:2035][0:223]; integer fp=1; initial begin :monitor #0; rdelay=1.1; fp=$fopen("monitor.txt","a");//append mode if(!fp) begin $display("can not open the file \"monitor.txt \""); disable monitor;//break the block end $fmonitor(fp,"a=%b wb=%b time=%f ",a,wb,$realtime); tp=10.11; i=tp; b=5; a<=#(tp) b; #(10.110); #(0.002); a=8'hff; #(10); a=8'h00; //new monitor for memory word #100; $fmonitor(fp,"new monitor1 :mem[%d][%d]=%b time=%f",a_addr,b_addr,mem[a_addr][b_addr],$realtime); for (i=0;i<8; i=i+2) begin mem[a_addr][b_addr][i +:2]=2'b11; #10; end //new monitor for memory bit on certain word #100; $fmonitor(fp,"new monitor 2 :mem[%d][%d][7]=%b time=%f",a_addr,b_addr,mem[a_addr][b_addr][7],$realtime); for (i=0;i<8; i=i+1) begin mem[a_addr][b_addr][i ]=0; #10; end //monitor off for moment $fdisplay(fp,"monitor off");//not work for fmonitor $monitoroff; for (i=0;i<8; i=i+2) begin mem[a_addr][b_addr][i +:2]=2'b11; #10; end //monitor on again $monitoron; $fdisplay(fp,"monitor on again"); for (i=0;i<8; i=i+1) begin mem[a_addr][b_addr][i ]=0; #10; end a=8'haa; $fdisplay(fp,"closing fmonitor"); $fclose(fp); //no fmonitor is available for (i=0;i<8; i=i+2) begin mem[a_addr][b_addr][i +:2]=2'b11; #10; end for (i=0;i<8; i=i+1) begin mem[a_addr][b_addr][i ]=0; #10; end end endmodule |
実行結果です。fminotor.txtの中身です。
a=xxxxxxxx wb=xxxxxxxx time=0.000000 a=00000101 wb=xxxxxxxx time=10.110000 a=11111111 wb=xxxxxxxx time=10.112000 a=11111111 wb=xxxxx1x1 time=13.210000 a=11111111 wb=11111111 time=13.212000 a=00000000 wb=11111111 time=20.112000 a=00000000 wb=00000000 time=23.212000 new monitor1 :mem[ 2022][ 222]=xxxxxx11 time=120.112000 new monitor1 :mem[ 2022][ 222]=xxxx1111 time=130.112000 new monitor1 :mem[ 2022][ 222]=xx111111 time=140.112000 new monitor1 :mem[ 2022][ 222]=11111111 time=150.112000 new monitor 2 :mem[ 2022][ 222][7]=1 time=260.112000 new monitor1 :mem[ 2022][ 222]=11111110 time=260.112000 new monitor1 :mem[ 2022][ 222]=11111100 time=270.112000 new monitor1 :mem[ 2022][ 222]=11111000 time=280.112000 new monitor1 :mem[ 2022][ 222]=11110000 time=290.112000 new monitor1 :mem[ 2022][ 222]=11100000 time=300.112000 new monitor1 :mem[ 2022][ 222]=11000000 time=310.112000 new monitor1 :mem[ 2022][ 222]=10000000 time=320.112000 new monitor 2 :mem[ 2022][ 222][7]=0 time=330.112000 new monitor1 :mem[ 2022][ 222]=00000000 time=330.112000 monitor off new monitor1 :mem[ 2022][ 222]=00000011 time=340.112000 new monitor1 :mem[ 2022][ 222]=00001111 time=350.112000 new monitor1 :mem[ 2022][ 222]=00111111 time=360.112000 new monitor1 :mem[ 2022][ 222]=11111111 time=370.112000 new monitor 2 :mem[ 2022][ 222][7]=1 time=370.112000 monitor on again new monitor1 :mem[ 2022][ 222]=11111110 time=380.112000 new monitor1 :mem[ 2022][ 222]=11111100 time=390.112000 new monitor1 :mem[ 2022][ 222]=11111000 time=400.112000 new monitor1 :mem[ 2022][ 222]=11110000 time=410.112000 new monitor1 :mem[ 2022][ 222]=11100000 time=420.112000 new monitor1 :mem[ 2022][ 222]=11000000 time=430.112000 new monitor1 :mem[ 2022][ 222]=10000000 time=440.112000 new monitor 2 :mem[ 2022][ 222][7]=0 time=450.112000 new monitor1 :mem[ 2022][ 222]=00000000 time=450.112000 closing fmonitor |
これを利用して、コンソールにだすこともできます。コンソールは、1番に割り振られています。ただし、クローズはできません。
//Nov.16.2004 realtime variable delay regression test //Nov.19.2004 real parameter net delay //Feb.3.2005 `timescale 1ns/1ps module real_delay_test; parameter net_real_delay=3.1;//3.345; real tp; reg [7:0] a,b; integer i; integer a_addr=2022,b_addr=222; real rdelay; wire [7:0] #(net_real_delay) wb=a; reg [7:0] mem [0:2035][0:223]; integer fp=1; initial begin :monitor #0; rdelay=1.1; fp=1;//Use console if(!fp) begin $display("can not open the file \"monitor.txt \""); disable monitor;//break the block end $fmonitor(fp,"a=%b wb=%b time=%f ",a,wb,$realtime); tp=10.11; i=tp; b=5; a<=#(tp) b; #(10.110); #(0.002); a=8'hff; #(10); a=8'h00; //new monitor for memory word #100; $fmonitor(fp,"new monitor1 :mem[%d][%d]=%b time=%f",a_addr,b_addr,mem[a_addr][b_addr],$realtime); for (i=0;i<8; i=i+2) begin mem[a_addr][b_addr][i +:2]=2'b11; #10; end //new monitor for memory bit on certain word #100; $fmonitor(fp,"new monitor 2 :mem[%d][%d][7]=%b time=%f",a_addr,b_addr,mem[a_addr][b_addr][7],$realtime); for (i=0;i<8; i=i+1) begin mem[a_addr][b_addr][i ]=0; #10; end //monitor off for moment $fdisplay(fp,"monitor off");//not work for fmonitor $monitoroff; for (i=0;i<8; i=i+2) begin mem[a_addr][b_addr][i +:2]=2'b11; #10; end //monitor on again $monitoron; $fdisplay(fp,"monitor on again"); for (i=0;i<8; i=i+1) begin mem[a_addr][b_addr][i ]=0; #10; end a=8'haa; end endmodule |
実行結果です。
F:\regression_test\monitor_test3.v(5)::real_delay_test Verilogのシミュレーションの準備が完了しました。スタートは,Goボタンを押してください。 ------------- シミュレーションを開始します。-------------------- a=xxxxxxxx wb=xxxxxxxx time=0.000000 a=00000101 wb=xxxxxxxx time=10.110000 a=11111111 wb=xxxxxxxx time=10.112000 a=11111111 wb=xxxxx1x1 time=13.210000 a=11111111 wb=11111111 time=13.212000 a=00000000 wb=11111111 time=20.112000 a=00000000 wb=00000000 time=23.212000 new monitor1 :mem[ 2022][ 222]=xxxxxx11 time=120.112000 new monitor1 :mem[ 2022][ 222]=xxxx1111 time=130.112000 new monitor1 :mem[ 2022][ 222]=xx111111 time=140.112000 new monitor1 :mem[ 2022][ 222]=11111111 time=150.112000 new monitor 2 :mem[ 2022][ 222][7]=1 time=260.112000 new monitor1 :mem[ 2022][ 222]=11111110 time=260.112000 new monitor1 :mem[ 2022][ 222]=11111100 time=270.112000 new monitor1 :mem[ 2022][ 222]=11111000 time=280.112000 new monitor1 :mem[ 2022][ 222]=11110000 time=290.112000 new monitor1 :mem[ 2022][ 222]=11100000 time=300.112000 new monitor1 :mem[ 2022][ 222]=11000000 time=310.112000 new monitor1 :mem[ 2022][ 222]=10000000 time=320.112000 new monitor 2 :mem[ 2022][ 222][7]=0 time=330.112000 new monitor1 :mem[ 2022][ 222]=00000000 time=330.112000 monitor off new monitor1 :mem[ 2022][ 222]=00000011 time=340.112000 new monitor1 :mem[ 2022][ 222]=00001111 time=350.112000 new monitor1 :mem[ 2022][ 222]=00111111 time=360.112000 new monitor1 :mem[ 2022][ 222]=11111111 time=370.112000 new monitor 2 :mem[ 2022][ 222][7]=1 time=370.112000 monitor on again new monitor1 :mem[ 2022][ 222]=11111110 time=380.112000 new monitor1 :mem[ 2022][ 222]=11111100 time=390.112000 new monitor1 :mem[ 2022][ 222]=11111000 time=400.112000 new monitor1 :mem[ 2022][ 222]=11110000 time=410.112000 new monitor1 :mem[ 2022][ 222]=11100000 time=420.112000 new monitor1 :mem[ 2022][ 222]=11000000 time=430.112000 new monitor1 :mem[ 2022][ 222]=10000000 time=440.112000 new monitor 2 :mem[ 2022][ 222][7]=0 time=450.112000 new monitor1 :mem[ 2022][ 222]=00000000 time=450.112000 a=10101010 wb=00000000 time=460.112000 a=10101010 wb=10101010 time=463.212000 ---------- シミュレーションを終了します。time=463---------- |
12.2.5 $timeformat
文法
timeformat_task ::= $timeformat [ ( units_number , precision_number , suffix_string , minimum_field_width ) ] ;
説明
・unit_numberは、単位です。0から-15までの数字です。-6なら、1us, -9なら1ns, -12なら 1psという具合です。
・precision_number は、小数点以下の桁数 これは、あくまで表示のための桁数であって、
シミュレーション分解能を指定するものではありません。 シミュレーション分解能は 、`timescale で設定した値になります。
・suffix_string は、好きなストリング文字を書きます。なににするかは自由ですが、unit_numberを-9にしたら、"ns" もしくは "nsec"にするのがよいでしょう。
一旦設定すると$display系の%tで、指定フォーマットで出力するようになります。
<斜め文字部はVeritak Uniqueです。>
Veritakでは、nsecや、psecをKEYワードにして時刻データをエディタが判別しています。ダブルクリックで波形に飛ぶには、
以下のようなフォーマットのいずれかを使ってください。
//Reasonable formats are
//$timeformat(-9, integer,"nsec",integer);
//$timeformat(-12,integer ,"psec",integer);
//$timeformat(-6,integer,"usec",integer);
//$timeformat(-3,integer,"msec",integer);
・minimum_field_widthは、表示桁数です。
サンプル
実行結果
Veritak Project のダウンロード(3.39D以上)
12.3 メモリ読み込み($readmemh ,$readmemb);
$readmemhは、16進、$readmembは、2進のテキストファイル読み込みタスクです。
reg [7:0] mem[1:256]; initial $readmemh ("mem.data", mem);//start addressが書いていないときは、左address、この場合[1]から右address[256]に向かって読み取られる。 initial $readmemh ("mem.data", mem, 16);//end addressが書いていないときは、start addressから、右address[256]に向かって読み取られる。 initial $readmemh ("mem.data", mem, 128, 1);//start address end address が書いてあるときは、start addressを始点として、end addressに向かって読み取られる。 |
12.4 FILEIO
Verilog2001では、FILEIOが強化されています。
大体、C言語のそれと同じようなイメージです。
例して次のようなテキストファイルを読んでみます。(regression folderに入っています。)
//fgets test pattern file # comment test @ 123 123.1423 0101111 abcd @ 789 1.1341e2 10000111 ffef0123 @ 323 -543e-8 1001000zx00z f0e03355 |
このテキストファイルを読むソースは次です。
`define EOF 32'hFFFF_FFFF //Aug.11.2004 //Test systems tasks // fgetc, fgets,ungetc,fscanf module fgets_test; integer fp; integer c,r; reg [8*120:1] buffer; integer num; real real_value; reg [15:0] bin_value; reg [31:0] hex_value; initial begin fp = $fopen("fgets_pattern.dat","r");//Verilog 仕様は、Default "w"で開いてしまうので、"r"がないとFILEを消してしまう。 if (fp !=0) begin c = $fgetc(fp); while (c !=`EOF) begin if (c=="#") begin r=$ungetc(c,fp); r=$fgets(buffer,fp);//#も表示されることの確認 $display("displaying: %s %d",buffer,r); end else if (c=="@") begin r=$fscanf(fp,"%d %f %b %h\n",num,real_value,bin_value,hex_value); $display("r=%d %d %g %b %h",r,num,real_value,bin_value,hex_value); end else begin $write("%c",c); end c=$fgetc(fp); end end end endmodule |
次の例は、$sformatを使ってCPUの逆アセンブラを作った例です。$sprintfは、Veritak Uniqueで、$sformatに同じです。
`ifdef Veritak //Disassenblar reg [30*8:1] inst; wire [5:0] op=IR[31:26]; wire [25:0] bra=PC+{{10{IR[15]}},IR[15:0]}*4;//+4; wire [4:0] rs=IR[25:21]; wire [4:0] rt=IR[20:16]; wire [4:0] rd=IR[15:11]; wire [4:0] sh=IR[10:6]; reg [5*8:1] reg_name="abcd"; reg [30*8:1] instD1,instD2; function [4*8:1] get_reg_name; input [4:0] field; begin case (field) 0: get_reg_name="$z0"; 1: get_reg_name="$at"; 2: get_reg_name="$v0"; 3: get_reg_name="$v1"; 4: get_reg_name="$a0"; 5: get_reg_name="$a1"; 6: get_reg_name="$a2"; 7: get_reg_name="$a3"; 8,9,10,11,12,13,14,15: $sprintf(get_reg_name,"$t%1d",field-8); 16,17,18,19,20,21,22,23,24,25: $sprintf(get_reg_name,"$s%1d",field-16); 26:get_reg_name="$k0"; 27:get_reg_name="$k1"; 28:get_reg_name="$gp"; 29:get_reg_name="$sp"; 30:get_reg_name="$s8"; 31:get_reg_name="$ra"; endcase end endfunction always @(posedge clock) begin instD1<=inst; instD2<=instD1; end always @*begin:sprintf //Jan.20.2005 @ (IR,op,bra,rs,rt,rd,sh) begin :sprintf reg [4*8:1] rdn;//Mar.15.2005 =get_reg_name(rd);// reg [4*8:1] rsn;//Mar.15.2005=get_reg_name(rs); reg [4*8:1] rtn;//Mar.15.2005 =get_reg_name(rt); rdn=get_reg_name(rd); rsn=get_reg_name(rs); rtn=get_reg_name(rt); case (op) 0: case (IR[5:0]) 0: if (rd==0 && rt==0 && rs==0 ) $sprintf(inst,"nop"); else $sprintf(inst,"tsll %s,%s,%2d\n",rdn,rtn,sh); 2: $sprintf(inst," srl %s,%s,%2d\n",rdn,rtn,sh); 3: $sprintf(inst," sra %s,%s,%2d\n",rdn,rtn,sh); 4: $sprintf(inst," sllv %s,%s,%s\n",rdn,rtn,rsn); 6: $sprintf(inst," srlv %s,%s,%s\n",rdn,rtn,rsn); 7: $sprintf(inst," srav %s,%s,%s\n",rdn,rtn,rsn); 8: $sprintf(inst," jr %s\n",rsn); 9: $sprintf(inst," jalr %s\n",rsn); 12: $sprintf(inst," syscall\n"); 13: $sprintf(inst," break"); 16: $sprintf(inst," mfhi %s\n",rdn); 17: $sprintf(inst," mthi %s\n",rsn); 18: $sprintf(inst," mflo %s\n",rdn); 19: $sprintf(inst," mtlo %s\n",rsn); 24: $sprintf(inst," mult %s,%s\n",rsn,rtn); 25: $sprintf(inst," multu %s,%s\n",rsn,rtn); 26: $sprintf(inst," div %s,%s\n",rsn,rtn); 27: $sprintf(inst," divu %s,%s\n",rsn,rtn); 32: $sprintf(inst," add %s,%s,%s",rdn,rsn,rtn); 33: if(rt==0) $sprintf(inst," move %s,%s\n",rdn,rsn); else $sprintf(inst," addu %s,%s,%s\n",rdn,rsn,rtn); 34: $sprintf(inst," sub %s,%s,%s\n",rdn,rsn,rtn); 35: $sprintf(inst," subu %s,%s,%s\n",rdn,rsn,rtn); 36: $sprintf(inst," and %s,%s,%s\n",rdn,rsn,rtn); 37: if(rt==0) $sprintf(inst," move %s,%s\n",rdn,rsn); else $sprintf(inst," or %s,%s,%s\n",rdn,rsn,rtn); 38: $sprintf(inst," xor %s,%s,%s\n",rdn,rsn,rtn); 39: $sprintf(inst," nor %s,%s,%s\n",rdn,rsn,rtn); 42: $sprintf(inst," slt %s,%s,%s\n",rdn,rsn,rtn); 43: $sprintf(inst," sltu %s,%s,%s\n",rdn,rsn,rtn); default: $sprintf(inst,"Unknown Func. %08h\n",IR); endcase 1: case (IR[20:16]) 0: $sprintf(inst," bltz %s,$%08h\n",rsn,bra); 1: $sprintf(inst," bgez %s,$%08h\n",rsn,bra); 16: $sprintf(inst," bltzal %s,$%08h\n",rsn,bra); 17: $sprintf(inst," bgezal %s,$%08h\n",rsn,bra); default: $sprintf(inst,"Unknown1 %08h\n",IR); endcase 2: $sprintf(inst," j $%08h\n",((IR*4)&32'h0ffffffc)+(PC&32'hf0000000)); 3: $sprintf(inst," jal $%08h\n",((IR*4)&32'h0ffffffc)+(PC&32'hf0000000)); 4: if(rs==0 && rt==0) $sprintf(inst," bra $%08h\n",bra); else $sprintf(inst," beq %s,%s,$%08h\n",rsn,rtn,bra); 5: $sprintf(inst," bne %s,%s,$%08h\n",rsn,rtn,bra); 6: $sprintf(inst," blez %s,$%08h\n",rsn,bra); 7: $sprintf(inst," bgtz %s,$%08h\n",rsn,bra); 8: $sprintf(inst," addi %s,%s,#$%04h\n",rtn,rsn,IR[15:0]); 9: if(rs==0) $sprintf(inst," li %s,#$%08h\n",rtn,IR[15:0]); else $sprintf(inst," addiu %s,%s,#$%04h\n",rtn,rsn,IR[15:0]); 10: $sprintf(inst," slti %s,%s,#$%04h\n",rtn,rsn,IR[15:0]); 11: $sprintf(inst," sltiu %s,%s,#$%04h\n",rtn,rsn,IR[15:0]); 12: $sprintf(inst," andi %s,%s,#$%04h\n",rtn,rsn,IR[15:0]); 13: if(rs==0) $sprintf(inst," li %s,#$%08h\n",rtn,IR[15:0]); else $sprintf(inst," ori %s,%s,#$%04h\n",rtn,rsn,IR[15:0]); 14: $sprintf(inst," xori %s,%s,#$%04h\n",rtn,rsn,IR[15:0]); 15://load upper immediate $sprintf(inst," lui %s,#$%04h",rtn,IR[15:0]); 16, 17, 18, 19: begin if(rs>=16) $sprintf(inst," cop%d $%08h\n",op&3,IR[25:0]); else case(rsn) 0: $sprintf(inst," mfc%d %s,%s\n",op&3,rtn,rdn); 2: $sprintf(inst," cfc%d %s,%s\n",op&3,rtn,rdn); 4: $sprintf(inst," mtc%d %s,%s\n",op&3,rtn,rdn); 6: $sprintf(inst," ctc%d %s,%s\n",op&3,rtn,rdn); 8, 12: if(rt&1) $sprintf(inst," bc%dt %d,%08h\n",op&3,rs*32+rt,bra); else $sprintf(inst," bc%df %d,%08h\n",op&3,rs*32+rt,bra); default: $sprintf(inst,"Unknown16 %08h\n",IR); endcase end 32: $sprintf(inst," lb %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 33: $sprintf(inst," lh %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 34: $sprintf(inst," lwl %s,$%04h(%s)\n",IR[15:0],rsn); 35: $sprintf(inst," lw %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 36: $sprintf(inst," lbu %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 37: $sprintf(inst," lhu %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 38: $sprintf(inst," lwr %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 40: $sprintf(inst," sb %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 41: $sprintf(inst," sh %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 42: $sprintf(inst," swl %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 43: $sprintf(inst," sw %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 46: $sprintf(inst," swr %s,$%04h(%s)\n",rtn,IR[15:0],rsn); 48, 49, 50, 51: $sprintf(inst," lwc%d %s,$%04h(%s)\n",op&3,rtn,IR[15:0],rsn); 56, 57, 58, 59: $sprintf(inst," swc%d %s,$%04h(%s)\n",op&3,rtn,IR[15:0],rsn); default: $sprintf(inst,"UnknownOp %08h\n",IR); endcase end `endif |