🏩

VitisHLS 高位合成によるビットブロック表示回路の作成

2023/04/26に公開

VitisHLS高位合成によるビットブロック表示回路の作成

はじめに

前回に続き、「FPGAプログラミング大全 第2版」をやる
https://amzn.to/40isQyG

本投稿では本書11-2~「高位合成の応用」を実施したメモを書きます
内容としては前回記事の続きです

環境

FPGA : Xilinx Zybo Z7-20
OS : WSL2 Ubuntu20.04
開発環境 : Vivado ML edition 2022.1 Linux版

やりたいこと

Vitis HLSを使って高位合成によってビットブロック表示回路を作る
IP化を行い、前回作成したパターン表示回路と合わせてZynqのブロックデザインに組み込み実機確認まで行う
https://zenn.dev/ryo_tan/articles/f04c19d2268a79

ビットブロック描画回路仕様

  • 転送元の画像を2つ用意できる
  • 透明度αにより2つの画像に対する画素間演算を行う
  • 演算結果を表示用メモリに格納する

実装

projectの作成~回路合成

*ソースコードは以下より
https://www.shuwasystem.co.jp/support/7980html/6326.html

  • SourceとTest benchを追加
  • Directiveの追加
  • C synthesis

下記はSourceに対してDirectiveを付与したもの

#include <ap_int.h>
#include "bitblt.h"


u32 calc(u32 src, u32 dst, u8 alpha)
{

    u32 src_r = (src>>16) & 0xff;
    u32 src_g = (src>> 8) & 0xff;
    u32 src_b =  src      & 0xff;

    u32 dst_r = (dst>>16) & 0xff;
    u32 dst_g = (dst>> 8) & 0xff;
    u32 dst_b =  dst      & 0xff;

    dst_r = (alpha*src_r + (255-alpha)*dst_r)/255;
    dst_g = (alpha*src_g + (255-alpha)*dst_g)/255;
    dst_b = (alpha*src_b + (255-alpha)*dst_b)/255;

    return ((dst_r<<16) & 0xff0000) | ((dst_g<<8) & 0xff00) | (dst_b & 0xff);
}

void bitblt(
    volatile u32 *srcin,
    volatile u32 *dstin,
    volatile u32 *dstout,
    u8  alpha,
    u11 width,
    u11 height)
{
#pragma HLS INTERFACE mode=s_axilite port=height
#pragma HLS INTERFACE mode=s_axilite port=width
#pragma HLS INTERFACE mode=s_axilite port=alpha
#pragma HLS INTERFACE mode=m_axi bundle=dst depth=307200 max_write_burst_length=32 num_write_outstanding=16 port=dstout offset=slave
#pragma HLS INTERFACE mode=m_axi bundle=dst depth=307200 max_write_burst_length=32 num_write_outstanding=16 port=dstin offset=slave
#pragma HLS INTERFACE mode=m_axi bundle=src depth=307200 max_read_burst_length=32 num_read_outstanding=16 port=srcin offset=slave
    u32 src[XSIZE], dst[XSIZE];

    height_loop: for (int y=0; y<height; y++) {
#pragma HLS LOOP_TRIPCOUNT avg=240 max=480 min=1
#pragma HLS DATAFLOW
        src_loop: for (int x=0; x<width; x++) {
#pragma HLS PIPELINE
#pragma HLS LOOP_TRIPCOUNT avg=320 max=640 min=1

            src[x] = srcin[x + y*XSIZE];
        }
        dstin_loop: for (int x=0; x<width; x++) {
#pragma HLS PIPELINE
#pragma HLS LOOP_TRIPCOUNT avg=320 max=640 min=1

            dst[x] = dstin[x + y*XSIZE];
        }
        dstout_loop: for (int x=0; x<width; x++) {
#pragma HLS PIPELINE
#pragma HLS LOOP_TRIPCOUNT avg=320 max=640 min=1
            dstout[x + y*XSIZE] = calc(src[x], dst[x], alpha);
        }
    }
}


合成結果

  • 動作周波数・サイクル
  • 回路規模

C-RTL Cosimulation

  • C-RTL Cosimulationを実行
  • 1ライン目はsrc,dst各1ポートずつReadしており、dstの書き込みは行われていない

1画素のトランザクション

  • src port Read: burst長=32、Hライン画素数320より、320/32=10トランザクション

  • dst port Read: burst長=16、Hライン画素数320より、320/16=20トランザクション

  • トランザクション終了後にR/AR ValidがLになり、次のVラインまでのマージンを設けている

  • 画素最終部分。1画素目とは反対に、dstポートの書き込みのみが行われている。ここからパイプライン処理が実装されていると分かる

出力の確認

テストベンチで作成したrawfileを確認

  • 中央部分が青+赤になっており、画素同士の補正ができている

    データ的にはこの部分

Export RTLよりIP化して終了

Discussion