Útržky z jazyka VHDL

Jako student fakulty informačních technologií často řeším nejrůznější projekty. Zpočátku jsem myslel, že mi projekt do předmětu Návrh počítačových systémů dá zabrat, protože to není zrovna moje parketa a jazyk VHDL jsem dosud moc neovládal, ale nakonec jsem byl příjemně překvapen a měl jsem z projektu dobrý pocit.

Nebudu se ovšem zmiňovat o proprietálním software, který je potřeba k programování ve VHDL. Program ModelSim a knihovny od společnosti Xilinx se mi na Linuxu nepodařily propojit a VHDL jsem kompiloval u kolegy. Z tohoto hlediska jsem zklamán, neboť už jenom dostat k požadovanému software licence může být heroický úkol (pro mě). Tím se zabývat nebudu. Místo toho představím 4 hardwarové komponenty v jazyce VHDL. Jinak řečeno vytrhnu čtyři součástky z projektu návrhu jednoduché střadačové architektury, ukážu jejich kód a malinko jej okomentuju.

Jednoduchou střadačovou architekturou zadavatel myslel třemi instrukcemi ovládanou poloviční sčítačku, která příjímá operandy z paměti a ze střadače a výsledek ukládá zpět do střadače. Jako ovládací prvek je použit konečný automat. Ten jako jediný vynechám a představím jen RAM, multiplexor, střadač a sčítačku. Všechno uvedu jako jednotlivé procesy v činnosti jednoduché střadačové architektury. Komponenty jsou propojeny signály (dráty), které budu definovat na přeskáčku, ale mělo by jít poznat, co k čemu patří.

Sčítačka

Požadovaná sčítačka je ve VHDL zapsána velice jednoduše, ale s tím přichází i její omezení. Jelikož jsou vstupy i výstup 8-bitové a sčítačka neošetřuje přetečení, musí být hodnoty obou vstupů menší než 128. V reálné praxi by se to jistě muselo ošetřit, ale zadavatel řekl neošetřovat, takže stačí použít operátor "+" jazyka VHDL a celý proces vypadá následovně.

scitacka: process(add_in1, add_in2)
begin
    add_out <= add_in1 + add_in2;
end process;

A signály, které jsou použity, jsou definovány jako 8-bitové.
signal add_in1, add_in2, add_out : std_logic_vector(7 downto 0);

Čekal jsem, že to bude horší, ale sčítačka ve VHDL je opravdu jednoduchá.

Střadač

Další součástkou je registr, který uchovává svou datovou hodnotu, dokud mu neřekneme, aby uchovával jinou. Dráty na vstupu i na výstupu jsou 8-bitové a součástka je řízena třemi drátky: CLK (hodinový signál), RESET (signál pro vynulování) a WRITE (signál povolující zápis).

signal add_in, add_out : std_logic_vector(7 downto 0);
signal WRITE, CLK, RESET : std_logic;
 
stradac: process(RESET, CLK)
begin
    if (RESET = '1') then -- vynulování
        acc_out <= (others => '0');
    elsif (CLK'event) and (CLK = '1') then -- zápis s náběžnou hranou
        if (WRITE = '1') then
            acc_out <= acc_in; -- jednoduše uděláme ze vstupu výstup
        end if;
    end if;
end process;

VHDL není zas tak hrozný jazyk, jak se může zdát. Selekce pomocí if-else je velmi podobná vyšším programovacím jazykům, stejně jako je ukládání hodnot signálů podobné definicím proměnných.

Multiplexor

Součástka, která má jako vstup několik signálů a my vybereme jeden jako její výstup, se dá ve VHDL zapsat několika způsoby. Já jsem multiplexor implementoval jako další samostatný proces. Ze dvou 8-bitových vstupů dat vybereme jeden na výstup pomocí 1-bitového signálu SELECT.

signal in1, in2, mux_out : std_logic_vector(7 downto 0);
signal SELECT : std_logic;
 
multiplexor: process(in1, in2, SELECT)
begin
    case SELECT is
        when '0'    => mux_out <= in1;
        when '1'    => mux_out <= in2;
        when others => mux_out <= "ZZZZZZZZ"; -- stav vysoké impedance
    end case;
end process;

Objevuje se zde další konstrukce jazyka VHDL, kterou všichni známe z vyšších programovacích jazyků. Konstrukci konečného automatu v jazyce C bychom zapsali pomocí klíčových slov switch a case. Ta jsou zde nahrazena za case a when, ale význam mají stejný.
Upozorňuji, že ve VHDL musí být uvedeno when others, jinak bude kompilátor hlásit chybu.

RAM

Poslední komponentou je paměť. V tomto případě se jedná o RAM složenou ze čtyř 8-bitových hodnot, tedy paměť adresovatelnou dvěma bity - 2-bitovým signálem. Vstup i výstup mají stejný počet bitů jako jedna paměťová buňka a vše je řízeno čtyřmi signály. Se signály CLK a RESET jsme se setkali u střadače, avšak narozdíl od něj potřebujeme kromě zápisu řídit i čtení, a proto je zde kromě signálu WRITE i signál READ. Jsou-li READ a WRITE oba v nule, nic se neděje. Naopak předpokládáme, že WRITE i READ nebudou mít současně hodnotu 1. Jinak aktivní WRITE značí, že se do paměti zapisuje vstup a aktivní READ značí čtení z paměti na výstup.

type mem_array is array(0 to 3) of std_logic_vector(7 downto 0);
signal mem : mem_array;
signal READ, WRITE : std_logic;
signal address : std_logic_vector(1 downto 0);
signal mem_in, mem_out : std_logic_vector(7 downto 0);
 
ram: process(RESET, CLK)
begin
    if (RESET = '1') then -- stav vynulování
        mem_out <= "ZZZZZZZZ"; -- vysoká impedance na výstupu
        mem(0)  <= X"50"; -- libovolné hodnoty v paměti
        mem(1)  <= X"4E"; -- X před uvozovkami vyjadřuje
        mem(2)  <= X"00"; -- hexadecimální hodnotu
        mem(3)  <= X"00";
    elsif (CLK'event) and (CLK =' 1') then
        if (READ = '1') then
            mem_out <= mem(conv_integer(address)); -- výstup z RAM
        elsif (WRITE = '1') then
            mem(conv_integer(address)) <= mem_in; -- vstup do RAM
            mem_out <= "ZZZZZZZZ"; -- výstup je vysoká impedance
        else -- nedefinovany stav
            mem_out <= "ZZZZZZZZ";
        end if;
    end if;
end process;

Za povšimnutí zde stojí vytváření pole signálů (úplně nahoře) a jeho použití (při stavu RESET). Dále je zde použita funkce conv_integer. Jinak se opět jedná o selekci a přiřazování signálů do signálů.

Co z toho plyne?

Programování v jazyce VHDL není težké a je velmi podobné vyšším programovacích jazykům, od kterých se liší hlavně klíčovými slovy a tím, že nepracujeme s abstraktními proměnnými, ale s defacto fyzickými věcmi typu drát nebo hradlo, které vedou odněkud někam a které jsou jen pojmenovány jako proměnné. Aspoň tak mi to příjde po víceméně první práci s tímto zajímavým jazykem. Nebojte se jazyka VHDL!