Verilog-HDL 文法(7):シミュレーション記述(3) 2015/09/27 |
[CategoryTop]
[Prev]
|
[目次]・シミュレーション記述例(3) + taskとは何か:引数についての注意 + すでに使っています:システムタスク + taskの記述例 ●シミュレーション記述例(3) ◆taskとは何か:引数についての注意 ・前回はevent文を扱いましたが、今回はtask文を説明しようと思います。task文 の特徴は「引数」を使用できる点にあります。 ・この「引数」を使えることから、taskは「プログラムのサブルーチンに相当する 機能」と説明されることが多いです。この場合しっくりこないのが あれ? moduleでも引数使うけど....? という点ではないでしょうか。 ・これは、引数の扱い方に起因しています。通常のプログラミング言語で、関数や サブルーチンの引数と言えば 値渡し(call-by-value) であるのが普通です。値渡しでは、渡されたサブルーチン側で値がコピーされ、 渡し元の値とは独立になります。 ・しかしVerilog HDLは回路を記述する言語です。wireやregといった物理的要素が 勝手にコピーされるというのはありえません。つまりmodule等で使用している引 数は、プログラミング言語で言うところの 参照渡し(call-by-reference) なのです。 ・これより引数に対する常識 プログラミング言語(C等)では : 引数と言えば : 値渡し 回路記述言語(Verilog HDL)では : 引数と言えば : 参照(実体)渡し になります。 ・これを頭に置いてもらった状態でtaskを説明すると、改めて プログラミング言語で言うところのサブルーチンである と言うことができます。そうです、taskの引数は「値渡し」になります。 ・逆に言うと「値渡し」という現実世界を無視した動作を行うため、回路記述その ものに用いることは無く、あくまで検証対象回路の入出力データの処理や、外部 回路のモデル記述に使用します。 ◆すでに使っています:システムタスク ・実を言うと、taskはすでに使っています。今まで観測に使っていた $display, $monitor 等がそうです。これはシステムタスクと呼ばれ、基本的にはVerilogコンパイラ に依存したセットになっています。 ・ただし、ファイル入出力のシステムタスク等は大体共通化されています。 $readmemh/$writemeh : 16進データread/write $readmemb/$readmemh : 2進データread/write (例)$readmemh("File名", レジスタ配列名, 開始アドレス, 終了アドレス); // 開始アドレス, 終了アドレスは省略可能 ・その他のシステムタスクについては必要に応じてマニュアルやwebを探してみて 下さい。 ◆taskの記述例 ・taskを使うのは、主に検証の場におけるモデル記述であることを先ほど説明しま した。ここでは例としてメモリコントローラからデータを与える場面を想定して みましょう。 [List.1 taskの記述例] ┌───────────────────────────────────┐ `timescale 1ns/1ns module top_verify; // テストベンチ parameter CYC = 100; reg CLK; // クロック always #(CYC/2) CLK = ~CLK; reg [15:0] DI; // Input Data reg [2:0] WA; // Write Address reg WE; // Write Enable wire [15:0] DO; // Output Data reg [2:0] RA; // Read Address reg RE; // Read Enable mod_checked mod_checked ( // 検証回路のインスタンス .CLK(CLK), .DI(DI), .WA(WA), .WE(WE), .DO(DO), .RA(RA), .RE(RE) ); // ----------------------------------------------------------------- task write_task; // writeタスク (addr,data) input [2:0] addr_task; input [15:0] data_task; begin #(CYC) WE = 1'b0; #(CYC) WA = addr_task; DI = data_task; #(CYC) WE = 1'b1; #(CYC/2) $display("WData[%3b]=%8b",WA,DI); #(CYC/2) WE = 1'b0; #(CYC); end endtask task read_task; // readタスク (addr) input [2:0] addr_task; begin #(CYC) RE = 1'b0; #(CYC) RA = addr_task; #(CYC) RE = 1'b1; #(CYC/2) $display("Data[%3b]=%16b,RE=%b", RA,DO,RE); #(CYC/2) RE = 1'b0; #(CYC); end endtask // ----------------------------------------------------------------- initial begin #(0) CLK = 1'b0; // クロック初期値決定 #(CYC); #(CYC) write_task(3'b000, 16'b0000_0001_0000_0001); // write write_task(3'b010, 16'b0101_0101_0101_0101); // write write_task(3'b100, 16'b1111_1111_1111_1111); // write read_task(3'b000); // read read_task(3'b010); // read read_task(3'b100); // read #(CYC) $finish; end endmodule // --------------------------------------------------------------------- module mod_checked ( // チェック対象回路 インチキメモリ CLK, DI,WA,WE, DO,RA,RE ); input CLK; input [15:0] DI; // Write data input [2:0] WA; // Write address input WE; // Write enable output [15:0] DO; // Read data input [2:0] RA; // Read address input RE; // Read enable reg [15:0] mem [7:0]; // Memory Cell always @(posedge CLK) begin if (WE) mem[WA] <= #(1) DI; end assign DO = (RE)? mem[RA] : 16'hx; endmodule └───────────────────────────────────┘ ┌───────────────────────────────────┐ [実行結果] WData[000]=0000000100000001 WData[010]=0101010101010101 WData[100]=1111111111111111 Data[000]=0000000100000001,RE=1 Data[010]=0101010101010101,RE=1 Data[100]=1111111111111111,RE=1 └───────────────────────────────────┘ ・taskはfunctionと同じようにmodule中で記述します。今回の例では入力のみ引数 を与えていますが、出力も与えることができます。この例だけ見ると、taskはテ ストベンチに記述しなければならないように見えますが、そうではありません。 ・その意味ですが、taskを包んだmoduleを構成することで 複数サイクルに渡る一連の動作モデル記述 が可能になることを意味しています。これがポイントです。 ┌───────────────────────────────────┐ module blockA(信号リスト); 信号定義; task task_A タスク定義 endtask always @(入力信号リスト) begin task呼び出し(引数); end endmodule └───────────────────────────────────┘ ・またtaskから他のtaskを呼ぶこともできるので、構造化記述も可能です。 ●最後に ・さてVerilog HDLの基本文法としては今回最後になりましたが、いかがでしょ うか。RTL記述の場合、ついその後のプロセスを忘れて技巧に走りがちですが、 最も重要なのは 平易で、他の人間が(検証エンジニアや、他の協力者)見てわかりやすい バックエンドによるチップ化が容易 テストパターン作成時に、特記/特例が無い 等、むしろその他の面で考えることの方が多くなる傾向にあります。 ・正直言って、RTLに自信があり、凝った記述が多いものほど、検証/量産から見る とひどいRTLになっている傾向があります。(私自身何度もひどい目にあいました。 おかげ様ですっかりIP不信です。) ・RTLは抽象度が高いので、何となくソフトウェアを書いているような気になるこ とも多いですが、我々の作ったものはハードウェアになるということ...物理的 に実現可能なことが絶対条件です。 ・例えばモデルの動作記述で、レジスタの初期値をinitial文で与えたとします。 この初期値が与えられることを、どうやって保証しますか? 回路は常に規定シー ケンスで動作開始するわけではありません。テストモード時は? 評価/量産時は? 周辺回路の誤動作時は? ・デジタル回路設計の記述そのものは、アナログに比べれば難しくありません。し かし、扱う機能範囲が広い分、システムとして考慮することが莫大になる。これ がデジタル回路設計の難しさ & 面白さなのです。 ・ここで書いたことは、あくまでデジタル回路設計の入口です。デジタル回路設計 の本当に面白いところはもっと奥にあります。これは企業Know-Howの色が濃く、 一般の書籍ではまず見ることのできない内容がほとんどです。このコンテンツが その領域へ行くまでの導入路となれば幸いです。 [Revision Table] |Revision |Date |Comments |----------|-----------|----------------------------------------------------- |1.00 |2008-05-01 |初版 |1.01 |2008-05-02 |まとめ追加 [end] Copyright(C) 2015 Altmo
|