PYNQ で遊ぶ : 3. BRAM を使う (1)


これは何か

PYNQ-Z1 を使って遊んでみます。

今回は、下記ができるようになる事を目指します。

  • BRAM を使ってみる
    • (本記事) AXI BRAM Controller を使って python から読み書きしてみる
    • (次の記事) 自作 IP を接続して、FPGA 内部で生成したデータを python から読み出してみる
関連記事:

関連するリンク

BRAM の概要

  • BRAM は、FPGA 内部に実装されたメモリです
  • 7 シリーズの場合、BRAM 1 つで、18 Kbit x2、または 36 Kbit x1 として使えます
  • PYNQ-Z1 に搭載されている XC7Z020-1CLG400C の場合、140 個乗っています (DS190 参照)

  • また、出力レジスタなし (1CLK) で取り出す場合 288 MHz、出力レジスタあり (2CLK) で取り出す場合 382 MHz で駆動可能です (PG58 参照)

  • 実際の FPGA 上での配置は下のような雰囲気です

3-1. プロジェクトの作成

3-2. BRAM 関連の IP を配置する

3-2-1. Block Memory Generator IP を配置する

IP を検索し、追加。

Block Memory Generator が追加されました。

今回はデフォルトのまま使用します。

3-2-2. AXI BRAM Controller IP を配置する

IP を検索し、追加。

配置されました。

デフォルトでは PORT A, PORT B が利用可能です。
PORT A だけを使用するように設定してみます。他のパラメータはデフォルトのままです。

3-2-3. 配線する

axi_bram_ctrl_0.BRAM_PORTA を blk_mem_gen_0.BRAM_PORTA に接続します。

配線されました。

Run Connection Automation を実行します。

配線されました。

Run Block Automation を実行します。

最終的にこうなりました。

BRAM の設定を確認してみましょう。

8 BRAM 使用して、1 クロックでデータを取り出せるようです。

3-3. 後仕上げ

3-3-1. HDL Wrapper を生成する

手順 1-5. HDL Wrapper を生成する と同様の手順です

3-3-2. 生成する

手順 1-7. 生成する と同様の手順です

こんな実装になりました。

3-4. PYNQ で実行する

3-4-1. ファイルのアップロード

scp ~/vivado/asobu/asobu03/asobu03.runs/impl_1/design_1_wrapper.bit [email protected]:pynq/overlays/asobu03/asobu03.bit
scp ~/vivado/asobu/asobu03/asobu03.srcs/sources_1/bd/design_1/hw_handoff/design_1.hwh [email protected]:pynq/overlays/asobu03/asobu03.hwh

3-4-2. jupyter で実行

asobu03.ipynb
import pynq
fpga = pynq.Overlay('asobu03.bit')

bram = pynq.MMIO(fpga.ip_dict['axi_bram_ctrl_0']['phys_addr'], length=8*1024)

# 読み込んでみます。
bram.read(0)
# >> 0
# 初期値は 0 が入っていました。

# 別の値を入れてみます。
bram.write(0, 100)
bram.read(0)
# >> 100

# 別のアドレスに値を入れます。
# read, write は 4 byte 単位でアクセスします。
# アドレス (offset) は、byte 単位で入れます。
[bram.write(i*4, i) for i in range(100)]

# 読み出してみましょう。
d = [bram.read(i*4) for i in range(100)]

d[20:30]
# >> [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
# 取り出せました。