電気回路/HDL/ModelSim の radix define のバックアップ差分(No.6)
更新- バックアップ一覧
- 現在との差分 を表示
- ソース を表示
- バックアップ を表示
- 電気回路/HDL/ModelSim の radix define へ行く。
- 追加された行はこの色です。
- 削除された行はこの色です。
[[公開メモ]]
#contents
* ステートマシンのステートを記号で表示したい [#sd720719]
ModelSim の wave ウィンドウでは信号線の状態を
2進数や16進数、アナロググラフなど、
さまざまな形式で表示することができます。
しかし、Verilog で書いたステートマシンのステートを、
分かりやすく記号で表示するのは一筋縄では行きません。
こんなのを例として考えます。
LANG:verilog
module trimac_tx (
...
);
...
localparam stIdle = 0;
localparam stMem = 1;
localparam stTx = 2;
localparam stUdpChecksum0 = 3;
localparam stUdpChecksum1 = 4;
localparam stUdpChecksum2 = 5;
localparam stUdpChecksum3 = 6;
localparam stUdpChecksum4 = 7;
localparam stDone = 8;
localparam stRewound = 9;
reg [3:0] state;
always @(posedge tx_clk)
if ( rst ) begin
state <= stIdle;
end else
case (state)
stIdle:
if (tx_start)
state <= stMem;
...
この state という信号は、stIdle, stMem などの値を取り得るのですが、
ModelSim 上では 0 や 1 などの数値として表示されてしまいます。
テスト時には頭の中で数値をステート名に翻訳しなければなりません。
これを数値ではなく記号で表示する方法として、以下の2つを見つけました。
色分けできること、処理が軽いこと、を考えると後者がお勧めです。
* 表示用の信号を別に用意する [#kb177b67]
http://cafeandverify.blogspot.com/2007/09/verilog-modeenum.html
にもあるように、テストベンチ側に表示用の信号を別に用意して、
それを wave ウィンドウに追加すれば、どんな表示も可能になります。
例えば、いくつかの状態を1つにまとめて表示するなどの応用も可能です。
LANG:verilog
string trimac_tx_state;
always @(uut.trimac.tx.state)
case (uut.trimac.tx.state)
0: trimac_tx_state = "Idle";
1: trimac_tx_state = "Mem";
2: trimac_tx_state = "Tx";
3,4,5,6,7: trimac_tx_state = "UdpChecksumX";
8: trimac_tx_state = "Done";
9: trimac_tx_state = "Rewound";
endcase;
string を使うとシミュレーション速度が気になる場合には、
SystemVerilog の enum 型に代入するだけでも良いのかもしれません。
これの応用で、[[ModelSim 用 PicoBlaze ディスアセンブラ>電気回路/HDL/ModelSim 用 PicoBlaze ディスアセンブラ]]を作ってみました。
PicoBlaze のテスト時に、インストラクションをアセンブラで表示できます。
* radix define を使う [#k00e70a5]
こちらは ModelSim のマニュアルから発見しました。
ModelSim の radix define コマンドを使います。
ModelSim の Transcript ウィンドウに以下を打ち込むか、
あるいは *.udo ファイルに以下を記述して読み込むと、
wave の Radix 指定で TrimacTxStates を選択できるようになります。
radix define TrimacTxStates {
4'd0 "Idle",
4'd1 "Mem",
4'd2 "Tx",
4'd3 "UdpChecksum0",
4'd4 "UdpChecksum1",
4'd5 "UdpChecksum2",
4'd6 "UdpChecksum3",
4'd7 "UdpChecksum4",
4'd8 "Done",
4'd9 "Rewound"
-default decimal
}
この方法の良いところは、記号で表示するだけでなく以下のように色も指定できるため、
文字が読めないくらいまで表示を縮小した場合にも、大まかな流れが分かります。
radix define TrimacTxStates {
0 "Idle" -color white,
1 "Mem" -color yellow,
2 "Tx" -color yellow,
3 "UdpChecksum0" -color yellow,
4 "UdpChecksum1" -color yellow,
5 "UdpChecksum2" -color yellow,
6 "UdpChecksum3" -color yellow,
7 "UdpChecksum4" -color yellow,
8 "Done" -color yellow,
9 "Rewound" -color red
-default decimal
-defaultcolor purple
}
~-default と -defaultcolor は、
本来あり得ない 10 以上の数が現れたときに適用されます。
表示のために余計な信号値を記憶する必要の無い分、
上の方法に比べるとテストが重くならずに済みます。
** radix define コマンドを Verilog コードに埋め込んでおく [#s8392c7b]
表示方法の指定がコードと離れたところにあると、
コードが変更されたときに更新し忘れそうなので、
radix define コマンドをコードに埋め込んでおいて
自動的に抜き出して使うことを考えました。
trimac_tx.v
LANG:verilog
...
localparam stIdle = 0;
localparam stMem = 1;
localparam stTx = 2;
localparam stUdpChecksum0 = 3;
localparam stUdpChecksum1 = 4;
localparam stUdpChecksum2 = 5;
localparam stUdpChecksum3 = 6;
localparam stUdpChecksum4 = 7;
localparam stDone = 8;
localparam stRewound = 9;
/* include in udo
radix define TrimacTxStates {
0 "Idle" -color white,
1 "Mem" -color yellow,
2 "Tx" -color yellow,
3 "UdpChecksum0" -color yellow,
4 "UdpChecksum1" -color yellow,
5 "UdpChecksum2" -color yellow,
6 "UdpChecksum3" -color yellow,
7 "UdpChecksum4" -color yellow,
8 "Done" -color yellow,
9 "Rewound" -color red
-default decimal
-defaultcolor purple
}
*/
...
のように radix define コマンドを Verilog コードにコメントとして埋め込んでおいて、
extract.rb
LANG:ruby
#!/usr/bin/ruby -Ks
require "jcode"
# 第1パラメータが検索するタグ名
search = ARGV.shift
regex_open = /\/\*\s*#{search}/
regex_close = /^[ \t]*\*\//
# 残りがファイル名
ARGV.each do |filename|
print "# #{filename}\n\n"
extract = 0;
line_number = 1;
File.readlines(filename).each do |line|
if (extract == 0)
extract = line_number if line =~ regex_open
else
if line =~ regex_close
extract = 0
else
print line
end
end
line_number += 1;
end
if extract != 0
$stderr.print "Error: section starting at line #{extract} was not closed in #{filename}."
exit(false)
end
end
exit(true)
なんてスクリプトを作ります。
もともとの .udo ファイルを別名で取っておくことにして、
LANG:console
$ cp trimac_test.udo trimac_test.udo.orig
以下のようにすれば、
LANG:console
$ mv trimac_test.udo.orig trimac_test.udo
$ ruby extract.rb "include in udo" *.v >> trimac_test.udo
~/* include in udo と */ で囲まれたコメント部分を
全ての .v ファイルから検索して .udo ファイルに抜き出せます。
trimac_test.udo
...
# trimac_tx.v
radix define TrimacTxStates {
0 "Idle" -color white,
1 "Mem" -color yellow,
2 "Tx" -color yellow,
3 "UdpChecksum0" -color yellow,
4 "UdpChecksum1" -color yellow,
5 "UdpChecksum2" -color yellow,
6 "UdpChecksum3" -color yellow,
7 "UdpChecksum4" -color yellow,
8 "Done" -color yellow,
9 "Rewound" -color red
-default decimal
-defaultcolor purple
}
* コメント [#zc826d8f]
#comment_kcaptcha
Counter: 15081 (from 2010/06/03),
today: 3,
yesterday: 2