Manchmal möchte man, dass sich die Wortbreite von Vektoren eines VHDL-Moduls z.B. über ein Generic einstellen lassen. Natürlich kann man das Ganze händisch machen:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity CalcBW is
Generic ( COUNT_MAX : natural := 100;
COUNT_WIDTH : natural := 7 -- 7 Bits sind nötig.
);
Port ( clk : in STD_LOGIC;
count : out STD_LOGIC_VECTOR (31 downto 0) := (others=>'0')
);
end CalcBW;
architecture Behavioral of CalcBW is
signal cnt : unsigned (COUNT_WIDTH-1 downto 0) := (others=>'0');
begin
process begin
wait until rising_edge(clk);
if (cnt < COUNT_MAX) then cnt <= cnt+1;
else cnt <= (others=>'0');
end if;
end process;
count(cnt'range) <= std_logic_vector(cnt);
end Behavioral;
Wesentlich eleganter ist aber, wenn hier z.B. nur der Zählerendwert übergeben und daraus in dem VHDL-Modul die nötige Vektorbreite berechnet wird. Das kann z.B. so gemacht werden:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
USE ieee.math_real.log2;
USE ieee.math_real.ceil;
entity CalcBW is
Generic ( COUNT_MAX : natural := 100
);
Port ( clk : in STD_LOGIC;
clear : in STD_LOGIC;
count : out STD_LOGIC_VECTOR (31 downto 0) := (others=>'0')
);
end CalcBW;
architecture Behavioral of CalcBW is
constant COUNT_WIDTH : integer := INTEGER(CEIL(LOG2(REAL(COUNT_MAX+1))));
signal cnt : unsigned (COUNT_WIDTH-1 downto 0) := (others=>'0');
begin
process begin
wait until rising_edge(clk);
if (cnt < COUNT_MAX) then cnt <= cnt+1;
else cnt <= (others=>'0');
end if;
end process;
count(cnt'range) <= std_logic_vector(cnt);
end Behavioral;
Mit den in der MATH_REAL Bibliothek enthaltenen Funktionen LOG2 wird zuerst die tatsächliche Bitzahl ausgerechnet und mit CEIL auf das nächste Bit aufgerundet. So erhält man z.B. für die Werte 100 und 126 die nötigen 7 Bits, für einen Wert von 129 dann 8 Bits.