FPGAで、VHDLで書いたinteger信号の範囲は守られるのだろうか

例えばVHDLで下記のようなintegerの信号を定義したとする。

signal sCountVal : integer range 0 to 9;

この信号は0~9の値を取る、と宣言している。
これはFPGAでどのように論理合成されるのだろうか。

FPGA上では信号線で値を表現するので、例えば信号線3本、3bitの信号なら0~7の値を取り、
信号線4本、4bitの信号なら0~15の値を取る。
値の取りうる範囲は2のべき乗にしかなり得ない。

0~9を表現できるのは4bitだが、では10~15はどうなるのだろうか。
10~15の値にならないように論理合成されるのだろうか。
DE0-CVでちょっと試してみよう。

DE0-CVの4つのプッシュスイッチのうち2つ(KEY0とKEY1)と7セグメントLEDを使って動作を確認する。
KEY0を押したらintegerのカウンターをカウントアップ
KEY1を押したらintegerのカウンターをカウントダウン
カウンターの値を7セグメントLEDに出力
という回路を作った。

コンパイルはQuartus Prime 17.0で行った。

    --------------------
    -- 略
    --------------------

    -- DE0-CVのPushスイッチ4つの立ち上がりエッジ信号
    signal sKEY_hiedge          : std_logic_vector( 3 downto 0);

    -- integerのカウンター
    signal sCountVal            : integer range 0 to 9;

begin
    --------------------
    -- チャタリング除去とか立ち上がりエッジ検出とかの記述
    -- 略
    --------------------

    -- up/down count
    process (CLOCK_50, RESET_N) is
    begin
        if (RESET_N = '0') then
            sCountVal <= 0;
        elsif rising_edge(CLOCK_50) then
            if (sKEY_hiedge(0) = '1') then
                sCountVal <= sCountVal + 1;  -- KEY0を押したらカウントアップ
            elsif (sKEY_hiedge(1) = '1') then
                sCountVal <= sCountVal - 1;  -- KEY1を押したらカウントダウン
            end if;
        end if;
    end process;

    --------------------
    -- 値を7セグメントLEDに出力
    -- 略
    --------------------

動かしてみた。

FPGAにsofファイルを書き込むと7セグメントLEDに0が表示される。
KEY0を押すとカウントアップする。
9までカウントアップした。
f:id:m_keishi2006:20170729230721j:plain

もしVHDLの記述通り、範囲が0-9であるのであれば次のカウントアップでオーバーフローして値が0になるはずである。
KEY0を押してみた。
f:id:m_keishi2006:20170729230729j:plain

7セグメントの値がA(16進表記)に変化した。
VHDLで記述したrangeの範囲を超えてしまった。
そのままカウントアップすると、F(16進表記)まで変化して、
f:id:m_keishi2006:20170729230735j:plain

もう一度押すとオーバーフローして0に戻った。
f:id:m_keishi2006:20170729230743j:plain

ちなみに0からカウントダウンするとFになった。

つまり、FPGAの実装としては4bit信号でカウンターが構成されているということ。
integerのrangeはあくまで何bitの信号とするのか決めるだけであり、値の範囲の制御はちゃんと記述する必要がある。
これを認識しないと思い違いによるバグを生みかねないので注意しよう。

ちなみにSTARCではintegerのrangeの範囲は2のべき乗にしなければならないというルールがあったはず。
(うろ覚えだけど)

追記:
ModelSimでカウントアップしてみた。
integerの範囲を超えるたときにFatal ErrorになってSimが止まった。
SimのFatal Errorが誤動作の原因になるような記述を見つける指標になると思う。