以下の記述の違いについて誰か教えてもらえますか?.
signal A: **unsigned**(3 downto 0);
signal B: **std_logic_vector**(3 downto 0);
std_logic_vector
とunsigned
はどちらもstd_logic
の制約のない配列です。 signed
タイプも同様です。 std_logic_vector
はstd_logic_1164
パッケージで宣言されています。 unsigned
とsigned
はパッケージnumeric_std
で宣言されています。 3つのタイプはすべて同じです。唯一の違いはそれらの名前です。
それで、そのポイントは何ですか?この点は、例によってよく示されています。
と
variable U : unsigned(3 downto 0);
variable S : signed(3 downto 0);
variable I : integer;
その後
U := "1111";
I := to_integer(U);
その結果、I
には値15が与えられますが、
S := "1111";
I := to_integer(S);
その結果、I
に値-1が与えられます。これは、unsigned
タイプがunsigned番号を表すために使用されているためです。これは、正の値のみです。したがって、"1111"
は数値15を表します。ただし、signed
型は負の数も表すことができる必要があり、signed
型では"1111"
は-1を表します(2の補数このタイプでは表現が使用されます)。
したがって、同じ関数(to_integer
)が"1111"
で呼び出されたときに、引数のタイプがunsigned
またはsigned
のどちらであるかに応じて、15または-1の2つの異なる結果を返すことがわかります。したがって、両方のタイプの違いは名前だけですが、両方のタイプを持つことのポイントを理解できます。
実際には、1つではなく2つのto_integer
関数があります。 1つはunsigned
引数を取ります。もう1つ(同じ名前のto_integer
)はsigned
引数を取ります。ご覧のとおり、動作は異なります。コンパイラーは、引数のタイプに基づいて、呼び出す必要のある関数を決定できます。コンパイラが引数のタイプに基づいて異なる(ただし同じ名前の関数)から選択できるこのアイデアは、オーバーロードと呼ばれます。これはソフトウェア言語では一般的です。
では、std_logic_vector
はどうですか?あなたが書いたとしましょう:
variable V : std_logic_vector(3 downto 0);
variable I : integer;
その後
V:= "1111";
I := to_integer(V);
to_integer
関数からどのような結果を期待しますか? 15または-1?このジレンマは、上記のコードが違法であるために解決されます-コンパイルされません。 to_integer
に対して定義されたstd_logic_vector
関数のバージョンがないため、コンパイルされません-to_integer
関数はタイプstd_logic_vector
に対してオーバーロードされていません。
したがって、正の数のみを表す必要がある場合は、unsigned
タイプを使用することをお勧めします。負の数を表す必要がある場合は、signed
タイプを使用する必要があります。ビットのパターンが数値ではないため、またはビットのパターンを計算していないため(単にある場所から別の場所に転送しているだけ)、本当に気にしない場合は、std_logic_vector
を使用するのが最善です。