一般規定
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言語での読み取り専用メモリデバイスの説明
読み取り専用メモリデバイスを記述する場合、プログラムの書き込み時にセルの内容を決定する必要があります。 メモリの内容を決定するには、いくつかのオプションを使用できます。
- 「配列」タイプの定数または信号の作成。
-
case
使用 - * .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コーディングスタイル。