SiTCPを利用してFPGAのSPI FLASHのリモート書き込みをします。 このモジュールはFPGAにインプリメントするファームウェアとPC上でmcsファイルを転送するrubyプログラムの2つからなります。 Xilinxダウンロードケーブルを使用するよりも高速に書き込みが行えます。
FPGA側のファームウェアはRBCPバスからの信号を内部バッファに書き込み、RBCPバスの特定のアドレスに特定の値を書き込んだイベントを検知して、それを転送スタート信号として、SPI通信を行います。 SPI通信で受信したデータは別の内部バッファに書き込まれRBCP通信を使って読み出すことが出来ます。
PC側のrubyスクリプトはmcsファイルをデコードし、UDP通信を使用してRBCPバスと通信を行います。 SPI FLASHに送るコマンド・アドレス・データの管理は主にrubyが行っています。 SPI FLASH情報はYAMLファイルに格納されているため、互換性のあるSPI FLASHであればYAMLファイルに追記することで対応させることができます。
- Artix 7 シリーズFPGA
(デバイスに依存する書き方はしていないので他のFPGAでも対応可能なはず)
- 以下のSPI FLASH
M25P32, M25P64, M25P128, N25Q032, N25Q064, N25Q128, N25Q256, W25Q32BV, W25Q64BV, W25Q128BV, W25Q80BW, W25Q64FV, W25Q128FV, W25Q32DW, W25Q64DW
これ以外のデバイスも互換性のあるものであれば、デバイス定義ファイルを更新することで対応することが出来ます。
- Cygwin or Linux
Windowsにもそのうち対応予定
- Ruby >= 2.1.0
Scientific LinuxにインストールされているRubyは古いので[Ruby][Ruby]からインストールすることをお勧めします。 [Ruby]: https://www.ruby-lang.org/
基本的には[Using SPI Flash with 7 Series FPGAs][XAPP586]を参考に接続してください。 7シリーズからCCLKをGPIOとして使用することが出来なくなっているので、他のGPIOをSPI FLASHのクロック入力ピンと接続してください(USER_CLK)。 コンフィグ後のCCLKをフローティングにすることでCCLKとUSER_CLKの衝突を防ぐことが出来ます。
fpgaディレクトリ内のVHDLファイルをプロジェクトに追加し、SPI-FLASH-Programmerをインスタンシエートしてください。
各ポートは次のように接続してください。
ポート名 | 方向 | ビット幅 | |
---|---|---|---|
SPI_CLK | 入力 | 1 | SPI通信用クロック入力 SPI FLASHにはこの半分の周波数でSPI通信が行われます。 |
SITCP_CLK | 入力 | 1 | SiTCPクロック入力 RBCPバスを駆動しているクロックを入力 |
RESET | 入力 | 1 | リセット入力 |
RBCP_ACT | 入力 | 1 | RBCP_ACT入力 |
RBCP_ADDR | 入力 | 32 | RBCP_ADDR入力 |
RBCP_WE | 入力 | 1 | RBCP_WE入力 |
RBCP_WD | 入力 | 8 | RBCP_WD入力 |
RBCP_RE | 入力 | 1 | RBCP_RE入力 |
RBCP_RD | 出力 | 8 | RBCP_RD出力 |
RBCP_ACK | 出力 | 1 | RBCP_ACK出力 |
SPI_SCLK | 出力 | 1 | SPI FLASHのクロック入力 |
SPI_SS_N | 出力 | 1 | SPI FLASHのチップセレクト |
SPI_MOSI | 出力 | 1 | SPI FLASHのデータ入力に接続 |
SPI_MISO | 入力 | 1 | SPI FLASHのデータ出力に接続 |
方向はSPI-FLASH-Programmerから見た入出力の方向です。 SPI_CLKに供給する周波数は各SPI FLASHのデータシートを参照の上決定ください。
ジェネリックには次のように値を設定してください。
ジェネリック名 | データ型 | |
---|---|---|
G_SPI_FLASH_PROGRAMMER_ADDRESS | std_logic_vector(31 downto 0) | 割り当てるRBCPアドレスの開始アドレス |
G_SITCP_CLK_FREQ | real | SITCP_CLKの周波数(MHz) |
G_SPI_CLK_FREQ | real | SPI_CLKの周波数(MHz) |
SPI-Flash-ProgrammerにG_SPI_FLASH_PROGRAMMER_ADDRESSから始まる8195byte分のアドレス空間を割り当ててください。
RBCPバスに他のモジュールが接続されているときにはRBCP_RD、RBCP_ACKを次のように処理してください。
RBCP_RD <= RBCP_RD_SPI_PROGRAMMER when(RBCP_ACK_SPI_PROGRAMMER = '1') else
RBCP_RD_OTHER_MODULE when(RBCP_ACK_OTHER_MODULE = '1') else
(others => 'X');
RBCP_ACK <= RBCP_ACK_SPI_PROGRAMMER or RBCP_ACK_OTHER_MODULE;
SPI_*の接続先は多くのSPI FLASHでは次のような名称のピンになっています。
SPI-FLASH-Programmerのポート名 | SPI FLASHのピン名 |
---|---|
SPI_SCLK | C |
SPI_SS_N | S# |
SPI_MOSI | DQ0 |
SPI_MISO | DQ1 |
セットアップタイムの確保のためにSPI_*はIOBのレジスタにマップするように配置制約をかけてください。
set_property IOB true [get_ports SPI_SCLK]
set_property IOB true [get_ports SPI_SS_N]
set_property IOB true [get_ports SPI_MOSI]
set_property IOB true [get_ports SPI_MISO]
コンフィグ後のCCLKピンがフロートになるように制約をかけてください。
set_property BITSTREAM.CONFIG.CCLKPIN Pullnone [current_design]
インターネットに接続されているPCでpc/install.sh
を実行してください。
必要なライブラリがインストールされます。
Rubyのバージョンが古い場合は2.1.0以上をインストールしてください。
settings.ymlを以下のように変更してください。
udp_port: <UDP port>
rbcp_address: <RBCP address of SPI-FLASH-Programmer>
-
udp_port
: RBCP通信に使用するUDPポート番号(通常は4660) -
rbcp_address
SPI-FLASH-Programmerをインプリメントする際に割り当てたRBCPアドレス
そして以下のコマンドを実行して書き込みを行ってください。
pc/spi_flash_programmer.rb [option] <IP address> <mcs file>
以下のオプションに対応しています。
--port
: UDPポート番号 setting.ymlに書いたものよりもこちらが優先される。-q, --quiet
: プログレスバーとSPI FLASH情報を表示しない-h, --help
: ヘルプメッセージを表示する-v, --version
: バージョンを表示する
-
<IP address> is unreachable
<IP address>にしてpingが通りません。- 指定したIPアドレスがSiTCPのものか確認してください。
ボードの電源が入っており、FPGAのRAMにファームウェアが書き込まれていることを確認してください。
- 指定したIPアドレスがSiTCPのものか確認してください。
-
Verify failed
Erase、Write後のVerifyに失敗しました。- SPI FLASHにファームウェアが正常に書かれていない可能性が高いです。
ファームウェアの書き込みをもう1度行ってください。 - それでも解決しない場合は
SPI_*
ピンのタイミング制約が間違っている場合があります。
SPI FLASHデバイスのセットアップタイム、ホールドタイムを満たしているか確認してください。
- SPI FLASHにファームウェアが正常に書かれていない可能性が高いです。
-
No such file: <mcs file>
mcsファイルが見つかりません。- mcsファイルへのパスが正しいか確認してください。
-
<mcs file> is broken
mcsファイルが破損しています。- ISE, vivadoを使用して生成しなおしてください。
-
unknown JEDEC ID code
対応していないJEDECコードのSPI FLASHが接続されています。- M25Pと互換性のあるデバイスであればデバイス情報をdevice.ymlに追記することで対応することが出来ます。
- device.ymlにデバイス情報が書かれているにも関わらずこのエラーが出る場合は
SPI_*
ピンのタイミング違反が考えられます。
SPI FLASHデバイスのセットアップタイム、ホールドタイムを満たしているか確認してください。
-
capacity of SPI FLASH is smaller than binary size
SPI FLASHの容量がmcsファイルのサイズより小さいです。- mcsファイル生成の際に指定したSPI FLASHのサイズを確認してください。
-
RBCP Timeout
RBCP通信がタイムアウトしました。- 指定したIPアドレスがネットワークに存在しますが、SiTCPではない可能性があります。 IPアドレスを確認してください。
- インスタンシエートしたアドレスをsettings.ymlに正しく設定していない可能性があります。 ファームウェアのソースコードとsettings.ymlを確認してください。
- SPI-FLASH-Programmerの使用しているRBCPアドレスが競合している可能性があります。 RBCPのアドレスマップを再確認してください。
-
RBCP Error
その他のRBCP通信に関するエラーです。- SPI-FLASH-Programmerの使用しているRBCPアドレスが競合している可能性があります。
RBCPのアドレスマップを再確認してください。
- SPI-FLASH-Programmerの使用しているRBCPアドレスが競合している可能性があります。
使用デバイス: XC7A100T-2
論理合成ツール: vivado 2014.1
合成オプション:
synth_design -top TopLevel -part xc7a100tfgg676-2 -flatten_hierarchy rebuilt
opt_design
power_opt_design
place_design
phys_opt_design
route_design
プリミティブ | 使用数 |
---|---|
LUT | 107 |
FFs | 137 |
RAMB36 | 2 |
RAMB18 | 1 |
使用デバイス: XC7A100T-2
SPI FLASH: M25P32 (32Mbit)
書き込みケーブル: XILINX Platform Cable USB
SPI_CLKの周波数: 66MHz
書き込み方法 | 書き込み時間 |
---|---|
iMPACT 14.6 | 8:00 |
SPI-FLASH-Programmer | 1:22 |
SPI FLASHはM32Pと互換性を持っており、以下のコマンドセットに対応している必要があります。
コマンド名 | コマンド | アドレス長 | データ長 |
---|---|---|---|
READ_DATA_BYTE | 0x03 | 3 | 1~∞ |
READ_STATUS_REGISTER | 0x05 | 0 | 1 |
READ_IDENTIFICATION | 0x9F | 0 | 20 |
WRITE_ENABLE | 0x06 | 0 | 0 |
PAGE_PROGRAM | 0x02 | 3 | 1~256 |
SECTOR_ERASE | 0xD8 | 3 | 0 |
BULK_ERASE | 0xC7 | 0 | 0 |
ただし、256Mbit以上のデバイスは代わりに以下のコマンドセットに対応している必要があります。
コマンド名 | コマンド | アドレス長 | データ長 |
---|---|---|---|
4_BYTE_ADDRESS_READ_DATA_BYTE | 0x13 | 4 | 1~∞ |
READ_STATUS_REGISTER | 0x05 | 0 | 1 |
READ_IDENTIFICATION | 0x9F | 0 | 20 |
WRITE_ENABLE | 0x06 | 0 | 0 |
4_BYTE_ADDRESS_PAGE_PROGRAM | 0x12 | 4 | 1~256 |
4_BYTE_ADDRESS_SECTOR_ERASE | 0xDC | 4 | 0 |
BULK_ERASE | 0xC7 | 0 | 0 |
デバイス情報を以下のフォーマットに従ってdevices.ymlに追記してください。
<JEDEC ID code>: {
name: <Device name>,
capacity: <Capacity in Mbit>,
sector: <total sector>,
sector_size: <sector size in KB>,
address_mode: <address mode 3 or 4>
},
-
JEDEC ID code
: READ_IDENTIFICATIONコマンドで読み出した時の最初の3byte -
capacity
デバイスの容量をMbit単位で -
sector
全セクター数 -
sector_size
ERASE_SECTORコマンドで消すことのできるセクターサイズをKB単位で -
address_mode
アドレスモードを3byteにするか4byteにするか。256Mbit以上であれば4、以下であれば3に設定
- mcsファイルのアドレスが連続していないときにはmcsファイルのデコードを正しく行えない ISE、vivadoの出力するmcsファイルはそのようなフォーマットになっていないので実用上問題ありません。
- [SiTCP][SiTCP]
- [Using SPI Flash with 7 Series FPGAs][XAPP586]
- [Intel HEX format][IntelHEX] [SiTCP]: http://research.kek.jp/people/uchida/technologies/SiTCP/ [XAPP586]: http://www.xilinx.com/support/documentation/application_notes/xapp586-spi-flash.pdf [IntelHEX]: http://en.wikipedia.org/wiki/Intel_HEX
Copyright © 2014 Takehiro Shiozaki Licensed under the [MIT License][MIT]. [MIT]: http://www.opensource.org/licenses/mit-license.php