Upload
lyngoc
View
220
Download
0
Embed Size (px)
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