ModelSim
2009年12月09日
ModelSimでビットマップのリードライト(完成)
以前、「ModelSimでビットマップのリードライト」で紹介したモジュールがやっと完成した。
これを使えば簡単にビットマップをテストベクタとして利用できるので画像処理なんかには便利だと思う。
また、FLI等は使わずVHDLの記述だけで実現しているので修正も出来るし応用も出来る。
という事で、他の人にも使って貰えればと思うのでソースコードを公開します。
動作環境
OS:Windows系
シミュレータ:ModelSim(XEでも大丈夫だと思う)
使用方法
上記環境で、ModelSimにPathが通っていれば、解凍したファイルの「sim.bat」を実行すればサンプルが動きます。
このサンプルは、解凍したファイルの「read.bmp」を読み出しピクセルデータを反転して「write.bmp」に書き込むだけです。
後は適当にソースコードを見て下さい。
ドキュメントが少ないので申し訳ないが要望があれば整備します。
2007年08月06日
ModelSimでビットマップのリードライト
ModelSim+VHDLでビットマップのリードライトを行えるモジュールを作成中だが、思ったように時間がとれないので難航している。
とりあえずパッケージだけ出来たので公開。(ボディは半分くらい)これを作るのに「textio.vhd」はとても参考になる。一度目を通すことをおすすめしたい。
これが出来るとModelSimXE Starterでビットマップを直接扱うことが出来る。
私の仕事上、画像ファイルを扱うことが多いのでこれが出来るとModelSimのライセンスが空いていない時にもシミュレーションが出来るようになる。ModelSimSEだとFLIが使えるので前に作ったコレでも出来るが...
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
package bmp_pkg is
----------------------------------------------------------------------------
-- データタイプ定義
----------------------------------------------------------------------------
-- ファイルヘッダ定義
type BITMAPFILEHEADER is record
bfType : bit_vector(15 downto 0);
bfSize : bit_vector(31 downto 0);
bfReserved1 : bit_vector(15 downto 0);
bfReserved2 : bit_vector(15 downto 0);
bfOffBits : bit_vector(31 downto 0);
end record;
-- インフォヘッダ定義
type BITMAPINFOHEADER is record
biSize : bit_vector(31 downto 0);
biWidth : bit_vector(31 downto 0);
biHeight : bit_vector(31 downto 0);
biPlanes : bit_vector(15 downto 0);
biBitCount : bit_vector(15 downto 0);
biCompression : bit_vector(31 downto 0);
biSizeImage : bit_vector(31 downto 0);
biXPelsPerMeter : bit_vector(31 downto 0);
biYPelsPerMeter : bit_vector(31 downto 0);
biClrUsed : bit_vector(31 downto 0);
biClrImportant : bit_vector(31 downto 0);
end record;
-- パレット定義
type RGBQUAD is record
rgbBlue : bit_vector(7 downto 0);
rgbGreen : bit_vector(7 downto 0);
rgbRed : bit_vector(7 downto 0);
rgbReserved : bit_vector(7 downto 0);
end record;
-- パレットのポインタ定義
type RGBQUADARRAY is array( natural range <> ) of RGBQUAD;
type RGBQUADACCESS is access RGBQUADARRAY;
-- バイトのポインタ定義
subtype BYTE is bit_vector(7 downto 0);
type BYTEARRAY is array( natural range <> ) of BYTE;
type BYTEACCESS is access BYTEARRAY;
-- ビットマップ全体を定義
type BMP_INFO is record
bmp_fh : BITMAPFILEHEADER;
bmp_ih : BITMAPINFOHEADER;
col_tbl : RGBQUADACCESS;
pix_data : BYTEACCESS;
end record;
-- ファイルタイプ定義
type BIN is file of character;
----------------------------------------------------------------------------
-- 公開サブプログラム定義
----------------------------------------------------------------------------
-- ビットマップオープン(ファイル指定)
procedure open_bmp (
filename : in string;
bmp_info_data : out BMP_INFO;
result : out boolean
);
-- ビットマップオープン(空データ)
procedure open_bmp (
x_size : in std_logic_vector(31 downto 0);
y_size : in std_logic_vector(31 downto 0);
bitcount : in integer;
bmp_info_data : out BMP_INFO;
result : out boolean
);
-- ビットマップ保存
procedure save_bmp (
filename : in string;
bmp_info_data : inout BMP_INFO;
result : out boolean
);
-- ビットマップクローズ
procedure close_bmp (
bmp_info_data : inout BMP_INFO;
result : out boolean
);
-- ビットマップリード
procedure read_bmp (
x_pos : in std_logic_vector(31 downto 0);
y_pos : in std_logic_vector(31 downto 0);
pix_data : out std_logic_vector(31 downto 0);
bmp_info_data : inout BMP_INFO
);
-- ビットマップライト
procedure write_bmp (
x_pos : in std_logic_vector(31 downto 0);
y_pos : in std_logic_vector(31 downto 0);
pix_data : in std_logic_vector(31 downto 0);
bmp_info_data : inout BMP_INFO
);
end bmp_pkg;
2007年08月02日
ModelSim TIPS 「ModelSimでバイナリファイルの操作」
以前、バイナリファイルの読み込みと書き込みを紹介したが、その時、「ファイルを最後まで読み出した事が分からず最後の次を読み出そうとした瞬間にFatalエラーとなってしまう。」と書いた。
しかし、EOF(エンドオブファイル)を検出出来る関数があることを知ったので、それを使って以前のサンプルを書き直す事にする。
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity bin_rw is
end bin_rw;
architecture behavior of bin_rw is
type BIN is file of character;
file FILEIN : BIN open READ_MODE is "binary_in.bin";
file FILEOUT : BIN open WRITE_MODE is "binary_out.bin";
signal BYTEDATA : std_logic_vector(7 downto 0);
begin
process
variable FREAD_CHAR : character;
variable FWRITE_CHAR : character;
begin
-- ファイルの終わりを検出するまでループ
while ( endfile( FILEIN ) = FALSE ) loop
-- ファイルリード
read( FILEIN, FREAD_CHAR );
-- std_logic_vectorに変換(今回は変換する意味は無いが、参考のため)
BYTEDATA <= conv_std_logic_vector( character'pos(FREAD_CHAR), 8 );
-- デルタ遅延を入れてBYTEDATAを更新
wait for 0 ns;
-- characterに変換(今回は変換する意味は無いが、参考のため)
FWRITE_CHAR := character'val( conv_integer(BYTEDATA) );
-- ファイルライト
write( FILEOUT, FREAD_CHAR );
end loop;
wait;
end process;
end behavior;
今回は、whileでEOFを検出するまで無限ループしているのでFatalエラーとなることはない。ただし、ループ中にデルタ遅延を入れているので大きなファイルの場合、Modelsimのリミットでストップされてしまうかもしれない。この場合は、ウエイトの値に1以上を入れるかModelsimのメニューから「Simulate」→「Runtime Option」→Defaultsタブの「Iteration Limit」の値を大きくする。
2007年07月22日
ModelSim TIPS 「ModelSimでバイナリファイルの書き込み」
今回は、バイナリファイルの書き込みをテストした。
以下のソースコードはバイナリファイルを読み込みSTD_LOGIC_VECTORに変換してからバイナリファイルに書き込みを行う。要はファイルのコピーを行う。
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity bin_rw is
end bin_rw;
architecture behavior of bin_rw is
type BIN is file of character;
file FILEIN : BIN open READ_MODE is "binary_in.bin";
file FILEOUT : BIN open WRITE_MODE is "binary_out.bin";
signal BYTEDATA : std_logic_vector(7 downto 0);
begin
process
variable FREAD_CHAR : character;
variable FWRITE_CHAR : character;
begin
for i in 0 to 255 loop
read( FILEIN, FREAD_CHAR );
BYTEDATA <= conv_std_logic_vector( character'pos(FREAD_CHAR), 8 );
wait for 0 ns;
FWRITE_CHAR := character'val( conv_integer(BYTEDATA) );
write( FILEOUT, FREAD_CHAR );
end loop;
wait;
end process;
end behavior;
これを実行すると「binary_in.bin」と同じ内容の「binary_out.bin」ファイルが生成される。(ソースコードと「binary_in.bin」を置いておく)
ただ前回同様に、これはModelSimでの動作を確認しただけで保証されている訳ではなく、他のシミュレータでは動作しない可能性がある。
また、ファイルを最後まで読み出した事が分からず最後の次を読み出そうとした瞬間にFatalエラーとなってしまう。これを回避するにはファイル中にそれが分かる情報を入れるか事前に読み出すサイズを決めるなどの方法が考えられる。
2007/08/02 - EOFを検出する方法を発見 ModelSim TIPS 「ModelSimでバイナリファイルの操作」を参照。
(今まで「printf」を使ったソースコードを紹介していたが文字列パラメータの最後に¥nが入っていなかった。これが入っていないと表示が出てこない。どうやらBlogに貼り付けたときに抜けてしまっていたようだ。)
2007年07月20日
ModelSim TIPS 「ModelSimでバイナリファイルの読み込み」
以前、ModelSim TIPS 「ModelSimでビットマップ操作」を書いたが、これはModelSimのFLI機能を使っていた。
今回は、FLIを使用せずVHDLだけでバイナリファイルを操作する方法を紹介する。
以下のソースコードはバイナリファイルを読み込みSTD_LOGIC_VECTORに変換してTranscriptウィンドウに表示する動作を行う。
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
library c;
use c.stdio_h.all;
entity test_bread is
end test_bread;
architecture behavior of test_bread is
type BIN is file of character;
file FILEPOINT : BIN open READ_MODE is "binary.bin";
signal PRINTD : std_logic_vector(7 downto 0);
begin
process
variable FREAD_CHAR : character;
begin
for i in 0 to 255 loop
read( FILEPOINT, FREAD_CHAR );
PRINTD <= conv_std_logic_vector(character'pos(FREAD_CHAR), 8 );
wait for 0 ns;
printf( "0x%02x ", PRINTD );
end loop;
wait;
end process;
end behavior;
表示するために「for」を使ったり「library c;」の「printf」を使用しているがバイナリファイルの読み込みには一切関係ない。
重要な部分は、
type BIN is file of character;
file FILEPOINT : BIN open READ_MODE is "binary.bin";
これだけだ。
(動作させるには読み出す対象の"binary.bin"ファイルも必要)
FLIを使用していないのでもしかするとModelSimXEでも動作するかもしれない。この要望は結構多いので後で実験してみようと思う。
2007/07/20 - ModelSimXE Starterでの動作が確認できた。
ただ、これはModelSimでの動作を確認しただけで保証されている訳ではなく、他のシミュレータでは動作しない可能性がある。
また、ファイルを最後まで読み出した事が分からず最後の次を読み出そうとした瞬間にFatalエラーとなってしまう。これを回避するにはファイル中にそれが分かる情報を入れるか事前に読み出すサイズを決めるなどの方法が考えられる。
2007/08/02 - EOFを検出する方法を発見 ModelSim TIPS 「ModelSimでバイナリファイルの操作」を参照。
近いうちに、この機能を使ってビットマップのリードライトが出来るモジュールを作って公開しようと思う。
2007年07月13日
ModelSim TIPS 「Utilパッケージ(ファンクション使用例)」
今度は、ModelSim標準Utilパッケージのファンクション使用例を書いてみた。
ソースコードは次のようになる。
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
library modelsim_lib;
use modelsim_lib.util.all;
library c;
use c.stdio_h.all;
entity mti_func_test is
end mti_func_test;
architecture behavior of mti_func_test is
begin
process
variable resolution : real;
variable alignment_time : time;
variable current_time : real;
variable wait_time : real;
begin
-- シミュレーションレゾリューションの取得
resolution := get_resolution;
printf( "Resolution = %f\n", resolution );
-- 半端なウエイト
wait for 12345678 fs;
-- 半端なウエイトをアライメント
wait_time := to_real(12345678 fs);
-- 現シミュレーション時間の取得
current_time := to_real(now);
printf( "Current Time = %f\n", current_time );
printf( "Wait Time = %f\n", wait_time );
-- 半端なウエイトをアラインメント
alignment_time := to_time(12345.678);
wait for alignment_time;
-- 現シミュレーション時間の取得
current_time := to_real(now);
printf( "Current Time = %f\n", current_time );
wait;
end process;
end behavior;
これをModelSimでシミュレーションするとTranscriptウィンドウに次のように表示される。
シミュレーションレゾリューションが1nsの場合
# Resolution = 1.000000e-009
# Current Time = 1.200000e+001
# Wait Time = 1.200000e+001
# Current Time = 1.235800e+004
シミュレーションレゾリューションが1psの場合
# Resolution = 1.000000e-012
# Current Time = 1.234600e+004
# Wait Time = 1.234600e+004
# Current Time = 2.469200e+004
シミュレーションレゾリューションが1fsの場合
# Resolution = 1.000000e-015
# Current Time = 1.234568e+007
# Wait Time = 1.234568e+007
# Current Time = 1.235802e+007
2回目の「Current Time」は「alignment_time := to_time(12345.678);」の単位がシミュレーションレゾリューションによって変化するため、このような結果になる。
2007年07月12日
ModelSim TIPS 「Utilパッケージ(ファンクション解説)」
ModelSimには標準でUtilパッケージが入っている。
このパッケージには6種類のプロシージャと3種類のファンクションが含まれており以下のライブラリ宣言で使用する事が出来る。(ModelSimのバージョンによっては入っていない物もある)
library modelsim_lib;
use modelsim_lib.util.all;
ファンクションの使用方法
・get_resolution
用途:シミュレーションのレゾリューションを取得する。
引数:なし
戻り:
型:real
説明:シミュレーションのレゾリューション
例:
variable resolution : real;
resolution := get_resolution;
シミュレーションのレゾリューションが「1ps」の場合「1e-12」が戻る。
・to_real
用途:シミュレーションのレゾリューションにアラインメントされた実数値を取得する。
引数:
名前:timeval
型:time
説明:アラインメントしたい時間値
戻り:
タイプ:real
説明:シミュレーションのレゾリューションにアラインメントされた実数値
例:
variable alignment_real : real;
alignment_real := to_real(123.45 ns);
シミュレーションのレゾリューションが「1ps」の場合「123450」が戻る。
・to_time
用途:シミュレーションのレゾリューションにアラインメントされた時間値を取得する。
引数:
名前:realval
型:real
説明:アラインメントしたい実数値
戻り:
タイプ:time
説明:シミュレーションのレゾリューションにアラインメントされた時間値
例:
variable alignment_time : time;
alignment_time := to_time(123.45);
シミュレーションのレゾリューションが「1ps」の場合「123ps」が戻る。
今回はファンクションの使用方法のみでプロシージャはいずれ書こうと思う。
2007年06月25日
ModelSimパフォーマンス比較
ずいぶん昔のデータだが、ModelSimの各エディションでのパフォーマンスを比較してみた。
比較方法は、メモリモデルや画像演算などを含んだそんなに小さくない回路を30秒間シミュレーションした時のシミュレーションの進捗である。
動作環境はWindows2000でXEON3GHzDual、MEM2GByte、U320SCSIと当時(5年位前)では最強スペックのマシンだ。
XE5.7c Sterter 4ms
PE5.8 120ms
SE5.7g 260ms
結果からXEの遅さが際だっている...
やはりXEでは仕事にならない、最悪でもPE、出来ればSEを購入したい所だ。またシノプシスやケイデンスのシミュレータと言う手もあるが、XilinxのFPGAをWindows上で開発するのにはModelSimが一番良いのではと思う。
尚、私はメンター社とは一切関係ありません。
使った事は無いが、Verilog使いの方はVeritakと言うシミュレータもある。これを使う為だけにVHDLからVerilogに移行しても良いと思えるほど良さそうである。
これを作っている方のホームページを見ると分かると思うが、本当にすごい人だと思う。
2007年06月23日
ModelSim TIPS 「ModelSimでビットマップ操作」
シミュレーションを行う時、バイナリファイルを操作したいと思うことが多々ある。VHDLで出来なくは無いのだが結構面倒くさい(そのうちこれのやり方もBlogに書こうと思う)ので、Windows+ModelSimSEの環境限定でバイナリファイルを読み書き出来るDLLを作成してみた。ついでに私は仕事で画像ファイルを扱う事が多いのでビットマップを操作出来るDLLも作成した。
このDLLはModelSimSEのFLI機能を使ってModelSimからDLLを呼び出すような形で使用する(FLIで呼び出されるDLLの作り方もそのうちBlogに書こうと思う)。
使用方法:
各DLLはそれぞれサンプルを添付しています。
ここでは代表でビットマップリードの使い方を説明します。
まず、シミュレータからDLLを呼び出してもらうためのアーキテクチャ「bmpread.vhd」を編集する必要があります。編集箇所は「attribute foreign」の「bmpread_init」以降で
./bmpread/Release/bmpread.dll;
使用するDLLのファイルを指定します。ただし後述の「MGC_WD」がある場合やModelSimの作業フォルダに存在する場合はパス部分は不要です。
dlg;
ファイル選択ダイアログを開く指定です。代わりに「fix;」と書きそれに続けてファイル名を書けばダイアログを開かず固定ファイルを使用します。この場合以降のオプションは記述出来ません。
Bitmap File Select;
ダイアログのタイトルです。
Bitmap (*.bmp)\*.bmp\All Files (*.*)\*.*\
ファイルの種類を限定する為の指定です。
フィルタコメント¥フィルタ指定¥...を複数指定出来ます。
例:
"bmpread_init ./binaryread.dll;dlg;Read File Select1;Bitmap (*.bmp)\*.bmp\All Files (*.*)\*.*\";
"bmpread_init ./binaryread.dll;fix;./test.bmp";
あとは、これを呼び出すだけです。
サンプルの「bmpread_call.vhd」を見ればだいたいわかると思います。
一切コメントがありませんが...
環境設定:
FLI機能を使用するにはWindowsの環境変数に「MGC_WD」を設定してDLLのフォルダを指定するかModelSimの作業フォルダにDLLを直接コピーしておく必要があります。(DLLの場所をVHDLで直接指定する場合は不要)
例:
MGC_WD=c:/modelsim/fli
注意:
このファイルの使用は自由ですが無保証です。
ダウンロード:
バイナリリード(バイト操作)
バイナリリード(4バイト操作)
バイナリライト(バイト操作)
バイナリライト(4バイト操作)
ビットマップリード
ビットマップライト