2009/01/14(水)[HDL][Quartus II] constant function

[Quartus II][HDL]今日の不思議:constant functionが作れない?

状況

parameter化を行うため,カウンタに必要なビット数を得たいと考えた.同様のVHDL実装は,FPGAの部屋で紹介されていました.どこかで見かけたなぁと思ったら,Verilog2001-LRMの"constant function"の使い方として紹介されていました.

ところが,QuartusII v8.1(SOPC Builderのmodule登録時のAnalysis)にてsynthesisを試みたところ,エラーが出てきました.エラーはVerilog codeの中にコメントで記します.

妄想

function文が,constantを返すと認識していないようですねぇ.\QuartusIIの制限事項にでも記載されているのかしら(未確認).Verilog-2001対応のはずですよね...

とりあえずcounter変数をintegerとして逃げました.regでビット幅を指定すると,余計なレジスタを作らないので安心なのですが.integerならbit幅違いや定数のビット数指定が抜けてもwarningが出ないので見た目が気持ち良いというか何というか….

	parameter CLK_DIVIDER = 2 ;
	localparam CLK_DIVIDER_WIDTH = clogb2(CLK_DIVIDER) ;
	// Error: Error (10192):
	// Verilog HDL Defparam Statement error at avalonif_dai.v(49):
	// value for parameter "CLK_DIVIDER_WIDTH" must be constant expression File: ----


//////////////////////////////////////////////////////////////////////
// Verilog LRM "10.3.5 Use of constant functions"
//

// define the clogb2 function
  function integer clogb2;
    input depth;
    integer i,result;
    begin
      for (i = 0; 2 ** i < depth; i = i + 1)
        result = i + 1;
      clogb2 = result;
    end
  endfunction

参考(VHDLでのLOG2実装例)

ttp://www.opencores.org/cvsweb.cgi/~checkout~/AVR_Core/VHDL/AVRuCPackage.vhd?rev=1.1.1.4;content-type=text%2Fplain

勝手に持ってきたのでこっそりと(ぇ

-- Functions
function LOG2(Number : positive) return natural is
  variable Temp : positive := 1;
  begin
    if Number=1 then
      return 0;
    else
      for i in 1 to integer'high loop
        Temp := 2*Temp;
          if Temp>=Number then
            return i;
          end if;
      end loop;
    end if;
end LOG2;
-- End of functions

2009/01/06(火)[SOPC] 長船さんのMMC/SPIインタフェース

はじめに

SPIコアのコメントで,長船さんからSDカードアクセスまで動作した実績のIPを開示いただいた.これをNEEKに組み込んでみようというネタ.

動作確認ができたのでクローズ.HDL開示は別記事にて予定...



問題発生

いただいたVHDLコードをとりこんで,SOPC Builderで論理合成をパス.しかし,Nios II IDEで作ったコードをダウンロード実行してもSDカードのIDLEへの遷移が確認できず(デバッガによるトレース).

実績のあるIPであることから,端子割付やタイミング設定が怪しまれる.ModelSimは,WEB editionだとVerilog-HDLとVHDLの混在シミュレーションができない*1

勉強もかねて,Verilog-HDLへの移植を行うこととした.


*1 : ModelSIM SE以上でないといけないハズ...?

やったこと/やってること/やろうとしていること

やったこと~1

  • 机上確認
    • Verilog移植\OK@6/Jan./2009\長船さんから公開していただいたSPI interface IPを元に移植.FatFSも最近のものへと置換した.\レジスタ初期化漏れをsimulationで検出し,修正済み.\(実使用上は問題ない.合成時にロジックが増えるかもしれないので,ゲート数削減のためにリセット時未初期化にしたのかもしれない.)\OK@7/Jan./2009\tclを手動編集:set_interface_property avalon_slave_0 addressSpan 1024\TOPレベルモジュールのport宣言でin/outを間違っていた.\Timeout検出用のカウンタ(FRC)の実装漏れ….あとで処理しようとして放置していた.ボケとる.
    • Simulation確認\たぶんOK@6/Jan./2009\制御レジスタへのアクセス,SCKtxdatレジスタの変化を確認できた.
    • ピンアサイン確認\SDまわり問題なしぽい.@1650訂正\TOP moduleにて,DI/DOを逆に接続していた.下表のようにまとめてみると間違いに気づけるわ….\本日実機を持ってきていないのでここまで.\参考:NEEKの端子一覧(まとめなおして移動するかも?)
SD pin symbol name Direction HSMC name HSMC pin FPGA pin name
CMD/DIHC_SD_CMDFPGA.outputHSMC_D3HSMC#44FPGA-L6
DAT/DOHC_SD_DATFPGA.inputHSMC_D5HSMC#48FPGA-M3
DAT3/CSHC_SD_DAT3FPGA.outputHSMC_D8HSMC#53FPGA-N8
CLKHC_SD_CLKFPGA.outputHSMC_TX_p8HSMC#101FPGA-M2

  • 実機確認
    • signal測定\レベル確認(アナログ),SCK確認,SDI確認(SD挿入時).(TxDataは0xFFなので変化しない)
    • タイミング確認(実時間)\\

何か出ているならロジアナで吸い上げてタイミングを確認する.

    • SD応答確認

期待通りならSDカードを取り替えたりして確認する.

やったこと~2

ModelSim(WebEdition)にて,タイミング確認.

  • DMA機能を使わず,SPI部のみを使った動作確認\→正常に動作した
  • DMA機能のステートマシンチェック\→シミュレーションレベルでは正常そう
  • DPRAMアクセス\write機能が無かったのでエイヤで実装した.\byte enableを使ってBYTEアクセスを許容し,write時にもDMA転送ができるように見越しても良いだろう.

最終日のオチ

  • Verilogへの移植の際に実装漏れ,実装ミスがあった.
  • MegaWizardで生成したDualport RAMブロックについても,出力段にレジスタを入れていたため,リードレイテンシ2でのCPU読み出しが成功するときとしないときがあった.\NiosII IDEから8bit/16bit/32bitアクセスを行った際に,連続・ステップ実行・Memory Dumpで読み出せる値が変化したことから明確になった.

※32bit接続のIPであっても,NiosIIのDynamicBUS sizing?により必要な値(BYTE)だけを正しく取得することができた.おそらくarbitorのあたりでうまいことやってるのだろう.



メモ

SPI/MMCインタフェースIPの移植

Avalon-MM I/Fの参考にさせていただきました.Quartus II 8.1の SOPC builderにある,Wizardを使ったりしながら再構築.tclファイルを作らせるために,Wizardを使ったほうが便利かもしれません(慣れればテキストのほうが早いか?).

当初はAvalon-MMの読み出しにレイテンシ2としていたのが不思議であったが,メモリセルのレイテンシであることが理解できた.レジスタリードについては,常にデコードしており,chipselect信号がアサートされればreaddataに正しい値が出力される.

レイテンシ0の場合って,前段のDDがアドレス・制御信号を出した次のクロックで出力をラッチするんですよね...アービタも通るし,配置制約として効いてきそうな気がしますねぇ.

動作としては,SDからリード時に,IP内のDPRAMへ指定ワード数だけデータ転送を行うIPでした.CPUのポーリング動作が要らないので便利そうです.
書き出しはCPU転送になっているようですが,現状読み出ししか考えて無いので問題なし.

拡張してAvalon-ST source portとしてデータクラスタだけ吐き出せると旨いかもしれないですね.ストリーミング再生時,CPUを介さずに音声なり動画なりを再生させることができそう.
まだまだ先の話ですがtp252_shock



モジュールのアドレス空間

offset symbol description
0statusSPIステータス,送受信データ(8bit)
1divideSPI clockに用いるmodule入力クロックの分周比(FofSCK = 入力周波数/divide/2)
2timerタイムアウト検出用ダウンカウンタ(module input clockで動作).0で止まる
3reserved0(予約/現実装ではstatusが見える)
4dmastatusDMAステータス
5~reserved[123](予約)
128~readbuff[128]DMA転送バッファ(現状読み出しのみ)

※offsetは,32bit word指定.CPUからのアドレスは x4して見える.※使用メモリ256Word = 1024Byte = 10bit

ビットフィールド

status(MMC IF status)
bit description mmc_spi.hシンボル
31-16const zero-
15割込み許可フラグ1:mmc_irq_enable
14-13const zero-
12MMC I/F FRCゼロフラグ1:mmc_zf_bitmask
11MMC-Write Protect1:mmc_wp_bitmask
10MMC-Card Detection1:mmc_cd_bitmask
9MMC I/F転送フラグ(0書き込みで転送開始要求)1:mmc_commexit / 0:mmc_commstart
8MMC Chip Select(Active Low)1:mmc_selnegete / 0:mmc_selassert
7-0MMC I/F受信データ8bitデータ.読み出し=RxData,書き込み=TxData(txdataのリードバック不可)
dmastatus
bit description mmc_spi.hシンボル
31-16const zero-
15DMA function IRQ enable bit(1:enable, 0:disable)mmc_dmairq_enable
14assert(0->1) when transfer-endsmmc_dmadone_bitmask
131:受信データエラー@SPImmc_dmade_bitmask
121:受信タイムアウト@SPImmc_dmato_bitmask
11const zero-
10w1:転送開始,r1:転送中/r0:転送終了mmc_dmastart
9const zero-
8-0転送バイト数-