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
|