WebElektronika

Variációk D flip-flop-ra VHDL nyelvben

person access_time 2014.09.30.
A VHDL hardverleíró nyelv a mai napig nagy népszerűségnek örvend. Ezért megnézünk most néhány megoldást egy D flip-flop-ra. Kitérünk a bit és az std_logic típusok közötti különbségre is.


Nézzük meg az egyik leggyakrabban használt "D" tárolónak (1. ábra) a különböző VHDL nyelvi megvalósítási lehetőségeit.


1. ábra   A megvalósítandó D flipflop schema-ja
 

Először megnézzük a D flipflop-nak (DFF) azt a megvalósítását, amely nem tartalmaz "CLR" (reset) jelet. Azután kitérünk a szinkron és az aszinkron törlési lehetőségekre is.
 

 

D flipflop törlés nékül

 

Először a bemeneteket és a kimenteket bit típusként ábrázoljuk. Fontos tudni, hogy a bit típussal csak logikai 0-t és 1-et tudunk megjeleníteni. Ez a tulajdonság befolyásolni fogja a szimulációs eredményeinket.
 

Először a "CLR" bemenetet nem valósítjuk meg, csak a "D"-t és a "CLK"-t. Ennek a D flipflop-nak a VHDL kódja látható itt:

entity dff1 is
    port(D, CLK : in bit;
        Q, nQ : out bit);
end dff1;

architecture BEH of dff1 is
begin
    process(D, CLK)
    begin
        if CLK'event and CLK = '1' then
            Q <= D;
            nQ <= not(D);
        else
            null;
        end if;
    end process;
end BEH;

 

Az órajel felfutó élére beolvassuk a "D" bemenetet és a kimenetre (Q) tesszük, illetve a bemenet negáltját a kimenet negáltjára (nQ) írjuk ki.

Itt látható a szimulációs környezete az első D flipflop (dff1.vhd) megvalósításnak. A szimulálandó VHDL kódot komponensként illesztjük be a tesztkörnyezetünkbe.

entity dff1sim is
    port(Q, nQ : out bit);
end dff1sim;

architecture BEH of dff1sim is
    component dff1 is
        port(D, CLK : in bit;
            Q, nQ : out bit);
    end component;
signal SD, SCLK : bit;
begin
    nev: dff1 port map (SD, SCLK, Q, nQ);
    
    process
    begin
        SD <= '0';
        SCLK <= '0';
        wait for 20 ns;
        SCLK <= '1';
        wait for 10 ns;
        SCLK <= '0';
        wait for 30 ns;
    end process;
end BEH;

 

Fordítsuk le ezt a VHDL kódot is (Compile / Compile file 'dff1sim.vhd'), majd válasszuk ki, a projektünk melyik file-át kívánjuk szimulálni (2. ábra).


2. ábra   A szimulációs file kiválasztása
 

A 3. ábrán látjuk a szimulált D flipflopunk működését. Vegyük észre, hogy 0-20 ns között a ponált és a negált kimenet állapota megegyezik!


3. ábra   A szimulációs eredmény
 

Ez természetesen hibás, de a hiba oka nem a VHDL kódunk architektúrális leírásában keresendő, hanem típusban. A "bit" típus nem alkalmas már erre a szimulációra, hiszen 0-20 ns között ismeretlen kimenetet kellett volna kapnunk, mert az órajel (CLK) csak a 20 ns-ban vált állapotot. Viszont a "bit" típussal csak logikai nulla és logikai egy jeleníthető meg.

Keressünk egy másik típust!
 

Ezért módosítsuk az első VHDL kódunkat, a bit típust írjuk át std_logic-ra. Ez a kód (dff2.vhd) látható itt :

LIBRARY IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dff2 is
    port(D, CLK : in std_logic;
        Q, nQ : out std_logic);
end dff2;

architecture BEH of dff2 is
begin
    process(D, CLK)
    begin
        if CLK'event and CLK = '1' then
            Q <= D;
            nQ <= not(D);
        else
            null;
        end if;
    end process;
end BEH;

 

Látható az, hogy a típuson kívül mást nem változtattunk meg. Fontos, hogy az "std_logic" használatához elengedthetlen az IEEE könyvtár meghivatkozása és az IEEE.STD_LOGIC_1164.ALL csomag használata. Ezt kiemelten jelöltük az előző VHDL kódban.

Természetesen a szimulációs környezetben is módosítani kell a típust :
 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dff2sim is
    port(Q, nQ : out std_logic);
end dff2sim;

architecture BEH of dff2sim is
    component dff2 is
        port(D, CLK : in std_logic;
            Q, nQ : out std_logic);
    end component;
signal SD, SCLK : std_logic;
begin
    nev: dff2 port map (SD, SCLK, Q, nQ);
    
    process
    begin
        SD <= '0';
        SCLK <= '0';
        wait for 20 ns;
        SCLK <= '1';
        wait for 10 ns;
        SCLK <= '0';
        wait for 30 ns;
    end process;
end BEH;

 

 

Indítsuk újra a szimulációt, válasszuk ki a dff2sim file-t (4. ábra)


4. ábra   A dff2sim file kiválasztása
 

Az új szimulációs eredményt mutatja az 5. ábra.


5. ábra   A helyes szimulációs eredmény
 

A tesztvektor nem változott meg, ezért a kimeneti eredmény megegyezik azzal a különbséggel, hogy 0-20 ns között a kimenet már az "ismeretlen" állapotot veszi fel. Az órajel felfutásakor kapuzzuk be a "D" bemenet értékét (ez most logikai nulla) is.

Idáig logikai nulla volt a bemeneten a resetelés miatt, az órajel felfutásakor is ezt jelenítettük meg a kimeneten.
 

 

D flipflop aszinkron törléssel
 

Változtassuk meg a VHDL kódunkat, tegyünk be az entitásban egy "CLR" bemenetet, illetve módosítsuk az arhitektúrális leírást is (dff3.vhd) :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dff3 is
    port(D, CLK, CLR : in std_logic;
        Q, nQ : out std_logic);
end dff3;

architecture BEH of dff3 is
begin
    process(D, CLK)
    begin
        if CLR = '1' then
            Q <= '0';
            nQ <= '1';
        else
            if CLK'event and CLK = '1' then
                Q <= D;
                nQ <= not(D);
            else
                null;
            end if;
        end if;
    end process;
end BEH;

 

Helyezzük bele komponensként az előző VHDL kódot ebbe a tesztkörnyezetbe (dff3sim.vhd) :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dff3sim is
    port(Q, nQ : out std_logic);
end dff3sim;

architecture BEH of dff3sim is
    component dff3 is
        port(D, CLK, CLR : in std_logic;
            Q, nQ : out std_logic);
    end component;
signal SD, SCLK, SCLR : std_logic;
begin
    nev: dff3 port map (SD, SCLK, SCLR, Q, nQ);
    
    process
    begin
        SD <= '0';
        SCLK <= '0';
        SCLR <= '0';
        wait for 20 ns;
        SCLR <= '1';
        wait for 10 ns;
        SCLR <= '0';
        wait for 20 ns;
        SCLK <= '1';
        SD <= '1';
        wait for 10 ns;
        SCLK <= '0';
        SD <= '0';
        wait for 30 ns;
    end process;
end BEH;

 

Válasszuk ki a "dff3sim.vhd" file-t a szimulációhoz (6. ábra).


6. ábra   A CLR bemenetet tartalmazó VHDL file kiválasztása
 

Futtassuk most a szimulációt újra. Látható, hogy amikor a "CLR" jel 0->1-be megy, akkor az eddig ismeretlen állapotú kimenetek (Q, nQ) logikai 0-ba, illetve 1-be kerülnek. Amikor a "D" és a "CLK" bemenetekre logikai 1-et adunk, akkor kimenet (Q) logikai 1-be kerül, és ezt az állapotot egészen a következő "CLR=1" értékig meg is őrzi (7. ábra).


7. ábra   Aszinkron törlés
 

 

D flipflop szinkron törléssel

 

Készítsünk most egy szinkron törlésű D flipflop-ot. Ehhez csak az architektúrális részt kell módosítanunk, elvileg a következőképpen :

 

process(D, CLK, CLR)
    begin
        if CLK'event and CLK = '1' and CLR = '1' then
            Q <= '0';
            nQ <= '1';
        elsif CLK'event and CLK = '1' and CLR = '0' then
            Q <= D;
            nQ <= not(D);
        else
            null;
        end if;
end process;

 

A "CLK" és a "CLR" egy feltételvizsgálatban kaptak helyet, amely nem szerencsés, például a régebbi Xilinx fordítók nem kezelik ezt a megoldást.

Módosítsuk ezért a következőképpen a korábbi VHDL kódunkat (dff4jo.vhd) :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dff4jo is
    port(D, CLK, CLR : in std_logic;
        Q, nQ : out std_logic);
end dff4jo;

architecture BEH of dff4jo is
begin
    process(D, CLK, CLR)
    begin
        if CLK'event and CLK = '1' then
            if CLR = '1' then
                Q <= '0';
                nQ <= '1';
            else
                Q <= D;
                nQ <= not(D);
            end if;
        else
            null;
        end if;
    end process;
end BEH;

 

A "CLK" állapotát vizsgáló feltételes szerkezetbe betettük a "CLR"-t ellenőrző if-es szerkezetet, véleményünk szerint ez átláthatóbb, minden fejlesztőszoftver által fordítható kódot kaptunk. Helyezzük ezt a VHDL kódot (dff4jo.vhd) a korábbi szimulációs környezetünkbe (amellyel az aszinkron DFF-et vizsgáltuk) a következőképpen :

architecture BEH of dff3sim is
    component dff4jo is
        port(D, CLK, CLR : in std_logic;
            Q, nQ : out std_logic);
    end component;
signal SD, SCLK, SCLR : std_logic;
begin
    nev: dff4jo port map (SD, SCLK, SCLR, Q, nQ);

 

Látható a szimulációs eredményen, hogy hiába jelent meg a CLR-en a 0->1->0 átmenet (50 ns), a kimenetek továbbra is ismeretlenek maradtak, ezek csak akkor változnak meg, amikor az órajel megváltozik (8. ábra).


8. ábra   Szinkron törlésű DFF aszinkron tesztkörnyezetben
 

Azért kaptuk ezt a szimulációs eredményt, mert az aszinkron D flipflop tesztvektorát tettük a szinkron DFF-re. Viszont a törlőjel nincs szinkronizálva az órajelre.
 

Ezért módosítsuk most a tesztkornyezetünket (szimulációs vektort) a következők szerint : 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dff4sim is
    port(Q, nQ : out std_logic);
end dff4sim;

architecture BEH of dff4sim is
    component dff4jo is
        port(D, CLK, CLR : in std_logic;
            Q, nQ : out std_logic);
    end component;
signal SD, SCLK, SCLR : std_logic;
begin
    nev: dff4jo port map (SD, SCLK, SCLR, Q, nQ);
    
    process
    begin
        SD <= '0';
        SCLK <= '0';
        SCLR <= '0';
        wait for 20 ns;
        SCLR <= '1';
        SCLK <= '1';
        wait for 10 ns;
        SCLR <= '0';
        SCLK <= '0';
        wait for 10 ns;
        SCLK <= '1';
        SD <= '1';
        wait for 10 ns;
        SCLK <= '0';
        SD <= '0';
        wait for 30 ns;
    end process;
end BEH;

 

Válasszuk ki a "dff4sim.vhd" file-t a szimulációhoz (9, ábra) és futtassuk újra a szimulátort.


9. ábra   A "dff4sim.vhd" kiválasztása
 

A szinkron törlésű DFF szimulációs eredményén jól látható, hogy amikor a "CLR" és a "CLK" egyszerre megy fel logikai 1-be, akkor a kimenet törlésre kerül, megszűnik az ismeretlen állapot (10. ábra).


10. ábra   A szinkron törlésű D flipflip új szimulációja