FC2カウンター FPGAの部屋 レジスタ設定用AXI4 Master IPをVivado HLS で作ってみた
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

レジスタ設定用AXI4 Master IPをVivado HLS で作ってみた

PWM モジュールIP をシミュレーションするために、レジスタ設定用AXI4 Master IPをVivado HLS で作ってみた。

PWM モジュールIP は単体ではVivado HLS のC/RTLコシミュレーションで、PWM がきちんと動作するのを確認した。しかし、AXI4-Lite Slave IP として実際に使用するためには、AXI4 Lite Slave スタートさせた後、オートリスタートにする必要がある。さらに、オートリスタートしている間にPWM の比率を変更できるかどうか?も気になる点だ。よって、HDL レベルでシミュレーションを行いたいのだが、依然作製してある reg_set_axi_lite_master IP では、ある一定時間Wait することができないし、Read もできないので、Vivado HLS で作ってみることにした。

Vivado HLS 2016.2 を使って、reg_write_read プロジェクトを作成した。
reg_write_read_1_160613.png

まずは、レジスタ設定のWrite/Read を指定する配列 reg_ad[AD_ARRAY_LIMIT][4] を reg_write_read.h に書いた。フォーマットを次に示す。

// reg_addr_data フォーマット、
// 第1フィールド(reg_ad[x][0]):Write - 0, Read - 1
// 第2フィールド(reg_ad[x][1]):Delay、単位はクロック数
// 第3フィールド(reg_ad[x][2]):アドレス、16進数
// 第4フィールド(reg_ad[x][3]):データ、16進数
//
// 終了は第2フィールド:Delayに 0xffffffff が書いてあったとき


例えば、{0, 10, 0x104, 2} は、Write、ディレイが10 クロック、0x104 番地に 2 をWrite する。
最初に reg_write_read.h の一部を示す。

// reg_write_read.h
// 2016/06/10 by marsee
//
// reg_addr_data フォーマット、
// 第1フィールド(reg_ad[x][0]):Write - 0, Read - 1
// 第2フィールド(reg_ad[x][1]):Delay、単位はクロック数
// 第3フィールド(reg_ad[x][2]):アドレス、16進数
// 第4フィールド(reg_ad[x][3]):データ、16進数
//
// 終了は第2フィールド:Delayに 0xffffffff が書いてあったとき

#define AD_ARRAY_LIMIT 256
#define REG_WRITE 0
#define REG_READ 1

#define R_W_FIELD 0
#define DELAY_FIELD 1
#define ADDRESS_FIELD 2
#define DATA_FIELD 3

const unsigned int reg_ad[AD_ARRAY_LIMIT][4]={
        {000x1001},
        {1200x1000},
        {0100x1042},
        {0, 0xffffffff, 0, 0},
        {1000},
        {0000},
        {1000},
        {0000},
        {1000},
        {0000},
        {1000},
        {0000},


次に、reg_write_read.cpp を示す。

// reg_write_read.cpp
// 2016/06/11 by marsee
//
// レジスタにWrite or Read する
//

#include "reg_write_read.h"

int reg_write_read(volatile int *axi4m, volatile int *dummy_out){
#pragma HLS INTERFACE ap_none port=dummy_out
#pragma HLS INTERFACE ap_ctrl_hs port=return
#pragma HLS INTERFACE m_axi depth=1024 port=axi4m offset=off

    int ret;

    for(int i=0; i<255; i++){
        if(reg_ad[i][DELAY_FIELD] == 0xffffffff) // end
            break;
        for(unsigned int n=0; n<reg_ad[i][DELAY_FIELD]; n++){ // Delay count
#pragma HLS PIPELINE II=1
            *dummy_out = n;
        }
        int index = reg_ad[i][ADDRESS_FIELD]/sizeof(unsigned int);
        if(reg_ad[i][R_W_FIELD] == REG_WRITE){
            axi4m[index] = reg_ad[i][DATA_FIELD];
        } else { // read
            *dummy_out = axi4m[index];
        }
    }
}


20行弱のコードで書けてしまった。

次にテストベンチのreg_write_read_tb.cpp を示す。

// reg_write_read_tb.cpp
// 2016/06/12 by marsee
//

int reg_write_read(volatile int *axi4m, volatile int *dummy_out);

int main(){
    int axi4m[512];
    int dm_out;

    reg_write_read(axi4m, &dm_out);

    return 0;
}


これで C コードの合成を行った。結果を示す。
reg_write_read_2_160613.png 

Verilog コードを見ると、フィールドごとにROM になっていた。第 3 フィールドのアドレスを見ると、3 桁の16進数になっていた。
reg_write_read_6_160613.png 

アドレスのROM を読み込んでいるVerilog コードを見ると、DWIDTH が 9 ビットになっていた。
reg_write_read_7_160613.png 

これは後で、最大桁のアドレスや、ディレイの値を入れる必要があるようだ。最適なビット数に丸められてしまう。C/RTL コシミュレーションの関係でこのアドレスになったが、後で修正する。

次に、C/RTLコシミュレーションを行った。
reg_write_read_3_160613.png

シミュレーション波形はできたので、見てみよう。
reg_write_read_4_160613.png

reg_write_read_5_160613.png

AXI4 Master の Write と Read がうまくできているようだ。Wait も働いているようだ。

  1. 2016年06月13日 05:52 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog.fc2.com/tb.php/3492-9f597de0
この記事にトラックバックする(FC2ブログユーザー)