前回までで、ZedBoard用のハードウェアの基盤が出来上がったので、今度はPLロジック部に追加するハードウェアを作り、IPとして追加していこう。
- 使用ツール : Vivado 2016.2
- 使用OS : Windows 10
VivadoでIPを新規作成する
前回までの状態。ZedBoardのZynqプラットフォームが定義されている。
[Tools]→[Create and Package IP]を選択すると、ウィザードがスタートする。
[Create AXI4 Peripheral]を選択しておく。
IPの情報を入力する。ここでは、AXIのスレーブIPとして、simple_bramという小さなブロックRAMを追加する。
スレーブAXIポートの名前を[S_AXI]に変更しておく。
[Edit IP]を選択して、Finishをクリックする。これでIPの外形の作成は完了だ。
simple_bram_v_1_0_S_AXI.v を編集することにする。
simple_bram_v_1_0_AXI.vの基本構造
どうやら内部を見てみると、AXIのチャネルを4つのサブチャネルに分割したサンプル構造になっているようだ。
データ幅はC_S_AXI_DATA_WIDTH
で定義されてり、8ビット毎にバイトイネーブルが定義されている。WSTRBは
input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
として定義されていた。これをブロックRAMに格納するために、以下のようなRAMを用意して、書き込みを管理するようにする。バイト単位にアドレスを変えてデータを書き込む。
reg[ 7: 0] mems0[1023: 0]; ... always @( posedge S_AXI_ACLK ) begin if ( S_AXI_ARESETN == 1'b0 ) begin end else begin if (slv_reg_wren) begin for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 0 mems0[{axi_awaddr[11: ADDR_LSB], {ADDR_LSB{1'b0}}} + byte_index] = S_AXI_WDATA[(byte_index*8) +: 8]; end end end end
データの出力は以下のような論理を組み立てる。
always @(*) begin reg_data_out <= mems[axi_raddr[11: 0]]; end // Output register or memory read data always @( posedge S_AXI_ACLK ) begin if ( S_AXI_ARESETN == 1'b0 ) begin axi_rdata <= 0; end else begin // When there is a valid read address (S_AXI_ARVALID) with // acceptance of read address by the slave (axi_arready), // output the read dada if (slv_reg_rden) begin axi_rdata <= reg_data_out; // register read data end end end
これでIPは完成だ。
IPをZynqのプラットフォームに追加する
作成したsimple_bram_v1.0
をZynqプラットフォームに追加してみよう。
Diagramから[Add IP]をクリックし、simple_bram_v1.0
をクリックする。
追加されるので、[Run Block Automation]および[Run Connection Automation]をクリックする。
[Rgenerate Layout]をクリックすることで、配線した後のレイアウトを綺麗にすることができる。
ここでアドレスマップを見てみる。アドレス0x43C0_0000から0x43C0_FFFFまでマップされていることが分かる。
参考文献
以下を参考にさせて頂いた。というかほぼパクってしまった。ありがたい。