Look at this ... I agree with you! Restricting entity ports to std_logic and std_logic_vector puts arbitrary limits on a design. Use natural, unsigned, signed, wherever they make sense. At the very least, doing so reduces the number of type conversions that everyone seems to hate.
I must be missing something. Can you point me at a sizable project that uses the techniques you are suggesting, so I can look through the code?
But for now, here is my experiment I performed tonight. For a project I am working on. I get a 12-bit value from an ADC, and I need to scale an ADC reading by 503.75/4096 (or 2015/16348). So I coded it both ways, and implemented it in hardware.
So if I understand your suggested style, using integers or naturals on the interface makes sense, doubly so to a HDL newbie. It also makes sense to use '*' and '/' operators too.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity using_ints is
Port ( clk : in STD_LOGIC;
adc_reading : in integer;
temp : out integer);
end using_ints;
architecture Behavioral of using_ints is
begin
process(clk)
begin
if rising_edge(clk) then
temp <= adc_reading * 2015 / 16384;
end if;
end process;
end Behavioral;
Perfectly reasonable code, and implements and tests correctly. With the inputs and output registered outside of the his module, the usage within the module is 60 LUTs, 9 Flipflops, 1 DSP block, Fmax 117 MHz. I also tried it with 'naturals' rather than integers, with the same results.
Now using STD_LOGIC_VECTOR as the interface, and hinting at what is really efficient to do.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity using_slv is
Port ( clk : in STD_LOGIC;
adc_reading : in STD_LOGIC_VECTOR (11 downto 0);
tempx : out STD_LOGIC_VECTOR (8 downto 0));
end using_slv;
architecture Behavioral of using_slv is
signal adc_reading_x2048 : unsigned (22 downto 0);
signal adc_reading_x32 : unsigned (16 downto 0);
signal adc_reading_x1 : unsigned (11 downto 0);
signal result : unsigned (22 downto 0);
begin
adc_reading_x2048 <= unsigned(adc_reading) & to_unsigned(0,11);
adc_reading_x32 <= unsigned(adc_reading) & to_unsigned(0,5);
adc_reading_x1 <= unsigned(adc_reading);
temp <= std_logic_vector(result(result'high downto 14)); -- Divide by 2^14 = 16k
process(clk)
begin
if rising_edge(clk) then
result <= adc_reading_x2048 - adc_reading_x32 - adc_reading_x1;
end if;
end process;
end Behavioral;
Module usage 23 LUTs, 8 Flipflops, Fmax 384 MHz - less than half the LUTs, no DSP blocks, and three times faster.
To me, the results speak for themselves...