Verilog-HDL 文法(5):シミュレーション記述(1)
2015/09/27
[CategoryTop] [Prev] [Next]
[目次]・シミュレーション記述概要
     + テストベンチの構成
     + テストベンチ用moduleの構成
   ・テストベンチの記述例
     + モチーフ回路
     + モチーフ回路のテストベンチ

●シミュレーション記述概要

 ◆テストベンチの構成
 
  ・テストベンチとは、自分が作成した回路(module)に、シミュレーション上で信号を
   印加/観察するためのデータ構造
を指します。
  
  ・Verilog-HDLではテストベンチもmodule構造を持っています。以下にテストベンチの
   構成を示します。module myrtlが観測対象の回路という想定です。
  
   [Fig.1 テストベンチの構成]
  ┌─────────────────────────────────────┐
   +-- module myrtl_tb ------------------------------+
   |                         |
   |        +--module myrtl--+        |
   |        |        |        |
   | [reg clk;]o---+ clk      |        |
   |        |        |        |
   | [reg in1;]o---+ in1    out1+---o wire out1; |
   |      :  :        :  :      |
   | [reg inN;]o---+ inN    outM+---o wire outM; |
   |        |        |        |
   |        +----------------+        |
   |                         |
   +-------------------------------------------------+
  └─────────────────────────────────────┘
  
  ・Fig.1のように、テストベンチのmoduleは外部のポートを持っていません。信号を印
   加するためのregと、出力観測用のwireのみ
です。
  
  ・「わかりやすさ」の点から考えれば、テストベンチmoduleのreg, wire名は、観測
   moduleの入出力ポート名と同じにする
ことがほとんどです。
     reg 信号 <===> 入力ポート
     wire信号 <===> 出力ポート


 ◆テストベンチ用moduleの構成

  ・テストベンチ用module記述の雛型はList1のようになります。

   [List.1 テストベンチの構成(最もシンプルな例)]
  ┌─────────────────────────────────────┐
   `timescale Sim.単位/精度
   
   module テストベンチ名;
   
     reg 入力信号名_1;  // ---+
      :         //  +--- (1)信号入力reg定義
     reg 入力信号名_N;  // ---+
     
     
     wire 出力信号名_1;  // ---+
      :         //  +--- (2)出力観測wire定義
     wire 出力信号名_M;  // ---+
     
     
     観測module名 観測moduleインスタンス( // --+
       .入力信号名_1(入力信号名_1),   //  |
         :               //  |
       .入力信号名_N(入力信号名_N),   //  +--- (3)観測対象moduleの
       .出力信号名_1(出力信号名_1),   //  |    インスタンス定義
         :               //  |
       .出力信号名_M(出力信号名_M)    //  |
     );                  // --+
     
     
     initial begin      // --+
                  //  |
       #0 初期値設定;    //  +--- (4)信号印加記述
       #(CYCLE) 印加記述;  //  |
         :         //  |
         :         //  |
     end           // --+
     
     initial $monitor(出力記述); // (5)信号出力記述
     
   endmodule
  └─────────────────────────────────────┘
  
  ・テストベンチではシミュレーションの時間設定が必要です。それが冒頭の
     `timescale Sim.単位/精度
   です。これはシミュレータへの指示子になっています。
   
  ・List1で示したように、テストベンチ用moduleは大まかに5個のブロックで構成され
   ます。
     (1)信号入力reg定義
     (2)出力観測wire定義
     (3)観測対象moduleのインスタンス定義
     (4)信号印加記述
     (5)信号出力記述
  
  ・これら5ブロックの記述方法ですが、テストベンチの記述は論理合成を意識していな
   いので、Verilog-HDLの文法を全て適用することができます。可能な記述については
   これから順次説明していきます。
  
  ・とりあえず今回はテストベンチのサンプルを見て、基本ステートメントを把握して
   下さい。


●テストベンチの記述例

 ◆モチーフ回路
 
  ・テストベンチを作る前に、観測対象とするモチーフ回路を記述してみます。今回は
   ちょっと変りネタの回路です。3bitのPRPG(Pseudo Random Pattern Generator)を作
   成してみます。(*1)

   [Fig.2 モチーフ回路 : PRPG -- 疑似ランダムパターン発生器]
  ┌─────────────────────────────────────┐
   モチーフ回路
  └─────────────────────────────────────┘
  
  ・モチーフ回路はLFSR(Linear Feedback Shift Register)を利用したランダムパター
   ン発生器
です。
  
  ・動きですが、最初にInit信号を立ててから、初期値Seed[2:0](必ず何かのbitが1)を
   設定し、Clkを1回入れることで各FFに初期値を格納します(同期動作)。
  
  ・その後、Initを下げてClkを叩くと、FeedBackループのデータ演算結果に伴い、
   Rdata[2:0]から3bitの値がランダムに出力されるという回路です。全bit0以外の値
   が発生されるので、3bitの場合は(2^3-1 = 7)種類の値を取ります。
  
  ・このモチーフ回路のRTL(*2)はList2になります。
  
   [List.2 モチーフ回路 : prpg_3 RTL]
  ┌─────────────────────────────────────┐
   module prpg_3 (
     Clk,
     Init,
     Seed,
     Rdata
   );
     input    Clk;
     input    Init;
     input [2:0] Seed;
     output [2:0] Rdata;
     
     reg  [2:0] Rdata;
     
     always @ ( posedge Clk )
      begin
       if ( Init ) // Seed In (Sync Clk)
        begin
         Rdata <= Seed;
        end
       else    // LFSR Loop
        begin
         Rdata[2] <= Rdata[1];
         Rdata[1] <= Rdata[0] ^ Rdata[2];
         Rdata[0] <= Rdata[2];
        end
      end
     
   endmodule
  └─────────────────────────────────────┘


 ◆モチーフ回路のテストベンチ
 
  ・それではモチーフ回路のテストベンチ及び、想定信号波形をList3に示します。
      
   [List.3 テストベンチ : prpg_3_tb]
  ┌─────────────────────────────────────┐
   信号波形
   テストベンチで想定している信号波形
   
   ─────────────────────────────────────
   
   `timescale 1ns/1ns
   
   module prpg_3_tb;
   
     reg    Clk;
     reg    Init;
     reg [2:0] Seed;
     wire [2:0] Rdata;
     
     parameter RATE = 100;     // Cycle Rate = 100ns(10MHz)
     
     prpg_3 prpg_3 (        // Instanciation
       .Clk  ( Clk ),
       .Init ( Init ),
       .Seed ( Seed ),
       .Rdata ( Rdata )
     );
     
     always #(RATE/2) Clk = ~Clk; // Clock Generation
     
     initial begin
       #0    Clk  = 0;    // Initialize
            Init = 1'b0;
            Seed = 3'b000;
           
       #(RATE) Init = 1'b1;   // Seed Set
            Seed = 3'b010;
           
       #(RATE) Init = 1'b0;   // Generation Start
            Seed = 3'b000;
       
       #(RATE * 10)        // Random Output 10 Cycle
         $finish;
     end
     
     initial
       $monitor ( $stime,
             " Clk=%b Init=%b Seed=%3b Rdata=%3b",
             Clk, Init, Seed, Rdata );
            
   endmodule
  └─────────────────────────────────────┘
  
  ・記述内容を説明します。1行目の
    `timescale 1ns/1ns
   はSimulationの実行単位と精度の指定です。スラッシュ(/)を挟んで前が実行単位、
   後ろが精度の指定になっています。通常、同じ単位を指定すれば問題ありません。
  
  ・19行目の
    always #(RATE/2) Clk = ~Clk;
   はクロック波形の生成です。alwaysはシミュレーション開始後、文字通り「常に」
   動作する信号を記述します。この場合、時間がRATE(100ns)の半分進んだら、Clkを
   反転させる
という記述です。
  
  ・21行目のinitial「開始時に1度だけ実行されるステートメント」です。このテス
   トベンチではinitial文が2ヶ所あります。21行目の信号印加ブロック。そして36行
   目はシステムタスクである$monitorを起動しています。
  
  ・#0 はディレイ指定ですが、ここで初期値を設定しています。Clkを0にし、この後は
   alwaysの設定に従い、ディレイ(RATE/2)によって変化
します。
   
  ・その後は規定のディレイで信号設定を順次記述しているだけです。
  
  ・37行目の$monitor引数の信号に変化がある場合値を出力します。引数の中にある
   $stimeシミュレーションの時間を示すシステムタスクです。
  
  ・このテストベンチで実行したSimulation結果をList4に示します。
  
   [List.4 シミュレーション結果]
  ┌─────────────────────────────────────┐
      0 Clk=0 Init=0 Seed=000 Rdata=xxx
     50 Clk=1 Init=0 Seed=000 Rdata=xxx
     100 Clk=0 Init=1 Seed=010 Rdata=xxx
     150 Clk=1 Init=1 Seed=010 Rdata=010 ---- : 010 (初期値)
     200 Clk=0 Init=0 Seed=000 Rdata=010 ↑
     250 Clk=1 Init=0 Seed=000 Rdata=100 | : 100
     300 Clk=0 Init=0 Seed=000 Rdata=100 |
     350 Clk=1 Init=0 Seed=000 Rdata=011 | : 011
     400 Clk=0 Init=0 Seed=000 Rdata=011 |
     450 Clk=1 Init=0 Seed=000 Rdata=110 | : 110
     500 Clk=0 Init=0 Seed=000 Rdata=110 |
     550 Clk=1 Init=0 Seed=000 Rdata=111 | : 111
     600 Clk=0 Init=0 Seed=000 Rdata=111 |
     650 Clk=1 Init=0 Seed=000 Rdata=101 | : 101
     700 Clk=0 Init=0 Seed=000 Rdata=101 |
     750 Clk=1 Init=0 Seed=000 Rdata=001 | : 001
     800 Clk=0 Init=0 Seed=000 Rdata=001 ↓
     850 Clk=1 Init=0 Seed=000 Rdata=010 ---- : 010 (初期値へ戻る)
     900 Clk=0 Init=0 Seed=000 Rdata=010
     950 Clk=1 Init=0 Seed=000 Rdata=100
    1000 Clk=0 Init=0 Seed=000 Rdata=100    以後、繰り返し
    1050 Clk=1 Init=0 Seed=000 Rdata=011
    1100 Clk=0 Init=0 Seed=000 Rdata=011
    1150 Clk=1 Init=0 Seed=000 Rdata=110
  └─────────────────────────────────────┘
 
  ・List4の結果を見ればわかるように、初期値010設定後、Rdata[2:0]の値はランダム
   に変化
しています。
  
  ・データ発生を変えたい場合、Seed[2:0]の値を変えます。尚、all0を出力したい場合
   はSeed[2:0]をall0にします。ただし、この場合はClkを入れてもRdataはall0固定に
   なります。
  
  ・尚、この結果を波形で確認したい場合、vcdファイルに格納する方法があります。テ
   ストベンチに少しだけ追加記述を行いますが、それは「Verilog-HDLのフリー環境」
   を参照して下さい。iverilogによる実行も本レポートに書いています。
  
  ・最も基本的なテストベンチの構成については以上になります。次回からはテストベ
   ンチで可能な様々な記述を見ていくことにします。

 

(*1)最近のLogic向けDFTでは、よく記述/利用されるタイプの回路です。

(*2)RTLはRegister Transfer Levelの略です。Clkに伴うレジスタ間のデータ転送レベルで
  記述したVerilog-HDLデータを指します。


[Revision Table]
 |Revision |Date    |Comments
 |----------|-----------|-----------------------------------------------------
 |1.00   |2003-11-24 |初版
 |1.01   |2005-11-20 |リンク更新 (2年振りの追加です)
[end]

Copyright(C) 2015 Altmo