FC2カウンター FPGAの部屋 Verilog2001版DDR SDRAMコントローラのバグ
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Verilog2001版DDR SDRAMコントローラのバグ

mixiの方からModelSimとは違うシミュレータでVerilog2001版DDR SDRAMコントローラがシミュレーションできないという報告をもらった。

最初のバグは、ontroller.v 724行目のendcaseの後に ; を入れてしまったことだ。こう書いてもModelSimではエラーを出さないようだ。VHDLだと ; を書くので思わず入れてしまったようだ。

もう1つは write_data_module.v でグローバル変数 j を定義してその j を2つのalways @* 内で使用してしまったのでレース状態が発生してしまったらしい。ModelSimはそれでも動作するがシミュレータによっては無限ループになるらしい。必ずしもシミュレータが悪いのではなく、記述が悪かった。
元のVerilogコードは、(途中を抜いているが。。。)

    integer  j;

    // inferr the 3-State buffer
    always @ * begin
        for (j=DDR_DATA_WIDTH-1; j>=0; j=j-1) begin
            if (out_tri[j] == 1'b1)
                ddr_dq[j] <= 1'bZ;
            else
                ddr_dq[j] <= ddr_out[j];
        end
    end

    // inferr the 3-State buffer
    always @ * begin
        for (j=DDR_DQS_DM_WIDTH-1; j>=0; j=j-1) begin
            if (dqs_tri_enable_2dx[j]==1'b1)
                ddr_dqs[j] <= 1'bZ;
            else
                ddr_dqs[j] <= dqs_out[j];
        end
    end


これだとalways @*なのでイベントリストには j も入ってしまって、2つのalways @*文の間で無限ループになってしまうということだ。
シミュレータの作りとしては、

1) グローバル変数 j の値とイベントフィールドをタイムホイールに生成する。
2) 1つ目の always @* をDELTA時間で評価する。j が変化したので値とイベントフィールドを更新。
3) j の変更イベントフィールドがアップデートされているので、2つ目の always @* を同じDELTA時間で評価する。j が変化したので値とイベントフィールドを更新。
4) j の変更イベントフィールドがアップデートされているので、1つ目の always @* を同じDELTA時間で評価する。j が変化したので値とイベントフィールドを更新。

ということで、3)と4)を繰り返すことが考えられる。
間違っているかもしれないが、このようなことなのだろうと理解した。
j をグローバル変数ではなく、ローカル変数にする方法も教えていただいたのでローカル変数に変更して、この問題を逃れた。それが下のVerilogコードだ。(ちなみに本当はgenerate文で書いたほうが良いそうだ。)

    // inferr the 3-State buffer
    always @ * begin :Ddr_Dq_Gen_Loop
        integer k;
        
        for (k=DDR_DATA_WIDTH-1; k>=0; k=k-1) begin
            if (out_tri[k] == 1'b1)
                ddr_dq[k] <= 1'bZ;
            else
                ddr_dq[k] <= ddr_out[k];
        end
    end

    // inferr the 3-State buffer
    always @ * begin :Ddr_Dqs_Gen_Loop
        integer k;
        
        for (k=DDR_DQS_DM_WIDTH-1; k>=0; k=k-1) begin
            if (dqs_tri_enable_2dx[k]==1'b1)
                ddr_dqs[k] <= 1'bZ;
            else
                ddr_dqs[k] <= dqs_out[k];
        end
    end


always @ * begin :Ddr_Dq_Gen_Loop というようにbegin end に :Ddr_Dq_Gen_Loop というようなユニークな名前をつけると、その中でスコープを保証する記述になるそうです。(なお、Quartusではローカル変数を使ったVerilog記述は使用できない可能性があるそうです)

もう1つgenerateのgenvarもユニークな変数を割り当てなければだめなようです。

いろいろ問題点を指摘していただいて、ありがとうございます。

今度はインプリメントを説明してみようと思う。
もうわかっている方もいらっしゃると思うが、シミュレーションとインプリメントでパラメータを変更できるようになっている。実際のパラメータでシミュレーションすると何時間かかるかわからない。。。
  1. 2007年02月12日 18:34 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:10

コメント

> endcaseの後に ; を入れてしまったことだ。
> こう書いてもModelSimではエラーを出さないようだ。

systemverilog だとセミコロンだけの空行が認められています。
が、IEEE1364-2001 では、書ける範囲が限られていて、
ホントに 1 行しか書けないところだけのようです。
以上、LRM をひっくり返す気のおこらない外野でした。
  1. 2007/02/12(月) 18:55:53 |
  2. URL |
  3. #-
  4. [ 編集 ]

情報ありがとうございます。

とすると ; は空行として解釈されているんですね。
勉強になりました。
  1. 2007/02/12(月) 19:00:54 |
  2. URL |
  3. marsee #-
  4. [ 編集 ]

verilog hdl の空行

それが、modelsim を長く使ってる方に拠ると、
modelsim では systemverilog サポートの前から、
空行が書けてはいけないところで書けていて、
最近になって軒並みエラーではじかれるように
なっちまったらしいですわ...
  1. 2007/02/13(火) 06:53:16 |
  2. URL |
  3. 言いだしっぺの外野 #VWFaYlLU
  4. [ 編集 ]

こんにちは。

となるとModelSim6.2系統ではエラーになるんでしょうか?
インストールして調べてみようかな?
  1. 2007/02/13(火) 08:57:46 |
  2. URL |
  3. marsee #-
  4. [ 編集 ]

いえ多分逆です。
昔の modelsim では、空行がそこそこ書けたりする。
sv で仕様が変わったので、sv じゃないモードでも
検査を厳密にするようになったというあたりかと。
エラーにしたいときは、最新の modelsim で、
sv 以外のモードでコンパイルですな。
  1. 2007/02/13(火) 11:54:14 |
  2. URL |
  3. 言いだしっぺの外野 #VWFaYlLU
  4. [ 編集 ]

最新のModelSimが6.2ですね?
ということは、GUIからコンパイルするとディフォルトでsvモードですか?
  1. 2007/02/13(火) 16:15:53 |
  2. URL |
  3. marsee #-
  4. [ 編集 ]

手元の xilinx 版だと、
メニューから comile -> compile options -> verilog
で見えますけど default という選択肢が何なのか
今一ち意味不明ですねえ。

vlog -help でもそれらしい情報なし。
modelsim.ini も何も書いてないようなもん。

少なくとも xilinx 自体のライブラリには、
2001 の構文がふんだんに使われているので、
2001 あたりなんじゃないかと。
昔はこんなええ加減なツールじゃなかったような
気がするんですけど...
  1. 2007/02/14(水) 19:37:34 |
  2. URL |
  3. 言いだしっぺの外野 #VWFaYlLU
  4. [ 編集 ]

今、endcase; にしてやってみたんですが、ModelSim XEⅢ6.1e StarterではDefault, Use Verilog 1995, Use Verilog 2001, Use System Verilog のどれでもコンパイル通りました。
  1. 2007/02/14(水) 20:11:13 |
  2. URL |
  3. marsee #-
  4. [ 編集 ]

達人に確認したところ、
6.1 からデフォルトが 2001 になっているそうです。
sv にするにはオプション指定する必要あり。
また、旧バージョンとの互換性オプションでは、
最早厳密には元に戻らないんだそうです。
キーワードのバッティング回避用らしい。
  1. 2007/02/14(水) 21:47:39 |
  2. URL |
  3. 言いだしっぺの外野 #VWFaYlLU
  4. [ 編集 ]

情報ありがとうございました。

私としては、endcase; で通ってくれても問題ないですけど。。。
  1. 2007/02/15(木) 05:52:38 |
  2. URL |
  3. marsee #-
  4. [ 編集 ]

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog.fc2.com/tb.php/415-84645cd8
この記事にトラックバックする(FC2ブログユーザー)