FC2カウンター FPGAの部屋 2009年04月
fc2ブログ

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

FPGAの部屋

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

ISE11.1iをインストールした(続き2)

”ISE11.1iをインストールした(続き)”の続き。
Place & Routeのエラーは、下のようなエラーだった。

Place:120 - There were not enough sites to place all selected components.
Some of these failures can be circumvented by using an alternate algorithm (though it may take longer run time). If you would like to enable this algorithm please set the environment variable XIL_PAR_ENABLE_LEGALIZER to 1 and try again


これに対するXilinxのアンサーがあった。”23634 - 8.1i PAR - 「ERROR:Place:120 - There were not enough sites to place all selected components...」というエラー メッセージが表示される”
これによると、結局、環境変数XIL_PAR_ENABLE_LEGALIZER に1をセットして再度Place & Routeすればいいらしい。
環境変数XIL_PAR_ENABLE_LEGALIZER に1をセットした。
ISE11_1i_8_090428.png

セット後、Project Navigatorを落として再起動し、ReRunして、もう一度Place & Routeを行った。結果はやはりエラー。下のようなエラー内容だった。

Place:120 - There were not enough sites to place all selected components.
Place:418 - Failed to execute IOB Placement


今度はエリア制約をしているのでエリアが十分ではないのかな?特にエリアにIOBの領域が含まれていないのだろうか?エリア制約を取り除いてみることにする。

#INST "rddata_afifo_inst" AREA_GROUP = "AG_rddata_afifo_inst";
#AREA_GROUP "AG_rddata_afifo_inst" RANGE = SLICE_X9Y48:SLICE_X0Y79;


これでどうだと、再々インプリメント。やっと通りました。良かった。

結果はどうかというと、小さいのでよくわからない。
ISE10.1i SP3の結果。

Design Summary
--------------
Number of errors:      0
Number of warnings:   10
Logic Utilization:
  Number of Slice Flip Flops:            64 out of  11,776    1%
  Number of 4 input LUTs:               133 out of  11,776    1%
Logic Distribution:
  Number of occupied Slices:             93 out of   5,888    1%
    Number of Slices containing only related logic:      93 out of      93 100%
    Number of Slices containing unrelated logic:          0 out of      93   0%
      *See NOTES below for an explanation of the effects of unrelated logic.
  Total Number of 4 input LUTs:         133 out of  11,776    1%
    Number used as logic:                69
    Number used for Dual Port RAMs:      64
      (Two LUTs used per Dual Port RAM)
  Number of bonded IOBs:                173 out of     372   46%
  Number of ODDR2s used:                 40
    Number of DDR_ALIGNMENT = NONE       40
    Number of DDR_ALIGNMENT = C0          0
    Number of DDR_ALIGNMENT = C1          0
  Number of BUFGMUXs:                     4 out of      24   16%
  Number of DCMs:                         1 out of       8   12%


ISE11.1の結果。

Design Summary
--------------
Number of errors:      0
Number of warnings:   10
Logic Utilization:
  Number of Slice Flip Flops:            64 out of  11,776    1%
  Number of 4 input LUTs:               135 out of  11,776    1%
Logic Distribution:
  Number of occupied Slices:             97 out of   5,888    1%
    Number of Slices containing only related logic:      97 out of      97 100%
    Number of Slices containing unrelated logic:          0 out of      97   0%
      *See NOTES below for an explanation of the effects of unrelated logic.
  Total Number of 4 input LUTs:         135 out of  11,776    1%
    Number used as logic:                71
    Number used for Dual Port RAMs:      64
      (Two LUTs used per Dual Port RAM)

  The Slice Logic Distribution report is not meaningful if the design is
  over-mapped for a non-slice resource or if Placement fails.

  Number of bonded IOBs:                173 out of     372   46%
  Number of ODDR2s used:                 40
    Number of DDR_ALIGNMENT = NONE       40
    Number of DDR_ALIGNMENT = C0          0
    Number of DDR_ALIGNMENT = C1          0
  Number of BUFGMUXs:                     3 out of      24   12%
  Number of DCMs:                         1 out of       8   12%


ISE11.1iの方がLUTが2つ余計に使っている。
さらに、ISE11.1iのSLICEの配置具合をPlanAheadで見てみた。エリア制約をかけなくてもまとまっている。
ISE11_1i_9_090428.png
  1. 2009年04月29日 17:04 |
  2. Xilinx ISEについて
  3. | トラックバック:0
  4. | コメント:0

サイクリングに行ってきた

今日は小学校の娘の授業参観だった。道徳の授業を見てから、全校集会は奥さんに任せて家に帰ってきた。奥さんは成人教育委員長なので、行く必要がある。ちなみに成人教育委員会は大人、つまり親を教育しようという委員会だそうだ。講演会を聞いたり、そんなことをやるらしい。教育されるなんて余計な御世話のような気もするが。。。
さて、今日は天気もよく、風もないので、昼食までの間に小貝川の土手をぶらぶらと自転車でサイクリングしてきた。この辺の小貝川の土手は完全に舗装されている。自転車は奥さんのマウンテンバイク。自分のはうちの親父にあげたのでない。奥さんはマウンテンバイクを買ったはいいが乗っていないので、私がたまに使っている。もう17年前のアラヤのバイクだ。結構品質が良く、ギアチェンジも快適。
小貝川の愛国橋からスタート。小貝川の西側の堤防の上を南に向かってサイクリング。

大きな地図で見る

道の両側は菜の花でいっぱいでした。筑波山とマウンテンバイクの写真を撮った。
cycling_1_090429.jpg

途中、車や本格的なロードバイクでサイクリングしている人とすれ違った。今日は本当によい天気。気持ちよくマウンテンバイクをこぐことができた。
cycling_2_090429.jpg

石下の長峰橋に着いた。
cycling_3_090429.jpg


大きな地図で見る

反対側の土手を帰ろうと思ったのだが、反対側の土手がない。。。結局、戻って同じ道を帰った。
なかなか楽しかった。今度は、水海道の方まで道がつながっているだろうから、その辺まで行ってみたい。

実は最近、”山さ行がねが”というページを読んでいる。壮絶な記録だけど、何か心惹かれるものがある。そういうこともあり、久しぶりにマウンテンバイクに乗りたくなった。けど、1時間程度しか乗っていないのに、尻が痛い。
  1. 2009年04月29日 13:51 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

ISE11.1iをインストールした(続き)

”ISE11.1iをインストールした”で出ていたエラーを解析する。
エラーはこんなのや。

ConstraintSystem:59 - Constraint [Sources/ddr2_sdram_cont_test.ucf(40)]: NET "ddr2_clkb" not found. Please verify that:
1. The specified design element actually exists in the original design.
2. The specified object is spelled correctly in the constraint source file.


こんなので、

ConstraintSystem:59 - Constraint [Sources/ddr2_sdram_cont_test.ucf(41)]: NET "ddr2_clk" not found. Please verify that:
1. The specified design element actually exists in the original design.
2. The specified object is spelled correctly in the constraint source file.


結局、ddr2_clkやddr2_clkbがないと言われています。
ちなみに、ddr2_clkやddr2_clkbの定義は下のようです。

output wire [QUANTITY_OF_CLK_OUTPUT-1 : 0] ddr2_clk; // DDR2のCLK
output wire [QUANTITY_OF_CLK_OUTPUT-1 : 0] ddr2_clkb; // DDR2のCLKB


#英語の使い方は間違っているかもしれませんが、ご容赦を。。。
QUANTITY_OF_CLK_OUTPUTは1なので、[0:0] ddr2_clkになっている。どうしてこうなったかというと、複数のDDR2 SDRAMを使っている場合など、場合によってクロックを複数供給する場合があって、その時に対応するためだ。
現在は1本ずつddr2_clkとddr2_clkbを使用している。この名前が違っているらしい。
ISE11.1iのXSTのRTLスケマで見てみたのが下の図。
ISE11_1i_5_090428.png

ddr2_clk(0)とddr2_clkb(0)になっている。定義からだと、この方が自然だと思うが、ISE10.1i SP3では、ddr2_clkとddr2_clkbになっていた。下の図。
ISE11_1i_6_090428.png

XSTのIOパッドの名前の付け方が変わったようだ。今までの下のUCFの記述を

NET "ddr2_clkb" LOC = "M2" |IOSTANDARD = SSTL18_II ;
NET "ddr2_clk" LOC = "M1" |IOSTANDARD = SSTL18_II ;


を下のように変えたらTranslateは通った。

NET "ddr2_clkb(0)" LOC = "M2" |IOSTANDARD = SSTL18_II ;
NET "ddr2_clk(0)" LOC = "M1" |IOSTANDARD = SSTL18_II ;


そうしたら、今度はPlace & Routeでエラー発生。このトラブルシュートは次回に。。。
ISE11_1i_7_090428.png

今度のISE11.1i はかなりのメジャーアップデートなのかもしれない?
  1. 2009年04月29日 07:45 |
  2. Xilinx ISEについて
  3. | トラックバック:0
  4. | コメント:0

ISE11.1iをインストールした

ISE11.1iが無事にダウンロードできたので、さっそくインストールしてみた。やはりPlanAheadがインストールされた。System Generatorもインストールされた。ISE Design Suite 11 の新機能を読むと、”Floorplanner および PACE に代わって PlanAhead をフロアプラン、ピン配置に使用”で、”PlanAhead を Project Navigator から直接起動”だそうです。これからは、配置制約系はPlanAheadに統一か?
下図がISE11.1i Project Navigatorの起動画面。
ISE11_1i_1_090428.png

プロジェクトファイルの拡張子も.xise に変更になったようだ。早速、今やっている10.1.03のプロジェクトを変換してみた。今までのProject Navigatorと違う感じ?Eclipseベース?
User ConstrantsもI/O Pin Planning や Floorplan もPlanAheadベースになっている。
ISE11_1i_2_090428.png

アクセサリからもFloorplannerは完全になくなった。やはりPlanAheadを勉強する必要がありそうだ。I/O Pin Planningをしてみたところが下図。
ISE11_1i_3_090428.png

次にコンパイルして見たんですが、Translateでエラーになってしまった。
ISE11_1i_4_090428.png

エラー解析結果はまたあとで。。。
  1. 2009年04月28日 21:56 |
  2. Xilinx ISEについて
  3. | トラックバック:0
  4. | コメント:0

ISE11.1iが出ました

@eleのぐらろさんの日記で知ったのですが、XilinxのホームページにISE11.1i が出ています。ダウンロードもできます。
私も今、WebPackをダウンロードしていますが、全部で2.67GBあります。今のところ、2.09GBまで行っていますが、だんだんとダウンロードスピードが遅くなっています。ダウンロードできるかどうか心配です。
資料も少し読んだのですが、もしかして、PlanAheadがWebPackにもついてくるんでしょうか?チェックが入っています。
どのようにツールが変わっているか、ダウンロードしてインストールしてみるのが楽しみです。
  1. 2009年04月28日 12:25 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:2

Spartan3A Starter KitのDDR2 SDRAMコントローラのインプリメント(再度インプリ)

”Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのシミュレーション3”で非同期FIFOを自作してシミュレーションがうまくいったようなので、インプリメントをしてみた。Floorplannerで、分散RAMの位置固定を、もう一度やってみると、うまくいったのでddr2_dqから最短の遅延で非同期FIFOのRAMに接続することができた。ucfファイルを書き換えたので、一度インプリメントし直す。上手く行ったか?さっそくTiminig Analyzerを立ち上げて、結果を見てみた。そうすると、クロックの立ち上がりのクロック解析はエラーが出ていて、クロックの立下りのクロック解析結果は解析するパスがないとのこと。え、FALLINGのパスがない?おかしい。なぜだろうということで、FPGA Editorを立ち上げて見てみることにした。
DQ0用のクロックの立下りのときのデータをサンプルするrdd_afifo_dout_0_OBUFを見てみた。下がそのSLICEMの図。
spa3A_skit_io_inp_1_090426.png

ここでクロックの部分を拡大してみる。すると、CLKにつながっているノードはdqs_clkではなく、DQS2intclk_FIFO_FALL_not0000というノードが接続されている。しかもCLK_Bが選択されて反転されていない。
spa3A_skit_io_inp_2_090426.png

こちらの予定と違っている。ちなみにクロックの立ち上がりでサンプルする方のSLICEM、rdd_afifo_dout_16_OBUFを見てみると、CLKにdqs_clkが入っている。
spa3A_skit_io_inp_3_090426.png

さらにDQS2intclk_FIFO_FALL_not0000を探してみると、dqs_clkを反転してDQS2intclk_FIFO_FALL_not0000ノードに出すだけでした。
spa3A_skit_io_inp_4_090426.png

DQS2intclk_FIFO_FALL_not0000ノード全体はこんな感じで、各クロックの立下りをクロックとする
分散RAM(SLICEM)に行っているようです。
spa3A_skit_io_inp_5_090426.png

これは大誤算でした。上のモジュールでdqs_clkを反転して非同期FIFOに与えているのだが、RAM16X1Dプリミティブが立ち上がり動作なので、こうなってしまったのか?本来は、分散RAM(SLICEM)の中でCLK_Bを使うことによってクロックを反転したいんだが。。。
これでは困るので、プリミティブで書かないで、分散RAMを推定させる記述をしてみる。(XSTでRAMを推定させる話は、VHDLだけど、”VHDLでのブロックRAMや分散RAMの初期化(外部データファイル)”を参照)
だが、結果は同じだった。
ここで、async_fifo.vの上位のモジュールはrddata_afifo.v でここで async_fifo.v を呼び出しているところを見ると、以下のようなVerilogコードになっている。

    // 16ビット幅の非同期FIFOをインスタンシエーション(DQSクロックの立ち上がりでデータをサンプル、下位)
//    DQS2intclk_FIFO DQS2intclk_FIFO_RISE(
    async_fifo DQS2intclk_FIFO_RISE(
        .din    (din[15:0]),
        .rd_clk    (clk),
        .rst    (reset),
        .rd_en    (rd_en),
        .wr_en    (wr_en),
        .wr_clk    (dqs_clk),    // DQSクロックの立ち上がりをAFIFOに入力する
        .almost_empty    (almost_empty_rise),
        .almost_full    (almost_full_rise),
        .dout    (dout[31:16]),
        .empty    (empty_rise),
        .full    (full_rise)
    );
    
    // 16ビット幅の非同期FIFOをインスタンシエーション(DQSクロックの立下りでデータをサンプル、下位)
//    DQS2intclk_FIFO DQS2intclk_FIFO_FALL(
    async_fifo DQS2intclk_FIFO_FALL(
        .din    (din[15:0]),    // dinは立ち上がりと同じ
        .rd_clk    (clk),
        .rst    (reset),
        .rd_en    (rd_en),
        .wr_en    (wr_en),
        .wr_clk    (~dqs_clk),    // DQSクロックの立下りをAFIFOに入力する。
        .almost_empty    (almost_empty_fall),
        .almost_full    (almost_full_fall),
        .dout    (dout[15:0]),
        .empty    (empty_fall),
        .full    (full_fall)
    );


DQS2intclk_FIFO_FALLの.wr_clkにdqs_clkを入れるところで反転していた。

もしかしてと思い、async_fifo_rise.v と async_fifo_fall.v に分割して、fallの方は、generate のRAM16X1Dのインスタンス時のwr_clkに入力するところで、~wr_clk (~dqs_clk)としてみた。

    generate 
    genvar i;
        for (i=15; i>=0; i=i-1) begin : DPRAM_GEN
            RAM16X1D #(
                .INIT(16'h000)
            ) RAM16X1D_inst (
                .WCLK(~wr_clk),
                .WE(wr_en),
                .A0(wp[0]),
                .A1(wp[1]),
                .A2(wp[2]),
                .A3(wp[3]),
                .D(din[i]),
                .SPO(),
                .DPRA0(rp[0]),
                .DPRA1(rp[1]),
                .DPRA2(rp[2]),
                .DPRA3(rp[3]),
                .DPO(dout[i])
            );
        end
    endgenerate    


次に当然、上のモジュールでの呼び出しも以下のように変更した。

    // 16ビット幅の非同期FIFOをインスタンシエーション(DQSクロックの立ち上がりでデータをサンプル、下位)
//    DQS2intclk_FIFO DQS2intclk_FIFO_RISE(
    async_fifo_rise DQS2intclk_FIFO_RISE(
        .din    (din[15:0]),
        .rd_clk    (clk),
        .rst    (reset),
        .rd_en    (rd_en),
        .wr_en    (wr_en),
        .wr_clk    (dqs_clk),    // DQSクロックの立ち上がりをAFIFOに入力する
        .almost_empty    (almost_empty_rise),
        .almost_full    (almost_full_rise),
        .dout    (dout[31:16]),
        .empty    (empty_rise),
        .full    (full_rise)
    );
    
    // 16ビット幅の非同期FIFOをインスタンシエーション(DQSクロックの立下りでデータをサンプル、下位)
//    DQS2intclk_FIFO DQS2intclk_FIFO_FALL(
    async_fifo_fall DQS2intclk_FIFO_FALL(
        .din    (din[15:0]),    // dinは立ち上がりと同じ
        .rd_clk    (clk),
        .rst    (reset),
        .rd_en    (rd_en),
        .wr_en    (wr_en),
        .wr_clk    (dqs_clk),    // DQSクロックの立下りをAFIFOに入力する。
        .almost_empty    (almost_empty_fall),
        .almost_full    (almost_full_fall),
        .dout    (dout[15:0]),
        .empty    (empty_fall),
        .full    (full_fall)
    );



こうしたらうまく行きました。やった~。しかし上のモジュールやるとだめで、プリミティブの入力のときに反転するとうまくいくんだ~ということがわかった。コードを書くときには注意しないといけない。
FPGA EditorでFALL側の分散RAMを見るとCLK入力にdqs_clkが入力されていて、CLK_Bが選択されているのがわかる。
spa3A_skit_io_inp_6_090426.png

これでだいたいIO部分とリード部分は行けたと思う。今度は本体を作ることにしよう。

<追記>
とりあえず何の役にも立たないプロジェクトですけど、Veritakのプロジェクトとテストベンチ付きでだれかほしい方はいらっしゃいますか?もし、いらしたら、公開しようかと思います。どこかの方がバグをリポートしていただければ、私にもすごいメリットがありますし。。。

<もう一度追記>
うまくいかない記述とうまくいく記述のXSTでの論理合成結果を比べてみた。
うまくいかない記述(上のモジュールでdqs_clkを反転しているもの)は、XSTのRTLスケマで見ると、上のモジュール(rddata_afifo.v) のところでasync_fifo_fall.v に対してインバータが入っている。言ってみれば当然なのかも?
spa3A_skit_io_inp_7_090428.png

うまくいく記述(async_fifo_fall.v でRAM16X1D直前でwr_clkを反転)は、上のモジュールはそのままで、aync_fifo_fall.v のWCLKの直前でインバータが入っている。
spa3A_skit_io_inp_8_090428.png

そういえば、XSTのKeep HierarchyオプションがYesでやっていたので、これかな?と思って、Noに変更してみたが結果は同じだった。やはり直前でやらないとSLICEMのCLK_Bは使用されないようだ。

  1. 2009年04月27日 21:39 |
  2. Spartan3A Starter Kit
  3. | トラックバック:0
  4. | コメント:4

読んでいる本、家具作り、etc...

昨日読み終わった本は石田衣良の池袋ウエストゲートパーク6、灰色のピーターパン。娘が池袋ウエストゲートパークを買ってきて、それを読んでからファンになった。池袋の果物屋の息子が池袋の若者たちの事件を、やくざやストリートギャングの親玉の同級生たちの力を借りて解決する物語。私は面白いと思う。1~6まで読んだが、7,8は文庫じゃないのでどうしようか?と思っている。この年になると、新しい小説を手にとって買おうと思わないので、娘に本を借りるのはとても良いきっかけになる。
今日読んでいるのは、笹本祐一のミニスカ宇宙海賊2 ”黄金の幽霊船”。笹本さんの本はだいたい持っている。軽快な読み物で読みやすい。宇宙へのパスポートも1,2,3と持っている。いつかは、ロケットの打ち上げを見に行ってみたい。

今日は家具作りで作ってあった長椅子をオイルフィニッシュで塗装した。30分ごとにふき取らなくちゃ。
タケノコがおばさんの家でたくさん取れたということで、親が山のように貰ってきた。竹山がいっぱいあるようだ。親が外で薪ストーブに釜をかけて、米ぬかで煮ていた。あくを取るそうである。たくさんあって食べられないので、奥さんの実家に持っていくことなった。(本当に田舎です)うちの親は、日常的に薪や炭で炊事をしている。さすがに、ご飯は電気炊飯器だけど。。。

非同期FIFOを自作したDDR2のIO部分をインプリメントしてみたら、驚きの現象が。。。そうか、そう来たか。またまた波乱万丈。。。

  1. 2009年04月26日 12:46 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:2

Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのシミュレーション3

”Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのシミュレーション2”の続き。CoreGenで作った非同期FIFOが使用にマッチしないので、”同期FIFOと非同期FIFO”で自作した非同期FIFOで再チャレンジした。
最初は自分で非同期FIFOを自作せずに、www.asic-world.comの Asynchronous FIFOを使わせてもらって何とかしようとしたのだが、どうもうまく動かない。いろいろ修正したのだが、よくわからないところがあるので、限界を感じて自分でスクラッチから書くことにした。
まずはバイナリ→グレイ変換だが、ウィキペディアのグレイコードに書いてあった。”最上位桁から1であれば残り下桁を反転、0であれば残り下桁を変化させない。 例えば、2進数が1010であれば、グレイコードは1111となる。”(ウィキペディアのグレイコードから転載)を忠実にVerilogにした。それが下のコード。

for (j=3; j<=0; j=j-1) begin
    if (j=3) // 最上位はそのままグレーコードに
        wgray[3] <= inc_wp[3];
    else
        if (wgray[i-1]) // 上位の桁が1だったら
            wgray[i] <= ~inc_wp[i];
        else // 0だったらそのまま
            wgray[i] <= inc_wp[i];
end


エラーチェックしてないので間違っているかも?
でも、なんとはなしにwww.asic-world.comの非同期FIFOのコードを眺めていたら、なるほど、これでいいんだと思った。

wgray <= {inc_wp[3], inc_wp[2:0] ^ inc_wp[3:1]}; // 結局上位の桁をXORすればOK


これも後でインプリメントした時の違いを見てみることにしようか?あまり変わらないかもしれないけど。。。
これでいいと思って、非同期FIFO全体をVerilogで書いて前回のシミュレーション環境でシミュレーションしてみたんだけど、どうもグレイコードの0110がバイナリの0100に変換するときに0101に変換してしまう。おかしい。。。
その変換のVerilogコードは下。

assign rdbinary = {rgrayd2[3], rgrayd2[2:0] ^ rgrayd2[3:1]};


自分で計算してみるが、グレイコード0110は0101になってしまう。あれれ、おかしいぞ。何かおかしい。もう一度グレイ→バイナリ変換のサイトを見てみると、よく見ると最上位からバイナリとグレイの-1桁目を排他的論理和取っているじゃないですか。。。間違ってしまった。下のVerilogコードに変更。

// Read Gray Counterの値をバイナリ変換
always @* begin : READ_GRAY2BINARY
    integer j;
    
    for(j=3; j>=0; j=j-1) begin
        if (j==3)
            rdbinary[j] <= rgrayd2[j];
        else
            rdbinary[j] <= rgrayd2[j] ^ rdbinary[j+1];
    end
end


これでだいたいOKかな。シミュレーションしてみたところ、OKのようだ。
DDR2_read_sim_1_090425.png

ddr2_dqに来たデータがdq_data、ddr2_dqsに届いたクロックがdqs_clkに伝搬している。dqs_clkはすでに遅延させている。sd_loop_outが非同期FIFOのWrite Enableとなる。その非同期FIFOのデータをrdd_afifo_rd_enが1のときに、rdd_afifo_doutに出力している。だいたいOKそう。。。

これで苦労してFloorplanした非同期FIFOの最初のRAM素子の位置の制約がパーになってしまったので、もう一度やり直す必要がある。なんかFloorplannerでやってみたら、ddr2_dqのIOパッドが見えなかったので、Floorplan Editorでやる必要があるかな?

一応、非同期FIFOの全ソースを張っておきます。何か間違いがあったら教えてください。

// async_fifo.v
// 4bitアドレス、15深度
// Dual-Port RAMはRAM16X1Dプリミティブを使用する
// 出力は同期化されていないので、上のモジュールでFFを通す必要がある

`default_nettype none
`timescale 1ns / 1ps

module async_fifo (
    din,
    rd_clk,
    rd_en,
    rst,
    wr_clk,
    wr_en,
    almost_empty,
    almost_full,
    dout,
    empty,
    full);

    input wire    [15 : 0] din;
    input wire    rd_clk;
    input wire    rd_en;
    input wire    rst;
    input wire    wr_clk;
    input wire    wr_en;
    output wire    almost_empty;
    output wire    almost_full;
    output wire    [15 : 0] dout;
    output wire    empty;
    output wire    full;

    reg [3:0] wp, rp;
    wire [3:0] inc_wp, inc_rp;
    reg [3:0] wgray, rgray;
    reg [3:0] rgrayd1, rgrayd2;
    reg [3:0] wgrayd1, wgrayd2;
    reg [3:0] rdbinary, wrbinary;
    
    generate 
    genvar i;
        for (i=15; i>=0; i=i-1) begin : DPRAM_GEN
            RAM16X1D #(
                .INIT(16'h000)
            ) RAM16X1D_inst (
                .WCLK(wr_clk),
                .WE(wr_en),
                .A0(wp[0]),
                .A1(wp[1]),
                .A2(wp[2]),
                .A3(wp[3]),
                .D(din[i]),
                .SPO(),
                .DPRA0(rp[0]),
                .DPRA1(rp[1]),
                .DPRA2(rp[2]),
                .DPRA3(rp[3]),
                .DPO(dout[i])
            );
        end
    endgenerate
    
    
    // Write Clock Domain
    assign inc_wp = wp + 1;
    always @(posedge wr_clk, posedge rst) begin : WRITE_COUNTERS
        integer j;
        
        if (rst) begin
            wp <= 4'h0;
            wgray <= 4'h0;
        end else begin
            if (wr_en) begin
                wp <= wp + 4'h1;
                wgray <= {inc_wp[3], inc_wp[2:0] ^ inc_wp[3:1]}; // 結局上位の桁をXORすればOK
            end
        end
    end
    
    // Read Gray Counterからのグレーコードをwr_clkで同期化する
    always @(posedge wr_clk, posedge rst) begin
        if (rst) begin
            rgrayd1 <= 4'h0;
            rgrayd2 <= 4'h0;
        end else begin
            rgrayd1 <= rgray;
            rgrayd2 <= rgrayd1;
        end
    end
    
    // Read Gray Counterの値をバイナリ変換
    always @* begin : READ_GRAY2BINARY
        integer j;
        
        for(j=3; j>=0; j=j-1) begin
            if (j==3)
                rdbinary[j] <= rgrayd2[j];
            else
                rdbinary[j] <= rgrayd2[j] ^ rdbinary[j+1];
        end
    end
    
    assign full = (wp == rdbinary-4'h1) ? 1'b1 : 1'b0;
    assign almost_full = (wp==rdbinary-4'h2) ? 1'b1 : 1'b0;
    
    
    //Read Clock Domain
    assign inc_rp = rp + 1;
    always @(posedge rd_clk, posedge rst) begin : READ_COUNTERS
        integer j;
        
        if (rst) begin
            rp <= 4'h0;
            rgray <= 4'h0;
        end else begin
            if (rd_en) begin
                rp <= rp + 4'h1;
                rgray <= {inc_rp[3], inc_rp[2:0] ^ inc_rp[3:1]}; // 結局上位の桁をXORすればOK
            end
        end
    end
    
    // Write Gray Counterからのグレーコードをrd_clkで同期化する
    always @(posedge rd_clk, posedge rst) begin
        if (rst) begin
            wgrayd1 <= 4'h0;
            wgrayd2 <= 4'h0;
        end else begin
            wgrayd1 <= wgray;
            wgrayd2 <= wgrayd1;
        end
    end
    
    // Write Gray Counterの値をバイナリ変換
    always @* begin : WRITE_GRAY2BINARY
        integer j;
        
        for(j=3; j>=0; j=j-1) begin
            if (j==3)
                wrbinary[j] <= wgrayd2[j];
            else
                wrbinary[j] <= wgrayd2[j] ^ wrbinary[j+1];
        end
    end
    
    assign empty = (wrbinary == rp) ? 1'b1 : 1'b0;
    assign almost_empty = (wrbinary-4'h1==rp) ? 1'b1 : 1'b0;
endmodule


  1. 2009年04月25日 19:04 |
  2. Spartan3A Starter Kit
  3. | トラックバック:0
  4. | コメント:3

息子の誕生会

今日は息子の15歳の誕生日だった。いつもはケーキを買ってきて家で祝うのだが、今日は焼き肉が食べたいということになって牛角に食べに行った。
結構食べきれないくらい頼んでしまったが、腹がいっぱいになってしまって、下の娘の頼んだご飯は残してしまった。まあまあだったが、寿司よりも高価だった。私はこの頃の飲み会が焼肉屋ばっかりだったので寿司の方が良かった。。。まあ、息子のリクエストなのでこれでよかった。

息子もいままでは中学に入っていたが、保健室通学(相談室)だったので、ほとんど授業に出ていなかった。つまりまったく勉強していない。中3になって、高校に行きたくなったらしく、辛いけどクラスに戻るという選択をして、頑張って勉強するために中学に通っている。塾にも行きだして、勉強している姿を見ることができるようになった。勉強について聞かれたら、なるべく教えるようにしている。しかし、やはり相当つらいらしく、毎日愚痴を言ってくるが、何をおいても耳を傾けて話を聞くようにしている。それが息子のストレスを少しでも解消してくれるならばよい。この前少し腰が痛くなったらしく、とても心配した。また入院になってしまっては、元も子もないので、ほどほどにだんだんと、なれていってほしいものだ。。。
  1. 2009年04月24日 22:04 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

DWM誌の2007年8月号と2007年10月号の基板でカメラの画像を表示2

”DWM誌の2007年8月号と2007年10月号の基板でカメラの画像を表示”でカメラの画像をディスプレイに表示できたが、どうやらDCMの位置でおかしくなるという現象が出た。今日は、どこのDCMを使うとどうだめなのか検証してみた。
まずは、ダメなところから、CLKパッドからIBUFG(つまりGCLK入力を使用している)、そしてBUFG(BUFGMUX)を通してDCMに入力するパターン。途中のBUFGはBUFGMUX_X2Y1、DCM_X1Y1、DCMのCLK0のフィードバック用BUFGはBUFGMUX_X2Y10。概略図は下の図。FPGAの中身で、FPGAチップの左右の真ん中あたり、上下の端にあるDCMとBUFGMUXだ。
DCM_BUFGMUX_1_090424.png

左下のXが示すとおりに、この配置を使うとディスプレイはNO SIGNALとなって、何も表示しない。DCMからの出力クロックが消えているっぽい。
次に、CLKパッドからのBUFGを取り去って、近くのBUFGを使うことにしてみる。CLKパッドからIBUFGを通してDCMへ入力、DCM(DCM_X1Y0)のCLK0のフィードバック用BUFGはBUFGMUX_X1Y0。子の概略図は下図参照。
DCM_BUFGMUX_2_090424.png

三角が示す通り、これはコンフィグが不安定、数分はCMOSカメラの画像がディスプレイに表示されるが、数分でNO SIGNAL。
今度は、上と同じようだが、DCMの位置をDCM_X0Y0に、BUFGの位置はBUFGMUX_X2Y1にした。概略図は下図を参照。
DCM_BUFGMUX_3_090424.png

これはOK。30分、ディスプレイに表示させてもOK。
ちなみに各図の青色の線がメインの48MHzクロックだ。

原因は考えにくいけれど、やはり水晶発振規のジッタが問題になるだろうか?今のところ皆目分からない?今日見てみたが、確かに48MHzの水晶発振器の直近にはパスコンはついていないように見える。アキシャル部品になってしまうが、積層セラミックコンデンサを上に抱かせてみようかと思う。

  1. 2009年04月24日 21:48 |
  2. FPGAのトラブル
  3. | トラックバック:0
  4. | コメント:3

DWM誌の2007年8月号と2007年10月号の基板でカメラの画像を表示

DWM誌の2007年8月号2007年10月号に記事が載っていて、イーエスピー企画が出している。画像ベースボード、デジタルCMOSカメラ、208ピンSpartan3E XC3S500+2M高速SRAM基板を使って、カメラで撮影した画像をアナログRGBディスプレイに表示することができた。
2007年10月号と基板を買った時のCDにプロジェクトが入っているが、それはSH2のプロセッサボードをつけた時のISEプロジェクトとSH2のソフトウェアだった。SH2のボードは持っていはいるが、SH2を今から勉強するのも面倒だし、部品を買う必要もあるので、FPGA内にステートマシンを実装してCMOSカメラの設定と画面キャプチャの設定を行うことにした。(PicBlazeやMico32などの組み込みプロセッサを組み込むことも考えたが、それほどでもないという結論になった)
ISEの添付されたプロジェクトをとりあえずインプリメントしてみると、動作周波数が仕様を満たさない。。。48MHzの水晶のクロックも、使用するが、その半分の24MHzのクロックも使用する。24MHzのクロックを作る回路はDフリップフロップの反転Q出力をD入力にフィードバックするような記述だった。DCMも使用してなかったので、こちらでDCMを追加してCLKDV出力で24MHzのクロックを出力するようにした。(CLKDV_DIVIDE => 2.0)
DCMはCoreGeneratorのIPを使用した。これで、インプリメントして、ダウンロードしてみたら、アナログRGBディスプレイに表示されない。おまけにNO SIGNALだった。HSYNCやVSYNCも出ていないみたい。ModelSimでのシミュレーションだとそれは出ているはずなんだけど。。。
もしかしてと思い、Chipscopeを組み込むと波形が表示できない。これはDCMのクロック出力がおかしい。。。
試しに自分でDCMをプリミティブでVHDLファイルを記述すると、映った!!!やった~。しかし、動作が不安定。コンフィグを数回やらないと失敗するときがある。カメラの画像をアナログRGBディスプレイに表示していても、数分後には映らなくなってしまう。その場合はChipscopeも表示されなくなってしまうので、やはりクロックが止まっているっぽい。。。
いろいろDCMの設定を変えてみる。FACTORY_JFをいじってみたら、現象変わらず。。。DCMに入力する前にIBUFGの後にBUFGを通してみると完全に映らない。CoreGenのIPを使った時のような症状になった。
これは、もしかして、DCMの位置が問題なのでは?と思い、FPGA Editorで見るとDCM_X1Y0を使用してた(不安定な状態のとき)。これはCLK入力から一番近いDCMなので、妥当な線だと思ったが、試しにFloorplannerで隣のDCM_X0Y0にアサインしてみた。下がアサイン後のFPGA Editorの図。
CAMERA_CPT_Board_090423.png

<注>訂正。上図のDCM_D0Y1はDCM_X0Y0の間違いです


こうしたら、うまく行きました。30分たっても画像は消えない。コンフィグも安定している。原因は何だろうかわからない。DCM_X1Y0がおかしいのか?それともジッタの多い配線ルート、少ない配線ルートがあるのか?
そういえばDCMのフィードバック入力用のBUFGの位置もどうだろか?このDCMはFPGAチップの下側の中央に位置している。確かめてみると、BUFGMUX_X2Y1を使っていて、上のFPGA Editorの図の一番右下のBUFGを使っているから問題なさそうだし。。。(これはうまくいった時のBUFGだったので、いい位置にあるのは当たり前?でした)
なにか、原因に心当たりがある方はぜひ教えてください。
CAMERA_board_1_090423.jpg
CAMERA_board_2_090423.jpg

明日、おかしい状態のときに、どのDCMやBUFGを使っているか調べてみようと思う。
  1. 2009年04月23日 20:00 |
  2. FPGAのトラブル
  3. | トラックバック:0
  4. | コメント:2

ネットブックがほしい!

最近ネットブックがはやっているようだ。うちの妹もNECのネットブックを買ったので、無線LANの設定やOpenOffice.orgのインストールをやってあげた。
なんか見ていると私もほしくなってきた。今のところ、ASUSのEee PC 1000HEがいいかな?やはり、バッテリー駆動時間9.3時間が魅力的。
HPのHP Mini 2140 Notebook PCも液晶ディスプレイに1,366×768ドット表示対応10.1型ワイドを使っているのが非常に魅力的。しかし、標準では3セルバッテリーでオプションで6セルバッテリーを買い足す必要があるのが痛い。8万円以上になってしまいそう。下手するとASUS2台買えそう。。。
光センサー搭載のMebiusもよさそうだし、東芝も富士通も新しいネットブックを出したようだ。みんなバッテリー駆動時間は標準バッテリーでは短い。
NVIDIAのIONが搭載されるまで待つという選択肢もあるかな?AMDのソリューションも魅力的か?いろいろ迷って、結局買えない気がする。。。
  1. 2009年04月22日 06:07 |
  2. パソコン関連
  3. | トラックバック:0
  4. | コメント:10

肩こりとマッサージ

このブログにも、肩こりとマッサージのことを書いてきたが、また、首や肩、背中も凝ってきたので、マッサージに行ってきた。このようにブログを書いているのも、肩こりにはいけないことなのだろうが、どうもやめられない。というか、仕事が肩こりを誘発しているのだと思う。
思えば、マッサージに行く前は、頭が痛い状態や、くらっとめまいがするとか、いろいろな身体症状があって医者に行って、脳のMRIを取ってもらったり、薬をもらったりしてみたが一向に良くならずに悩んでいた。たまたまマッサージに行ってみたら、非常に具合が良くなった。もっと早く行けばよかったなと思った。
目を使う仕事で、頭が痛い、めまいがするという人の中には肩こり、首のこりがひどい人がいるのではないかと思う。そういう場合はマッサージ屋さんでマッサージをしてもらうことをお勧めする。やはり本職は違うと思う。マッサージは免許が必要で、専門学校を出て国家試験を通っているそうだ。カイロは国家試験がないので、玉石混交ということらしい。
目を酷使する割合が多くなって、若い方でも肩こりの方は増えていると思う。事実、私の高校生の娘は小学校高学年のころから頭が痛いと言っていて、医者にかかって脳のCTも取ったが異常なし。やはりマッサージに連れて行ったところ肩こり、首こりがひどいとのことだった。それでだいぶ改善されたみたいだ。たまにだけど、娘もマッサージにかかっている。実は、小学校5年生の娘も頭が痛いという時がある。症状を聞いてみると、私とそっくり。こっちは肩をもむと痛がるのだが、頭が痛いのが軽減するとのことだ。こんなに小さい頃から肩こり。。。やはり遺伝かもしれない。。。

昨日は、FPGA BBSで面白そうなネタがあったので検証してみた。どうも元ネタの記述に引っ張られてしまった気がする。
takepon256さんのコードに感心した。そうか素直に2のn乗すればよかったのね?それはそうか。。。
私の記述では、ISE10.1SP3でSpartan3A-700を使った時にLUTを32個使用した。
非同期FIFOの作成は今日に持ち越し。
  1. 2009年04月20日 06:05 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:4

同期FIFOと非同期FIFO

”Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのシミュレーション2”でCore Generatorで生成したFIFOがフリーランクロックでないとおかしくなる件だが、結局、XilinxCoreLibフォルダのFIFO_GENERATOR_V4_4.vを見てもよくわからなかった。
この上は、自分で非同期FIFOを作ろうか?と思って、調べていたら、Asynchronous FIFO(verilogのサンプル)を見つけたが、これを非同期リセットに書き換えてやってみたが、まだシミュレーション結果がおかしい。
そのほかに、非同期FIFOの資料はSunburst Design, Inc.のSimulation and Synthesis Techniques for Asynchronous FIFO Designがあったが、結構長いので、あまり読む気がせずに困っていた。
検索していると、なつたんさんの”FPGAで非同期のクロックを扱う方法”がヒット。そういえば、私も"Advanced FPGA Design: Architecture, Implementation, and Optimization"を買ったんだった。
さっそく、職場にあったので、取りにって見てみると、96ページにありました。そのものばっちりの図が。Figure 6.14 Simplified asynchronous FIFO.です。図を見たら一発でわかりました。(誤解しているかもしれませんが。。。)初めてこの本を買ってよかったと思いました。

ちょっと説明を加えると、非同期FIFOはWriteのクロックとReadのクロックが非同期だ。なので、普通の同期FIFOの構成だと、たぶんたまに動作がおかしくなる。
私の考える同期FIFOは下の図のように、Dual-Port Memoryがあって、そのアドレスはBinaryカウンタのWrite CounterとRead Counterから入力している。各カウンタの値でEmptyかFullかを判定するロジックがある。
Synchronus_FIFO_090418.png

ここで、例えば、書き込み側のWrite Counterの値と読み出し側のRead Counterの値が等しくなるときはEmpty、 Read Counter - 1 = Write CounterのときにFullとする。ここで各Counterは4ビットアドレスだとmodulo=16で演算されているのでリングバッファになる。(この辺で図がほしいところだが、面倒なので割愛する)
さて、この同期FIFOの回路でWriteとReadのクロック領域を分けると、Wirte Counterのアドレスの変化とRead Counterのアドレスの変化が同期しなくなる。バイナリカウンタは例えば、"0111"という値の次は"1000"になる。その時に、配線遅延などのために、ビット2~0が"111"から"000"に変化するj時間よりも、ビット3番目の0が1に変わるのが速かったとしよう。そのような仮定に基づくと、ある時間カウンタの値が"1111"に見えるときが出てきてしまう。同期クロックの場合はそのような時間はクロックのすぐ後となり、次のクロックまでには"1000"に安定している。しかし、非同期クロックの場合はタイミングによってはそのような状況が反対側のクロック領域へ影響してしまう。なので、1カウントに1ビットしか変化しないグレイコードを用いる。グレイカウンタならば、一回に1ビットしか変わらないので、"0111"の次を"1111"に間違うようなことは起こらない。よって、非同期FIFOはグレイコードカウンタを使う可能性が大きい。
私の考えた非同期FIFOは以下のようになった。これは上記の本の図を参考にしている。
Asynchronus_FIFO_090418.png

ここで、わざわざグレイコードをバイナリに直して演算しなくてもいいかも?とは思った。4ビットなのでテーブル持っていてもそんなに大変じゃないと思う。とりあえず上図で作ってみることにしようと思う。
バイナリ-グレイコード変換についてはここグレイコード‐バイナリ変換についてはここを参照する。

ちなみに、相手側のクロック領域のカウンタのカウント値がFFが2つ入ることになる。それによって、Full flagやEmpty flagにどんな影響が出てくるかを考えてみよう。Full GeneratorやEmpty Generatorに入力されるカウント値が遅れるわけだ。Full Generatorで考えると、Read Counter値が遅れてくる。その間にWrite Counterが進むとするとFullが出力されるのが速くなって、Write側の書き込みが、必要以上に早期に止まる可能性がある。これは、フェールセーフの面から言っても安全方向に振れているわけで不正に書き込みができるということはない。Empty Generatorはどうかというと、これも同様で必要以上に早期にEmptyとなる可能性はあっても、データがないのにReadする可能性はない。かくして安全面に振れるのでどちらもOKということになる。

何か間違いがあったら、指摘してください。
  1. 2009年04月18日 22:05 |
  2. IP
  3. | トラックバック:0
  4. | コメント:9

QUCSを使ってみた

検索していたらQUCS(Quite Universal Circuit Simulator)が見つかった。日本語も対応しているし、GPLライセンスだし、回路シミュレータとしてなかなかよさそうだったので使ってみた。今回はWindowsをインストールしたが、Ubuntuでもパッケージマネージャーから探して、インストールすることができた。
まずはQucs projectのページ。VHDLシミュレータもVerilogシミュレータも統合して論理シミュレーションもできる感じ。スクリーンショットを見るといろんなことができそう。
日本のサイトでは山梨大学のQUCS入門ぐうたらの部屋 電子回路部Qucs(電子回路シュミレータ)によく書いてあった。
鳥取大学の電気電子工学実験Ⅰでは実験に使っているようだ。電気回路シミュレータQucs説明書としてPDFの詳細なマニュアルもある。
とりあえず、ぐうたらの部屋 電子回路部、Qucs(電子回路シュミレータ)のページに載っていたサンプルを入力してみた。サンプル回路はダウンロード出来たが、ツールになれるために自分で下のように積分回路(ローパスフィルタ)を入力してみた。
qucs_1_080415.png

しかし、載っていた波形のようにはならずに、下の様な波形になってしまった。
qucs_2_080415.png

ぐうたらの部屋 電子回路部、Qucs(電子回路シュミレータ)のページからサンプルファイルをダウンロードしてどこが違うか確かめてみると、自分で回路図を入力したものは、トランジット解析のプロパティのステップ数が11しかなかった。
qucs_3_080415.png

これを300に変えるとちゃんと波形が出てきた。
qucs_4_080415.png

ソース元部品を2kHzのAC電圧源に変更した時の、トランジェント解析とACシミュレーションの結果を下に示す。
qucs_5_080415.png

qucs_6_080415.png

なかなか面白そう。。。VHDLファイルやVerilogファイルを読ませるとポートを判別してシンボルを作ってくれる。

  1. 2009年04月16日 21:50 |
  2. EDAツールについて
  3. | トラックバック:0
  4. | コメント:4

Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのシミュレーション2

”Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのシミュレーション1”で、ddr2_dqが最初から0000を出力してしまっているが、これはZZZZのはずという不具合があったが、これはIOBUFのトライステート条件を入力するT入力の論理を間違えていたからだった。Tは0で出力、1でハイインピーダンスだった。したがってT入力に入力する信号を反転した。

    IOBUF IOBUF_DQ(
        .O(dq_data_to_io),
        .IO(io_pad),
        .I(to_io_pad),
        .T(~tri_out)
    );


ちなみにシミュレーション用のテストベンチの概略は下のように書いてある。

    task READ_DATA_SIG; // DDR2のリード信号を生成
        input [63:0] read_data;
        
        begin
            #1;
            read_timing = 1'b0;
            @(posedge clk);
            #1; // 明確にクロックの立ち上がりの後を宣言
            ddr2_dqs_node = 1'b0;
            @(posedge clk);
            #1;
            read_timing = 1'b1;
            ddr2_dqs_node = 1'b1;
            ddr2_dq_node = read_data[63:48];
            @(negedge clk);
            #1;
            ddr2_dqs_node = 1'b0;
            ddr2_dq_node = read_data[47:32];
            @(posedge clk);
            #1;
            ddr2_dqs_node = 1'b1;
            ddr2_dq_node = read_data[31:16];
            @(negedge clk);
            #1;
            ddr2_dqs_node = 1'b0;
            ddr2_dq_node = read_data[15:0];
            @(posedge clk);
            #1;
            read_timing = 1'b0;
            ddr2_dqs_node = 1'bz;
            ddr2_dq_node = {DDR2_DATA_WIDTH{1'bz}};
        end
    endtask
    
    assign ddr2_dqs = ddr2_dqs_node;
    assign ddr2_dq = ddr2_dq_node;    
    
    always @* begin // rdd_afifo_emptyのときに読みだす
        if (~rdd_afifo_empty)
            #100    rdd_afifo_rd_en <= 1'b1;
        else
            #100    rdd_afifo_rd_en <= 1'b0;
    end
        
    always begin // クロックの生成
       #(CLK_PERIOD/2)    clk = 1'b1 ;
       #(CLK_PERIOD/2)    clk = 1'b0 ;
    end
    
    initial begin // resetの動作
                reset = 1'b0;
        #1000    reset = 1'b1;
        #20000    reset = 1'b0;
    end
    
    initial begin
        ddr2_dq_node = {DDR2_DATA_WIDTH{1'bz}};
        ddr2_dqs_node = {DDR2_DQS_DM_WIDTH{1'bz}};
        read_timing = 1'b0;
        #1;
        @(posedge reset);
        #1;
        @(negedge reset); // リセット終了
        #1;
        @(posedge ddr2_sdram_cont_test_inst.dcm_locked); // DCMがロックするのを待つ
        #10000;
        READ_DATA_SIG(64'h123456789ABCDEF0);
        #10000;
        READ_DATA_SIG(64'h1122334455667788);
        #100000;
        $stop;
    end


DDR2 SDRAMのリード信号を生成するREAD_DATA_SIGというtaskを作って、一番下のinital文でリセットが終了して、DCMがロックするのを待って、READ_DATA_SIGを2度呼びだしている。こういうときにVerilog-HDLは下のインスタンスの信号を簡単に参照できるので便利だ。VHDLだと面倒なことをする必要がある。
これで再度、シミュレーションをしてみた。それを下の図に示す。今度はddr2_dqもZZZZとなって正常になった。しかし、FIFOの動作がおかしい。
spa3A_skit_io_sim_2_090415.png

まずは非同期FIFOのタイミングに問題がある。reset_dcmが下がってリセットが解除されているところまでに(ピンクの矢印部分)、rdd_afifo_fullが0になっていない。非同期リセットならばすぐに0にさがるはずなのだが。。。rdd_afifo_fullが0になるのは2回目のリードデータが来る時だ(緑の矢印)。その後、rdd_afifo_emptyが0になって、リードデータが来ていることがわかるが、データは1個だけしか読めない。上のテストベンチを読むとわかるが、rdd_afifo_emptyが0になったら即、rdd_afifo_rd_enを1にして非同期FIFOのデータを読み出すことになっている。
やはり、非同期FIFOのwr_clkにフリーランではない、DQSを入れているのがまずいのだろうか?ためしに内部使用クロックを入れてみることにする。そうしてみてシミュレーションしてみたのが、下の図。
spa3A_skit_io_sim_3_090415.png

緑色の矢印の位置で、rdd_afifo_fullが0になってリセットされている。やはり同期リセットのような気がする。rdd_afifo_doutを見るとデータが正常に出力されている。やはりフリーランクロックでないとダメ?
もう一度Core Generatorの設定を見てみると、非同期リセット固定のように見える。なぜだろうか?
spa3A_skit_io_sim_4_090415.png

次は、XilinxのVerilogコードを見てこの謎を解明してみようと思う。
  1. 2009年04月16日 05:52 |
  2. Spartan3A Starter Kit
  3. | トラックバック:0
  4. | コメント:0

Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのシミュレーション1

”Spartan3A Starter KitのDDR2 SDRAMコントローラの途中経過7(DQS0のみ使用)”の続き。

いろいろ用事があって遅れていたが、Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールができあがったので、シミュレーションをしてみた。
その結果まだ、おかしい。ddr2_dqが最初から0000を出力してしまっている。これはZZZZのはず。。。どこかおかしいようだ。原因を追及しなければ。。。まだまだ完成度が低い。。。
spa3A_skit_io_sim_1_090414.png

そういえば、まとめサイトをしばらく更新していないので、そろそろ更新しなくてはと思っている。
  1. 2009年04月14日 06:10 |
  2. Spartan3A Starter Kit
  3. | トラックバック:0
  4. | コメント:0

筑波山にカタクリの花を見に行った

今日は筑波山にカタクリの花を見に行った。
家から筑波山までは近いので、大体30分あれば筑波山神社まで到着する。筑波山神社からケーブルカーに乗って筑波山頂駅へ。駅を降りて女体山山頂へ向けて少し歩くとカタクリの花の群生地がある。でも栽培している花の公園のように密生しているのではなく、群生といってもそんなに密集しているわけではなかった。花が小さいので、きらびやかさはないが可憐な感じ。
katakuri_1_090412.jpg
katakuri_2_090412.jpg

その後、女体山山頂まで行きました。山頂はずいぶん前は神社と岩だけだったのだけど、石の柵が増えていた。結構いろいろ作っているんだな~。機材をも持ち上げるのも大変なんだろうけど。。。
またケーブルカーに乗って、筑波山神社まで降りてきたら、足ががくがくしてしまった。運動不足だな。。。もう少し鍛えないと。。。
katakuri_3_090412.jpg
  1. 2009年04月12日 18:45 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

ディジタル・デザイン・テクノロジ2009年春号

Sim's blogさんの”ディジタル・デザイン・テクノロジのページ開設”でも書いてありましたが、CQ出版社のディジタル・デザイン・テクノロジのページが開設されていますね。いろいろなFPGAの情報があって充実していると思いました。読んで勉強してみようかな?
同様にマルツパーツ館にもディジタル・デザイン・テクノロジ「FPGA超入門」 企画に協賛しているというページができました。パーツやベースボードを売り出しています。ベースボードですが、よく見るとパラレルポートのコネクタがあるので、コンフィグ回路内蔵でコンフィグできるのでしょうか?もしそうだとすれば、私のパソコンパラレルポートがないのでパスかな。。。
USBのダウンロードケーブルを何とかしないと、私のところでは検証できないですね。どうしよう。。。
ディジタル・デザイン・テクノロジだけ購入して、死蔵となってしまうかも?
そういえばCQ出版の中の人のブログを発見?しました。”(葵)の今日学んだこと”さんです。もうディジタル・デザイン・テクノロジを手にされていますね。(当たり前か。。。)どうやらエレキジャックの編集の方らしいです。
”エレキジャックNo.11の予告”で洋服に電飾付けて街のクリスマス電飾の前に立っている写真が載っていますが、なかなか良いですね。女性で服に電飾付けていると似合いそうですね。けど、着るのには勇気がいりそうです。リリパッドなどでも簡単にできそうですね。私もやってみようかな?(おかしくなったといわれるのが落ちのような気がしますが。。。)
エレキジャックも買ってみようかな。。。

2009/04/10 追記:
今、ディジタル・デザイン・テクノロジを買ってきました。97ページにベースボードについて書いてありましたが、やはりプリンタポート接続みたいですね。うちのパソコンにはつなげないの決定です。でも、Latticeだけではなく設定ピンでXilinxやAlteraのFPGAに接続可能だそうです。私はなひたふさんの78Kマイコンでのコンフィグを試してみようと思っています。78Kマイコンは持っています。
  1. 2009年04月10日 04:45 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:2

PICマイコンを使った

前はH8だったが、お仕事でPICマイコンを使うことになった。用途としては、水晶発振器の代替ICだ。
CMOS ICでタイマーを作る学生実験をしていて、今まではEPSONのSPG8650Bを使って100Hzのクロックを出していたのだが、ディスコンで代替品を探す必要が出てきた。
そこで、いろいろ探していたが、ある先生からPICはどうだろうということで提案を受けた。実際にプログラムしていただいたのだった。それは1年ほど前のことなのだが、今年から発信器を8ピンのPIC(PIC12F683)に変更することになった。
秋月電子からAKI-PICプログラマー Ver.4を購入してあったので、これでPIC12F683を書き込むことにした。
まずはMicrochipのサイトからMPLAB8.3をダウンロードしてインストールした。うまくC言語がインストールできない。いいやということでアセンブラのみでやることにする。(Freeのところにチェックを入れずにデフォルトでインストールしたら出来ました)
PIC_1_090407.png

PICで遊ぶ電子工作さんのところにPIC12F683の情報が満載なので、これでお勉強。よく書かれていて本当に助かりました。ありがとうございました。
”内部クロックで動作させる”を参考に、0.5秒間隔でLED点滅を5msでGPIOを1、0反転に書き換えさせていただいた。これでプログラムをビルドして、HEXファイルを作ることができた。
さてAKI-PICプログラマー Ver.4で書き込もうと、パソコンにインストールしてあるPICプログラマーVer.6.5を立ち上げて、HEXファイルを読み込み、プログラムしたら最後でオーバーロードというエラーダイアログが出て異常終了。
一応、書き込んだPIC12F683を動作させてみたら、一応100Hz付近のクロックは出るのだが、たまに異常な波形が出ている。やはりだめそうだ。PIC12F683をAKI-PICプログラマー Ver.4をリードするとCONFIGが書き込まれていないみたい。
これではだめだと、PICプログラマ Ver.4 beta6.72 を秋月電子のサイトからダウンロードしてインストールを試みるが、どうしてもDLLがあって再起動しろというダイアログが表示されて、永久にインストールできない。
しょうがないので、ほかのバージョンはないかとCDを探ってみるとPICプログラマ Ver.4 beta6.70があったので、インストールしてみると、インストールできました。何回かやりなおしましたが、ファームウェアもアップデートできました。よかった。
PIC_2_090407.png

これで正常に書き込みができた。出力クロックを測ると99.87Hz?(だったかな)になっていて、少し低いので、ループの中のカウントを1つ減らしたのだけど、今度は周波数が高すぎたので、ループでないところにNOPを2つ入れたらちょうど良くなった。100.06Hz。こんなもんでしょう。
この周波数は電源電圧5Vでの値なので、電圧を変化させると、一旦は周波数が下がって、また上がって、さらに下がるという結果になった。だいたい2.5Vまではそれほど、出力周波数の変動がなさそうので、大丈夫そう。。。
あとは、あと2つ程度、どのくらい周波数に変差があるか調査予定。変動がある場合は1つずつNOPの数の調整が必要だろうか?
しかし、このマイコンいろいろ機能があって面白そう。いろいろ試してみても良いかもしれないと思った。

2009/04/08:追記
5つのPICを上と同様のプログラムを入れて出力周波数を測ってみた。電源電圧4.5Vでの結果は以下の通り。
100.03Hz, 99.89Hz, 99.58Hz, 99.98Hz, 99.59Hz

最初のPICマイコンでだいたい100Hzに合わせたので、こうなった。最初のPICマイコンは動作周波数が高い方だったようだ。電源電圧変動を最初のPICマイコンで調べると以下のようになった。
5V 100.06Hz
4.5V 100.03Hz
4V 100.00Hz
3.5V 99.99Hz
3V 100.05Hz
2.5V 100.11Hz
2V 99.90Hz
追加で2つほど、電源電圧―出力周波数特性を測ったが、だいたい同じ傾向だった。

100Hzからの偏差を少なくするために、プログラムでNOPを2つ入れたのを抜いたら、最初のPICの出力周波数が100.26Hz、最後のPICの出力周波数は99.88Hzとなった。
100.26Hzだと、出来上がったタイマーで約6分カウントすると1秒狂うという精度。まあまあかな???
  1. 2009年04月08日 06:13 |
  2. マイコン関連
  3. | トラックバック:0
  4. | コメント:0

花見

今日は朝早く出かけて、花見に行きました。最初に腹ごしらえということでマクドナルドで朝マック。そのあと、つくばの農林団地の花見に行きました。つくば周辺では桜が見事で有名なスポット。朝に行くと人が少ないので、ゆっくり花が観賞できます。桜は北の方は8分咲き、南の方は5分咲きというところでしょうか?花や家族の写真をたくさん取ってきました。
来週末のほうがもしかするとよいかもしれません。一番いいのは来週の真ん中かな?
本当は今日は歩く会に行く予定だったのですが、ちょっと風邪気味?で調子が今位置なので、花見に切り替えました。花見に行けてよかったです。
sakura_1_090405.jpg
sakura_2_090405.jpg

  1. 2009年04月05日 21:22 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

日経エレクトロニクス1001号(ハードだってオープンソース)

私は20年以上日経エレクトロニクスを読んでいる。今回の日経エレクトロニクス1001号の特集はハードだってオープンソースだった。
GaninerやArduinoの話、chumby、そして、OpenCoresのプロセッサのようなオープンソースのCPUコアの話、LatticeMico32も載っていた。P板も載っていた。
そして、自分で3DCADで書いたものをプリントしてモデルを作る3Dプリンターの話。とても、興味ぶかく、ざっと斜め読みした。実は最近、3DCADの講習会を受けているという記事を書いたのだが、その作品を実習ということで3Dプリンターでプリントしてみたのだった。ただし、1/10スケールで作った。1/1だとプリンタ内に入らない。
model_090405.jpg

高さは約18cm。表面は結構ざらざらしているが、非常によくできる。
”すろ~り~ ろぐ”さんの記事、”フリーの3DCAD”によるとフリーの3DCADもあるそうだ。私もダウンロードして試してみようと思う。
日経エレクトロニクスにも書いてあるが、ABS立体出力サービスという、STL形式かOBJ形式のファイルを送ってモデルを作ってくれるサービスもあるようだ。
面白そう。Makeにもつながる話題だと思う。
  1. 2009年04月05日 15:03 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Spartan3A Starter KitのDDR2 SDRAMコントローラの途中経過7(DQS0のみ使用)

”Spartan3A Starter KitのDDR2 SDRAMコントローラの途中経過6(DCMやBUFGの配置)”でDQやDQSの配置は終わったと思っていた。SD_LOOP_INの信号を使用して非同期FIFOにライトイネーブルを入れようと思うと、DQS0とDQS1の遅延の差が気になる。DQS0とDQS1の間には0.62nsの遅延差がある。遅延差があると、SD_LOOP_INは1つなので、どちらかにずれが出てきてしまいそうだ。と言うわけで、お間抜けで、せっかく確定したのではあるが、DQ8~DQ15のクロックをDQS1からDQS0に変更しようと思う。DQS1の入力は使用せずにライト時のクロック出力だけとする。

注:途中まで書いたのが消えてしまったのでもう一度書きますが、完全には文の一貫性が取れない場合があります。本当に悲しいです。ブログのオートセーブは新規投稿だけでした。

すべてのDQのクロックをDQS0に書き換えたところ、DQS0のクロック遅延が増えてしまった。3.597ns になってしまった。DQ0のセットアップ時間は1.592ns 。
Spa3A_DDR2_37_090403.png

これは、ddr2_cont_iob_inst/dqs_clk_node<0> が1.145ns から1.360ns になったためだ。Floorplan Editorで見てみると、下図のようになった。
Spa3A_DDR2_38_090403.png

BUFGの位置をなるべく近いほうがよいかと思って、いちばん上にして見たところ、その下よりも遅延が大きいようだ。やはり、位置では遅延は予測できないというのがよくわかった。
上のFloorplan Editor図を見るて、気がついたがddr2_cont_iob_inst/dqs_clk_node<0>のネットの遅延が違っている。よく見るとTiming Analyzerの遅延値はデータパスがMaximum値でクロックパスがMinimum値だった。これではDQ0のセットアップ時間は1.592nsは標準値ではさらに悪くなることが考えられる。これではだめなので、DQのIBUF_DELAY_VALUEを1にすることにした。IBUF_DELAY_VALUEを1にすると約1ns 程度遅延するので、少し遅延が大きすぎるきらいもあるので、BUFGまでネットの遅延が少し大きいBUFGを使用することにした。
いろいろやってみたが真ん中あたりのBUFGを使うとBUFGまでのネットの遅延が大きいようなので、上から4番目のBUFG (BUFGMUX) を使うことにした。これの状態でのDQ0のTiming Analyzerの解析結果は下図のようになった。
Spa3A_DDR2_39_090403.png

ddr2_cont_iob_inst/dqs_clk_node<0>ネットの遅延は1.436ns。
DQ0のセットアップ時間はクロックパス遅延3.675ns - データパス遅延2.962ns = 最小のセットアップ時間0.713ns となった。これより小さくなることはないので、これで大丈夫だろう。。。

さて次に、非同期FIFOのwr_en の設定を確認する。Timing Analyzerで確認したsd_loop_inのネットだが、本当にたくさんある。ちなみにsd_loop_outにリードのタイミング信号(CAS LATENCYだけ遅れた)を出力してDDR2 SDRAMのあたりまでいって戻ってきて、sd_loop_inに戻ってきた信号をリード・データの書き込みタイミングとして使おうという戦略だ。
Spa3A_DDR2_40_090403.png

これでは多すぎるので、とりあえずこのネットを減らすために、今まで、8ビット幅分散RAM使用非同期FIFO4個から、16ビット幅分散RAM使用非同期FIFO2個に変更した。パラメタライズド記述は望めないだろうから、なるべくロジックを減らそうとしてみた。これでインプリメントしてみたところ下図のFloorplan Editorに示すように、かなりロジックセルが減少した。ロジックセルは薄い紫で染められた部分。
Spa3A_DDR2_41_090403.png

以前の8ビット幅分散RAM使用非同期FIFO4個から比べるとだいぶロジックセルが減っている。下に以前のFloorplan Editorでみたロジックセルを示す。
Spa3A_DDR2_31_090330.png

これでよかったのだが、以前苦労してかけたIOパッド(IOB)から非同期FIFOまでのネットの遅延制約がインスタンスが変わってしまったので、エラーになってしまった。やり直し。。。面倒だ。。。面倒がっていても仕方がないので、Floorplannerでやり直した。
よし全部OK。
今度はSD_LOOP_INだが、セットアップ時間を1.5ns にした。これも制約をかけてクリアした。
Spa3A_DDR2_42_090403.png

次はこのIOBと非同期FIFOの部分だけでシミュレーションしてみることにする。
  1. 2009年04月04日 19:13 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

Spartan3A Starter KitのDDR2 SDRAMコントローラの途中経過6(DCMやBUFGの配置)

前回の”Spartan3A Starter KitのDDR2 SDRAMコントローラの途中経過5(ロジックセルの固定の微調整)”でデータパスの遅延調整は終了したので、今度はクロックパスの遅延を調整する。

クロックのIOB(Input Output Block) からBUFGへのネットの遅延はDQS0が3.141ns、DQS1が1.988ns。このSpartan3A-700には、8つのBUFG、4つのDCMがある。そのうちの1/2づつ、FPGAチップの上の真ん中と下の真ん中に配置されている。DQS0は下のBUFGに接続され、DQS1は上のBUFGに接続されている。下図参照。DQS1が見にくいけど青色の線、DQS0が赤色の線。
Spa3A_DDR2_31_090330.png

BUFGはDCM用に3つ、DQS0とDQS1で1つずつ使っているので、5個使用している。あと、BUFGを使う予定は、50MHzをDCMで4倍にして200MHzにする必要があるからCLK0とCLKFXにBUFGを入れる必要があるので、最低2個は必要だが、このFPGAには24個のBUFGがあるので、まだ余裕。
それにシステムクロックの位置をまだ固定していなかったので、固定しながら最適な位置を探ることにする。それにBUFGの位置をFPGAチップの左側に変更しようと思う。
まずは、BUFGの位置を固定しよう。今回はクロスプロービングしないので、Floorplan EditorでBUFGの位置を固定してみる。ProcessesウインドウのUser Constrainsを展開してFloorplan Area / IO / Logic - Post - Synthesis をダブルクリックして、Floorplan Editorを起動する。
左側の真ん中付近を"Zoom to Box"アイコンをクリックして矩形選択してズームすると、BUFG(BUFGMUX)が8個見える。一番上とその下のBUFGにDQS0とDQS1をアサインしてみる。
右上のSourcesウインドウのddr2_cont_iob_instを展開して下のほうを見るとDQS用のBUFGが2つ見える。
Spa3A_DDR2_32_090331.png

それを右側のウインドウにドラックアンドドロップする。
Spa3A_DDR2_33_090331.png

これでセーブした。そうすると下に書いた制約がUCFファイルに追加された。
I

NST "ddr2_cont_iob_inst/DQS_CLK_BUFG_INST[0].BUFG_inst" LOC = BUFGMUX_X0Y3;
INST "ddr2_cont_iob_inst/DQS_CLK_BUFG_INST[1].BUFG_inst" LOC = BUFGMUX_X0Y2;


後はシステムクロックの入力パッドの指定だが、スタータキットのユーザーズマニュアルにUCFがあるので、UCFファイルに直接記述した。

NET "sysclk" LOC = "E12"| IOSTANDARD = LVCMOS33 ;


これで再度インプリメント。
DQ0が1.145ns、DQ1が1.631nsとなった。Floorplan Editorで見てみると下図のようになった。
Spa3A_DDR2_34_090331.png

紫色の線がDQ1、赤の線がDQ0を表している。
これでデータ、クロックのネット双方ともOKになったので、IOBの遅延を加えることにする。
現在の遅延値を見てみる。まずはDQS0クロックのほうからDQ0のクロック遅延とデータ遅延を見てみると、
Spa3A_DDR2_35_090331.png

クロックの遅延が3.377ns、データの遅延が2.005nsとなり、その差が1.372nsとなっている。ここで下のタイミングチャートを参照するとわかるが、DQSとDQは同位相なので、この差はちょうど良い値になっている。このままでOKのようだ。
Spa3A_StKit_DDR2_timing_2_090322.png

同じDQS0をクロックとして使用するDQ1~DQ7までの値を見ていくと、1.332ns、1.232ns程度だった。DQ7で1.232nsなので、遅延をはさまないで、このままで行くことにする。

次にDQS1クロックの方だが、DQ8のクロックの遅延が3.957ns、データの遅延が2.075nsなので、その差は1.882ns。ちょっと差が大きいか?
FPGA Editorを使用して、DQ8のIOBのIBUF_DELAYをDLY1にしてみた。(やり方は、”ISE10.1のFPGA EditorでIOBやSLICEのパラメータを変更”を参照)
そうするとDQ8のデータの遅延は3.032ns となった。その差は0.925ns。ちょっと差が少ないかと思うけど、大丈夫かな?
Spartan3Aのデータシートをみると、CLB分散RAMのスイッチ特性で一番大きいのはTws(分散RAMのCLK入力のアクティブエッジまでに、ライトイネーブル入力が安定していなければならない時間)で-4スピードグレードで0.59ns となっているので、大丈夫そう。しかもこれは、ライトイネーブルなので、データとは関係がなく、SD_LOOP_INからのライトイネーブルに関係している信号だ。
次に、今は暫定的にFPGA EditorでIBUF_DELAYをDLY1にしたが、今度はUCFファイルに制約を書いてDQ8~DQ15までのIBUF_DELAYをDLY1にすることにする。

NET "ddr2_dq<8>" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq<9>" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq<10>" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq<11>" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq<12>" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq<13>" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq<14>" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq<15>" IBUF_DELAY_VALUE = 1;


これでインプリメントしてみると、ロジックだけで遅延が制約を超えているので、インプリメントできないというエラーが出てしまった。クロックとデータの位相が同じ状態なので、DQのタイミング制約を変更することにする
しかし、どうセットアップ時間を変えてもエラーが出てしまう。エラーを検索したところ、”19014 - 9.1i - 「ERROR:Pack: 1653 - PAR: At least one timing constraint is impossible to meet because component delays alone exceed the constraint.」というエラー メッセージが表示される”を見つけたので、それに従って、Mapのタイミング解析で解析。どうやらセットアップ時間でなくてホールド時間がだめのようなので、VALID時間も5nsに変更した。
実際の制約はこうすることにした。

NET "ddr2_dq<0>" OFFSET = IN 1.5 ns VALID 5 ns BEFORE "ddr2_dqs<0>" RISING;
NET "ddr2_dq<0>" OFFSET = IN 1.5 ns VALID 5 ns BEFORE "ddr2_dqs<0>" FALLING;


これでやっとPlace & Routeが通った。
DQ8~DQ15にIBUF_DELAY_VALUE=1を入れた結果は、最少のセットアップ時間がDQ14の0.855ns なので、大丈夫だと思う。DQとDQSの遅延関係については、このタイミングで行くことにする。
Spa3A_DDR2_36_090331.png

  1. 2009年04月02日 06:10 |
  2. Spartan3A Starter Kit
  3. | トラックバック:0
  4. | コメント:0