符号つき整数加算器

pp.261-262

+演算子の場合、出力のビット幅は、複数ある入力のうち最大のビット幅と同じでなければならない。

VHDL 2008ではsignedとシングルビット値とが加算できるようになったらしいがQuartus Prime Liteはまだサポートしていないようなので、下のコードでは'0' & cinのように0を連結して無理矢理ベクタにした。

複数ある入力は、1つだけを符号拡張して出力ビット幅に合わせればよい。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adder_signed is
    generic(
        NUM_BITS: integer := 4
    );
    port( -- 原則1: 入出力ポートはstd_logic型、std_logic_vector型にする。
        a, b: in std_logic_vector(NUM_BITS-1 downto 0);
        cin : in std_logic;

        sum: out std_logic_vector(NUM_BITS-1 downto 0);

        cout, oflow, sumMSB: out std_logic
    );
end entity;

architecture rtl of adder_signed is
   -- 加算値を假置きするための信号を定義する。
    signal sum_sig: signed(NUM_BITS downto 0);
begin
   -- 原則2: 演算型に変換してから演算をする。シングルビットはそのままでよい。
   -- キャリーアウト、オーバーフローを得るため1ビット増やして加算する。
    sum_sig <= resize(signed(a),   NUM_BITS+1) +
               signed(b) +
               ('0' & cin);

   -- 原則3: std_logic型、std_logic_vector型に変換してから出力する。シングルビットはそのままでよい。
   -- 加算結果(キャリーアウト、オーバーフローは含めない)を出力する。
    sum    <= std_logic_vector(sum_sig(NUM_BITS-1 downto 0));

   -- 加算結果(キャリーアウト、オーバーフローは含める)の最上位ビットを出力する。
    sumMSB <= sum_sig(NUM_BITS);

    cout   <= a(NUM_BITS-1) xor b(NUM_BITS-1) xor sumMSB;
    oflow  <= sumMSB xor sum(NUM_BITS-1);
end architecture;