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