Day by Day
(EN google-translate)
(PL google-translate)
Verzeichnis der im Verlauf des Semesters behandelten Themen
Donnerstag 18.03.2021
|
Links zu den passenden Inhalten auf kramann.info:
69_FPGA/01_Einfuehrung
69_FPGA/05_Beispiele/03_Mustervergleich
"Saal"-übung: UND-Gatter
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity and_gate is Port ( A : in STD_LOGIC; B : in STD_LOGIC; C : out STD_LOGIC); end and_gate; architecture Behavioral of and_gate is begin C <= A and B; end Behavioral;
Code 0-1: VHDL-Code zum UND-Gatter.
NET "A" LOC = "P139" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "B" LOC = "P135" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "C" LOC = "P131" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ;
Code 0-2: Constraints (.ucf-Datei) zum UND-Gatter.
Donnerstag 25.03.2021
|
Wenn Sie die Hardware haben, sollten Sie die Entwicklungsumgebung ISE 14.7 von Xilinx und die so genannte BitloadApp installieren und ein erstes Beispielprojekt erstellen und sehen, ob es sich auf den DLP-FPGA übertragen läßt.
|
Damit Sie (freie) Software von Xilinx herunterladen und installieren können, müssen Sie sich bei Xilinx registrieren. Es macht Sinn, das zu allererst zu machen. das wird nicht im Video gezeigt. Während des Installationsprozesses werden Sie auch aufgefordert, sich eine Lizenz erstellen zu lassen. Das Lizenzfile wird Ihnen dann per E-Mail zugeschickt und auf das Dateisystem kopiert werden. Der Ort, wo das ist, muß der Installtion bekannt gemacht werden.
Ich habe probiert, die 14.7er-Version zu installieren, bei der explizit Windows 10 steht. Das hat nicht geklappt. Diese Version wurde unter Linux erstellt und ist in eine Virtual Machine eingebettet. Damit sie läuft, müssen Änderungen an den Einstellungen im BIOS vorgenommen werden. Dies fand ich nicht zumutbar, weshalb ich die Version unmittelbar davor genommen habe (auch 14.7). Diese war nativ für Windows 7 entwickelt worden, läuft aber auch unter Windows 10, sowohl unter 64Bit, als auch 32Bit. In dem Video wird gezeigt, wie diese Version installiert wird. Der Einfachheit gebe ich nachfolgend aber bereits die wichtigsten Links hierzu an:
Zu der "richtigen" 14.7-Version (die Zweite, wo NICHT Windows 10 steht) gehören vier gepackte Files. Deren Links gebe ich nachfolgend explizit an. Die sollten Sie alle gemeinsam in den Download-Ordner herunterladen:
Xilinx_ISE_DS_14.7_1015_1-2.zip.xz
Xilinx_ISE_DS_14.7_1015_1-3.zip.xz
Xilinx_ISE_DS_14.7_1015_1-4.zip.xz
Da auf das verwendete Board von Digikey "DLP-FPGA" nicht direkt aus der ISE14.7 heraus Programme übertragen werden können, muß mit ISE 14.7 eine Datei mit der Endung .bit erstellt werden. Diese wird mit einer Extrasoftware auf das Board übertragen. Diese Extrasoftware gibt es für Windows und Linux. Sie heißt BitloadApp und Sie können sie unter folgendem Link umsonst herunterladen:
Diese Software wird einfach irgendwo entpackt und das Executable darin durch Doppelklicken gestartet. Die zu übertragende .bit-Datei sollten Sie vorher in den gleichen Ordner legen, wo auch dieses Executable liegt.
Hier folgen nun die Links zu den Videos, die die Installtion von ISE 14.7 unter Windows 10 zeigen und wie ein erstes Beispielprojekt umgesetzt werden kann. Dieses Beispielprojekt und auch die Notwendigen Einstellungen von ISE 14.7 finden Sie auch auf meiner Webseite:
Quelltext für das Beispielprojekt (blinkled.vhd und blinkled.ucf) und die Beschaltung des DLP-FPGA: 69_FPGA/05_Beispiele/01_Blinkende_LED
Screenshots zum Erstellen eines neuen Projektes für den DLP-FPGA mit ISE 14.7: 69_FPGA/21_XSE14
Video 1 (Teil1): Einführung https://youtu.be/hirAbmhThvA
Video 2 (Teil4): Herunteladen der benötigten Files https://youtu.be/1ceUsO36sH8
Video 3 (Teil5): Herunteladen der benötigten Files (Fortsetzung) https://youtu.be/hFDQj1Teh20
Video 4 (Teil6): Installtion (insb. Auswahl "WebPack") https://youtu.be/yTZssXbqvZM
Video 5 (Teil7): Rest Installation / Erstellen und kompilieren eines ersten Projektes https://youtu.be/_JFIOo7dukU
Video 6 (Teil8, letztes Video): Herunterladen und Verwenden der BitLoadApp, um die kompilierte Datei auf den FPGA zu übertragen https://youtu.be/SbOgoREXxyQ
Donnerstag 08.04.2021
Teil 1 (praktischer Teil)
|
and_gate.zip -- ISE 14.7 - Projekt and_gate.
69_FPGA/03_DLP_FPGA -- siehe Bild 0-2: Zuordnung zwischen den Board-Pins und den FPGA-Chip-Pins (Xilinx Spartan 3E). Die Nummer der FPGA-Chip-Pins wird in den Programmen benötigt.
Übung
Die nachfolgende Übung kann aufgrund der bisherigen Kenntnisse umgesetzt werden.
|
Hinweis: Das logische NICHT ist in VHDL not.
Teil 2 (theoretischer Teil)
|
69_FPGA/05_Beispiele/03_Mustervergleich
Wie sähe der VHDL-Quelltext und die .ucf-Datei zu einem Programm aus, bei dem es zwei Mustervleicher gleichen Typs gäbe: Den, den wir kennen und einen zweiten, bei dem die Eingänge gegenüber gespiegelt auf der anderen Seite des Boards sitzen und die LED bei Pin 22?
Merke: Parallele Strukturen sind möglich und üblich beim FPGA.
Donnerstag 15.04.2021
Themen
|
Bitshiftoperationen -- 69_FPGA/11_VHDL
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity lauflicht is Port ( MEINECLOCK : in STD_LOGIC; FUENFBIT : out STD_LOGIC_VECTOR(4 downto 0) ); end lauflicht; -- Clock-In == 6MHz, Toggeln nach 3000000 Schritten ergibt 1Hz Blinkfrequenz. architecture Behavioral of lauflicht is signal zaehler : integer range 0 to 2999999 := 0; signal wort : std_logic_vector(4 downto 0) := "00001"; begin process begin wait until rising_edge(MEINECLOCK); if (zaehler<2999999) then zaehler <= zaehler+1; else zaehler <= 0; wort <= wort(3 downto 0) & wort(4); end if; end process; FUENFBIT <= wort; end Behavioral;
Code 0-3: Lauflicht VHDL-Code
## GCLK6 ist auf FPGA-Chip Pin 56 NET "MEINECLOCK" LOC = "P56"; NET "FUENFBIT<4>" LOC = "P125"; NET "FUENFBIT<3>" LOC = "P126"; NET "FUENFBIT<2>" LOC = "P130"; NET "FUENFBIT<1>" LOC = "P131"; NET "FUENFBIT<0>" LOC = "P132"; NET "MEINECLOCK" IOSTANDARD = LVCMOS25; NET "FUENFBIT<4>" IOSTANDARD = LVCMOS33; NET "FUENFBIT<3>" IOSTANDARD = LVCMOS33; NET "FUENFBIT<2>" IOSTANDARD = LVCMOS33; NET "FUENFBIT<1>" IOSTANDARD = LVCMOS33; NET "FUENFBIT<0>" IOSTANDARD = LVCMOS33;
Code 0-4: Lauflicht, zugehörige UCF-Datei
Donnerstag 21.04.2021
Da die Syntax von VHDL und deren Bedeutung sich sehr von den ihnen bisher vertrauten Programmiersprachen abhebt, soll der Umgang damit in der heutigen LV weiter vertieft werden. Darum wird nichts Neues eingeführt, sondern es sollen statt dessen die nachfolgend beschriebenen drei Übungen bearbeitet werden.
Machen Sie dabei regen Gebrauch von den Sprachelementen, die Sie bisher kennengelernt haben. Schlagen Sie die bereits behandelten Beispiele nochmals nach.
Belassen Sie für die nachfolgenden Übungen so weit es geht den vorhandenen Aufbau mit den LEDs.
Übung 1
Analysieren Sie den Bitvergleicher, der von alleine die verschiedenen Muster durchgeht und passen Sie dieses Beispiel so an, dass es mit den bereits beim letzten mal angebrachten LEDs funktioniert.
Sie dazu: Version 2 - Automatischer Binärzähler, hier: 69_FPGA/05_Beispiele/03_Mustervergleich
Übung 2
Im Fach Mikrocontrollertechnik wurde eine "Fußgängerampel" programmiert: Zunächst leuchtet eine rote LED auf. Nach Betätigen eines Tasters leuchtet für eine Weile eine grüne LED auf, danach wieder nur die rote.
Diskutieren Sie die Möglichkeit diese Funktionalität mit einem VHDL-Programm zu realisieren.
Setzen Sie Ihre Idee um.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ampel is Port ( MEINECLOCK : in STD_LOGIC; TASTER : in STD_LOGIC; GRUEN : out STD_LOGIC; ROT : out STD_LOGIC); end ampel; architecture Behavioral of ampel is signal logikpegel : std_logic := '0'; signal ausgang : std_logic := '0'; signal zaehler : integer range 0 to 5999999 := 0; begin process begin wait until rising_edge(MEINECLOCK); -- Zaehler Null setzen, wenn Taste gedrückt: if (logikpegel = '1') then zaehler <= 0; end if; -- Zaehlprozess if (zaehler<5999999) then zaehler <= zaehler+1; ausgang <= '1'; -- Ampel soll grün sein else ausgang <= '0'; -- Ampel soll rot sein end if; end process; logikpegel <= not TASTER; GRUEN <= ausgang; ROT <= not ausgang; end Behavioral;
Code 0-5: ampel.vhd (Musterlösung)
## GCLK6 ist auf FPGA-Chip Pin 56 NET "MEINECLOCK" LOC = "P56"; ## IO_L05P_0 ist auf FPGA-Chip Pin 125 NET "GRUEN" LOC = "P125"; NET "ROT" LOC = "P126"; NET "MEINECLOCK" IOSTANDARD = LVCMOS25; NET "TASTER" LOC = "P135" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "GRUEN" IOSTANDARD = LVCMOS33; NET "ROT" IOSTANDARD = LVCMOS33;
Code 0-6: ampel.ucf (Constraints zur Musterlösung)
Bild 0-1: Test des Projektes
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity fussgaengerampel is Port ( CLOCK : in STD_LOGIC; MASSE : in STD_LOGIC; LED_ROT : out STD_LOGIC; LED_GRUEN : out STD_LOGIC ); end fussgaengerampel; architecture Behavioral of fussgaengerampel is signal zaehler : integer range 0 to 5999999 := 0; signal Ampelzaehler: integer range 0 to 4 := 0; signal wort : std_logic_vector(1 downto 0); signal A,B : std_logic; begin process begin wait until rising_edge(CLOCK); if (zaehler < 5999999) then zaehler <= zaehler +1; else zaehler <= 0; if (Ampelzaehler < 4) then Ampelzaehler <= Ampelzaehler +1; else Ampelzaehler <= 0; end if; end if; end process; --quasi_zaehler wort <= conv_std_logic_vector(Ampelzaehler, 2); A <= wort(0); B <= wort(1); LED_GRUEN <= (A and B and (not MASSE)); LED_ROT <= (not A) or (not B) or MASSE; end Behavioral;
Code 0-7: alternative studentische Lösung
NET "CLOCK" LOC = "P56"; NET "CLOCK" IOSTANDARD = LVCMOS25; NET "MASSE" = "P124" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "LED_ROT" LOC = "P105" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ; NET "LED_GRUEN" LOC = "P112" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ;
Code 0-8: Constraints zur studentischen Lösung.
Übung 3
Diskutieren Sie, wie sie mit VHDL ein Lauflicht programmieren können, bei dem ein Lichtpunkt hin und her wandert (Typ "Zylon").
Bei der Musterlösung bleibt die Ampel grün, wenn die Taste gedrückt bleibt. Kann das verhindert werden?
Donnerstag 29.04.2021
Themen
|
Übung
Bilden Sie nachfolgendes Projekt von vorn nach. Prüfen Sie, ob das Verhalten dem erwarteten entspricht.
Übung
Reduzieren Sie die beiden nachfolgenden Projekte so, dass die Taktpulse zum Weiterzählen von Hand über einen Taster erfolgen.
69_FPGA/12_UNISIM -- D-Flip-Flop aus UNISIM Library
Donnerstag 06.05.2021
Themen
|
Nachbesprechung und Fertigstellung der Projekte von letzter Woche
Fußgängerampel
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ampel is Port ( MEINECLOCK : in STD_LOGIC; TASTER : in STD_LOGIC; GRUEN : out STD_LOGIC; ROT : out STD_LOGIC); end ampel; architecture Behavioral of ampel is signal logikpegel : std_logic := '0'; signal ausgang : std_logic := '0'; signal zaehler : integer range 0 to 5999999 := 0; begin process begin wait until rising_edge(MEINECLOCK); -- Zaehler Null setzen, wenn Taste gedrückt: if (logikpegel = '1') then zaehler <= 0; ausgang <= '1'; -- Ampel soll grün sein end if; -- Zaehlprozess if (zaehler<5999999) then zaehler <= zaehler+1; else ausgang <= '0'; -- Ampel soll rot sein end if; end process; logikpegel <= not TASTER; GRUEN <= ausgang; ROT <= not ausgang; end Behavioral;
Code 0-9: VHDL-Code zu einer Variation der Fußgängerampel.
## GCLK6 ist auf FPGA-Chip Pin 56 NET "MEINECLOCK" LOC = "P56"; ## IO_L05P_0 ist auf FPGA-Chip Pin 125 NET "GRUEN" LOC = "P125"; NET "ROT" LOC = "P126"; NET "MEINECLOCK" IOSTANDARD = LVCMOS25; NET "TASTER" LOC = "P135" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "GRUEN" IOSTANDARD = LVCMOS33; NET "ROT" IOSTANDARD = LVCMOS33;
Code 0-10: Constraints zu einer Variation der Fußgängerampel.
Hand-geseteuertes Schieberegister
Vergleiche Hierzu die Quelltexte hier:
69_FPGA/12_UNISIM -- automatisch getaktetes Schieberegister aus D-Flip-Flops der UNISIM-Library.
schieberegister2021.zip -- Musterlösung, Gesamtes Projekt zu "Hand-geseteuertes Schieberegister", erstellt mit ISE14.7
Eigentlich mit dem Ziel eine einfache Übungsaufgabe zu stellen, war gefordert, den vorhandenen Quelltext zu einem intern getakteten Schieberegister so umzuschreiben, das die Taktung über einen Taster von außen von Hand erfolgt.
Hierbei trat leider das Problem des Prellens des Tasters auf, wodurch stets mehr als ein Puls von außen kommend registriert wurde und damit der Schiebevorgang unkontrolliert läuft.
Um dieses Problem lösen zu können, muß ein weiterer Prozeß implementiert werden, der nach dem ersten herein kommenden Impuls durch den Clock-Taster den Eingang für eine gewisse Zeit nicht beachtet, damit nachfolgende Prellpulse unberücksichtigt bleiben. Im Zuge hier während des Unterrichts eine Lösung zu finden, hat sich herausgetellt, dass die Lösung dieses Problems nicht so trivial ist, wie das beispielsweise bei Verwendung eines Mikrocontrollers wäre.
Wesentlich zu beachten ist, dass bereits in jeder Flip-Flop-Instanz je ein Prozeß enthalten ist. Desweiteren wird um die temporäre Desensibilisierung des Tasters zu bewerkstelligen dann doch weiterhin die interne 6MHz-Clock verwendet, um genau diesen zeitlichen Prozeß zu handhaben.
Um die Warning, dass kein dedizierter Clock-Signaleingang verwendet wird weg zu bekommen, wird statt P142 besser P122 als Eingang verwendet. Dies ist bei der Verkabelung zu beachten!
Nochfolgend finden Sie eine funktionierende Lösung, die im Verlauf dieser LV vorgestellt und besprochen wird:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; ---- Clock-Leitung nicht an vorgesehenem Pin führt zu: ---- ---- in ucf nötig: NET "CLOCK" CLOCK_DEDICATED_ROUTE = FALSE; ---- ---- WARNING:Place:1019 - A clock IOB / clock component pair have been found that are not placed at an optimal clock IOB / ---- clock site pair. The clock component <CLOCK_BUFGP/BUFG> is placed at site <BUFGMUX_X1Y10>. The IO component <CLOCK> ---- is placed at site <P142>. This will not allow the use of the fast path between the IO and the Clock buffer. This is ---- normally an ERROR but the CLOCK_DEDICATED_ROUTE constraint was applied on COMP.PIN <CLOCK.PAD> allowing your design ---- to continue. This constraint disables all clock placer rules related to the specified COMP.PIN. The use of this ---- override is highly discouraged as it may lead to very poor timing results. It is recommended that this error ---- condition be corrected in the design. entity schieberegister is Port ( CLOCK6MHZ : in STD_LOGIC; CLOCK : in STD_LOGIC; -- #### Name geändert in CLOCK RESET : in STD_LOGIC; BITIN : in STD_LOGIC; VIERBIT : out STD_LOGIC_VECTOR (3 downto 0)); end schieberegister; architecture Verhalten_Schieberegister of schieberegister is signal sig_d : std_logic_vector (3 downto 0) := "0000"; signal sig_q : std_logic_vector (3 downto 0) := "0000"; signal clock1Hz : std_logic := '0'; signal all_reset : std_logic := '1'; signal zaehler : integer range 0 to 2999999 := 0; begin -- Erzeugen der 1Hz-Clock mit Hilfe eines Prozesses (vergl. Blink-LED) -- #### Porzess ersetzen process begin wait until rising_edge(CLOCK6MHZ); if( CLOCK='0' and zaehler=0) then clock1Hz <= '1'; zaehler <= 299999; else clock1Hz <= '0'; --- NEU *** NEU **** testen! if(zaehler>0) then zaehler <= zaehler-1; end if; --- NEU *** NEU **** end if; end process; -- Vier D-FlipFlops instanziieren FLIP3: entity dflipflop port map(D => sig_d(3), CLOCK => clock1Hz, RESET => all_reset, Q => sig_q(3)); FLIP2: entity dflipflop port map(D => sig_d(2), CLOCK => clock1Hz, RESET => all_reset, Q => sig_q(2)); FLIP1: entity dflipflop port map(D => sig_d(1), CLOCK => clock1Hz, RESET => all_reset, Q => sig_q(1)); FLIP0: entity dflipflop port map(D => sig_d(0), CLOCK => clock1Hz, RESET => all_reset, Q => sig_q(0)); -- Signalwege / Verbindungen laut Schaltplan beschreiben -- Verbindungen zwischen den D-FlipFlops und zum Eingangsschalter sig_d(0) <= not BITIN; sig_d(1) <= sig_q(0); sig_d(2) <= sig_q(1); sig_d(3) <= sig_q(2); -- Verbindungen zu den LEDs VIERBIT(3) <= sig_q(3); VIERBIT(2) <= sig_q(2); VIERBIT(1) <= sig_q(1); VIERBIT(0) <= sig_q(0); all_reset <= RESET; end Verhalten_Schieberegister;
Code 0-11: VHDL-Code zu Schieberegister mit Clock über Taster und temporärer Desensibilisierung dieses Tasters.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity dflipflop is Port ( D : in STD_LOGIC; CLOCK : in STD_LOGIC; RESET : in STD_LOGIC; Q : out STD_LOGIC); end dflipflop; architecture Verhalten_Dflipflop of dflipflop is signal sig_d : std_logic := '0'; signal sig_clock : std_logic := '0'; signal sig_reset : std_logic := '0'; signal sig_q : std_logic := '0'; begin process(sig_clock,sig_reset) begin if (sig_reset='1') then sig_q <= '0'; elsif (sig_clock'event and sig_clock='1') then sig_q <= sig_d; end if; end process; sig_clock <= CLOCK; sig_reset <= not RESET; -- inverse Logik wg. externer Pullup sig_d <= D; Q <= sig_q; end Verhalten_Dflipflop;
Code 0-12: Untergeordneter VHDL-Code des von Hand geschriebenen D-Flip-Flops.
## ERSETZT: GCLK6 ist auf FPGA-Chip Pin 56 NET "CLOCK6MHZ" LOC = "P56"; NET "CLOCK6MHZ" IOSTANDARD = LVCMOS25; ## statt dessen einfacher Taster: ## NET "CLOCK" LOC = "P142" | PULLUP | IOSTANDARD = LVCMOS33; ## dedizierten Clock-Eingang nehmen, um Warnung weg zu bekommen: NET "CLOCK" LOC = "P122" | PULLUP | IOSTANDARD = LVCMOS33; ## NET "CLOCK" CLOCK_DEDICATED_ROUTE = FALSE; NET "VIERBIT<3>" LOC = "P126"; NET "VIERBIT<2>" LOC = "P130"; NET "VIERBIT<1>" LOC = "P131"; NET "VIERBIT<0>" LOC = "P132"; NET "VIERBIT<3>" IOSTANDARD = LVCMOS33; NET "VIERBIT<2>" IOSTANDARD = LVCMOS33; NET "VIERBIT<1>" IOSTANDARD = LVCMOS33; NET "VIERBIT<0>" IOSTANDARD = LVCMOS33; NET "RESET" LOC = "P12" | PULLUP | IOSTANDARD = LVCMOS33; NET "BITIN" LOC = "P135" | PULLUP | IOSTANDARD = LVCMOS33;
Code 0-13: Constraints zu Schieberegister mit Clock über Taster und temporärer Desensibilisierung dieses Tasters.
Übung
|
LUT4
69_FPGA/13_LUTÜbung -- Konfigurierbares Lauflicht mittels LUT4
Das Konzept "Lauflicht" soll auf die Verwendung von Lookup-Tabellen übertragen werden.
|
Donnerstag 20.05.2021
Themen
|
In anderen Zusammenhängen, beispielsweise Mikrocontrollertechnik, haben Sie wahrscheinlich Bussysteme und insbesondere die UART-Schnittstelle kennengelernt.
Hier sind einige Angaben dazu als Wiederholung:
45_Mikro17/07_UART/03_RS232
Einfacher Test einer Emulation von RS232 mit einem FPGA vom Typ Artix7 und einer Taktquelle von 100MHz
Das nachfolgende Beispiel ist nicht für das FPGA-Board umgesetzt worden, auf dem in diesem Kurs gearbeitet wird. Aber es soll in der Übung danach für dieses angepaßt werden.
FPGA#2 -- Emulation einer einfachen UART/RS232 Verbindung an zwei digitalen Pins. Simples Sendebeispiel und simples Empfangsbeispiel als erster Test, dann Modularisierung mit Beispiel und Anleitung. Arduino dient als Zwischenstation zum PC. Eventuell Erweiterung hin zu einer Midi-Schnittstelle.
|
Funktion des nachfolgenden Beispiels:
|
Hinweise zur Emulation: https://www.vs.inf.ethz.ch/edu/WS9900/VS/VernetSys5.pdf
|
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity serial is Port ( MEINECLOCK : in STD_LOGIC; TXD : out STD_LOGIC); end serial; architecture Behavioral of serial is --constant pattern: STD_LOGIC_VECTOR(0 to 32) := "110_10000010_110_01000010_110_11000010"; -- !!!! to NICHT DOWNTO hier !!!! -- Pause zwischen Frames um 2 Zyklen verlängert: 11110 statt 110. constant pattern: STD_LOGIC_VECTOR(0 to 38) := "111101000001011110010000101111011000010"; signal zaehler : integer range 0 to 83332 := 0; --1200Baud signal index : integer range 0 to 39 := 0; signal logikpegel : std_logic := '1'; -- Beim Start sicherer High-Pegel begin process begin wait until rising_edge(MEINECLOCK); if (zaehler<83332) then zaehler <= zaehler+1; else zaehler <= 0; logikpegel <= pattern(index); index <= index +1; if (index=39) then index <= 0; end if; end if; end process; TXD <= logikpegel; end Behavioral;
Code 0-14: VHDL-File, das mit 1200Baud seriell ABCABCABC usw. sendet.
## 100MHz Clock auf Board NET "MEINECLOCK" LOC = "R4"; ## PMOD-Ausgang NET "TXD" LOC = "AB18"; NET "MEINECLOCK" IOSTANDARD = LVCMOS25; NET "TXD" IOSTANDARD = LVCMOS12;
Code 0-15: Zugehörige Constraints
//Leitet empfangene serielle //Daten von Serial1 an Serial0 (PC) weiter. void setup() { Serial.begin(9600); Serial1.begin(1200); } int zeichen = 32; void loop() { if(Serial1.available()) { Serial.write(Serial1.read()); } }
Code 0-16: Arduino-Programm zum Empfangen und Weiterleiten der Daten
Bild 0-2: Verbindung zwischen Nexys-Video und Arduino-Micro. AB18->RXD, GND->GND
Bild 0-3: Ausgabe auf Serial Monitor in der Arduino IDE.
ENDE VON "FPGA#2 -- Emulation einer einfachen UART/RS232 Verbindung an zwei digitalen Pins. Simples Sendebeispiel und simples Empfangsbeispiel als erster Test, dann Modularisierung mit Beispiel und Anleitung. Arduino dient als Zwischenstation zum PC. Eventuell Erweiterung hin zu einer Midi-Schnittstelle."
Übung
|
Musterlösung zu 2): Passen Sie obiges Beispiel so an, dass es auf Ihrem Board zusammen mit dem Arduino-Micro läuft.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity serialdsp1 is Port ( MEINECLOCK : in STD_LOGIC; TXD : out STD_LOGIC); end serialdsp1; architecture Behavioral of serialdsp1 is constant pattern: STD_LOGIC_VECTOR(0 to 38) := "111101000001011110010000101111011000010"; signal zaehler : integer range 0 to 4999 := 0; --1200Baud signal index : integer range 0 to 39 := 0; signal logikpegel : std_logic := '1'; -- Beim Start sicherer High-Pegel begin process begin wait until rising_edge(MEINECLOCK); if (zaehler<4999) then zaehler <= zaehler+1; else zaehler <= 0; logikpegel <= pattern(index); index <= index +1; if (index=39) then index <= 0; end if; end if; end process; TXD <= logikpegel; end Behavioral;
Code 0-17: VHDL-Queltext (ABC zyklisch seriell übertragen mittels DSPFPGA mit 1200Baud)
## GCLK6 ist auf FPGA-Chip Pin 56 NET "MEINECLOCK" LOC = "P56"; ## IO_L05P_0 ist auf FPGA-Chip Pin 125 NET "TXD" LOC = "P125"; NET "MEINECLOCK" IOSTANDARD = LVCMOS25; NET "TXD" IOSTANDARD = LVCMOS33;
Code 0-18: Constraints (.ucf-Datei).
//Leitet empfangene serielle //Daten von Serial1 an Serial0 (PC) weiter. void setup() { Serial.begin(9600); Serial1.begin(1200); } int zeichen = 32; void loop() { if(Serial1.available()) { Serial.write(Serial1.read()); } }
Code 0-19: Quelltext Arduino-seitig (ArduinoMicro)
Bild 0-4: Plan der Verbindungen zwischen Mikrocontroller und FPGA.
Bild 0-5: Foto der Verbindungen zwischen Mikrocontroller und FPGA.
Bild 0-6: Ausgabe über den Seriellen Monitor (Teil der Arduino-IDE)
Teillösung 3): Je nach IN0 wird das ein- oder andere Muster gesendet
Wichtig: Die Variable hilfe wird benötigt, um nur dann zwischen den zu sendenden Mustern zu wechseln, wenn das letzte vollständig übertragen wurde.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity serial is Port ( MEINECLOCK : in STD_LOGIC; TXD : out STD_LOGIC; In0 : in STD_LOGIC; In1 : in STD_LOGIC; In2 : in STD_LOGIC; In3 : in STD_LOGIC); end serial; architecture Behavioral of serial is --constant pattern: STD_LOGIC_VECTOR(0 to 32) := "110_10000010_110_01000010_110_11000010"; -- !!!! to NICHT DOWNTO hier !!!! -- Pause zwischen Frames um 2 Zyklen verlängert: 11110 statt 110. constant pattern0: STD_LOGIC_VECTOR(0 to 12) := "1111010000010"; --A constant pattern1: STD_LOGIC_VECTOR(0 to 12) := "1111001000010"; --B constant pattern2: STD_LOGIC_VECTOR(0 to 12) := "1111011000010"; --C constant pattern3: STD_LOGIC_VECTOR(0 to 12) := "1111000100010"; --D signal zaehler : integer range 0 to 4999 := 0; --1200Baud //Berechnung des taktes ... taktfrequenz des Bords geteilt durch gewünschte Baudrate -- also 6000000/1200=5000 (da wir bei 0 beginnen also 4999) signal index : integer range 0 to 13 := 0; signal logikpegel : std_logic := '1'; -- Beim Start sicherer High-Pegel signal hilfe : std_logic := '0'; begin process begin wait until rising_edge(MEINECLOCK); if (zaehler<4999) then zaehler <= zaehler+1; else if (hilfe='1') then logikpegel <= pattern0(index); else --if (hilfe='0') then logikpegel <= pattern1(index); end if; index <= index +1; if (index=13) then index <= 0; if (In0='1') then hilfe<='1'; else hilfe<='0'; end if; end if; zaehler <= 0; end if; end process; TXD <= logikpegel; end Behavioral;
Code 0-20: VHDL-Datei
## 6MHz Clock auf Board NET "MEINECLOCK" LOC = "P56"; ##Output NET "TXD" LOC = "P126" | IOSTANDARD = LVCMOS33; ##Input NET "In0" LOC = "P135" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "In1" LOC = "P139" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "In2" LOC = "P140" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "In3" LOC = "P142" | PULLUP | IOSTANDARD = LVCMOS33 ;
Code 0-21: UCF-Datei
Donnerstag 27.05.2021
Themen
Fortsetzung der Umsetzung einer seriellen Datenübertragung, insbesondere:
|
Die Arbeit heute ist ergebnisoffen. Der "selbstbewußte" Umgang mit der Programmiersprache VHDL soll so etwas gefördert werden.
Zu klären:
|
Eine Lösung, wie das Pattern als ASCII-Zeichen, z.B. 1100 übertragen werden kann
Diskutieren Sie Lösungsmöglichkeiten für folgende Weiterentwicklungen: Fall1: Bei Zustandsänderungen an den 4 Eingängen wird nur einmalig einmal ein Buchstabe gesendet. 1. Ansatz: Abfrage von rising/falling-edge nutzen, um nur genau in diesen Augenblicken etwas zu senden. ... nachgelesen: Rising/Falling-edge reserviert für Clocks / ungeeignet für Auswertung von Schaltern und Tastern. Problem: Ansätz, bei denen mehr als ein Pattern gleichzeitig gesendet werden müßte. Idee: Arduino sagt FPGA, dass er aufhören soll zu senden, wenn ein Buchstabe empfangen wurde. 2. Ansatz: 4 Schleifen, 4 Hilfsvariablen... Keine Lösungsidee das alles zusammenzubringen. Keine Idee, dass nur 1 A gesendet wird und nicht dauernd welche. Fall2a: Zyklisch wird der komplette 4-Bit-Zustand an den Mikrocontroller gesendet 1110 1110 1110... Lösung (wenn auch aufwändig): Alle 16 möglichen Pattern als zu sendende Bitfolge bereitstellen und über den Index, der aus den 4Bit in diesem Fall gewonnen wird auswählen. Flexibilisierung: Statt alle Muster komplett bereit zu halten, bauen wir die Muster nach Bedarf zusammen. nach dem Prinzip hier: --Verknüpfung zweier Vierbit-Worte zu einem 8-Bit-Wort wort3 <= wort1 & wort2; http://www.kramann.info/69_FPGA/11_VHDL/index.php Ich halte bereit: Pattern um 1 zusenden als ASCII-Zeichen: P1 Pattern um 0 zusenden als ASCII-Zeichen: P0 je nach Bitmuster am Eingang baue ich "kurz vor dem Senden" aus 4 solcher Varianten mein zu sendendes Pattern zusammen. Beispiel: Ich möchte 1011: zu_senden <= P1 & P0 & P1 & P1; if(IN0='0') DANN zu_senden <= P0 SONST zu_senden <= P1; if(IN1='1') DANN zu_senden <= zu_senden & P0 SONST zu_senden <= zu_senden & P1; ... Fall2b: wie a) aber statt des Patterns wird eine diesem entsprechende Dezimalzahl zyklisch gesendet.
Code 0-22: Ergebnis der vorangehenden Diskussion
Musterlösung
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity serialpatternsend is Port ( MEINECLOCK : in STD_LOGIC; TXD : out STD_LOGIC; IN0 : in STD_LOGIC; IN1 : in STD_LOGIC; IN2 : in STD_LOGIC; IN3 : in STD_LOGIC); end serialpatternsend; architecture Behavioral of serialpatternsend is -- pattern: hier wird eine Folge von pnull und peins verkettet, am Anfang High-Pegel, 4*13Bit=52 Einser -- Problem: "71. Size of concat operation is different than size of the target." -- deshalb Hilfspattern der richtigen Länge vorbereiten: signal pattern13: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; signal pattern26: STD_LOGIC_VECTOR(0 to 25) := "11111111111111111111111111"; signal pattern39: STD_LOGIC_VECTOR(0 to 38) := "111111111111111111111111111111111111111"; signal pattern52: STD_LOGIC_VECTOR(0 to 51) := "1111111111111111111111111111111111111111111111111111"; --4er Muster plus Leerzeichen danach! signal pattern: STD_LOGIC_VECTOR(0 to 64) := "11111111111111111111111111111111111111111111111111111111111111111"; constant pnull: STD_LOGIC_VECTOR(0 to 12) := "1111000001100"; -- ASCII-Code von 0 ist 48 constant peins: STD_LOGIC_VECTOR(0 to 12) := "1111010001100"; -- ASCII-Code von 1 ist 49 constant leerzeichen: STD_LOGIC_VECTOR(0 to 12) := "1111000000100"; -- ASCII-Code von Leerzeichen ist 32 signal zaehler : integer range 0 to 4999 := 0; --1200Baud signal index : integer range 0 to 65 := 0; signal logikpegel : std_logic := '1'; -- Beim Start sicherer High-Pegel signal SIGIN0 : std_logic := '0'; signal SIGIN1 : std_logic := '0'; signal SIGIN2 : std_logic := '0'; signal SIGIN3 : std_logic := '0'; begin process begin wait until rising_edge(MEINECLOCK); if (zaehler<4999) then zaehler <= zaehler+1; else zaehler <= 0; logikpegel <= pattern(index); index <= index +1; if (index=65) then index <= 0; --Beginn neuer Teil!: -- ausserdem Pattern neu zusammenbauen, gemäß -- Zustand an den Eingängen: if (SIGIN0='1') then pattern13 <= peins; else pattern13 <= pnull; end if; if (SIGIN1='1') then --pattern26 <= pattern13 & peins; pattern26 <= peins & pattern13; else --pattern26 <= pattern13 & pnull; pattern26 <= pnull & pattern13; end if; if (SIGIN2='1') then --pattern39 <= pattern26 & peins; pattern39 <= peins & pattern26; else --pattern39 <= pattern26 & pnull; pattern39 <= pnull & pattern26; end if; if (SIGIN3='1') then --pattern52 <= pattern39 & peins; pattern52 <= peins & pattern39; else --pattern52 <= pattern39 & pnull; pattern52 <= pnull & pattern39; end if; --pattern <= pattern52 & leerzeichen; pattern <= leerzeichen & pattern52; --Ende neuer Teil! end if; end if; end process; TXD <= logikpegel; SIGIN0 <= IN0; SIGIN1 <= IN1; SIGIN2 <= IN2; SIGIN3 <= IN3; end Behavioral;
Code 0-23: Musterlösung: Bitmuster am Eingang wird in zu sendendes Pattern mit 4 Zeichen + Leerzeichen umgewandelt.
## GCLK6 ist auf FPGA-Chip Pin 56 NET "MEINECLOCK" LOC = "P56"; ## IO_L05P_0 ist auf FPGA-Chip Pin 125 NET "TXD" LOC = "P125"; NET "MEINECLOCK" IOSTANDARD = LVCMOS25; NET "TXD" IOSTANDARD = LVCMOS33; NET "IN0" LOC = "P135" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "IN1" LOC = "P139" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "IN2" LOC = "P140" | PULLUP | IOSTANDARD = LVCMOS33 ; NET "IN3" LOC = "P142" | PULLUP | IOSTANDARD = LVCMOS33 ;
Code 0-24: Constraints zum gleichen Projekt.
Bild 0-7: Screenshot: Links Kamerabild der erweiterten Schaltung mit Dipschaltern, hier auf 1001 gesetzt. Rechts: Serial-Monitor liefert auch Muster 1001.
//Leitet empfangene serielle //Daten von Serial1 an Serial0 (PC) weiter. void setup() { Serial.begin(9600); Serial1.begin(1200); } long x=0; int c=32; void loop() { if(Serial1.available()) { c = Serial1.read(); } if(x%1000==0) { Serial.write(c); Serial.write('\r'); Serial.write('\n'); } x++; }
Code 0-25: Veränderter Arduino-Code, der nur alle tausend Zeichen etwas anzeigt.
Donnerstag 03.06.2021
WICHTIG: Gruppenaufteilung für Probe-E-Test festlegen!
Themen
|
Vorstellung des Konzepts innerer Zustände eines Systems
https://en.wikipedia.org/wiki/Finite-state_machine (passender als de-Version unten)
https://de.wikipedia.org/wiki/Endlicher_Automat
Anwendungsfall: Innere Zustände sind bei der seriellen Datenübertragung:
|
Andere Beispiele:
|
Weitere Themen
|
Diskussion: Flag als inneren Zustand einführen, das sagt: Hier ist etwas Neues zum senden. Oder: Veränderung im Gesamtzustand erkennen und nur dann senden. Zuerst: als ein einziges Programm. Später: als Modul umsetzen.
Hinweise / Übung
9:00-10:00 Uhr erste Gruppe Fritsche Mielke Seela Zuber Wenzel Gebauer alle anderen, auch wer nicht da ist: 2. Gruppe 10:30Uhr zweite Gruppe bis 11:30Uhr Übung1: gleich lange Hilfsvariablen hilf0..3 einführen. Übung2: Zyklisch im Sekundentakt Ziffern 0..9 senden Übung3: wie Ü2, aber das zyklische Senden ist ein Testfall für die allgemeinere Fähigkeit einzelne ASCII-Zeichen zu senden.
Code 0-26: Hinweise / Übung
Musterlösung zu Übung 1
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity serial is Port ( MEINECLOCK : in STD_LOGIC; TXD : out STD_LOGIC; IN0 : in STD_LOGIC; IN1 : in STD_LOGIC; IN2 : in STD_LOGIC; IN3 : in STD_LOGIC); end serial; architecture Behavioral of serial is -- pattern: hier wird eine Folge von pnull und peins verkettet, am Anfang High-Pegel, 4*13Bit=52 Einser -- Problem: "71. Size of concat operation is different than size of the target." -- deshalb Hilfspattern der richtigen Länge vorbereiten: signal hilf0: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; signal hilf1: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; signal hilf2: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; signal hilf3: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; --4er Muster plus Leerzeichen danach! signal pattern: STD_LOGIC_VECTOR(0 to 64) := "11111111111111111111111111111111111111111111111111111111111111111"; constant pnull: STD_LOGIC_VECTOR(0 to 12) := "1111000001100"; -- ASCII-Code von 0 ist 48 constant peins: STD_LOGIC_VECTOR(0 to 12) := "1111010001100"; -- ASCII-Code von 1 ist 49 constant leerzeichen: STD_LOGIC_VECTOR(0 to 12) := "1111000000100"; -- ASCII-Code von Leerzeichen ist 32 signal zaehler : integer range 0 to 4999 := 0; --1200Baud signal index : integer range 0 to 65 := 0; signal logikpegel : std_logic := '1'; -- Beim Start sicherer High-Pegel signal SIGIN0 : std_logic := '0'; signal SIGIN1 : std_logic := '0'; signal SIGIN2 : std_logic := '0'; signal SIGIN3 : std_logic := '0'; begin process begin wait until rising_edge(MEINECLOCK); if (zaehler<4999) then zaehler <= zaehler+1; else zaehler <= 0; logikpegel <= pattern(index); index <= index +1; if (index=65) then index <= 0; --Beginn neuer Teil!: -- ausserdem Pattern neu zusammenbauen, gemäß -- Zustand an den Eingängen: if (SIGIN0='1') then hilf0 <= peins; else hilf0 <= pnull; end if; if (SIGIN1='1') then --pattern26 <= pattern13 & peins; hilf1 <= peins; else --pattern26 <= pattern13 & pnull; hilf1 <= pnull; end if; if (SIGIN2='1') then --pattern39 <= pattern26 & peins; hilf2 <= peins; else --pattern39 <= pattern26 & pnull; hilf2 <= pnull; end if; if (SIGIN3='1') then --pattern52 <= pattern39 & peins; hilf3 <= peins; else --pattern52 <= pattern39 & pnull; hilf3 <= pnull; end if; --pattern <= pattern52 & leerzeichen; pattern <= leerzeichen & hilf3 & hilf2 & hilf1 & hilf0; --Ende neuer Teil! end if; end if; end process; TXD <= logikpegel; SIGIN0 <= IN0; SIGIN1 <= IN1; SIGIN2 <= IN2; SIGIN3 <= IN3; end Behavioral;
Code 0-27: Übung1 VHDL-Code (gleichlange Hilfsvariablen hilf0..3)
Musterlösung Ü2 (nicht getestet!)
library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values -- wegen der arithmetrischen Operationen: use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity serialziffern is Port ( MEINECLOCK : in STD_LOGIC; TXD : out STD_LOGIC); end serialziffern; architecture Behavioral of serialziffern is --Benutzer des Sendemoduls signal xwert : integer range 0 to 9 := 0; --das, was gesendet werden soll --Sendemodul: signal logikpegel : std_logic := '1'; -- Beim Start sicherer High-Pegel signal zaehler : integer range 0 to 4999 := 0; --1200Baud signal zeichen : integer range 0 to 255 := 32; --zu sendendes ADCII-Zeichen signal fertig : std_logic := '1'; -- '1'=> bereit für neues Zeichen signal neu : std_logic := '1'; -- '1'=> neues Zeichen liegt vor signal index : integer range 0 to 13 := 0; -- immer nur ein Zeichen senden constant leerzeichen: STD_LOGIC_VECTOR(0 to 7) := "00000100"; -- ASCII-Code von Leerzeichen signal ascii: STD_LOGIC_VECTOR(0 to 7) := leerzeichen; signal pattern: STD_LOGIC_VECTOR(0 to 12) := "1111000000100"; begin process begin wait until rising_edge(MEINECLOCK); if (zaehler<4999) then zaehler <= zaehler+1; else zaehler <= 0; -- drei Möglichkeiten: -- 1) ist fertig, es liegt neues Zeichen an -- 2) ist fertig, es liegt kein neues Zeichen an -- 3) sendet noch Rest von Zeichen if (fertig = '0') then logikpegel <= pattern(index); index <= index +1; -- wechsel des inneren Zustands bei Überlauf von index: if (index=13) then index <= 0; --bereit für neuen Sendezyklus fertig <= '1'; --bereit neues Zeichen zum senden zu bekommen end if; else -- wenn gerade nichts gesendet wird... -- ... und ein neues Zeichen bereit liegt if (neu='1') then -- neues Zeichen in den puffer übernehmen ascii <= conv_std_logic_vector(zeichen,ascii'length); -- Bitreihenfolge umdrehen (?) --ascii <= ascii(0) & ascii(1) & ascii(2) & ascii(3) & ascii(4) & ascii(5) & ascii(6) & ascii(7); -- zu sendendes Pattern bilden, immer mit High-Pegel enden! pattern <= "11" & ascii & "110"; fertig <= '0'; --senden im nächsten Zyklus starten neu <= '0'; --Bereitschaft für neues Zeichen signalisieren else -- wenn kein neues Zeichen bereitliegt, dann -- neues Zeichen bereit stellen. -- Dieser Teil kommt später in einen anderen Prozess! -- er repräsentiert die Benutzung des Sendemoduls. -- Genau hier macht dann in Zukunft das Sendemodul gar nichts! -- im andere Prozeß wird dann geprüft: neu='0' --Benutzer des Sendemoduls -- Aktuelle Ziffer zum Senden vorbereiten: zeichen <= 48+xwert; -- Verändern des aktuellen Wertes if (xwert<9) then xwert <= xwert+9; else xwert <= 0; end if; end if; end if; end if; end process; TXD <= logikpegel; end Behavioral;
Code 0-28: Musterlösung Ü2 (nicht getestet!)
studentische Teillösung
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; entity MehrZiffern is Port ( CLOCK : in STD_LOGIC; TxD : out STD_LOGIC; IN0 : in STD_LOGIC; IN1 : in STD_LOGIC; IN2 : in STD_LOGIC; IN3 : in STD_LOGIC); end MehrZiffern; architecture Behavioral of MehrZiffern is signal hilf0: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; signal hilf1: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; signal hilf2: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; signal hilf3: STD_LOGIC_VECTOR(0 to 12) := "1111111111111"; --4er Muster plus Leerzeichen danach! -- signal pattern: STD_LOGIC_VECTOR(0 to 64) := "11111111111111111111111111111111111111111111111111111111111111111"; signal pattern: STD_LOGIC_VECTOR (0 to 25) := "11111111111111111111111111"; constant pnull: STD_LOGIC_VECTOR(0 to 12) := "1111000001100"; -- ASCII-Code von 0 ist 48 constant peins: STD_LOGIC_VECTOR(0 to 12) := "1111010001100"; -- ASCII-Code von 1 ist 49 constant leerzeichen: STD_LOGIC_VECTOR(0 to 12) := "1111000000100"; -- ASCII-Code von Leerzeichen ist 32 signal zaehler : integer range 0 to 4999 := 0; --1200Baud signal index : integer range 0 to 25 := 0; signal logikpegel : std_logic := '1'; -- Beim Start sicherer High-Pegel signal SIGIN0 : std_logic := '0'; signal SIGIN1 : std_logic := '0'; signal SIGIN2 : std_logic := '0'; signal SIGIN3 : std_logic := '0'; -- 0 bis 9 vereinbaren?? signal zahl: integer range 0 to 9 :=0; signal Zahlen: STD_LOGIC_VECTOR (0 to 7) := "11111111"; --constant pnull: STD_LOGIC_VECTOR(0 to 12) := "1111000001100"; 0 --constant peins: STD_LOGIC_VECTOR(0 to 12) := "1111010001100"; 1 --constant pzwei: STD_LOGIC_VECTOR(0 to 12) := "1111001001100"; 2 --constant pdrei: STD_LOGIC_VECTOR(0 to 12) := "1111011001100"; 3 --constant pvier: STD_LOGIC_VECTOR(0 to 12) := "1111000101100"; 4 --constant pfuenf: STD_LOGIC_VECTOR(0 to 12) := "1111010101100"; 5 --constant psechs: STD_LOGIC_VECTOR(0 to 12) := "1111001101100"; 6 --constant psieben: STD_LOGIC_VECTOR(0 to 12) := "1111011101100"; 7 --constant pacht: STD_LOGIC_VECTOR(0 to 12) := "1111000011100"; 8 --constant pneun: STD_LOGIC_VECTOR(0 to 12) := "1111010011100"; 9 signal zahl1999: integer range 0 to 1999 := 0; begin process begin wait until rising_edge(CLOCK); if (zaehler<4999) then zaehler <= zaehler+1; else zaehler <= 0; logikpegel <= pattern(index); index <= index +1; if (index=26) then index <= 0; if (zahl1999<1999) then zahl1999 <= zahl1999 +1; else zahl1999 <= 0; Zahlen <= conv_std_logic_vector(zahl + 48 , Zahlen'length); zahl <=zahl + 1; if(zahl = 9) then zahl <= 0; end if; --Zahlen <= Zahlen(0) & Zahlen(1) & Zahlen(2) & Zahlen(3) & Zahlen(4) & Zahlen(5) & Zahlen(6) & Zahlen(7); Zahlen <= Zahlen(7) & Zahlen(6) & Zahlen(5) & Zahlen(4) & Zahlen(3) & Zahlen(2) & Zahlen(1) & Zahlen(0); end if; end if; pattern <= Zahlen & "01111" & leerzeichen; end if; end process; TXD <= logikpegel; SIGIN0 <= IN0; SIGIN1 <= IN1; SIGIN2 <= IN2; SIGIN3 <= IN3; end Behavioral;
Code 0-29: studentische Teillösung.