VHDL で署名付きおよび署名なしを使用する方法
VHDL の符号付きおよび符号なしの型は、std_logic_vector 型と同様にビット ベクトルです。違いは、std_logic_vector はデータ バスの実装には優れていますが、算術演算の実行には役に立たないことです。
std_logic_vector 型に数値を追加しようとすると、ModelSim は次のコンパイル エラーを生成します:中置演算子 "+" の実行可能なエントリがありません。これは、ベクトルであるこのビットのコレクションを解釈する方法をコンパイラが認識していないためです。
このブログ投稿は、基本的な VHDL チュートリアル シリーズの一部です。
ベクトルを符号付きまたは符号なしとして宣言して、コンパイラがそれを数値として扱うようにする必要があります。
署名付きおよび未署名のシグナルを宣言するための構文は次のとおりです。signal <name> : signed(<N-bits> downto 0) := <initial_value>;
signal <name> : unsigned(<N-bits> downto 0) := <initial_value>;
std_logic_vector と同様に、範囲は to
にすることができます または downto
任意の範囲。ただし、downto 0
以外の範囲でシグナルを宣言する めったにないことなので、この話題にこれ以上時間を費やすことは、私たちを混乱させるだけです。初期値はオプションで、デフォルトでは 'U'
です
すでに integer
を使用しています 前のチュートリアルの算術演算の型。では、なぜ符号付きと符号なしの型が必要なのでしょうか?ほとんどのデジタル設計者は、信号が実際に使用するビット数をより詳細に制御したいと考えています。
また、署名された値と署名されていない値はラップアラウンドしますが、integer
の場合、シミュレーターは実行時エラーをスローします。 限界を超えて増加します。最後に、signed と unsigned は 'U'
のような他の値を持つことができます と 'X'
、整数は数値のみを持つことができます。これらのメタ値は、設計のエラーを発見するのに役立ちます。
エクササイズ
このビデオでは、符号付き信号と符号なし信号がどのように同じように動作し、どのように異なる動作をするかを学びます:
このチュートリアルで作成した最終的なコード:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T12_SignedUnsignedTb is end entity; architecture sim of T12_SignedUnsignedTb is signal UnsCnt : unsigned(7 downto 0) := (others => '0'); signal SigCnt : signed(7 downto 0) := (others => '0'); signal Uns4 : unsigned(3 downto 0) := "1000"; signal Sig4 : signed(3 downto 0) := "1000"; signal Uns8 : unsigned(7 downto 0) := (others => '0'); signal Sig8 : signed(7 downto 0) := (others => '0'); begin process is begin wait for 10 ns; -- Wrapping counter UnsCnt <= UnsCnt + 1; SigCnt <= SigCnt + 1; -- Adding signals Uns8 <= Uns8 + Uns4; Sig8 <= Sig8 + Sig4; end process; end architecture;
ModelSim の波形ウィンドウ。興味深い部分を拡大:
分析
波形のすべての信号の基数は 16 進数に設定されているため、それらを等しく比較できます。
ラッピング カウンターの例では、符号付きと符号なしの信号がまったく同じように動作することがわかります。両方 UnsCnt
および SigCnt
0 から始まり、FF まで 1 つずつインクリメントされます。 Hex FF (10 進数 255) は、8 ビット信号が保持できる最大値です。したがって、次のインクリメントは両方を 0 に戻します。
2 つの 4 ビット信号 Uns4
を作成しました と Sig4
、両方に初期値「1000」を与えました。波形から、どちらも 16 進数の 8 (バイナリ 1000) であることがわかります。
作成した最後の 2 つの 8 ビット信号は Uns8
でした そして Sig8
.波形から、予想どおり、初期値が 0 であることがわかります。しかし、そこから、彼らは異なる行動をとります!どうやら、異なる長さの 2 つの信号を追加するときに、符号付きと符号なしの型が違いを生んだようです。
これは、符号拡張と呼ばれるものによるものです。 .等しい長さのベクトルに格納された正または負の数値を加算することは、デジタル ロジックでは同じ操作です。これは、2 の補数がどのように機能するかによるものです。ベクトルの長さが異なる場合、最短のベクトルを延長する必要があります。
符号なし 4 ビットの 2 進数「1000」は 10 進数の 8 であり、符号付き 4 ビットの数値「1000」は 10 進数の -8 です。符号付き数値の左端の「1」は、これが負の数値であることを示します。したがって、2 つの 4 ビット信号は、コンパイラによって異なる方法で符号拡張されます。
これは、符号拡張が Uns8
の異なる値を作成する方法を視覚化したものです そして Sig8
シグナル:
テイクアウト
- signed および unsigned 型の信号は、算術演算で使用できるベクトルです
- signed および unsigned 型のシグナルは静かにオーバーフローします
- 符号拡張により、符号付きと符号なしの型で異なる結果が生じる可能性があります
次のチュートリアルに進む »
VHDL