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
- 机上確認
- 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/DI | HC_SD_CMD | FPGA.output | HSMC_D3 | HSMC#44 | FPGA-L6 |
DAT/DO | HC_SD_DAT | FPGA.input | HSMC_D5 | HSMC#48 | FPGA-M3 |
DAT3/CS | HC_SD_DAT3 | FPGA.output | HSMC_D8 | HSMC#53 | FPGA-N8 |
CLK | HC_SD_CLK | FPGA.output | HSMC_TX_p8 | HSMC#101 | FPGA-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を介さずに音声なり動画なりを再生させることができそう.
まだまだ先の話ですが
モジュールのアドレス空間
offset | symbol | description |
---|---|---|
0 | status | SPIステータス,送受信データ(8bit) |
1 | divide | SPI clockに用いるmodule入力クロックの分周比(FofSCK = 入力周波数/divide/2) |
2 | timer | タイムアウト検出用ダウンカウンタ(module input clockで動作).0で止まる |
3 | reserved0 | (予約/現実装ではstatusが見える) |
4 | dmastatus | DMAステータス |
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-16 | const zero | - |
15 | 割込み許可フラグ | 1:mmc_irq_enable |
14-13 | const zero | - |
12 | MMC I/F FRCゼロフラグ | 1:mmc_zf_bitmask |
11 | MMC-Write Protect | 1:mmc_wp_bitmask |
10 | MMC-Card Detection | 1:mmc_cd_bitmask |
9 | MMC I/F転送フラグ(0書き込みで転送開始要求) | 1:mmc_commexit / 0:mmc_commstart |
8 | MMC Chip Select(Active Low) | 1:mmc_selnegete / 0:mmc_selassert |
7-0 | MMC I/F受信データ | 8bitデータ.読み出し=RxData,書き込み=TxData(txdataのリードバック不可) |
dmastatus
bit | description | mmc_spi.hシンボル |
---|---|---|
31-16 | const zero | - |
15 | DMA function IRQ enable bit(1:enable, 0:disable) | mmc_dmairq_enable |
14 | assert(0->1) when transfer-ends | mmc_dmadone_bitmask |
13 | 1:受信データエラー@SPI | mmc_dmade_bitmask |
12 | 1:受信タイムアウト@SPI | mmc_dmato_bitmask |
11 | const zero | - |
10 | w1:転送開始,r1:転送中/r0:転送終了 | mmc_dmastart |
9 | const zero | - |
8-0 | 転送バイト数 | - |