3. Prozesse in VHDL - · PDF file3 Im Beispiel auf der letzten Folie wird dieselbe Technik...

Preview:

Citation preview

1

3. Prozesse in VHDL

2

entity VOLLADDIERER isport ( A, B, CIN: in std_logic;

S, COUT: out std_logic;end VOLLADDIERER;

architecture VERHALTEN of VOLLADDIERER isbeginVA: process (A, B, CIN)

variable TEMP_IN: std_logic_vector (2 downto 0);variable TEMP_OUT: std_logic_vector (1 downto 0);begin

TEMP_IN := CIN&A&B;case TEMP_IN is

when “000“ => TEMP_OUT := “00“;when “011“ => TEMP_OUT := “10“;when “101“ => TEMP_OUT := “10“;when “110“ => TEMP_OUT := “10“;when “111“ => TEMP_OUT := “11“;when others => TEMP_OUT := “01“;

end case;S <= TEMP_OUT(0);COUT <= TEMP_OUT(1);

end process VA;end VERHALTEN;

3

Im Beispiel auf der letzten Folie wird dieselbe Technik angewendet, um einen Volladdierer zu modellieren. Die Möglichkeit, die drei Eingangssignale in einen std_logic_vector (TEMP_IN) zusammenzufassen erlaubt die sehr kompakte Formulierung in der case -Anweisung.

Man beachte, dass für den Vektor TEMP_OUT die Verwendung einer variableerforderlich ist. Hätte man TEMP_OUT als signal (außerhalb des Prozesses) deklariert, wäre auch ein syntaktisch korrektes VHDL-Programm entstanden, das aber eine andere Funktion modellieren würde (siehe nächste Folie). Warum?

4

entity VOLLADDIERER isport ( A, B, CIN: in std_logic ;

S, COUT: out std_logic );end VOLLADDIERER;

architecture VERHALTEN of VOLLADDIERER issignal TEMP_OUT: std_logic_vector (1 downto 0);beginVA: process (A, B, CIN)

variable TEMP_IN: std_logic_vector (2 downto 0);begin

TEMP_IN := CIN&A&B;case TEMP_IN is

when "000" => TEMP_OUT <= "00";when "011" => TEMP_OUT <= "10";when "101" => TEMP_OUT <= "10";when "110" => TEMP_OUT <= "10";when "111" => TEMP_OUT <= "11";when others => TEMP_OUT <= "01";

end case ;S <= TEMP_OUT(0);COUT <= TEMP_OUT(1);

end process VA;end VERHALTEN;

5

Mehrere Alternativen in einer case-Anweisung können durch einen senkrechten (oder-) Strich in einer Zeile aufgeführt werden. Das ursprüngliche Beispiel des VOLLADDIERERS mit dieser Modifikation ist auf der folgenden Folie angegeben.

6

entity VOLLADDIERER isport ( A, B, CIN: in std_logic;

S, COUT: out std_logic;end VOLLADDIERER;

architecture VERHALTEN of VOLLADDIERER isbeginVA: process (A, B, CIN)

variable TEMP_IN: std_logic_vector (2 downto 0);variable TEMP_OUT: std_logic_vector (1 downto 0);begin

TEMP_IN := CIN&A&B;case TEMP_IN is

when “000“ => TEMP_OUT := “00“;

when “011“ │ “101“ │ “110“ => TEMP_OUT := “10“;when “111“ => TEMP_OUT := “11“;when others => TEMP_OUT := “01“;

end case;S <= TEMP_OUT(0);COUT <= TEMP_OUT(1);

end process VA;end VERHALTEN;

7

Die if-Anweisung

if <Bedingung_1> then{<Sequentielle Anweisungen>};

[ elsif <Bedingung_2> then{<Sequentielle Anweisungen>};]….

[ else{<Sequentielle Anweisungen>};]

end if ;

8

Die if-Anweisung

if <Bedingung_1> then{<Sequentielle Anweisungen>};

[ elsif <Bedingung_2> then{<Sequentielle Anweisungen>};]….

[ else{<Sequentielle Anweisungen>};]

end if ;

Die Anzahl der elsif -Zweige ist beliebig. Sie können, wie auch der else -Zweig, entfallen. Als Abfragebedingungen sind boolesche Ausdrücke erlaubt. Also Signale vom Typ boolean oder logische Vergleichsaussagen oder Verknüpfungen daraus. Das folgende Beispiel illustriert dies:

9

architecture TEST of TEST_ENT issignal S1, S2: std_logic;signal B1, B2: boolean;beginPROC: process (S1, S2)

beginif S1 then -- Fehler: kein boolean...elsif S1 = ‘0‘ then -- korrekt...elsif B1 then -- korrekt...elsif B1 and (S1 = ‘0‘) -- korrekt...end if;

end process PROC;end TEST;

10

entity MUX4X1_2 is -- 4-auf-1-Multiplexer mit ifport ( S: in std_logic_vector (1 downto 0);

E: in std_logic_vector (3 downto 0);Y: out std_logic );

end MUX4X1_2;

architecture VERHALTEN of MUX4X1_2 isbeginMUX: process (S, E)

beginif S = “00“ then

Y <= E(0);elsif S = “01“ then

Y <= E(1);elsif S = “10“ then

Y <= E(2);else

Y <= E(3);end if;

end process MUX;end VERHALTEN;

11

Das auf der folgenden Folie angegebene VHDL-Modell wirkt auf den ersten Blick wie eine Schaltung, bei der das Signal SIG immer nach Ablauf des Prozesses auf 0 liegen wird. Warum ist dies jedoch in Wirklichkeit nicht der Fall?

12

architecture VERHALTEN of FALLE issignal A, SIG: std_logic;beginWASNHIERLOS: process (A)

beginSIG <= ‘1‘;if SIG = ‘1‘ then

SIG <= ‘0‘;end if;

end process WASNHIERLOS;end VERHALTEN;

13

Schleifen

[Bezeichner:]for <Schleifenspezifikation> loop

{<Sequentielle Anweisungen>};end loop ;

14

Schleifen

[Bezeichner:]for <Schleifenspezifikation> loop

{<Sequentielle Anweisungen>};end loop ;

Als Schleifenspezifikation sind die beiden folgenden Varianten zulässig:

<Schleifenindex> in <Untere_Grenze> to <Obere_Grenze>

<Schleifenindex> in <Obere_Grenze> downto <Untere_Grenze>

Der Schleifenindex muss nicht deklariert werden. Er wird implizit durch die Verwendung des for -Konstrukts deklariert. Die Schleifengrenzen müssen statisch sein.

15

entity PARITAET is -- Parity-Checker mit for loopgeneric (BITS: integer :=4);port ( D: in std_logic_vector (BITS-1 downto 0);

UNGERADE: out std_logic );end PARITAET ;

architecture VERHALTEN of PARITAET isbeginPARGEN: process (D)

variable PAR: boolean; begin

PAR := false;for I in BITS-1 downto 0 loop

if D(I)=‘1‘ thenPAR := not PAR;

end if ;end loop ;if PAR then UNGERADE <= ‘1‘;

else UNGERADE <= ‘0‘;end if ;

end process PARGEN;end VERHALTEN;

16

Das macht die Synthese daraus. Diese einfache Hardwarelösung verdeutlicht den Stand der Logiksynthese: Auch relativ komplizierte Prozesse werden auf optimale Hardwarelösungen abgebildet. Allerdings kann man sich nicht immer darauf verlassen. Wenn man das Modell vereinfachen kann, sollte man es tunlichst auch tun, um das Synthesetool in die richtige Richtung zu lenken.

=1Y

D[0]=1

=1

D[1]

D[2]

D[3]

17

Schaltwerke

Wir wollen ein positiv taktflankengesteuertes D-Flipflop mit asynchronem Rücksetzeingang und Taktfreigabeeingang entwerfen.In VHDL lässt sich die Synchronisierung einer Schaltung in einem Prozess mit Empfindlichkeitsliste durch eine if -Anweisung beschreiben, die als Bedingung die Flankenabfrage eines Signals (z.B. CLK‘event ) enthält. Diese Prozesse nennt man auch clock edge Prozesse.

Abfrage der ansteigenden Tanktflanke:

if CLK = ‘1‘ and CLK‘event then……end if ;

Abfrage der abfallenden Tanktflanke:

if CLK = ‘0‘ and CLK‘event then……end if ;

18

Prozesse ohne Empfindlichkeitsliste können eine Taktabfrage machen mit

Abfrage der ansteigenden Tanktflanke:

wait until CLK = ‘1‘ and CLK‘event

In beiden Fällen ist eine logische Verknüpfung mit weiteren Booleschen Ausdrücken kein guter Stil, wenngleich synthetisierbar, also z.B.

if CLK = ‘1‘ and CLK‘event and ENABLE=‘1‘ then

Ein D-Flipflop mit Enable übernimmt den Wert des Eingangs D bei der positiven Taktflanke an den Ausgang Q, falls ENABLE = ‘1‘ ist. Bei ENABLE = ‘0‘ behält es den alten Zustand Q bei. Ein asynchroner Reset-Eingang bewirkt bei RESET = ‘1‘ ein sofortiges Rücksetzen des Zustands des Flipflops auf 0, egal wie D und CLK stehen.

19

entity DFF_R_EN isport ( CLK, ENABLE, RESET, D: in std_logic ;

Q: out std_logic );end DFF_R_EN;

architecture VERHALTEN of DFF_R_EN isbeginFF: process (CLK, RESET)

beginif RESET = ‘1‘ then

Q <= ‘0‘;elsif CLK= ‘1‘ and CLK‘event then

if ENABLE=‘1‘ thenQ <= D;

end if;end if ;

end process FF;end VERHALTEN;

20

Das Ergebnis der VHDL-Synthese:

D-FF

CLK

RESET

&

≥1ENABLE

D

≥1 Q

1

D

R

D_INT

D_INT = (ENABLE ∧ D) ∨ (¬ENABLE ∧ Q)

21

Das Ergebnis der VHDL-Synthese mit einem andern Synthesetool:

D-FF

CLK

RESET

&

ENABLE

D

QD

R

Einfacher, aber fehlerträchtig wegen Clock-Skew. Bei größeren Schaltungen empfiehlt es sich, Taktsignale nicht mit anderen Signalen logisch zu verknüpfen.

22

Register

Wenn mehrere taktflankengesteuerte D-Flipflops parallel geschaltet werden, entsteht ein taktflankengesteuertes Register. Allerdings werden für Datenein- und –ausgänge hier zweckmäßigerweise Signale vom Typ std_logic_vector verwendet. Das Beispiel auf der folgenden Folie stellt ein negativ taktflankengesteuertes N-Bit-Register dar.

Die generic -Deklaration erlaubt die Benutzung von Parameterwerten, die innerhalb der Entity wie Konstanten interpretiert werden. Auf diese Weise können Hardwareelemente modelliert werden, deren Dimensionierung variabel gestaltet werden kann. Der generic -Wert kann nämlich von einer höheren Hierarchieebene überschrieben werden.

23

entity REGISTER isgeneric (N: integer:=16);port ( CLK, RESET: in std_logic ;

D: in std_logic_vector (N-1 downto 0);Q: out std_logic_vector (N-1 downto 0);

end REGISTER ;

architecture VERHALTEN of REGISTER isbeginREG: process (CLK, RESET)

beginif RESET = ‘1‘ then

Q <= ( others => ‘0‘);elsif CLK= ‘0‘ and CLK‘event then

Q <= D;end if ;

end process REG;end VERHALTEN;

24

Beispiel: Ein Johnson-Zähler mit Taktteiler

Ein Johnson-Zähler ist ein Zähler, bei dem die Darstellung der Zustände bei jedem Zustandsübergang nur in einem Bit wechselt. Man benutzt solche Zähler, um Hazards in Folgeschaltungen zu vermeiden.

Zur VHDL-Realisierung bietet sich ein taktflankengesteuerter Prozess an, in dem abhängig vom aktuellen Zählerstand der Folgezählerstand sowie der passende Pegel der Teilerausgänge erzeugt wird. Dazu wird eine case -Anweisung genutzt.

Der Zählerstand wird im lokalen Signal TEMP erzeugt und durch das Signal COUNT nach außen weitergegeben. Das Signal FTEIL zeigt die Pegel der heruntergeteiltenTaktfrequenz und zwar FTEIL(1) zeigt die im Verhältnis 2:1 heruntergeteilte Frequenz und FTEIL(0) die im Verhältnis 6:1 heruntergeteilte Frequenz.

25

entity FREQ_TEIL isport ( CLK, RESET: in std_logic ;

COUNT: out std_logic_vector (2 downto 0);FTEIL: out std_logic_vector (1 downto 0);

end FREQ_TEIL ;architecture VERHALTEN of FREQ_TEIL issignal TEMP: std_logic_vector (2 downto 0);beginP1: process (CLK, RESET)

if RESET = ‘1‘ thenTEMP <= “000“;FTEIL <= “11“;

elsif CLK = ‘1‘ and CLK‘event then ;case TEMP is

when “000“ => TEMP <= “001“; FTEIL <= “01“;when “001“ => TEMP <= “011“; FTEIL <= “10“;when “011“ => TEMP <= “111“; FTEIL <= “00“;when “111“ => TEMP <= “110“; FTEIL <= “10“;when “110“ => TEMP <= “100“; FTEIL <= “01“;when “100“ => TEMP <= “000“; FTEIL <= “11“;when others => TEMP <= “111“; FTEIL <= “11“;

end case ;end if ;

end process P1;COUNT <= TEMP;end VERHALTEN;

26

Beispiel: Bidirektionales Schieberegister mit einst ellbarer Schiebedistanz

Ein parallel ladbares Schieberegister der Breite WIDTH soll so gebaut werden, dass der Inhalt pro Takt um SHW bits nach links oder nach rechts geschoben werden kann. Eine solche Schaltung kann zum Beispiel eine Multiplikation mit einer Zweierpotenz (bzw. eine Division durch eine Zweierpotenz) realisieren. Die Initialisierung der Parameter erfolgt mit dem Datentyp natural , der Bestandteil des VHDL-Sprachschatzes ist und die natürlichen Zahlen und die Null umfaßt.Ein LOAD Signal steuert das parallele Laden des Schieberegisters. Wenn LOAD = ‘1‘ ist, wird geladen, wenn LOAD = ‘0‘ ist, wird geschoben. Die Schieberichtung wird bestimmt durch ein Signal R_L (‘0‘ Links, ‘1‘ Rechts). Die herausgeschobenen Bits gehen verloren und die nachgezogenen Bits sind ‘0‘.

27

entity SHIFTREG is -- Beispiel für Verwendung for-loopgeneric (WIDTH : natural : 4; -- Registerbreite

SHW : natural :2); -- Schiebeweiteport ( CLK, LOAD, R_L: in std_logic ;

DIN: in std_logic_vector (WIDTH-1 downto 0);YOUT: out std_logic_vector (WIDTH-1 downto 0);

end SHIFTREG ;architecture VERHALTEN of SHIFTREG issignal YINT : std_logic_vector (WIDTH-1 downto 0);signal TEMP: std_logic_vector (SHW-1 downto 0);beginZEROS: processbegin

for I in SHW-1 downto 0 loopTEMP(I) <= ‘0‘;

end loop;wait ;

end process ZEROS;

28

LOAD_AND_SHIFT: process (CLK)begin

if CLK = ‘1‘ and CLK‘event then ;if LOAD = ‘1‘ then YINT <= DIN;elsif R_L = ‘0‘ then -- Links

YINT <= YINT(WIDTH-1-SHW downto 0)&TEMP;else -- Rechts

YINT <= TEMP & YINT(WIDTH-1 downto SHW);end if ;

end if;end process LOAD_AND_SHIFT;YOUT <= YINT;end VERHALTEN;

29

D

D

D

D

YOUT

CLK

&

&

&

&

≥1

≥1

≥1

≥1

1R_L

&

&

&

&

LOAD

≥1

≥1

≥1

≥1DIN[3..0]

YINT

30

4. Automatenmodellierung mit VHDL

31

Beispiel: Impulsfolgenerkennung

Um einen Moore-Automaten zu modellieren, wählen wir als Beispiel einen Impulsfolgenerkenner. Solche Schaltungen benötigt man zum Beispiel in der Telekommunikationstechnik bei der Abwicklung von Protokollen. Hier sollen zwei Eingangsbits pro Takt interpretiert werden und ein Ausgangssignal soll auf ‘1‘wechseln, wenn direkt nacheinander die Folge “01“, “11“, “10“ am Eingang erkannt worden ist. Der entsprechende Automatengraph sieht folgendermaßen aus:

Z00

Z10

Z31

Z20

0111X0

01

11

10

11X0

01X0

01

00,11

RESET

32

-- Impulsfolgenerkennung (01, 11, 10): Moore-Automatlibrary IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;

Entity MOORE isport (

CLK : in std_logic; -- SystemtaktRST : in std_logic; -- asynchroner Reset (alles auf Null)ENABLE: in std_logic; -- ÜbergangsaktivierungE : in std_logic_vector(1 downto 0); -- EingabePTR : out std_logic); -- Ausgabebit: 1 wenn Folge erkannt

end MOORE;

architecture Behavioral of MOORE istype ZUSTAENDE is (Z0, Z1, Z2, Z3); -- Aufzählungstypsignal ZUSTAND, FOLGEZUSTAND: ZUSTAENDE;

beginZUSTANDSUEBERGANG: process (CLK, RESET)

beginif RESET = '1' then ZUSTAND <= Z0;elsif CLK = '1' and CLK'event then

if ENABLE = '1' then ZUSTAND <= FOLGEZUSTAND;end if ;

end if ;end process ZUSTANDSUEBERGANG;

33

ZUSTANDSBERECHNUNG: process (E, ZUSTAND)begin

case ZUSTAND iswhen Z0 => if E="01" then FOLGEZUSTAND <= Z1;

else FOLGEZUSTAND <= Z0;end if ;

when Z1 => if E="01" then FOLGEZUSTAND <= Z1;elsif E="11" then FOLGEZUSTAND <= Z2;else FOLGEZUSTAND <= Z0;end if ;

when Z2 => if E="01" then FOLGEZUSTAND <= Z1;elsif E="10" then FOLGEZUSTAND <= Z3;else FOLGEZUSTAND <= Z0;end if ;

when Z3 => if E="01" then FOLGEZUSTAND <= Z1;else FOLGEZUSTAND <= Z0;end if ;

end case ;end process ZUSTANDSBERECHNUNG;

AUSGABE: process (ZUSTAND)begin

case ZUSTAND iswhen Z3 => A <= '1';when others => A <= '0';

end case ;end process AUSGABE;

end Behavioral;

34

Die folgende Folie zeigt die Simulation des obigen VHDL-Codes.

Man beachte, dass sich dieser Automat wirklich nach dem Moore-Prinzip verhält: Zwar hat der geänderte Eingabevektor unmittelbar Auswirkungen auf den Folgezustand, diese schlagen aber erst zum Zeitpunkt der positiven Taktflanke auf den neuen Zustand und die Ausgabe durch. In einem Mealy-Automaten würde sich die Ausgabe zwischenzeitlich ändern, z.B. wenn eine neue Eingabe anliegt, aber noch keine Taktflanke gekommen ist.

35

36

Die folgende Folie zeigt die RT-Darstellung des Syntheseergebnisses

Hierbei ist es interessant zu beobachten, in welcher Weise der Zustand des Schaltwerks gespeichert wird: Die XilinX-Tools verwenden häufig nicht die minimale notwendige Anzahl von Flipflops (das wäre in diesem Falle 2) sondern sie codieren N Zustände in N Flipflops in einem 1-aus-N-Code. (Also immer ein Flipflop hat den Ausgang ‘1‘, alle anderen den Ausgang ‘0‘).

In der Realisierung hier ist Z0 gekennzeichnet durch eine ‘1‘ an Zustand_ffd4, Z1 durch eine ‘1‘ an Zustand_ffd3, Z2 durch eine ‘1‘ an Zustand_ffd2, Z3 durch eine ‘1‘an Zustand_ffd1.

Der Grund für diese Art der Implementierung ist der Aufbau der CLBs. Wenn der Automat mit zwei Flipflops realisiert werden würde, wären die Schaltnetze zwischen den Flipflops so aufwendig, dass sie nicht mit den Ressourcen jeweils einer LogicCell zu implementieren wären. Daher ist die gewählte Realisierung zwar verschwenderisch in Hinsicht auf Flipflops, aber sparsam im Hinsicht auf Gesamtaufwand.

Man kann den Synthesetools aber Vorgaben machen über die Zustandskodierung. Der default ist dann die One-hot-Codierung.

37

38

39

Die folgende Folie zeigt die Simulation des Syntheseergebnisses.

Tatsächlich kann man dasselbe Verhalten beobachten, wie zunächst in der Simulation des VHDL-Entwurfs. Allerdings sind jetzt die tatsächlichen Verzögerungszeiten (ca. 9 ns auf dem längsten Pfad) zu beobachten.

40

41

Beispiel: Impulsfolgenerkennung durch einen Mealy-A utomaten

Wieder sollen zwei Eingangsbits pro Takt interpretiert werden und ein Ausgangssignal soll auf ‘1‘ wechseln, wenn direkt nacheinander die Folge “01“, “11“, “10“ am Eingang erkannt worden ist. Der entsprechende Automatengraph sieht folgendermaßen aus:

Z0 Z1

Z2

01/011/0X0/0

01/0

11/0

X0/0

01/000/011/010/1

RESET

42

library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Mealy isport ( CLK, RESET, ENABLE: in std_logic;

E : in std_logic_vector(1 downto 0);A : out std_logic);

end Mealy;

architecture Behavioral of Mealy istype ZUSTAENDE is (Z0, Z1, Z2); -- Aufzählungstypsignal ZUSTAND, FOLGEZUSTAND: ZUSTAENDE;

beginUEBERGANG: process (CLK, RESET)

beginif RESET = '1' then ZUSTAND <= Z0;elsif CLK = '1' and CLK'event then

if ENABLE = '1' then ZUSTAND <= FOLGEZUSTAND;end if;

end if;end process UEBERGANG;

43

FOLGEZUSTANDSBERECHNUNG: process (E, ZUSTAND)begin

case ZUSTAND iswhen Z0 => if E = "01" then FOLGEZUSTAND <= Z1;

else FOLGEZUSTAND <= Z0;end if;

when Z1 => if E = "11" then FOLGEZUSTAND <= Z2;elsif E = "01" then

FOLGEZUSTAND <= Z1;else FOLGEZUSTAND <= Z0;end if;

when Z2 => if E = "01" then FOLGEZUSTAND <= Z1;else FOLGEZUSTAND <= Z0;end if;

when others => null;end case;

end process FOLGEZUSTANDSBERECHNUNG;

AUSGABEBERECHNUNG: process (E, ZUSTAND)begin

if (ZUSTAND = Z2 and E = "10") then A <= '1';else A <= '0';end if;

end process AUSGABEBERECHNUNG;end Behavioral;

44

Auffallend ist hier die Zeile

when others => null;

Diese ist eingefügt worden, da bei einer Codierung der drei Zustände mit zwei Bits eine Bitkombination vorkommt, die keinem Zustand entspricht. Um auch im Falle einer zufälligen Initialisierung in diesem Zustand auf jeden Fall in einen definierten Folgezustand zu kommen, wurde diese Zeile eingefügt.

45

46

47

Recommended