Electronic – Ranged vs Non-ranged Integers in VHDL

fpgavhdl

My purpose is to store values from 0 to 3.
From synthesis point of view, which one of the following will be more area efficient, when coding in VHDL ?

  1. signal a: integer;
  2. signal a: integer range 0 to 3;

Will the first choice takes up 32 bit register inside FPGA?

Best Answer

It depends, but it is almost always preferable to specify the range.

For illustration, consider this example:

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

entity naturals is 
    Port ( clk    : in  std_logic;
           rst    : in  std_logic;
           count  : out std_logic_vector(2 downto 0));
end naturals;

architecture behavioral of naturals is
    signal count_intern : natural := 0;
begin
    count <= std_logic_vector(to_unsigned(count_intern, count'length));
    process(clk)
    begin
        if (rising_edge(clk)) then
            if (rst = '1') then
                count_intern <= 0;
            elsif (count_intern = 5) then
                count_intern <= 0;
            else
                count_intern <= count_intern + 1;
            end if;
        end if;
    end process;
end behavioral;

This is a simple counter going from 0 to 5. It's simulation looks like this: simulation

However, I didn't limit the signal count_intern - so, internally it is 31-bits (integers are 32-bits, naturals are 31). Even though I am only actually using the lower 3 bits, all 31 end up in the addition and comparison operations. Why? Because on startup, the initial value of count_intern is undefined. It might, for instance, begin with a value of 7 - at which point, the counter will increment until all 31 bits fill up and overflow back to 0. The initialization (to 0) that I supplied in the code, only applies to simulation - it is ignored by the synthesizer.

The post-synthesis schematic, therefore, looks like this:

post-synthesis1

I realize the image is too large to make out its details - but that's the point. It's a mess; and for a very simple circuit.

Now, let's replace the single line:

signal count_intern : natural := 0;

with

signal count_intern : natural range 0 to 5 := 0;


Without proof, the simulation is exactly the same. However, the post-synthesis schematic now resolves to:

post-synthesis2

In fact, the results of this can be confirmed even post-implementation - where it truly counts:

Without limiting the natural range: post-implementation1

With range limit: post-implementation2

Notice the difference in flip-flops used.

While I used Naturals here, this (of course) extends to Integers as well.

Implementation results may vary. Here I am using the default settings in Vivado 2015. Either way, the point is - it is safer and preferable to always specify the range.