アウトプットブログ

勉強したことをまとめていきます。

DPI-CでVHDLモジュールの処理結果をコンペア

前回BMPファイルをDPI-C経由でVHDLモジュールに入力できました。今回はVHDLモジュールの出力結果をC関数に入力してコンペアを取ってみました。

以下テストベンチの流れです。
1.シミュレーション開始時にC関数によりBMPファイル読込と比較データ生成を実施。
2.毎クロックVHDLモジュールに画像データ入力。モジュールは画素値を2倍して出力する。
3.2倍された画素値をC関数に入力。コンペア結果をSystemVerilogへ返す。

ここでVHDL側はHigh Clip未実施、C側は実施としました。コンペアが正常動作しているかの確認のためです。
※High Clip:計算結果が255を超えた場合に値を255とする

以下ソースです。hoge_cは前回からの追加分のみ記載しています。
hoge_c.c

int cx, cy;         // 比較画像インデックス
char *compImage;    // 比較データ
// compare
int generateCompareData()
{
    int i, j, tmp;
    // 画像が読み込まれていることを確認
    if (bmpInfo.imageData == NULL) {
        printf("bmpInfo.imageData == NULL\n");
        return -1;
    }
    // 比較画像生成
    compImage = (char*)malloc(sizeof(char) * width * height);
    // 比較データ生成
    for (j = 0; j < height; j++) {
        for (i = 0; i < width; i++) {
            // 画像データを2倍
            tmp = 2 * bmpInfo.imageData[i + j * stride];
            // High Clip処理
            if (tmp > 255)  compImage[i + j * stride] = 255;
            else            compImage[i + j * stride] = (char)tmp;
        }
    }
    // インデックス初期化
    cx = 0;
    cy = 0;
    // 正常終了
    return 0;
}
// 画像比較
char compareImage(char data)
{
    char cRet = 0;
    // コンペア実施
    if (data != compImage[cx + cy * stride])    cRet = 1;   // NG
    // インデックスを進める
    // 画像左上から右へ進み、一番右まで進んだら次行の左端からといったように進み
    // 画像右下まで進んだらまた画像左上から開始して、以下ループ
    if (cx == (width - 1)) {
        cx = 0;
        if (cy == (height - 1)) cy = 0;
        else                    cy += 1;
    } else {
        cx += 1;
    }
    return cRet;
}

hoge_vhd.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity hoge_vhd is
    port (
        srst_i  :   in  std_logic;
        clk_i   :   in  std_logic;
        
        valid_i :   in  std_logic;
        d_i     :   in  std_logic_vector (7 downto 0);
        valid_o :   out std_logic;
        d_o     :   out std_logic_vector (7 downto 0)
    );
end hoge_vhd;

architecture rtl of hoge_vhd is

signal add  :   std_logic_vector (8 downto 0);

begin
-- 加算
add <= ('0' & d_i) + ('0' & d_i);
process (clk_i) begin
    if (rising_edge(clk_i)) then
        if (srst_i = '1') then
            valid_o <= '0';
            d_o     <= (others => '0');
        else
            valid_o <= valid_i;
            d_o     <= add(7 downto 0);
        end if;
    end if;
end process;

end rtl;

hoge_sv.sv

timeunit 1ns;
timeprecision 10ps;

module hoge_sv();
    // C関数をインポート
    import "DPI-C" function void callReadBMP();
    import "DPI-C" function byte getBMPData();
    import "DPI-C" function void freeImage();
    import "DPI-C" function int generateCompareData();
    import "DPI-C" function byte compareImage(byte data);
    // 信号宣言
    bit clk_i = 1'b0;   // クロック
    bit srst_i = 1'b1;  // リセット
    bit valid_i = 1'b0; // 画像有効信号
    byte d_i;           // 画像データ
    bit valid_o = 1'b0; // 2倍データ有効信号
    byte d_o;           // 画素値2倍データ
    byte cRet = 8'h00;  // 比較結果確認用
    
    // クロック
    always begin
        #5ns clk_i = ~clk_i;
    end
    
    // リセット
    initial begin
        #100ns;
        @(posedge clk_i) #1ps srst_i = 1'b0;
    end
    
    // シミュレーション開始直後にBMPファイル読み込みと比較データ生成
    initial begin
        callReadBMP();
        generateCompareData();
    end
    
    // 画像データ読み込みイネーブル
    always @(posedge clk_i) begin
        if (srst_i) begin
            valid_i = 1'b0;
        end else begin
            valid_i = 1'b1; // 今回は有効っぱなし
        end
    end
    
    // イネーブル有効中は毎クロック画像データを読み込み
    always @(posedge clk_i) begin
        if (srst_i) begin
            d_i = 8'h00;
        end else begin
            if (valid_i == 1'b1) begin
                d_i = getBMPData();
            end
        end
    end
    
    // 入力データを2倍して出力(high clip)
    hoge_vhd u_vhd (
        .srst_i(srst_i),    //: in  std_logic;
        .clk_i(clk_i),      //: in  std_logic;
        
        .valid_i(valid_i),  //: in  std_logic;
        .d_i(d_i),          //: in  std_logic_vector (7 downto 0);
        .valid_o(valid_o),  //: out std_logic;
        .d_o(d_o)           //: out std_logic_vector (7 downto 0)
    );
    
    // 2倍データ有効信号アサート中コンペア実施
    always @(posedge clk_i) begin
        if (srst_i) begin
            cRet = 8'h00;
        end else begin
            if (valid_o == 1'b1) begin
                cRet = compareImage(d_o);
            end else begin
                cRet = 8'h00;
            end
        end
    end
endmodule

シミュレーションしてみると、255を超えた場合のコンペア結果がcRetが1となっており、コンペアできているようです。
f:id:HappyField:20151206000000p:plain

とりあえず最低限のことは出来たので、DPI-Cはひと段落とします。本当はVisual C++で生成したDLLを使用してシミュレーションできるといいんですが…。何回かチャレンジしているのですが失敗していて、可能かもよく分からないので出来たら記事にしたいと思います。