TEXTIO を使用してファイルから RAM を初期化する方法
ブロック RAM に初期値を設定する便利な方法は、ASCII ファイルから 2 進数または 16 進数のリテラルを読み取ることです。これは、VHDL で ROM (読み取り専用メモリ) を作成する良い方法でもあります。結局のところ、FPGA では RAM と ROM は同じものであり、ROM は読み取り専用の RAM です。
この記事全体の例では、次の定数と RAM タイプが VHDL ファイルの宣言領域の先頭で宣言されていることを前提としています。
constant ram_depth : natural := 256; constant ram_width : natural := 32; type ram_type is array (0 to ram_depth - 1) of std_logic_vector(ram_width - 1 downto 0);
このブログ投稿は、VHDL での TEXTIO ライブラリの使用に関するシリーズの一部です。ここで他の記事を読む:
TEXTIO を使用してテストベンチで読み込まれた刺激ファイル
TEXTIO を使用して読み取った BMP ファイルのビットマップ イメージ
READLINE、LINE、HREAD、OREAD、BREAD
VHDL で外部ファイルを読み書きするために必要なサブプログラムとタイプは、TEXTIO
にあります。 パッケージ。このパッケージは std
の一部です 図書館。標準ライブラリは常にロードされます。したがって、library
で明示的にインポートする必要はありません。 キーワード。
TEXTIO
を使用するだけです。 次のように、VHDL ファイルのヘッダーにパッケージを追加します。
use std.textio.all;
RAM データは 1 行のテキストがメモリ スロットに対応する ASCII ファイルに保存します。テキスト行を読むには READLINE
を使用します TEXTIO
からの手順 パッケージ。このプロシージャは 2 つの引数を取ります。ファイル名を定数入力として、解析されたテキスト行を inout
として受け取ります。 変数。 READLINE
のプロトタイプ宣言 手順と LINE
VHDL 標準仕様から取得した型を以下に示します。
procedure READLINE (file F: TEXT; L: inout LINE); type LINE is access STRING; -- A LINE is a pointer -- to a STRING value.
LINE
のクラスですが、 READLINE
のプロトタイプ宣言でパラメータが明示的に指定されていません 、これは inout
のデフォルト クラスであるため、変数です。 パラメーター。 LINE
type は、動的に割り当てられた文字列オブジェクトへのポインタである文字列へのアクセス タイプです。
VHDL-2008 は OREAD
を定義します 、 HREAD
、および BREAD
LINE
から 8 進数、16 進数、および 2 進数値を抽出する手順 物体。 8 進値と 16 進値の読み取り方法は非常に似ており、8 進値は 16 進値のサブセットにすぎません。簡単にするために、この記事では 8 進数の読み取りをスキップし、テキスト ファイルから 16 進数と 2 進数の値を読み取る方法に焦点を当てます。
以下のコードは、私たちに関連する手順の定義を示しています。これらは、VHDL-2008 以降のリビジョンでのみ使用できます。 OREAD
と HREAD
プロシージャには、サポートされている出力タイプごとに 2 つのオーバーロードされたフレーバーがあります。オプションの GOOD
出力は読み取りエラーの検出に使用できますが、この出力が使用されているかどうかに関係なく、ほとんどのツールはエラーまたは警告を生成します。
procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; alias BREAD is READ [LINE, STD_ULOGIC_VECTOR];ここをクリックして、TEXTIO ライブラリの入力プロシージャの定義を確認してください
procedure READLINE (file F: TEXT; L: inout LINE); procedure READ (L: inout LINE; VALUE: out BIT; GOOD: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out BIT); procedure READ (L: inout LINE; VALUE: out BIT_VECTOR; GOOD: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out BIT_VECTOR); procedure READ (L: inout LINE; VALUE: out BOOLEAN; GOOD: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out CHARACTER; GOOD: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out CHARACTER); procedure READ (L: inout LINE; VALUE: out INTEGER; GOOD: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out INTEGER); procedure READ (L: inout LINE; VALUE: out REAL; GOOD: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out REAL); procedure READ (L: inout LINE; VALUE: out STRING; GOOD: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out STRING); procedure READ (L: inout LINE; VALUE: out TIME; GOOD: out BOOLEAN); procedure READ (L: inout LINE; VALUE: out TIME); procedure SREAD (L: inout LINE; VALUE: out STRING; STRLEN: out NATURAL); alias STRING_READ is SREAD [LINE, STRING, NATURAL]; alias BREAD is READ [LINE, BIT_VECTOR, BOOLEAN]; alias BREAD is READ [LINE, BIT_VECTOR]; alias BINARY_READ is READ [LINE, BIT_VECTOR, BOOLEAN]; alias BINARY_READ is READ [LINE, BIT_VECTOR]; procedure OREAD (L: inout LINE; VALUE: out BIT_VECTOR; GOOD: out BOOLEAN); procedure OREAD (L: inout LINE; VALUE: out BIT_VECTOR); alias OCTAL_READ is OREAD [LINE, BIT_VECTOR, BOOLEAN]; alias OCTAL_READ is OREAD [LINE, BIT_VECTOR]; procedure HREAD (L: inout LINE; VALUE: out BIT_VECTOR; GOOD: out BOOLEAN); procedure HREAD (L: inout LINE; VALUE: out BIT_VECTOR); alias HEX_READ is HREAD [LINE, BIT_VECTOR, BOOLEAN]; alias HEX_READ is HREAD [LINE, BIT_VECTOR];ここをクリックして、std_logic_1164 ライブラリの入力プロシージャの定義を確認してください
procedure READ (L : inout LINE; VALUE : out STD_ULOGIC; GOOD : out BOOLEAN); procedure READ (L : inout LINE; VALUE : out STD_ULOGIC); procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; alias BREAD is READ [LINE, STD_ULOGIC_VECTOR]; alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR]; procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR]; procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR];
ファイルから 16 進値を読み取る
16 進数は、2 つの 16 進数文字が 1 バイト (8 ビット) に直接変換されるため、RAM の内容を記述するのに便利な形式です。各文字はニブル (半バイト) を表し、テキスト ファイルの各行は 1 つの RAM スロットの内容を表します。以下のリストは、ram_content_hex.txt からの抜粋です。 ファイル。 10 進数で 1 から 256 までの範囲の値の例が含まれており、16 進数で記述されています。
12–255256 | 00000001 00000002 ... 000000FF 00000100 |
テキスト ファイルからデータをロードするには、ram_type
の下で宣言された不純な関数を使用します。 、ただし RAM 信号宣言の上。以下のコードは init_ram_hex
を示しています テキストファイルからデータを読み取り、それを ram_type
として返す関数 オブジェクト。
impure function init_ram_hex return ram_type is file text_file : text open read_mode is "ram_content_hex.txt"; variable text_line : line; variable ram_content : ram_type; begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); hread(text_line, ram_content(i)); end loop; return ram_content; end function;
readline
for ループ内のプロシージャは、一度に 1 行のテキストを読み取り、それを text_line
に割り当てます。 変数。このオブジェクトのタイプは line
です これは、文字列オブジェクトへのアクセス タイプであり、動的に割り当てられた文字列へのポインターです。次の行の hread
プロシージャは line
から文字列を読み取ります オブジェクトを取得し、それを std_ulogic_vector
に変換します .このタイプは std_logic_vector
に直接割り当てることができます 各 RAM セルを構成します。
最後に、init_ram_hex
を呼び出しながら RAM シグナルを宣言します。 初期値を提供する関数:
signal ram_hex : ram_type := init_ram_hex;
VHDL-2002 および VHDL-93 の HREAD
残念ながら、HREAD
手順は VHDL-2008 でのみ使用できます。以前のすべてのバージョンの VHDL では、標準の READ
代わりに手順を使用する必要があります。 READ
プロシージャは多くの異なる出力タイプでオーバーロードされていますが、16 進値を読み取るオプションはありません。
16 進数の ASCII 文字を VHDL std_logic_vector
に変換するためのカスタム アルゴリズムを書きましょう。 .まず、text_line
から文字を 1 つずつ読み取る必要があります。 オブジェクトの場合、それらの値をデコードし、RAM スロット ベクトルの正しいスライスに割り当てます。以下のコードは、init_ram_hex
の同等の実装を示しています。 従来の VHDL バージョンでも機能する関数。
impure function init_ram_hex return ram_type is file text_file : text open read_mode is "ram_content_hex.txt"; variable text_line : line; variable ram_content : ram_type; variable c : character; variable offset : integer; variable hex_val : std_logic_vector(3 downto 0); begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); offset := 0; while offset < ram_content(i)'high loop read(text_line, c); case c is when '0' => hex_val := "0000"; when '1' => hex_val := "0001"; when '2' => hex_val := "0010"; when '3' => hex_val := "0011"; when '4' => hex_val := "0100"; when '5' => hex_val := "0101"; when '6' => hex_val := "0110"; when '7' => hex_val := "0111"; when '8' => hex_val := "1000"; when '9' => hex_val := "1001"; when 'A' | 'a' => hex_val := "1010"; when 'B' | 'b' => hex_val := "1011"; when 'C' | 'c' => hex_val := "1100"; when 'D' | 'd' => hex_val := "1101"; when 'E' | 'e' => hex_val := "1110"; when 'F' | 'f' => hex_val := "1111"; when others => hex_val := "XXXX"; assert false report "Found non-hex character '" & c & "'"; end case; ram_content(i)(ram_content(i)'high - offset downto ram_content(i)'high - offset - 3) := hex_val; offset := offset + 4; end loop; end loop; return ram_content; end function;
このアルゴリズムは、すべての文字を調べながらすべての行を単純に処理し、正しいバイナリ値に変換します。 0x0-0xF の範囲にない文字が検出された場合、when others
でアサート エラーが発生します。 ブランチ。 offset
変数は、デコードされた値を割り当てる各メモリ セル内のスライス位置を制御します。
カスタムの hread
を作成しない理由を自問するかもしれません。 init_ram_hex
内にコーディングする代わりに、手順 関数? init_ram_hex
を変更する必要はありません。 まったく機能しない場合は、カスタムの hread
を使用するだけです 欠落している標準的な手順の代わりに手順を実行してください。
これは、ほとんどのシミュレーターや Lattice iCEcube2 などの一部のシンセサイザーでは機能しますが、Xilinx Vivado では合成できません。以下のエラー メッセージには、問題の内容が明確に示されています。
Vivado の場合:
[Synth 8-27] タイプ 'line' のプロシージャ引数はサポートされていません [init_ram_tb.vhd:15]
procedure hread(l: inout line; value: out std_logic_vector) is variable c : character; variable ok : boolean; variable i : integer := 0; variable hex_val : std_logic_vector(3 downto 0); begin while i < value'high loop read(l, c); case c is when '0' => hex_val := "0000"; when '1' => hex_val := "0001"; when '2' => hex_val := "0010"; when '3' => hex_val := "0011"; when '4' => hex_val := "0100"; when '5' => hex_val := "0101"; when '6' => hex_val := "0110"; when '7' => hex_val := "0111"; when '8' => hex_val := "1000"; when '9' => hex_val := "1001"; when 'A' | 'a' => hex_val := "1010"; when 'B' | 'b' => hex_val := "1011"; when 'C' | 'c' => hex_val := "1100"; when 'D' | 'd' => hex_val := "1101"; when 'E' | 'e' => hex_val := "1110"; when 'F' | 'f' => hex_val := "1111"; when others => hex_val := "XXXX"; assert false report "Found non-hex character '" & c & "'"; end case; value(value'high - i downto value'high - i - 3) := hex_val; i := i + 4; end loop; end procedure;
ファイルからバイナリ値を読み取る
RAM 幅が 8 の倍数でない場合は、RAM 値を 16 進文字ではなくバイナリ リテラルとして格納することをお勧めします。以下のリストは前と同じ内容を示していますが、文字 0
と 1
.
12–255256 | 00000000000000000000000000000001 00000000000000000000000000000010 ... 00000000000000000000000011111111 00000000000000000000000100000000 |
以下に示すアルゴリズムは、ファイルからバイナリ値を読み取るためのものです。 16 進数の読み取りに似ていますが、VHDL-2008 では BREAD
を使用する必要があります。 HREAD
の代わりに手続き呼び出し . 1 つの ASCII 文字を 1 つの std_ulogic
に変換します std_logic
に暗黙的に変換される値 .
impure function init_ram_bin return ram_type is file text_file : text open read_mode is "ram_content_bin.txt"; variable text_line : line; variable ram_content : ram_type; begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); bread(text_line, ram_content(i)); end loop; return ram_content; end function;
最後に、以下のコードに示すように、新しい不純な関数を呼び出して RAM シグナルを初期化します。
signal ram_bin : ram_type := init_ram_bin;
VHDL-2002 および VHDL-93 でのパン
READ
を呼び出すことで、コードをレガシー VHDL バージョンに簡単に移植できます。 BREAD
の代わりに .以下の VHDL 標準からの抜粋は、READ
のプロトタイプを示しています。
procedure READ (L: inout LINE; VALUE: out BIT);
READ
std_ulogic
を出力する手順 VHDL-2008 より前には存在しなかったため、bit
を使用する必要があります TEXTIO
のバージョン 図書館。幸いなことに、この型は std_logic
に簡単に変換できます 標準の To_StdLogicVector
を使用して 関数。
init_ram_bin
の実装 以下に示すのは、VHDL-2002 および VHDL-93 で機能します。
impure function init_ram_bin return ram_type is file text_file : text open read_mode is "ram_content_bin.txt"; variable text_line : line; variable ram_content : ram_type; variable bv : bit_vector(ram_content(0)'range); begin for i in 0 to ram_depth - 1 loop readline(text_file, text_line); read(text_line, bv); ram_content(i) := To_StdLogicVector(bv); end loop; return ram_content; end function;
IEEE std_logic_1164 ライブラリのバックポート
レガシ VHDL バージョンのコードを変更する代わりに、std_logic_1164_additions サードパーティ パッケージを使用することもできます。このライブラリをダウンロードしてプロジェクトに追加すると、VHDL-2002 および VHDL-93 でも新しい手順を使用できるようになります。もちろん、その後はさらに多くのインポートが行われ、コードは常にこのパッケージに依存することになります.
VHDL
- アルミニウムを腐食から保護する方法
- 金属元素と非金属元素の違い
- AWSを使用してCloudFormationテンプレートを作成する方法
- クラウドコンピューティングは、従来のコンピューティングとどのように異なりますか?
- FPGA ピンからの PWM を使用する RC サーボ コントローラー
- Cプログラミングでコメントを書く方法
- Java BufferedReader:例を使用して Java でファイルを読み取る方法
- Python Average:Python でリストの AVERAGE を見つける方法
- マイクロメータとは何ですか? |マイクロメータの読み方
- 情報モデルを使用して OPC UA クライアントからファンクション ブロックを呼び出す方法
- CNC ブループリントの読み方