If you need to describe operations such as counters that are not directly supported in the standard logic data types, you will almost certainly have to make use of type conversion functions to convert  the standard logic data types at your system interfaces to types such as integers that support such operations.

Type conversion functions are functions that accept an object of one data type and return the equivalent data value represented as a different data type. Some type conversion functions are provided in the IEEE 1164 std_logic_1164 package (functions to convert between std_logic_vector and bit_vector, for example), but no functions are provided in that package to convert between standard logic data types and numeric data types such as integers.

Arithmetic circuits (such as adders and counters) are common elements of modern digital systems, and of design descriptions intended for synthesis. So what do you do if you want to use standard logic data types and describe arithmetic operations? There are actually a number of possible solutions to this problem.

The first solution is to write your own synthesizable type conversion functions, so that you can translate between standard logic values that you will use for your system interfaces (such as the ports for your entities) and the internal numeric type signals and variables you will need to describe your arithmetic function. This is actually a rather poor solution, as it can be quite difficult (perhaps impossible) to write a general-purpose (meaning width-independent) type conversion function that your synthesis tool can handle.

The second solution is to make use of custom type conversion functions or data types that have been provided by your synthesis vendor for use with their tool. An example of such a method (using the std_logic_arith package provided by Synopsys) is shown below:

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

entity COUNT16 is

Data: in std_logic_vector(3 downto 0);

Count: out std_logic_vector(3 downto 0)

);

end COUNT16;

architecture COUNT16_A of COUNT16 is

begin

process(Rst,Clk)

-- The unsigned integer type is defined in synopsys.vhd...

variable Q: unsigned (3 downto 0);

begin

if Rst = '1' then

Q := "0000";

elsif rising_edge(Clk) then

for i in 3 downto 0 loop

Q(i) := Data(i);

end loop;

elsif Q = "1111" then

Q := "0000";

else

Q := Q + "0001";

end if;

end if;

Count <= conv_std_logic_vector(Q,Data'length);

end process;

end COUNT16_A;

In this example, the conv_std_logic_vector function has been provided in the std_logic_arith package, which was supplied by a synthesis vendor (in this case, Synopsys).

Using synthesis tool-specific packages such as std_logic_arith can be quite convenient, but may result in a non-portable design description. (This is particularly true if you use tool-specific type conversion functions, which often have completely different naming conventions and function parameters, and are typically incompatible with synthesis tools other than those they were originally written for.)

The best solution to the numeric data is to use the IEEE 1076.3 standard numeric data types, which are described in the section IEEE Standard 1076.3.