VHDLのメモリブロックの説明

この記事では、VHDLでROMおよびRAMモジュールを説明するための基本原則を示します。 この記事は初心者向けです。 その目的は、VHDL言語でのメモリモジュールの記述に関する一般的な概念を提供することです。 Quartus II vの例と図が提供されています。 9.1。 読者は、Quartus IIパッケージでプロジェクトを作成し、それをコンパイルおよびシミュレートする方法を知っていることが前提となります。



一般規定



VHDLメモリはarray



ベクトルのarray



として記述されます。 ベクトルのビット深度はメモリセルの幅によって決まり、ベクトルの数はメモリモジュール内のセルの数によって決まります。



たとえば、それぞれが8ビットを含む32セルのメモリモジュールの場合、それぞれが8ビットである32個のベクトルを含む配列を宣言する必要があります。



 type mem is array (0 to 31) of std_logic_vector (7 downto 0);
      
      





次に、アドレス入力、データ入力および出力、制御信号を記述する必要があります。 データポートのタイプは、単一セルのデータタイプと一致する必要があります。 上記の例では、これはstd_logic_vector (7 downto 0)



です。



 data_in: in std_logic_vector (7 downto 0); data_out: out std_logic_vector (7 downto 0);
      
      





アドレスのデータ型はinteger



またはそれに基づく型です。 アドレスはメモリ配列のインデックスとして使用されるため、 integer



型が必要です。



 addr: in integer range 0 to 31;
      
      





メモリの説明は、モジュールをパラメーター化することで最適に行われます。 これにより、記述されたコードを再利用できます。 以下は、32×8パラメーター化されたモジュールの例です。 この例では、 data_width



パラメーターとdata_width



パラメーターを使用してメモリモジュールを記述し、それぞれアドレスとデータバスの幅を指定します。 この場合のメモリブロック内のセルの数は2**addr_width



として定義され、それらのビット容量はdata_width



と等しくなりdata_width







 generic (addr_width: natural:= 5; data_width: natural:=8); port ( addr: in integer range 0 to 2**addr_width - 1; data_in: in std_logic_vector (data_width-1 downto 0); data_out: out std_logic_vector (data_width-1 downto 0) ); type mem is array (2**addr_width-1 downto 0) of std_logic_vector (7 downto 0);
      
      





VHDL言語での読み取り専用メモリデバイスの説明


読み取り専用メモリデバイスを記述する場合、プログラムの書き込み時にセルの内容を決定する必要があります。 メモリの内容を決定するには、いくつかのオプションを使用できます。

  1. 「配列」タイプの定数または信号の作成。
  2. case



    使用
  3. * .mifファイルと合成属性の使用。


3つのオプションのうち、最初の2つはどのメーカーのFPGAにも実装でき、3つ目はQuartus IIパッケージでのみ可能です。



定数または配列を使用してメモリの内容を決定します。


このオプションを使用する場合、最初にメモリブロックのサイズに一致する型を宣言する必要があります。 次に、このタイプの定数が宣言され、配列のすべてのセルの内容が決定されます。

たとえば、新しいタイプのROMを宣言します。これは8セルの配列で、各セルのサイズは8ビットです。 次に、ROMタイプのコンテンツ定数を定義します。



 type ROM is array (0 to 7) of std_logic_vector (7 downto 0); constant Content: ROM := ( 0 => "00000001", 1 => "00000010", 2 => "00000011", 3 => "00000100", 4 => "00000101", 5 => "00000110", 6 => "00000111", 7 => "00001000", );
      
      





このような定数を使用するには、アドレス行からの入力を使用して、配列内の必要なセルをアドレス指定するだけです。 ソースデータポートは、メモリブロックのセルタイプと同じタイプでなければなりません。 上記の例では、ソースData_out



ポートはstd_logic_vector (7 downto 0)



タイプでなければなりません。 メモリの内容へのアクセスは次のようになります。



 Data_out <= Content (Addr);
      
      





例1.定数を使用したメモリブロックの完全な記述の例を考えてみましょう。 この説明を満たすメモリブロックを図1に示します。





図1-例1で説明したメモリブロック



13行目と14行目は、それぞれが8ビットを含む32セルの配列タイプを宣言しています。

行15〜23は、配列内のセルの値を指定します。 これとは別に、値は最初の16セル(行16〜22)に対してのみ決定されます。他のすべてのセルには、単語otherを使用して同じ値 "1111 1111"が入力されます-行23

メモリモジュールの動作は、プロセスオペレータを使用して説明されます。プロセスオペレータの初期化リストには、それぞれ信号clk



cs



クロック、クリスタル選択が含まれます。 信号cs



が1に等しい場合、初期ROMラインはZ状態になります(ライン27および28)。 信号cs



がゼロに等しい場合、出力は動作状態になり、マイクロ回路は動作します。

行29は、クロック信号clk



の立ち上がりエッジをチェックします。

行30〜35は、ROMから情報を読み取るプロセスを説明しています。 信号rd



が1に等しい場合、情報の読み取りが許可され、ゼロに等しい場合、初期行はZ状態になります(行32)。 メモリモジュール内の特定のセルにアクセスするには、30行目を使用し、コンテンツ定数はstd_logic_vector



セルデータ型で、元のdata_out



信号の型に対応しています。 メモリモジュールのアドレス信号もstd_logic_vector



タイプであるため、コンテンツ配列のセルをアドレス指定するために必要な変換は、 std_logic_vector



タイプからinteger



タイプへの変換であり、 to_integer (unsigned (address)



構文を使用して実行されます。次にinteger



型に、 ここで型変換についてより明確に。



 1 library ieee; 2 use ieee.std_logic_1164.all; 3 use ieee.numeric_std.all; 4 entity ROM is 5 port (clk : in std_logic; 6 cs : in std_logic; 7 rd : in std_logic; 8 address : in std_logic_vector(4 downto 0); 9 data_out: out std_logic_vector(7 downto 0)); 10 end ROM; 11 architecture behav of ROM is 12 type ROM_array is array (0 to 31) 13 of std_logic_vector(7 downto 0); 14 constant content: ROM_array := ( 15 0 => "00000001", 16 1 => "00000010", 17 2 => "00000011", 18 . . . 19 12 => "00001101", 20 13 => "00001110", 21 14 => "00001111", 22 others => "11111111"); 23 begin 24 process(clk, cs) 25 begin 26 if(cs = '1' ) then 27 data_out <= "ZZZZZZZZ"; 28 elsif (clk'event and clk = '1') then 29 if rd = '1' then 30 data_out <= content(to_integer (unsigned (address))); 31 else 32 data_out <= "ZZZZZZZZ"; 33 end if; 34 end if; 35 end process; 36 end behav;
      
      





シミュレーション結果を図2に示します。



図2-メモリブロックのシミュレーション結果



case



を使用してメモリの内容を決定する。


caseステートメントを使用する場合、ポートを宣言する必要があり、メモリの内容の決定はアーキテクチャ本体で行われます。 各アドレス値は、このメモリセルの内容に対応しています。 デザインは次のようになります。



 when  => _ <= _;
      
      





例2.例として、256×6メモリモジュールの説明を考えます。 アドレスはstd_logic



型の8ビットベクトルで記述され、データ出力はstd_logic



型の6ビットベクトルで記述されます。 case演算子を使用して、メモリブロックの最初の10セルの内容が個別に決定され、他のすべてはwhen others



ステートメントと共に定義されます。



 library ieee; use ieee.std_logic_1164.all; entity mem is port ( clock : in std_logic; address : in std_logic_vector (7 downto 0); data_out : out std_logic_vector (5 downto 0)); end mem; architecture rtl of mem is begin process (clock) begin if rising_edge (clock) then case address is when "00000000" => data_out <= "000111"; when "00000001" => data_out <= "000110"; when "00000010" => data_out <= "000010"; when "00000011" => data_out <= "100000"; when "00000100" => data_out <= "100010"; when "00000101" => data_out <= "001110"; when "00000110" => data_out <= "111100"; when "00000111" => data_out <= "110111"; when "00001000" => data_out <= "111000"; when "00001001" => data_out <= "100110"; when others => data_out <= "101111"; end case; end if; end process; end rtl;
      
      





例2のメモリブロックのシミュレーション結果を図3に示します。



図3-例2のメモリブロックのモデリング



mifファイルを使用してメモリの内容を決定します。


メモリの内容を決定するこのオプションは、アルテラ製品でのみ機能しますが、メモリの内容を非常に迅速に変更することもできます。 説明するには、アルテラのaltera_syn_attributes



合成属性ライブラリを接続し、 ram_init_file



属性を使用するram_init_file



ます。 デフォルトでは、ライブラリは_quartus\libraries\vhdl\altera



フォルダにあります。 この属性は、メモリの内容に関する情報を含むmifファイルを指定します。

この属性を使用するには、合成属性を文字列型として宣言する必要があります。



 attribute ram_init_file : string;
      
      





ram_init_file



属性を、メモリブロックを記述する信号にリンクします。 属性値は、* .mifファイルの名前と一致する必要があります。



 attribute ram_init_file of rom : signal is "mem.mif";
      
      





例3。この例では、256×8メモリブロックの説明について説明します。 1行目から4行目は、これらのライブラリーのライブラリーとモジュールを説明しています。 1行目と4行目は、合成属性のライブラリを示していることがわかります。

行5〜9は、モジュールのインターフェース部分を説明しています。

11行目と12行目では、メモリモジュールを記述するmem_t



型とこの型の信号rom



紹介しています。

13行目は文字列タイプのram_init_file



属性を設定し、14行目ram_init_file



この属性をシグナルrom



ram_init_file



、メモリモジュールの内容を含むmem.mifファイルへの参照を作成します。

メモリモジュールの使用は19行目に記載されており、セルの内容のソースポートへの出力のみを表します。これはアドレス信号によって決定されます。



 1 library ieee, altera; 2 use ieee.std_logic_1164.all; 3 use ieee.numeric_std.all; 4 use altera.altera_syn_attributes.all; 5 entity mem is 6 port (clk: in std_logic; 7 addr: in natural range 0 to 255; 8 q: out std_logic_vector (7 downto 0)); 9 end entity; 10 architecture rtl of mem is 11 type mem_t is array (255 downto 0) of std_logic_vector(7 downto 0); 12 signal rom: mem_t; 13 attribute ram_init_file: string; 14 attribute ram_init_file of rom: signal is "mem.mif"; 15 begin 16 process(clk) 17 begin 18 if(rising_edge(clk)) then 19 q <= rom(addr); 20 end if; 21 end process; 22 end rtl;
      
      





mifファイルの内容は、mifファイルエディターを使用して決定されます。 この例では、メモリの内容を含むウィンドウが図4に示され、変調結果が図5に示されています。





図4-メモリモジュールの内容





図5-例3のメモリモジュールのタイミング図



ランダムアクセスメモリの説明


ランダムアクセスメモリ(RAM)の説明は、RAMに記録できるという点で、読み取り専用メモリの説明とは異なります。

例として、同期RAMを検討してください。 彼の仕事は次の表で説明されています。

Wn_R CSN 実行[3..0] 動作モード
0 0 Zzz 記録
1 0 ソースデータ 読書
× 1 Zzz 情報を保存する


メモリを操作するための前の例のように、新しい型を配列として定義します。これには、必要なメモリモジュールの次元があります。



 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; entity mem is port (clk : in std_logic; Wn_R : in std_logic; CSn : in std_logic; addr : in std_logic_vector(4 downto 0); Di : in std_logic_vector(3 downto 0); Do : out std_logic_vector(3 downto 0)); end mem; architecture syn of mem is type ram_type is array (31 downto 0) of std_logic_vector (3 downto 0); signal RAM : ram_type; begin process (clk, CSn) begin if CSn = '0' then if (clk'event and clk = '1') then if (Wn_R = '0') then RAM(to_integer(unsigned(addr))) <= Di; Do <= "ZZZZ"; else Do <= RAM(to_integer(unsigned(addr))); end if; end if; else Do <= "ZZZZ"; end if; end process; end syn;
      
      





メモリモジュールの刺激装置の動作の結果を図6に示します。ここでは、すべてのメモリセルの初期内容がゼロであるという事実に注意を払う必要があります。 これは、数字6〜8のセルを読み取るときに表示されます。



図6-RAMのタイミング図



詳細については、任意のバージョンのQuartus II Hahdbookを参照してください。 たとえば、現在のものは13です。 セクション6-推奨されるHDLコーディングスタイル。



All Articles