工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> VHDL

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 以降のリビジョンでのみ使用できます。 OREADHREAD プロシージャには、サポートされている出力タイプごとに 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]

ここをクリックして、HREAD プロシージャーの別の実装を確認してください
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 進文字ではなくバイナリ リテラルとして格納することをお勧めします。以下のリストは前と同じ内容を示していますが、文字 01 .

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

  1. アルミニウムを腐食から保護する方法
  2. 金属元素と非金属元素の違い
  3. AWSを使用してCloudFormationテンプレートを作成する方法
  4. クラウドコンピューティングは、従来のコンピューティングとどのように異なりますか?
  5. FPGA ピンからの PWM を使用する RC サーボ コントローラー
  6. Cプログラミングでコメントを書く方法
  7. Java BufferedReader:例を使用して Java でファイルを読み取る方法
  8. Python Average:Python でリストの AVERAGE を見つける方法
  9. マイクロメータとは何ですか? |マイクロメータの読み方
  10. 情報モデルを使用して OPC UA クライアントからファンクション ブロックを呼び出す方法
  11. CNC ブループリントの読み方