電気回路/HDL/ModelSim の radix define のバックアップ差分(No.10)
更新- バックアップ一覧
- 現在との差分 を表示
- ソース を表示
- バックアップ を表示
- 電気回路/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 のテスト時に、インストラクションをアセンブラで表示できます。 ちなみに、このような SystemVerilog のコードをテストベンチで使うには、 コードが SystemVerilog で書かれていることをコンパイラに伝えなければなりません。 一番楽にできるのは、ISE の Processes で右クリックして Process Properties を選択し、Other VLOG Command Line Options のところに -sv を入力することです。 これで、 ModelSim はすべての Verilog ファイルを SystemVerilog として解釈するため、 string その他を使った SystemVerilog 形式のテストベンチを使うことができるようになります。 * 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 } * 特に便利かもしれない使用法 [#q6155015] これ、PicoBlaze のデバッグに大変有効ですね。 通常、PicoBlaze のデバッグで pc の値を追いかけるためには個々の数値が見えるくらい拡大しないといけないのですが、特定のアドレスを見つけるのに目をこらさなければならないため大変です。 起点となるアドレスに radix define で色を付けておくと、かなり縮小してあっても一目で箇所を特定できます。 trimac_test.udo ... # trimac_tx.v radix define TrimacControllerPC { 'h007 "Idle" -color green, 'h126 "RxArp" -color yellow, 'h143 "RxUdp" -color yellow, ... -default hex -defaultcolor white } * コメント [#zc826d8f] - 私はステートのストリングをソースに埋め込んでいます。http://marsee101.blog19.fc2.com/blog-entry-400.html -- [marsee] &new{2010-05-19 (水) 08:11:35}; - はい、[[#kb177b67]] の方法ですね。radix define だと色が変えられるのが面白いと思います。 -- [武内(管理人)] &new{2010-05-19 (水) 15:24:05}; #comment_kcaptcha
Counter: 15081 (from 2010/06/03),
today: 3,
yesterday: 2