Mit der numeric_std lassen sich schöne Dinge anstellen, die den Code fast unlesbar machen
Hier einige akademische und praktische Beispiele, wie ein 16-Bit Integer in einzelne Nibble zerlegt werden kann:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Vectors is
Port ( vin : in STD_LOGIC_VECTOR (15 downto 0);
sel : in STD_LOGIC_VECTOR (3 downto 0);
voutA : out STD_LOGIC_VECTOR (3 downto 0);
voutB : out STD_LOGIC_VECTOR (3 downto 0);
voutC : out STD_LOGIC_VECTOR (3 downto 0);
voutD : out STD_LOGIC_VECTOR (3 downto 0));
end Vectors;
architecture Behavioral of Vectors is
signal s : std_logic_vector(1 downto 0);
signal i : integer range 0 to 2**16-1;
signal h : integer range 0 to 3;
begin
i <= to_integer(unsigned(vin));
s <= sel(1) & sel(3);
h <= to_integer(unsigned(s));
with s select
voutA <= std_logic_vector(to_unsigned(i,16)(3 downto 0)) when "00",
std_logic_vector(to_unsigned(i,16)(7 downto 4)) when "01",
std_logic_vector(to_unsigned(i,16)(11 downto 8)) when "10",
std_logic_vector(to_unsigned(i,16)(15 downto 12)) when others;
with s select
voutB <= std_logic_vector(to_unsigned(i ,4)) when "00",
std_logic_vector(to_unsigned(i/16 ,4)) when "01",
std_logic_vector(to_unsigned(i/256 ,4)) when "10",
std_logic_vector(to_unsigned(i/1024,4)) when others;
voutC <= std_logic_vector(to_unsigned(i,16)(h*4+3 downto h*4));
-- leider noch nicht synthetisierbar
voutD <= std_logic_vector(to_unsigned(i/(2**(h*4)),4));
end Behavioral;
Zuerst wird vorbereitend der Eingangsvektor vin in einen Integer i umgewandelt. Im echten Leben wäre i z.B. ein Zähler oder ein Rechenwert. Der Auswahlvektor s wird aus einzelnen Bits eines Eingangssignals zusammengesetzt. Über s wird dann jeweils ein Nibble von i auf voutA..C abgebildet.
Wie im RTL-Schaltplan zu sehen ist, werden alle drei gültigen Beschreibungen identisch implementiert:
voutD simuliert zwar schön, kann aber von der Synthese nicht abgebildet werden, Xilinx ISE meldet:
Operator <DIVIDE> must have constant operands or first operand must be power of 2
Die Fehlermeldung ist nicht ganz einsichtig, denn 2**(h*4) ist eine Zweierpotenz
Soll aus einem Integer ein einzelnes Bit herausgelöst werden, können diese Beschreibungen verwendet werden:
signal bit9 : STD_LOGIC;
signal bit8 : STD_LOGIC;
-- ein einzelnes Bit aus einem Integer herausholen
bit8 <= to_unsigned(i,9)(8);
-- to_unsigned(i,1) gibt einen Vektor (0 downto 0) zurück
-- daraus wird dann das Bit 0 verwendet
bit9 <= to_unsigned(i/2**9,1)(0);