2011年05月15日

AVR互換コアのクロック

AVR互換コアのクロック関係のコードを大幅に変更した。それについてや、その他クロックに関することをまとめておこう。

rtavr のクロック(従来)

    _____ _____
    CLK2X |_____| |_____| |__
    ___________
    CLK |___________| |__

    | --------- T -------- |

    rtavr は基本 2 つのクロック入力を使う。( "Number of BUFGMUXs" が 2) 。この関係は 上記のようになっている。1 つの期間は、L,L から始まって H,H で終わる。

    `define USE_DMY_CLOCK とすることで、CLKを入力しなくても良くできるが、"Number of BUFGMUXs" が 2 なのは変わらない。

    2 つのクロック入力 CLK と CLK2X との間の スキューの関係が定義されていないので、どうも最大周波数は信用できないようだ。CLK を 自分で生成した場合でも怪しい。

    それで、CLK2X だけで駆動すようにまずしてみた。そうすると、"Number of BUFGMUXs" がちゃんと 1 になった。

    しかし、速いはずの 標準速版 GPR(gpw_16w) の最大周波数が 30数 MHz まで落ちてしまった。これまた、なにか誤認しているようで信用できない。

Spartan-3 の DCM

    そもそも、同期した 2 つのクロック入力は、DCM で生成するのが前提。.... だが、周波数を自由に生成できる CLKFX の機能を使うと、2 つの クロックを生成できないようだ。

    基本的に rtavr は、FPGA のなかで メインの回路の面倒をみるサブシステムと捉えている。BUFGMUX や DCM をあまり消費したくない。

    結局のところ、CLK2X だけ入力して動かすことになる。

ARTEMISボードとクロック

    ARTEMISボードは 2 つのクロックが使えるように配慮している。

    CLK1 -- メインクロック 水晶モジュール使用
    33 MHz を予定
    CLK2 -- UM232R/UM162 ボードからの供給
    UM232R: 6/12/24/48 MHz
    UM162 : 8 MHz

    スタンドアローンで動かすことは、いまのところ考えておらず、UM232R/UM162 ボードが必ずつく。なので、水晶モジュールは、たぶん使わない。

      水晶モジュールは、5mm x 7mm 3.3V のタイプを使用していて、入手性自体は悪くない。ただ、少々高い。秋月で格安だった、SG-645PCP (33MHz) は売り切れてしまった。自分自身はいくつか確保しているが、ひとには薦められない。

      .. そもそも 33.000 MHz だから他の(きりのよい)クロックを生成できないのだった。実は不便なのかも。

    ただ、UM232R/UM162 ボードが供給できる周波数は制限がある。特に UM162 は 8 MHz しか供給できない。そうなると、DCM の CLKFX を使いたくなる。

      Spartan-3A の最低周波数は 5 MHz 。MEGA32U2 を 16 MHz で動かしても 8 MHz だけが条件にあう。 UM232Rの場合は、MProg などでピンの機能を設定する。近い値ということで、12 MHz を使うつもり。

      で、N MHz を生成するなら N/8 , N/12 で良いはず。2N/4N も問題ないから、ほぼ好きな周波数を生成できる。

    だから、1 つのクロック入力しか使わない設定を通常使用することになる。

水晶を直接使用する方法

  • MAX7256による水晶発振の実験
  • MAX7256によるCR発振の実験
    という記事を見つけた。... FPGA 側は、インバータひとつで良いらしい。外付けは、並列の R1 (100K) と 直列の R2 (1K)。 (R1 でよく見るのは、1M Ωだったりするがどうなんだろう?)

    これでいけることを確認できたなら、ARTEMISボードの次のバージョンは、水晶を付けられるようにしてみたい。幸いにも使っていないピンが 1 つだけある。(現在のバージョンは GND に結線してしまっている。)

    ただし、現状配線がギリギリで かなり厳しい。使っていないピンをGND に結線したのも絶対どこにも配線できないと考えたため。

    それはともかく、当面は SDRAM を使わないので、拡張ポート(2) を使って確認してみようかと思う。

    あと、IBUFG を使うと 入力遅延を設定できる。

    IBUFG BUFG_CLKIN # (
    .IBUF_DELAY_VALUE(100)
    ) (.I(XIN) , .O(CLKIN));
    assign XOUT = ~CLKIN;

    XOUT を 遅延させて出力すると、XIN と XOUT を直結するだけで 適当なクロックが生成できたりするのだろうか?

    WDT のクロックなど、それなりの周波数で発振してくれさえすれば良い場合もあるから、何か役に立つかもしれない。

    追記: Spartan-2 での 実装例を見つけた。

    • 汎用発振器の実験

      動いてしまったとあるが、なにかポイントがあるはず。... ちょっと見てみる。



        回路: パラレルの R1 は 1M Ωで R2 はない。水晶は 14.318 MHz

        UCF :

        NET "XIN" LOC = "P93";
        NET "XOUT" LOC = "P95";

        XC2S50-TQ144 で、普通の I/O ピン

        コード:

        wire x_inv;
        IBUF x_in(.I(XIN),.O(x_inv));
        OBUF_F_2 x_out(.O(XOUT),.I(~x_inv));

        IBUF とか OBUF のプリミティブを使っているが、パラメータは設定していない。


      R1 は付けるが、本当に普通に作れば動くのかも知れない。... 念のため実験ではマネをしてみよう。

    • FPGA PARK: DCOとは?

      ロジックだけで発振させる実装例も発見!

      これが出来ると、SPI-WRITER を作ったときに 外部クロックの設定が不要になり デバイスに対して 1:1 で bitstream ファイルを対応させられる!

rtavr のクロック(再設計)

    _____ _____
    CLK2X |_____| |_____| |__
    ___________
    CLK |___________| |__

    ___________ ___
    CLK_0 | |____________|
    ___________
    CLK_90 _______| |________
    ___________
    CLK_180 |___________| |__
    _____ ___________
    CLK_270 |___________| |__


    | --------- T -------- |

    実をいうと、4相クロックを使うようにできないか検討中。

    実際の回路では、CLK2X のみ使うのは前述のとおりだが、最大クロックがどれぐらいなのか、また分からなくなってきている。DCMを使ってインプリメントしたら、正しい周波数を出してくれるかも知れない。

    さて、上記の単相 CLK2X と 4相クロックを同一のコードで使うにはどうしたら良いのだろう?

    always @(`posedge_CLK_180) // posedge CLK
    begin
    if (RESET == 0)
    begin
    r_doa2 <= 0;
    end
    else if (~__CLK_180)
    begin
    r_doa2 <= DOA2;
    end
    end

    こんなコードでうまくいかないかトライ中。

    posedge CLK_180 なら、CLK_180 は 0 に決まっているのだが、CLK2X を使うときにこの if 文が必要になるのだ。

    問題は、2 倍速で動かすケース。

    always @(`posedge_CLK_90_270) // posedge CLK2X
    begin

    CLK2X では問題ないが、4相ではどうするのだろう?

    ... いろいろやってみたが、posedge CLK2X 使うしかなさそうだ。で、はまった。

      .. 再検討中(後述)

    posedge_CLK_90_270 の場合は、前なのか後なのか判断するのに CLK (or CLK_0 or CLK_180) が使える。

    _____ _____
    CLK2X |_____| |_____| |__
    ___________
    CLK |___________| |__
       (= CLK_180)
    ___________ ___
    CLK_0 | |____________|

    PE PE
    NE NE

    | --------- T -------- |

    PE ポイントでは、切り替わらないから問題ないわけだ。だが、NE ポイントでは、両者が切り替わる。だから、CLK_90 か CLK_270 を使わないといけない。

    コードを機械的に変換したので、そういう問題があるのに気がつくのに時間がかかってしまった。

      CLK2X のときも同じ事情がある。自分で生成する場合は普通の信号と同じ扱いで良いから問題はないが、外部から CLK を入力する場合、動かない。だが、使うつもりがないので放置する。(いずれ、外部からの CLK 入力そのものを削除予定)

    あと、4相の場合のシミュレーションも必要だ。

    reg [3:0] r_clk_0 = 4'b0110;
    reg [3:0] r_clk_90 = 4'b0011;
    reg [3:0] r_clk_180 = 4'b1001;
    reg [3:0] r_clk_270 = 4'b1100;
    reg [3:0] r_clk2x = 4'b1010;

    wire CLK_0 = r_clk_0[3];
    wire CLK_90 = r_clk_90[3];
    wire CLK_180 = r_clk_180[3];
    wire CLK_270 = r_clk_270[3];
    wire CLK2X = r_clk2x[3];

    assign CLK_OUT = CLK_180;

    // always @(posedge CLK4X or negedge CLK4X) // simulator only
    always @(posedge CLK4X)
    begin
    r_clk_0 <= { r_clk_0[2:0] , r_clk_0[3] };
    r_clk_90 <= { r_clk_90[2:0] , r_clk_90[3] };
    r_clk_180 <= { r_clk_180[2:0] , r_clk_180[3] };
    r_clk_270 <= { r_clk_270[2:0] , r_clk_270[3] };
    r_clk2x <= { r_clk2x[2:0] , r_clk2x[3] };
    end

    実際にも確かめられるようにするなら、こういうのが良いかも。SRL16 になるから LUT を 5 つ消費するだけ。ただ 4 倍クロックが必要。

    そういえば、CLKFX を使う場合、FLKFB も CLK0 も不要なのだが、RST がいる。これにもはまった。この RST 次のいんちきコードで簡易化できないだろうか?
     - FPGA を コンフィグした直後だけ 16 CLK の リセット。RST を使うという条件を満たすだけのもの。SPARTAN-3A では ロックが外れると 自働的に RST がかかる(UG331 参照) ので、問題ないだろう。

    reg [15:0] r_rst_once= 16'hffff;

    wire RST = r_rst_once[15];
    always @(posedge CLKIN)
    begin
    r_rst_once <= { r_rst_once[14:0] , 1'b0 };
    end



変更した結果

    rtavr 自体はできた。が、くみ合わせは非常に多くなって確認が面倒。

    // target xc3s200a-4vq100
    // gpr_16w: SYS_DRIVEN_CLOCK4PH
    // DCM_4X 4X DMY_4X
    Number of Slice Flip Flops 408 394 398
    Number of 4 input LUTs 1090 1115 1119
    Number of occupied Slices 707 702 702
    Total Number of 4 input LUTs 1193 1190 1194
    Number used as a route-thru 103 75 75
    Number used for Dual Port RAMs 80 80 80
    Number used as Shift registers - - 4
    Number of bonded IOBs 15 14 12
    Number of BUFGMUXs 3 4 4
    Number of DCMs 1 - -
    Number of BSCANs 1 - -
    Number of RAMB16BWEs 3 3 3
    (Maximum frequency: MHz) 51.658 62.913 61.485

    // target xc3s200a-4vq100
    // gpr_16: SYS_DRIVEN_CLOCK4PH
    DCM 4X 4X DMY_4X
    Number of Slice Flip Flops 404 390 395
    Number of 4 input LUTs 1075 1116 1123
    Number of occupied Slices 682 693 699
    Total Number of 4 input LUTs 1149 1154 1160
    Number used as a route-thru 74 36 37
    Number used for Dual Port RAMs 16 16 16
    Number used as Shift registers - - 5
    Number of bonded IOBs 15 15 12
    Number of BUFGMUXs 3 5 4
    Number of DCMs 1 - -
    Number of BSCANs 1 - -
    Number of RAMB16BWEs 3 3 3
    (Maximum frequency: MHz) 52.499 59.326 60.599

    DCM_4x (top-level: artemis_isp )
    4X (top-level rtavr )
    DY_4X (top-level rtavr , USE_DMY_CLOCK)

    DCM_4X は、DCM を 実際の回路に Implement した場合。4X は、rtavr を top-level にした場合で周辺回路構成はいつもの 50A 用。DMY_4X はシミュレータ用で 4倍の CLK4X を入力して内部で SRL16 により CLK_XX などを生成。

    たとえば、gpr_16w の場合、最大周波数はどれもさほど変わらないはず。なのに、大きく違う。DCM_4Xだけが、複数クロックの関係を知っているのであればつじつまが合いそうだ。

      単純に最大遅延を求めて 1/1 CLK として 周波数を出せば高い値になる。だが、実際の遅延の意味は 3/4 CLK だったりするわけだ。最大遅延が 3/4 CLK なら 周波数を 3/4 しなければならない。

      逆に CLK2X の場合 (CLK2X の) 2 CLK の部分を 1 CLK として計算すると最大周波数が低くなりすぎる。たとえば 45 MHz と出たとして それが CLK2X の最大周波数だとすれば悲しくなる。.. といっても CLK が 45 MHz というのも間違いでもう少し低いような気がする。


rtavr-wk12

  • rtavr-wk12.tar.gz

    上で書いたことを反映したもの。


    // TUNED NORMAL USE_GPR_16
    // Number of Slice Flip Flops: 425 413 406
    // Number of 4 input LUTs: 1196 1122 1099
    // Number of occupied Slices: 740 704 678
    // Total Number of 4 input LUTs: 1284 1215 1159
    // Number used for Dual Port RAMs: 80 80 16
    // Number of bonded IOBs: 15 15 15
    // Number of BUFGMUXs 2 2 2
    // Number of DCMs 1 1 1
    // Number of BSCANs 1 1 1
    // Number of RAMB16BWEs 3 3 3
    // Post-PAR Static Timing Report^
    // Maximum frequency(MHz): 48.347 41.377 46.742

    規模は、DCM を使ってインプリメントして、こうなった。(いんちき RST 入り) -- なんと、gpr_16w まで 50A に 入りそうだ。

CLK 見直し(その2)

    4相クロックは、そもそも計測用。なのに 4相以外の CLK2X が入ってしまって気持ち悪い。
    ... というわけで、パラメータから CLK2X を全部外して、4相だけでなんとかすることにした。

    ___________ ___
    CLK_0 | |____________|
    ___________
    CLK_90 _______| |________
    ____
    AND _______| |________________

    ___________
    CLK_180 |___________| |__
    _____ ___________
    CLK_270 |___________| |__
    _____
    AND __________________| |________

    CLK_90_270 : (CLK_0 & CLK_90) | ( CLK_180 & CLK_270)
    CLK_0_180 : (CLK_270 & CLK_0) | ( CLK_90 & CLK_180)

    CLK_0_180 も 90°前にずらしたのを独立に作る。

    あと、クロックのオプションについても整理した。

    SYS_DRIVN_CLK4PH USE_DMY_CLK input
    o x 4相
    o o CLK4X (4倍クロック: シミュレーション用)
    x o/x CLK2X

    この2つ。実際の回路では CLK2X のみ使うことを想定。SYS_DRIVN_CLK4PH は、性能検証用で、USE_DMY_CLK はシミュレータで動作を確かめるためのもの。

    ちなみに、コアの種類は 3 種類を想定。(それ以外に SPARTAN3A/SPARTAN6 で 違うパラメータあり)

    NORMAL : gpr_16w を使用。
    TUNED : gpr_16w を使用し、規模が増えるチューニング・
             パラメータ ON
    USE_GPR_16 : gpr_16 を使用し規模を減らす。

    そして、周辺装置のコンフィグ。これは、いろいろ設定できるが、代表は 3 つ。

    50A : XC3S50A 向けに機能を絞ったもの。
    LARGE : フル機能
    ARTEMIS : ARTEMIS ボード (50A) 向け にさらに機能を絞ったもの。

    全部の組み合わせが Implement 可能なので、これだけ試すと 3 x 3 x 3 = 91 通りもある。Spartan-6 も確認しておきたいし、なかなか大変。

参考にしたもの
posted by すz at 12:25| Comment(3) | TrackBack(0) | AVR_CORE
この記事へのコメント
CPLDによる発振器ですが、MAX7Kのような構造では発振するのですが、XILINXのXC9500のような構造や、おそらくFPGAではうまく発振しないかも知れません。
Posted by shirou at 2011年05月16日 22:23
論理設計だけは出来るようになりましたが、FPGA 初心者なもので、アドバイスは助かります。
で、理由は何でしょう? ... ひょっとして IBUF の遅延? なら、もっと遅らせて 180°付近にしたらうまくいくのかな?
Posted by すz at 2011年05月16日 23:56
おそらく遅延などが関係するのでしょうと思いますが詳しくは知りません。当時のALTERA代理店さんの技術資料に出ていた回路を試しててみました。実はLC発振も試しまして、簡単な金属探知機のような実験をやりました。FPGAではやったことが無いんです。XILINXのCPLDでは試したのですが発振しませんでした。
アナログ的な動作になるのでプロセスの違いが出るのかも知れません。
Posted by shirou at 2011年05月17日 07:54
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/45142414
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック