unsigned(MAX downto 0)
値を含む場合2**MAX - 1
、VHDL(87 | 93 | 200X)標準は、値を1つ増やすとどうなるかを定義していますか?(または、同様に、ゼロから1つデクリメントすると?)
3 に答える
簡潔な答え:
オーバーフロー処理はなく、オーバーフロー キャリーは単純に失われます。したがって、結果は単に2^MAXを法とする演算の整数結果です。
より長い答え:
numeric_std
パッケージは標準パッケージですが、VHDL 規格 (87,93,200X) の Core ではありません。参考:numeric_std.vhd
+
演算子は最後に関数を呼び出しますADD_UNSIGNED (L, R : unsigned; C : std_logic)
(with C = '0'
)。整数/自然オペランドは最初に に変換されることに注意してくださいunsigned
。
関数の定義は次のとおりです。
function ADD_UNSIGNED (L, R : unsigned; C : std_logic) return unsigned is
constant L_left : integer := L'length-1;
alias XL : unsigned(L_left downto 0) is L;
alias XR : unsigned(L_left downto 0) is R;
variable RESULT : unsigned(L_left downto 0);
variable CBIT : std_logic := C;
begin
for i in 0 to L_left loop
RESULT(i) := CBIT xor XL(i) xor XR(i);
CBIT := (CBIT and XL(i)) or (CBIT and XR(i)) or (XL(i) and XR(i));
end loop;
return RESULT;
end ADD_UNSIGNED;
ご覧のとおり、CBIT='1'
(キャリー ビット) for の場合、「オーバーフロー」が発生しi = L_left
ます。リザルト ビットRESULT(i)
は通常どおり計算され、最後のキャリー ボットの値は無視されます。
MAX の値が 7 の場合、1 を 2**7 - 1 (127) に加算すると、値は 2**7 (128) になります。
符号なしの最大値は、符号なし配列型の長さによって決まります。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
end entity;
architecture faa of foo is
constant MAX: natural := 7;
signal somename: unsigned (MAX downto 0) := (others => '1');
begin
UNLABELED:
process
begin
report "somename'length = " & integer'image(somename'length);
report "somename maximum value = " &integer'image(to_integer(somename));
wait;
end process;
end architecture;
集合体(others => '1')
は、各要素が符号なし配列型である「1」をsomename
表し、可能な最大のバイナリ値を表します。
これは与える:
foo.vhdl:15:9:@0ms:(レポート ノート): somename'length = 8
foo.vhdl:16:9:@0ms:(レポート ノート): somename 最大値 = 255
長さは 8 で、符号なし配列型で表現できる数値の範囲は 0 から 2**8 - 1 (255) で、可能な最大値は 2**7 (128) より大きく、オーバーフローはありません。
これは、新しい質問VHDL modulo 2^32 addで指摘されました。受け入れられた回答のコンテキストでは、左端の値ではなく長さを意味していると想定しています。
ゼロからのデクリメントは、2**8 - 1 (255) (MAX = 7) の値になります。数学の宗教に応じたアンダーフローまたはオーバーフロー。
リンクされた新しい質問でこれを指摘してくれたJonathan Droletに感謝します。
unsigned
C や Verilogのようにオーバーフロー/アンダーフローが必要であるという問題がありましresult
た。delta
unsigned
result <= unsigned(std_logic_vector(resize(('1' & result) - delta, result'length))); -- proper underflow
result <= unsigned(std_logic_vector(resize(('0' & result) + delta, result'length))); -- proper overflow
オーバーフロー'0' & result
はunsigned
、加算の値を正しく収容できるように 1 ビット大きい を作成します。resize
その後、正しいオーバーフロー値を生成するコマンドによって MSB が削除されます。アンダーフローも同様。