kramann.info
© Guido Kramann

Login: Passwort:










kramann.info
© Guido Kramann

Login: Passwort:




Echtzeitanwendungen auf Basis von HDL im Sommersemester 2025

(EN google-translate)

(PL google-translate)


ACHTUNG: In der neuesten Xubuntu-Installtion fehlen einige dynamische Bibliotheken, die notwendig sind, damit die hier benötigte Entwicklungsumgebung startet:


fehlende_dynamische_bibliotheken.zip

Laden Sie darum obigen Zip-Ordner herunter, entpacken ihn und kopieren alle Dateien darin nach /usr/lib/i386-linux-gnu/:

sudo cp libstdc++.so.5 /usr/lib/i386-linux-gnu/
sudo cp libXft.so.2 /usr/lib/i386-linux-gnu/
sudo cp libSM.so.6 /usr/lib/i386-linux-gnu/
sudo cp libICE.so.6 /usr/lib/i386-linux-gnu/
sudo cp libuuid.so.1 /usr/lib/i386-linux-gnu/
sudo cp libgthread-2.0.so.0 /usr/lib/i386-linux-gnu/
sudo cp libglib-2.0.so.0 /usr/lib/i386-linux-gnu/
sudo cp libXi.so.6 /usr/lib/i386-linux-gnu/
sudo cp libXrender.so.1 /usr/lib/i386-linux-gnu/
sudo cp libXrandr.so.2 /usr/lib/i386-linux-gnu/
sudo cp libfreetype.so.6 /usr/lib/i386-linux-gnu/
sudo cp libfontconfig.so.1 /usr/lib/i386-linux-gnu/
sudo cp libXext.so.6 /usr/lib/i386-linux-gnu/
sudo cp libX11.so.6 /usr/lib/i386-linux-gnu/
sudo cp libpcre.so.3 /usr/lib/i386-linux-gnu/
sudo cp libpng12.so.0 /usr/lib/i386-linux-gnu/
sudo cp libexpat.so.1 /usr/lib/i386-linux-gnu/
sudo cp libxcb.so.1 /usr/lib/i386-linux-gnu/
sudo cp libXau.so.6 /usr/lib/i386-linux-gnu/
sudo cp libXdmcp.so.6 /usr/lib/i386-linux-gnu/

Code 0-1: Konsolen-Befehle zum Beheben der Probleme.

  • Hier bei "day by day" werden chronologisch im Verlauf des Semesters die behandelten Inhalte vermerkt.
  • Meistens werden Links innerhalb von kramann.info angegeben, wo der jeweils behandelte Stoff dargestellt wird.
  • Zur Orientierung finden Sie auf kramann.info auch noch das "day by day" der gleichen Lehrveranstaltung vom vorangehenden Jahr.
  • Die Prüfung in diesem Fach ist eine Klausur in elektronischer Form (E-Test)
  • Die folgenden vorab angegebenen Links stellen Quellen dar, aus denen die hier behandelten Inhalte genommen werden:

69_FPGA
68_nexys
67_Echtzeitsysteme
95_ETEST -- Hinweise zu der elektronischen Prüfungsform "E-Test"

#1 Mo 24.03.2025

Vorlesung: Einführung in FPGA und VHDL

Einige gebräuchliche Abkürzungen und Bezeichnungen:
Abkürzung Bedeutung Beschreibung
FPGA Field Programmable Gate Array Chip der diskrete Schaltungen abbilden kann
VHSIC Very High Speed Integrated Circuit Beispiel: FPGA
VHDL VHSIC Hardware Description Language Programmiersprache für FPGAs
Verilog Bezeichnung Alternative Programmiersprache für FPGAs
DARPA Defense Advanced Research Projects Agency Forschungsbehörde des US amerikanischen Militärs
Xilinx Firma Stellt FPGA-Chips her und stellt Entwicklungsumgebungen zu ihrer Programmierung bereit

Tabelle 0-1: Einige gebräuchliche Abkürzungen und Bezeichnungen

Geschichtlicher Hintergrund
  1. Wie hat sich geschichtlich das Erfordernis und die Realisation von FPGAs und HDL ergeben?
  2. Wo stehen FPGA-Bausteine im Vergleich mit diskret aufgebauter digitaler Hardware und Mikrocontrollern?
  • Seit den 50er Jahren bis in die 70er Jahre hinein wurden regelungstechnische Aufgaben vornehmlich mit Hilfe diskreter elektronischer Schaltungen bewältigt.
  • Computer stellten damals keine Alternative zu der diskreten Technik dar.
  • Nachteil diskreter Schaltungen: Hoher Aufwand bei Verbesserungen wie der Entwurf einer neuen Platine, das Bereithalten tausender Datenblätter, Impedanzanpassungen.
  • In den 80ern beauftragte die DARPA die Entwicklung eines Chips, der diskrete Logik-Schaltungen abbilden kann.
  • Nicht die abgebildete Verdrahtung sollte bei der Verwendung beschrieben werden, sondern die Logik, die abgebildet werden soll.
  • Ergebnis der Entwicklung waren FPGA-Chips (FPGA=Field Programmable Gate Array) in Kombination mit der Programmiersprache VHDL (VHDL=VHSIC Hardware Description Language).
  • FPGA-Bausteine machen nur Sinn in Zusammenhang mit einem Compiler, der VHDL in ein Image für den FPGA umsetzt.
  • Eingebettete Computer laufen mittlerweile FPGAs immer mehr den Rang ab.
  • Verbleibende Anwendungsgebiete sind solche mit hohen Anforderungen an die Parallelisierung, wie bei fertig belernten Neuronalen Netzen.
  • Besonders häufig finden sich Anwendungen mit FPGAs im Bereich der Raumfahrt, um Raketenmotoren zu regeln:
Motivation / Diskussion ... Grey Walter's tortoises 1949
Schaltplan zu Grey Walter's tortoises.
Artikel: FPGA-Based Predictive Control System for SpacecraftRendezvous in Elliptical Orbits
Werbefilm von Xilinx: Introducing the Industry's First 20nm Space-Grade FPGA

Wie ist ein FPGA aufgebaut?

FPGAs auf Wikipedia -- https://de.wikipedia.org/wiki/Field_Programmable_Gate_Array
Was ist ein FPGA? -- 69_FPGA/01_Einfuehrung

Vorberetung der ersten Übung mit einem FPGA-Board

  1. Verwendung der (Linux-) Xubuntu-Distribution im PC-Pool IWZ140
  2. Start der Entwicklungs-IDE von Xilinx.
  3. Einrichten eines Projektes
  4. Getting started mit einem Programm, das eine LED blinken läßt
FPGA-Board DLP-FPGA -- 69_FPGA/03_DLP_FPGA
Getting started alte Version mit ISE9 -- 69_FPGA/04_Getting_Started
AKTUELL: Verwendung von XSE14 -- 69_FPGA/21_XSE14
Upload des kompilierten Images (Blinkende LED) -- 69_FPGA/02_Einrichtung/02_BitLoadApp
69_FPGA/11_VHDL -- Kleine Referenz zu VHDL

Übung: Umgang mit der Entwicklungsumgebung ISE von Xilinx

Führen Sie die in der Vorlesung dargestellten Schritte selber aus, um sich mit der Xilinx IDE und dem dspFPGA-Board vertraut zu machen:

  1. Verwendung der (Linux-) Xubuntu-Distribution im PC-Pool IWZ140
  2. Start der Entwicklungs-IDE von Xilinx.
  3. Einrichten eines Projektes
  4. Getting started mit einem Programm, das eine LED blinken läßt

#2 Mo 31.03.2025

In dieser Lehrveranstaltung sollen die zuvor eingeführten Sprachelemente selbsttätig verwendet werden und der Umgang mit der Entwicklungsumgebung von Xilinx praktisch geübt werden. Dem vorangestellt werden wir die wichtigsten Inhalte dazu wiederholen:

  • Wie wird die Entwicklungsumgebung gestartet?
  • Wie wird ein neues Projekt angelegt? (.vhd und .ucf-Datei)
  • Wozu dient die .ucf-Datei?
  • Was ist das besondere an der .vhd-Datei?
  • Was unterscheidet ein VHDL-Programm von beispielsweise einem C-Programm?
  • Können die Zeilen in einem VHDL-Programm (teilweise) vertauscht werden?
  • Wie aktiviert man die USB-Spannungsversorgung für das FPGA-Board?
  • Warum sollte man unbedingt den FPGA erst löschen, bevor man ein neues Programm flasht?
  • Wie wird die .bit-Datei erstellt und auf den FPGA übertragen?
69_FPGA/11_VHDL -- Kleine Referenz zu VHDL
Besprechung des Beispiels "Mustervergleich" hier: 69_FPGA/05_Beispiele/03_Mustervergleich
ÜBUNG 1
  • Vollziehen Sie die Beispiele von Mustervergleich praktisch nach.
ÜBUNG 2
  • Nachfolgend finden Sie ein UND-Gatter umgesetzt:
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-2: 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-3: Constraints (.ucf-Datei) zum UND-Gatter.


Beachten Sie die Pullup-Einträge bei den Eingängen (Besprechung im Unterricht).


  • Variieren Sie dieses Projekt so, dass es dann drei Eingänge hat.
  • Der Ausgang soll dabei dann logisch 1 annehmen, wenn der erste und zweite Eingang im gleichen Zustand sind und der Zustand des dritten Eingangs dazu invers ist.
ÜBUNG 3

Variieren Sie das Beispiel mit der blinkenden LED so, dass diese nun mit 4 Hertz blinkt.

ÜBUNG 4 (Zusatzaufgabe)

Versuchen Sie ein Programm und eine zugehörige Schaltung zu realisieren, bei der über zwei Eingänge A und B die Blinkfrequenz einer LED gesteuert werden kann:

  • B=0, A=0 => 1Hz
  • B=0, A=1 => 2Hz
  • B=1, A=0 => 3Hz
  • B=1, A=1 => 4Hz

#3 Mo 07.04.2025

Themen

  1. Musterlösungen zu Aufgabe 4
  2. Einführung Zu Neuronalen Netzen
  3. Identifikation geeigneter Probleme zur Umsetzung mit einem FPGA
  4. Anpassung der Struktur eines Neuronalen Netzes an die Möglichkeiten eines FPGAs
  5. Verwendung des Elements LUT
  6. Übung -- Konfigurierbares Lauflicht mittels LUT4

1. Musterlösungen zu Aufgabe 4

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity blinkled is
    Port ( MEINECLOCK : in   STD_LOGIC;
            MEINELED  : out  STD_LOGIC;
            a : in   STD_LOGIC;				
            b : in   STD_LOGIC);				
end blinkled;
-- Clock-In == 6MHz, Toggeln nach 3000000 Schritten ergibt 1Hz Blinkfrequenz.
architecture Behavioral of blinkled is
    constant w0: integer := 2999999;
    constant w1: integer := 1499999;
    constant w2: integer := 999999;
    constant w3: integer := 749999;
    signal zaehler    : integer range 0 to 2999999 := 0;
    signal logikpegel : std_logic := '0';
    signal asig : std_logic := '0';
    signal bsig : std_logic := '0';
    begin
        process begin
            wait until rising_edge(MEINECLOCK);
            if 
				      (  
						    ((zaehler<w0) and (((not bsig) and (not asig)) = '1'))  or
						    ((zaehler<w1) and (((not bsig) and (    asig)) = '1'))  or
						    ((zaehler<w2) and (((    bsig) and (not asig)) = '1'))  or
						    ((zaehler<w3) and (((    bsig) and (    asig)) = '1'))  
						) 
				then
                zaehler <= zaehler+1;
            else
                zaehler <= 0;
                logikpegel <= not logikpegel;
            end if;
        end process;
        MEINELED <= logikpegel;
		  asig <= a;
		  bsig <= b;
end Behavioral;

Code 0-4: zu testende Lösung VHD

## GCLK6 ist auf FPGA-Chip Pin 56
NET "MEINECLOCK" LOC = "P56";
## IO_L05P_0 ist auf FPGA-Chip Pin 125
NET "MEINELED"   LOC = "P125";

NET "MEINECLOCK" IOSTANDARD = LVCMOS25;
NET "MEINELED"   IOSTANDARD = LVCMOS33; 

NET "a"  LOC = "P140" | PULLUP  | IOSTANDARD = LVCMOS33 ;
NET "b"  LOC = "P139" | PULLUP  | IOSTANDARD = LVCMOS33 ;

Code 0-5: zu testende Lösung UCF

steuerled.zip -- Projektordner zur obigen Lösung.
...weitere Lösung unter Verwendung einer Lookup-Tabelle:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity blinkled is
    Port ( MEINECLOCK : in   STD_LOGIC;
            MEINELED  : out  STD_LOGIC;
            a : in   STD_LOGIC;				
            b : in   STD_LOGIC);				
end blinkled;
-- Clock-In == 6MHz, Toggeln nach 3000000 Schritten ergibt 1Hz Blinkfrequenz.
architecture Behavioral of blinkled is
    constant w0: integer := 2999999;
    constant w1: integer := 1499999;
    constant w2: integer := 999999;
    constant w3: integer := 749999;
    signal zaehler    : integer range 0 to 2999999 := 0;
    signal obergrenze  : integer range 0 to 2999999 := 0;
    signal logikpegel : std_logic := '0';
    signal wort : std_logic_vector(1 downto 0);	 
    signal wert : integer range 0 to 3 := 0;
    begin
        process begin
            wait until rising_edge(MEINECLOCK);
            if (zaehler<obergrenze) then
                zaehler <= zaehler+1;
            else
                zaehler <= 0;
                logikpegel <= not logikpegel;
            end if;
        end process;
        MEINELED <= logikpegel;
		  wort <= b & a;
		  wert <= to_integer(unsigned(wort));
        with wert select obergrenze <=
		      w0 when 0, 
		      w1 when 1, 
		      w2 when 2, 
				w3 when others;		  
end Behavioral;

Code 0-6: VHD-Datei

steuerled2.zip -- Projekt zu obiger Lösung.

2. Einführung Zu Neuronalen Netzen

67_Echtzeitsysteme/08_NeuronaleNetze

3. Identifikation geeigneter Probleme zur Umsetzung mit einem FPGA

4. Anpassung der Struktur eines Neuronalen Netzes an die Möglichkeiten eines FPGAs

5. Verwendung des Elements LUT

69_FPGA/13_LUT -- Verwendung eines Lookup-Tables (hier UNISIM LUT4) statt logischer Operationen, um ein bestimmtes logisches Verhalten zu realisieren.
6. Übung -- Konfigurierbares Lauflicht mittels LUT4

Nun soll der gezielte Einsatz eines Moduls aus der UNISIM-Library erübt werden.

Arbeiten Sie gerne in Zweiergruppen.

Das Konzept "Lauflicht" soll auf die Verwendung von Lookup-Tabellen übertragen werden.

  • Bedenken Sie:
  • Sie haben vier LUT4.
  • Jedes dieser Elemente hat genau einen Ausgang.
  • Jeder dieser vier Ausgänge soll nach außen als eine LED des Lauflichts mit vier Elementen zu sehen sein.
  • An die vier LUT4-Elemete ist ein und derselbe Binärzähler angeschlossen.
  • Skizzieren Sie das Gesamtsystem mittels gedachter digitaler Baugruppen.
  • Für die Dauer von je vier Takten des Binärzählers soll erst die erste, dann die zweite, die dritte, die vierte und dann wieder die erste usw. LED lauchten.
  • Wie sind dann die "generic maps" der vier LUT4-Elemente zu instanziieren? Diskutieren Sie das untereinander.
  • Ein Taktzyklus des Binärzählers soll eine halbe Sekunde dauern.
  • Wie lange leuchtet dann nach dem voran erläuterten jede LED?
  • Setzen Sie das Projekt um.
  • Überlegen Sie sich andere Blinkmuster und wie dann die Generic-maps zu ändern sind. Stellen Sie diese Varianten später für alle vor.
Übung 2:
  • Lösungen zu Aufgabe 4 praktisch nachvollziehen
Übung 3:
  • Machen Sie sich Gedanken darüber, wie ein Neuronales Netz auf einem FPGA realisiert werden könnte.

#4 Mo 14.04.2025

Themen

Um die Implementierung eines Neuronalen Netzes auf dem FPGA voranzutreiben, wird heute eine passende Struktur modellhaft am PC entwickelt und getestet. Eine Implementierung auf dem FPGA erfolgt beim nächsten Termin.

  1. Entwurf einer speziell für den FPGA gut geeigneten Neuronen-Variante
  2. Implementierung eines minimalen Netzes
  3. Optimierung des Netzes um ein Antivalenzgatter zu repräsentieren als Übungsaufgabe

1. Entwurf einer speziell für den FPGA gut geeigneten Neuronen-Variante

Eigenschaften eines einzelnen Neurons:

Anforderungen:

  1. Die auftretenden Berechnungswerte, auch bei Zwischenergebnissen, sollen möglichst klein und genau definiert sein.
  2. Die Berechnungen sollen möglichst einfach (und damit schnell und ressourcenschonend) erfolgen.
  3. Die Netze sollen tendenziell eher für "digitale" Problemstellungen geeignet sein.
  4. Für die genetische Optimierung stellt der begrenzte Zahlenbereich einen großen Vorteil dar, da die Anzahl der Möglichen Zustände stark beschränkt wird.
  5. Statt Schwellwerte werden beliebige Zuordnungen zwischen Neuronenausgang und gewichteter Summe u festgelegt. Dadurch: Nicht linear / maximale Anpassbarkeit. Nachteil: Nicht differenzierbar.
  • Input in_x 4 Bit vorzeichenbehaftet, d.h. Wertebereich [-8,+7].
  • Gewichte w_x 4 Bit vorzeichenbehaftet, d.h. Wertebereich [-8,+7].
  • Jeweils sofortige Division in_x*w_x durch die Anzahl der Eingänge n des Neurons, dadurch zunächst Begrenzung der gewichteten Summe u auf [-56,+64]
  • Nochmalige Division von u durch 8, dadurch weitere Begrenzung auf [-7,8]
  • Völlig beliebig wählbare Zuordnung jedes der 16 Werte zwischen [-7,8] von u zu einem Outputwert im Intervall [-8,+7].
  • Bei binären Ausgängen soll für out={-8,-7,-6,-5,-4,-3,-2,-1,0} logisch 0 ausgegeben werden und für out={1,2,3,4,5,6,7} logisch 1.

2. Implementierung eines minimalen Netzes

Entwurf des FPGA-fähigen, genetisch optimierbaren Neuronalen Netzes am Beispiel eines Äquivalenzgatters.

Bild 0-1: Entwurf des FPGA-fähigen, genetisch optimierbaren Neuronalen Netzes am Beispiel eines Äquivalenzgatters.

  • Die Implementierung erfolgt als Live-Coding innerhalb der Lehrveranstaltung und wird dann an dieser Stelle hochgeladen.

3. Optimierung des Netzes um ein Äquivalenzgatter zu repräsentieren als Übungsaufgabe

import java.util.Random;
Random zzz = new Random();

public int zufall()
{
     return zzz.nextInt(16)-8; // [-8,7]
}

public double fehler(int[] gen)
{
    int out0 = netz(-8,-8,gen); 
    int out1 = netz(-8,7,gen); 
    int out2 = netz(7,-8,gen); 
    int out3 = netz(7,7,gen);
    
    int err = (out0-7)*(out0-7) + (out1+8)*(out1+8) + (out2+8)*(out2+8) + (out3-7)*(out3-7);
    
    return Math.sqrt((double)err);
}

public int netz(int in0, int in1, int[] gen)
{
     int w0=gen[0]; int w1=gen[1]; int w2=gen[2]; int w3=gen[3]; int w4=gen[4]; int w5=gen[5];
     
     int u0 = (  ((w0*in0)/2) + ((w1*in1)/2)  )/8; // [-7,8]
     int u1 = (  ((w2*in0)/2) + ((w3*in1)/2)  )/8;
     
     u0+=7; // [0..15]
     int out0 = gen[6+u0];
     u1+=7; // [0..15]
     int out1 = gen[6+16+u1];
     
     int u2 = (  ((w4*out0)/2) + ((w5*out1)/2)  )/8;
     u2+=7; // [0..15]
     
     int out2 = gen[6+16+16+u2];
     
     return out2;
}


public void setup()
{
     int[] gen = new int[54];
     for(int i=0;i<gen.length;i++)
        gen[i]=zufall();
        
     double aktueller_fehler = fehler(gen);
     
     println("err="+aktueller_fehler);
}

public void draw()
{
}

Code 0-7: Processing-Sketch als Ausgangspunkt, der die Grundlage für das Optimierungsprogramm liefert.

MUSTERLÖSUNG (nur setup-Methode)
public void setup()
{
     int[] gen = new int[54];
     int[] genN = new int[54];
     for(int i=0;i<gen.length;i++)
        gen[i]=zufall();
       
       
     for(int DURCHLAUF=0;DURCHLAUF<500;DURCHLAUF++)
     {
        int a = zzz.nextInt(gen.length);
        int b = gen[a];
        double bb=fehler(gen);
        gen[a]=zufall();
        double cc = fehler(gen);
        if(bb<cc)
        {
           gen[a]=b;
        }
        else
        {
            if(cc<bb)
               println("err="+cc);
        }
     }
     double aktueller_fehler = fehler(gen);
    
     println("err="+aktueller_fehler);
     println();
     // Codegenerator als Unterstützung für die Erstellung des FPGA-Programms
     String EINRUECKUNG = "        ";
     //  constant w0: integer := -77;
     for(int i=0;i<6;i++)
        println(EINRUECKUNG+"constant w"+i+": integer := "+gen[i]+";");
     for(int i=0;i<48;i++)
        println(EINRUECKUNG+"constant l"+i+": integer := "+gen[6+i]+";");
     println();        
     println(EINRUECKUNG+"with u0 select out0 <=");
     for(int i=0;i<15;i++)
        println(EINRUECKUNG+"l"+i+" when "+(i-7)+", ");
     println(EINRUECKUNG+"l15 when others;");   
     println();        
     println(EINRUECKUNG+"with u1 select out1 <=");
     for(int i=0;i<15;i++)
        println(EINRUECKUNG+"l"+(16+i)+" when "+(i-7)+", ");
     println(EINRUECKUNG+"l31 when others;");   
     println();        
     println(EINRUECKUNG+"with u2 select out2 <=");
     for(int i=0;i<15;i++)
        println(EINRUECKUNG+"l"+(32+i)+" when "+(i-7)+", ");
     println(EINRUECKUNG+"l47 when others;");   
}

Code 0-8: Optimierer und Codegenerator, um die Programmteile im VHDL-Quelltext nutzen zu können.

        constant w0: integer := -6;
        constant w1: integer := -2;
        constant w2: integer := 2;
        constant w3: integer := 2;
        constant w4: integer := -1;
        constant w5: integer := -4;
        constant l0: integer := -8;
        constant l1: integer := 6;
        constant l2: integer := -4;
        constant l3: integer := -5;
        constant l4: integer := 1;
        constant l5: integer := 2;
        constant l6: integer := -7;
        constant l7: integer := -7;
        constant l8: integer := 1;
        constant l9: integer := -3;
        constant l10: integer := -1;
        constant l11: integer := -1;
        constant l12: integer := -4;
        constant l13: integer := 2;
        constant l14: integer := 3;
        constant l15: integer := 3;
        constant l16: integer := 0;
        constant l17: integer := 2;
        constant l18: integer := 4;
        constant l19: integer := -6;
        constant l20: integer := -6;
        constant l21: integer := 4;
        constant l22: integer := -6;
        constant l23: integer := -4;
        constant l24: integer := -1;
        constant l25: integer := -4;
        constant l26: integer := 3;
        constant l27: integer := -8;
        constant l28: integer := 4;
        constant l29: integer := -5;
        constant l30: integer := -1;
        constant l31: integer := -6;
        constant l32: integer := -1;
        constant l33: integer := 3;
        constant l34: integer := -1;
        constant l35: integer := 0;
        constant l36: integer := -7;
        constant l37: integer := 6;
        constant l38: integer := 7;
        constant l39: integer := 7;
        constant l40: integer := -8;
        constant l41: integer := -6;
        constant l42: integer := 4;
        constant l43: integer := -8;
        constant l44: integer := -2;
        constant l45: integer := -4;
        constant l46: integer := 7;
        constant l47: integer := 2;

        with u0 select out0 <=
        l0 when -7, 
        l1 when -6, 
        l2 when -5, 
        l3 when -4, 
        l4 when -3, 
        l5 when -2, 
        l6 when -1, 
        l7 when 0, 
        l8 when 1, 
        l9 when 2, 
        l10 when 3, 
        l11 when 4, 
        l12 when 5, 
        l13 when 6, 
        l14 when 7, 
        l15 when others;

        with u1 select out1 <=
        l16 when -7, 
        l17 when -6, 
        l18 when -5, 
        l19 when -4, 
        l20 when -3, 
        l21 when -2, 
        l22 when -1, 
        l23 when 0, 
        l24 when 1, 
        l25 when 2, 
        l26 when 3, 
        l27 when 4, 
        l28 when 5, 
        l29 when 6, 
        l30 when 7, 
        l31 when others;

        with u2 select out2 <=
        l32 when -7, 
        l33 when -6, 
        l34 when -5, 
        l35 when -4, 
        l36 when -3, 
        l37 when -2, 
        l38 when -1, 
        l39 when 0, 
        l40 when 1, 
        l41 when 2, 
        l42 when 3, 
        l43 when 4, 
        l44 when 5, 
        l45 when 6, 
        l46 when 7, 
        l47 when others;

Code 0-9: Ergebnis des Code-Generators.

  • Implementieren Sie einen genetischen Algorithmus, oder einfacher als Vorstufe ein modifiziertes Gradientenverfahren, um ein Netz zu erhalten, das als Antivalenzgatter arbeitet.

Kurzfassung zur Implementierung eines modifizierten Gradientenverfahrens:

  • Zufällige Wahl der Parameter
  • Zyklisch Zufällige Änderung, prüfen, ob besser geworden ODER WENIGSTENS GLEICH GEBLIEBEN, ggf. behalten, sonst Änderung verwerfen.

Kurzfassung zur Implementierung eines genetischen Algorithmus':

  • Zufällige Wahl der Parameter z.B. bei 100 Netzen.
  • 10 Besten auswählen.
  • Rekombination 90 neuer aus den 10 besten.
  • Mutationen bei den 90.
  • Wieder 10 Besten auswählen usw.
Optimierung mittels modifiziertem Gradientenverfahren -- 50_Simulationstechnik/06_Optimierung/03_ModifizierteG
Genetische Algorithmen -- 50_Simulationstechnik/07_Genalgorithmus
Siehe Machbarkeitsstudie zu Neuronalen Netzen mit Hilfe eines FPGAs -- 69_FPGA/99_day_by_day_SoSe2018

#5 Mo 28.04.2025

Themen

  1. ÜBUNG: Implementierung des Neuronale-Netz-basierten Äquivalenzgatters
  2. Diskussion der studentischen Lösungen und einer Musterlösung
  3. Überlegungen zu Kapazität und Potential des Konzepts und Möglichkeiten zur Reduktion

1. ÜBUNG: Implementierung des Neuronale-Netz-basierten Äquivalenzgatters

Es soll die Übung von letzter Woche fortgesetzt werden, bei der das zunächst mit Java realisierte digitale Neuronale Netz in VHDL realisiert werden soll.

Hinweise zur Umsetzung:

  • Fangen Sie mit den Ein- und Ausgängen an (PORT-Variablen).
  • Definieren Sie dann die Parameter (Gewichte, Ausgangswerte) als Konstanten.
  • Definieren Sie nun alle internen Hilfsvariablen (Signale, Variablen für die Gewichte, gewichtete Summen und Ausgänge).
  • Definieren Sie schließlich die formelmäßigen Zusammenhänge aller Berechungsschritte. Orientieren Sie sich dazu an der Methode int netz(int in0, int in1, int[] gen) im Java-Programm.
  • Bauen Sie die entsprechende Schaltung auf, übertragen und testen Sie das fertige System.
  • Wegen der notwenigen VHDL Sprachelemente orientieren Sie sich an einer andersartigen Machbarkeitsstudie zu Neuronalen netzen mit FPGAs hier:
Siehe Machbarkeitsstudie zu Neuronalen Netzen mit Hilfe eines FPGAs -- 69_FPGA/99_day_by_day_SoSe2018

2. Diskussion der studentischen Lösungen und einer Musterlösung

3. Überlegungen zu Kapazität und Potential des Konzepts und Möglichkeiten zur Reduktion

Laut der aufgegebenen Statistik wurden 2% der Ressourcen verbraucht, somit bietet der verwendete FPGA das Potential ein Neuronales Netz diesen Typs mit maximal 150 Neuronen aufzubauen.

Welche Möglichkeiten gäbe es, die Anzahl der implementierbaren Neuronen zu erhöhen?

MUSTERLÖSUNG NXOR mittels Neuronalem Netz-Derivat auf FPGA
NeuroNetzNXOR.zip -- Xilinx-Projekt: MUSTERLÖSUNG zur Generierung eines Netzes mit nur 2 Bit Ausgangswertebereich pro Neuron.
Hinweis:

Statt direkt

		 u0 <= (((w0*in0)/2)+((w1*in1)/2))/8;

...wurde

         xu0 <= w0*in0;
		 yu0 <= w1*in1;
		 u0 <= ((xu0/2)+(yu0/2))/8;
implementiert, da sonst beim Kompilieren eine Warnung 
zu einem möglichen Datenverlust angezeigt wurde.


Code 0-10: Hinweis.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity NeuroNetzNXOR is
    Port ( inputA : in  STD_LOGIC;
           inputB : in  STD_LOGIC;
           outputC : out  STD_LOGIC);
end NeuroNetzNXOR;

architecture Behavioral of NeuroNetzNXOR is
-- Konstanten einfügen:
        constant w0: integer := -6;
        constant w1: integer := -2;
        constant w2: integer := 2;
        constant w3: integer := 2;
        constant w4: integer := -1;
        constant w5: integer := -4;
        constant l0: integer := -8;
        constant l1: integer := 6;
        constant l2: integer := -4;
        constant l3: integer := -5;
        constant l4: integer := 1;
        constant l5: integer := 2;
        constant l6: integer := -7;
        constant l7: integer := -7;
        constant l8: integer := 1;
        constant l9: integer := -3;
        constant l10: integer := -1;
        constant l11: integer := -1;
        constant l12: integer := -4;
        constant l13: integer := 2;
        constant l14: integer := 3;
        constant l15: integer := 3;
        constant l16: integer := 0;
        constant l17: integer := 2;
        constant l18: integer := 4;
        constant l19: integer := -6;
        constant l20: integer := -6;
        constant l21: integer := 4;
        constant l22: integer := -6;
        constant l23: integer := -4;
        constant l24: integer := -1;
        constant l25: integer := -4;
        constant l26: integer := 3;
        constant l27: integer := -8;
        constant l28: integer := 4;
        constant l29: integer := -5;
        constant l30: integer := -1;
        constant l31: integer := -6;
        constant l32: integer := -1;
        constant l33: integer := 3;
        constant l34: integer := -1;
        constant l35: integer := 0;
        constant l36: integer := -7;
        constant l37: integer := 6;
        constant l38: integer := 7;
        constant l39: integer := 7;
        constant l40: integer := -8;
        constant l41: integer := -6;
        constant l42: integer := 4;
        constant l43: integer := -8;
        constant l44: integer := -2;
        constant l45: integer := -4;
        constant l46: integer := 7;
        constant l47: integer := 2;
-- Eingangssignale definieren:
        signal in0 : integer range -8 to 7 := 0; -- 4Bit Variable
        signal in1 : integer range -8 to 7 := 0; -- 4Bit Variable
-- Ergebnisse der gewichteten Summen definieren:
-- wegen int u0 = (  ((w0*in0)/2) + ((w1*in1)/2)  )/8; // [-7,8]
-- kann u0 theoretisch als Zwischenergebnis maximal 16*7=112, bzw. minimal -16*8=128 annehmen.
-- Darum wird als Bereich der einer vorzeichenbehafteten 8-Bit-Integerzahl gewählt:
        signal u0 : integer range -127 to 128 := 0; -- 8Bit Variable
        signal u1 : integer range -127 to 128 := 0; -- 8Bit Variable
        signal u2 : integer range -127 to 128 := 0; -- 8Bit Variable
-- Ausgänge der Neuronen definieren:
        signal out0 : integer range -8 to 7 := 0; -- 4Bit Variable
        signal out1 : integer range -8 to 7 := 0; -- 4Bit Variable
        signal out2 : integer range -8 to 7 := 0; -- 4Bit Variable
-- Testweise Zwischenergebnisse berechnen und in Hilfsvariablen speichern:
-- Hilfsvariablen wegen warning, s.u.:
        signal xu0 : integer range -127 to 128 := 0; -- 8Bit Variable
        signal yu0 : integer range -127 to 128 := 0; -- 8Bit Variable
        signal xu1 : integer range -127 to 128 := 0; -- 8Bit Variable
        signal yu1 : integer range -127 to 128 := 0; -- 8Bit Variable
        signal xu2 : integer range -127 to 128 := 0; -- 8Bit Variable
        signal yu2 : integer range -127 to 128 := 0; -- 8Bit Variable		  
begin
-- Aus den logischen Eingängen die Neuronen-Inputs gewinnen:
-- Eingänge invertieren, wg. Pullup
		  in0 <= 7 when (inputA = '0') else -8;
		  in1 <= 7 when (inputB = '0') else -8;
-- Berechnung der gewichteten Summen
         xu0 <= w0*in0;
		 yu0 <= w1*in1;
		 u0 <= ((xu0/2)+(yu0/2))/8;
-- WARNING ohne Hilfsvariablen:
-- line 114: The result of a 4x4-bit multiplication is partially used. 
-- Only the 7 least significant bits are used. If you are doing this on purpose, 
-- you may safely ignore this warning. Otherwise, 
-- make sure you are not losing information, leading to unexpected circuit behavior.		  
        xu1 <= w2*in0;
		yu1 <= w3*in1;    
        u1 <= (  (xu1/2) + (yu1/2)  )/8;        
-- Lookup-Tabellen um aus u0 out0, bzw. aus u1 out1 zu bestimmen:
        with u0 select out0 <=
        l0 when -7, 
        l1 when -6, 
        l2 when -5, 
        l3 when -4, 
        l4 when -3, 
        l5 when -2, 
        l6 when -1, 
        l7 when 0, 
        l8 when 1, 
        l9 when 2, 
        l10 when 3, 
        l11 when 4, 
        l12 when 5, 
        l13 when 6, 
        l14 when 7, 
        l15 when others;

        with u1 select out1 <=
        l16 when -7, 
        l17 when -6, 
        l18 when -5, 
        l19 when -4, 
        l20 when -3, 
        l21 when -2, 
        l22 when -1, 
        l23 when 0, 
        l24 when 1, 
        l25 when 2, 
        l26 when 3, 
        l27 when 4, 
        l28 when 5, 
        l29 when 6, 
        l30 when 7, 
        l31 when others;
-- Behandlung der zweiten Neuronenschicht (nur ein Neuron):
        xu2 <= w4*out0;
		yu2 <= w5*out1;    
        u2 <= (  (xu2/2) + (yu2/2)  )/8;
-- Lookup-Tabelle, um aus u2 out2 zu bestimmen:
        with u2 select out2 <=
        l32 when -7, 
        l33 when -6, 
        l34 when -5, 
        l35 when -4, 
        l36 when -3, 
        l37 when -2, 
        l38 when -1, 
        l39 when 0, 
        l40 when 1, 
        l41 when 2, 
        l42 when 3, 
        l43 when 4, 
        l44 when 5, 
        l45 when 6, 
        l46 when 7, 
        l47 when others;
-- Umwandlung des Integer-Ausgangssignals von out2 in den logischen Ausgang outputC:
        with out2 select outputC <=
		      '0' when -8 to 0, 
				'1' when others;
end Behavioral;

Code 0-11: VHDL-Datei.

NET "inputA"  LOC = "P126" | PULLUP  | IOSTANDARD = LVCMOS33 ;
NET "inputB"  LOC = "P130" | PULLUP  | IOSTANDARD = LVCMOS33 ;
NET "outputC"   LOC = "P125" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ;

Code 0-12: Constraints-Datei.


Der entsprechende Testaufbau konnte erfolgreich getestet werden.


Laut der aufgegebenen Statistik wurden 2% der Ressourcen verbraucht, somit bietet der verwendete FPGA das Potential ein Neuronales Netz diesen Typs mit maximal 150 Neuronen aufzubauen.

MUSTERLÖSUNG zur Generierung eines Netzes mit nur 2 Bit Ausgangswertebereich pro Neuron
FPGA_NEURON_004_out4bit.zip -- Projekt: MUSTERLÖSUNG zur Generierung eines Netzes mit nur 2 Bit Ausgangswertebereich pro Neuron
//004: Output nur 2 statt 4 Bit 
import java.util.Random;
Random zzz = new Random(0);

public int zufall()
{
     return zzz.nextInt(16)-8; // [-8,7]
}

public double fehler(int[] gen)
{
    int out0 = netz(-8,-8,gen); 
    int out1 = netz(-8,7,gen); 
    int out2 = netz(7,-8,gen); 
    int out3 = netz(7,7,gen);
    
    int err = (out0-7)*(out0-7) + (out1+8)*(out1+8) + (out2+8)*(out2+8) + (out3-7)*(out3-7);
    
    return Math.sqrt((double)err);
}

public int netz(int in0, int in1, int[] gen)
{
     int w0=gen[0]; int w1=gen[1]; int w2=gen[2]; int w3=gen[3]; int w4=gen[4]; int w5=gen[5];
     
     // -8,7 => min -8*7=-56, max -8*-8=64 , /64=-1..2 == 2Bit!!
     int u0 = (  (w0*in0) + (w1*in1)  )/64; // [-1,2]
     int u1 = (  (w2*in0) + (w3*in1)  )/64;
     
     u0+=1; // [0..3]
     int out0 = gen[6+u0];
     u1+=1; // [0..3]
     int out1 = gen[6+4+u1];
     
     int u2 = (  (w4*out0) + (w5*out1)  )/64;
     u2+=1; // [0..3]
          
     int out2 = gen[6+4+4+u2];
     
     return out2;
}


public void setup()
{
     int[] gen = new int[18]; //6+16+16+16=54, 6+4+4+4=18
     int[] genN = new int[18];
     for(int i=0;i<gen.length;i++)
        gen[i]=zufall();
       
       
     for(int DURCHLAUF=0;DURCHLAUF<900;DURCHLAUF++)
     {
        int a = zzz.nextInt(gen.length);
        int b = gen[a];
        double bb=fehler(gen);
        gen[a]=zufall();
        double cc = fehler(gen);
        if(bb<cc)
        {
           gen[a]=b;
        }
        else
        {
            if(cc<bb)
               println("err="+cc);
        }
     }
     double aktueller_fehler = fehler(gen);
    
     println("err="+aktueller_fehler);
     println();
     // Codegenerator als Unterstützung für die Erstellung des FPGA-Programms
     String EINRUECKUNG = "        ";
     //  constant w0: integer := -77;
     for(int i=0;i<6;i++)
        println(EINRUECKUNG+"constant w"+i+": integer := "+gen[i]+";");
     for(int i=0;i<12;i++)
        println(EINRUECKUNG+"constant l"+i+": integer := "+gen[6+i]+";");
     println();        
     println(EINRUECKUNG+"with u0 select out0 <=");
     for(int i=0;i<3;i++)
        println(EINRUECKUNG+"l"+i+" when "+(i-1)+", ");
     println(EINRUECKUNG+"l3 when others;");   
     println();        
     println(EINRUECKUNG+"with u1 select out1 <=");
     for(int i=0;i<3;i++)
        println(EINRUECKUNG+"l"+(4+i)+" when "+(i-1)+", ");
     println(EINRUECKUNG+"l7 when others;");   
     println();        
     println(EINRUECKUNG+"with u2 select out2 <=");
     for(int i=0;i<3;i++)
        println(EINRUECKUNG+"l"+(8+i)+" when "+(i-1)+", ");
     println(EINRUECKUNG+"l11 when others;");   
}

public void draw()
{
}

Code 0-13: MUSTERLÖSUNG zur Generierung eines Netzes mit nur 2 Bit Ausgangswertebereich pro Neuron

err=15.297058540778355
err=15.033296378372908
err=14.594519519326424
err=13.892443989449804
err=12.884098726725126
err=9.055385138137417
err=6.324555320336759
err=2.8284271247461903
err=0.0
err=0.0

        constant w0: integer := 1;
        constant w1: integer := 5;
        constant w2: integer := 7;
        constant w3: integer := 5;
        constant w4: integer := -8;
        constant w5: integer := 6;
        constant l0: integer := 7;
        constant l1: integer := 6;
        constant l2: integer := -3;
        constant l3: integer := -6;
        constant l4: integer := -4;
        constant l5: integer := -1;
        constant l6: integer := -3;
        constant l7: integer := -8;
        constant l8: integer := 7;
        constant l9: integer := -8;
        constant l10: integer := 5;
        constant l11: integer := -4;

        with u0 select out0 <=
        l0 when -1, 
        l1 when 0, 
        l2 when 1, 
        l3 when others;

        with u1 select out1 <=
        l4 when -1, 
        l5 when 0, 
        l6 when 1, 
        l7 when others;

        with u2 select out2 <=
        l8 when -1, 
        l9 when 0, 
        l10 when 1, 
        l11 when others;

Code 0-14: Ausgabe des Optimierers und Code-Generators.

#6 Mo 05.04.2025

Vorab, Rolle von FPGAs von Xilinx im Ukraine-Krieg:

Siehe "#10 Mi 24.05.2023", dort: 08_Archiv/04_SoSe2023/05_HDL_day_by_day.

Themen

  • Anstatt ein größeres Projekt mit Neuronalen Netzen weiter zu verfolgen, soll nun der Fokus auf kleinere Aufgaben gehen, die einzeln oder in Zweiergruppen selbstständig gelöst und dann präsentiert werden sollen.
  • Nachfolgend sind mögliche Themen zur Wahl aufgelistet.
  • Es sind die gegebenen Projekte zu verstehen, nachzubauen, zu testen, eine eigene Variante umzusetzen und dann vor den anderen zu präsentieren:
  • Eventuell macht es Sinn, wenn im Verlaufe der kommenden Lehrveranstaltungen jede Gruppe 2 bis 3 dieser Projekte umsetzt.

#1 In VHDL formuliertes D-Flip-Flop mit Synchronisierungseingang: 69_FPGA/08_Synchronisieren

#2 Ansteuerung eines Modellbau-Servos mittels mehrerer Prozesse: 69_FPGA/10_Servo

#3 Emulation einer seriellen Schnittstelle in Verbindung mit einem Arduino Micro, siehe "14 -- Donnerstag 13.06.2019 (V) " dort: 69_FPGA/30_day_by_day, ev. die Übung bei "14-- Dienstag 18.06.2019 (Ü) " als Variation.

#4 Umsetzung einer Stoppuhr in Verbindung mit einer 4-fach-7-Segment-Anzeige, siehe ab "#8 Do 12.05.2022", hier: 08_Archiv/02_SoSe2022/03_HDL

#5 Tongenerator, siehe "2. Projekt Digitales Musikinstrument weiter bringen", hier: 08_Archiv/04_SoSe2023/05_HDL_day_by_day

#7 Mo 13.05.2025

Themen

  1. Präsentation zu Projekt #1: D-Flip-Flop (?)
  2. Erstellen eigener Module und deren Einbindung am Beispiel D-Flip-Flop und Schieberegister
  3. Verwendung der vorgefertigten Module der UNISIM Bibliothek
  4. Fortsetzung der Projektarbeiten

1. Präsentation zu Projekt #1: D-Flip-Flop (?)

69_FPGA/08_Synchronisieren

2. Erstellen eigener Module und deren Einbindung am Beispiel D-Flip-Flop und Schieberegister

69_FPGA/09_Uebung

3. Verwendung der vorgefertigten Module der UNISIM Bibliothek

69_FPGA/12_UNISIM
69_FPGA/13_LUT

4. Fortsetzung der Projektarbeiten

#8 Mo 19.05.2025

  • Die Projektephase soll abgeschlossen werden und ss sollen alle Projekte so weit wie es geht präsentiert werden.

Themen

  1. Projektpräsentation zur Emulation einer seriellen Schnittstelle
  2. Projektpräsentation zur Ansteuerung eines Modellbau-Servos
  3. Projektpräsentation zur Verwendung einer 4-fach Sieben-Segment-Anzeige
  4. ÜBUNG: Schieberegister bestehend aus vier D-Flip-Flops, die aus einem Modul instanziiert werden

4. ÜBUNG: Schieberegister bestehend aus vier D-Flip-Flops, die aus einem Modul instanziiert werden

69_FPGA/09_Uebung -- Vollziehen Sie theoretisch und praktisch das Projekt bestehend aus Code 0-1, 0-2 und 0-3 nach.

1. Projektpräsentation zur Emulation einer seriellen Schnittstelle

Transfert.zip -- ISE Projekt, studentische Lösung.
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
 
ENTITY Transfert IS
    PORT (
        MEINECLOCK : IN STD_LOGIC;
        TXD : OUT STD_LOGIC
    );
END Transfert;
 
ARCHITECTURE BEHAVIORAL OF Transfert IS
  
    TYPE char_array IS ARRAY (0 TO 4) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
    CONSTANT LETTRES : char_array := (
        0 => "01001000", -- H 
        1 => "01000101", -- E 
        2 => "01001100", -- L 
        3 => "01001100", -- L
        4 => "01001111" -- O 
    );
 
   
    SIGNAL zaehler : INTEGER RANGE 0 TO 624 := 0; 
    SIGNAL bit_counter : INTEGER RANGE 0 TO 15 := 0; 
    SIGNAL char_index : INTEGER RANGE 0 TO 4 := 0; 
    SIGNAL logikpegel : STD_LOGIC := '1'; 
    SIGNAL current_word : STD_LOGIC_VECTOR(15 DOWNTO 0); 
 
    CONSTANT PREFIX : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1110";
    CONSTANT POSTFIX : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0111";
 
BEGIN
 
    current_word <= PREFIX & LETTRES(char_index) & POSTFIX;
 
    PROCESS (MEINECLOCK)
    BEGIN
        IF rising_edge(MEINECLOCK) THEN
            IF zaehler = 624 THEN
                zaehler <= 0; -- Réinitialisation du compteur de timing
 
                logikpegel <= current_word(15 - bit_counter);--MSB senden
                TXD <= logikpegel;
 
                IF bit_counter = 15 THEN
                    bit_counter <= 0; 
                    
                    IF char_index = 4 THEN
                        char_index <= 0;
                    ELSE
                        char_index <= char_index + 1; 
                    END IF;
                ELSE
                    bit_counter <= bit_counter + 1;
                END IF;
            ELSE
                zaehler <= zaehler + 1;
            END IF;
        END IF;
    END PROCESS;
END BEHAVIORAL;

Code 0-15: VHDL-Quelltext, studentische Lösung.

## 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-16: Constraints-Datei.

#9 Mo 26.05.2025

Themen

  1. Quiz
  2. Übersicht zu den bereits behandelten Themen
  3. Beispiel: Erzeugung eines Sinustones unter Verwendung eines R-2R-Netzes
  4. Beispiel: Erzeugung einer "Obertonmusik"
  5. Projektübung: Entwicklung eines elektronischen Musikinstruments

1. Quiz

  1. Was war historisch der Beweggrund gewesen, die FPGA-Technik in Kombination mit VHDL zu entwickeln?
  2. Können mehrere Prozesse parallel auf einem FPGA laufen?
  3. Wie kann eine Bitshift-Operation mit VHDL realisiert werden?
  4. Warum ist reiner VHDL-Quelltext von einem FPGA auf einen anderen portierbar?
  5. Worin liegen Vor- und Nachteile beim Einsatz der Elemente der UNISIM-Library?
  6. Lassen sich mit einem FPGA Bussysteme realisieren?

2. Übersicht zu den bereits behandelten Themen

  1. Grundverständnis für einen FPGA (Hardware in Kombination mit VHDL)
  2. Umgang mit der Xilinx IDE
  3. Sprachelemente von VHDL
  4. VHDL: Verknüpfende Befehle
  5. VHDL: Prozesse
  6. VHDL: Constraints
  7. VHDL: Module selber schreiben
  8. VHDL: Standardmodule verwenden, insbesondere D-FlipFlop und LUT4
  9. VHDL-Sprachelemente: Bit-Wörter neu kombinieren mit &
  10. VHDL-Sprachelemente: Logische Operatoren
  11. VHDL-Sprachelemente: Konvertieren von Integerwerten in Bitwörter
  12. VHDL-Sprachelemente: Konstanten definieren
  13. VHDL-Sprachelemente: case-Anweisung
  14. Beispiel: Blinkende LED
  15. Beispiel: Logische Schaltungen realisieren
  16. Beispiel: Mustervergleich
  17. Beispiel: Serielle Schnittstelle emulieren
  18. Beispiel: Modelbauservo ansteuern
  19. Beispiel: Digitalanzeige ansteuern

3. Beispiel: Erzeugung eines Sinustones unter Verwendung eines R-2R-Netzes

Testumsetzung: Tonausgabe über DA-Wandler R/2R-Netzwerk, nur Rechtecksignal

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; -- WICHTIG, DAMIT CONCURRENT WHEN einen Effekt hat!

-- Umsetzung eines DAC am Beispiel eines Rechteckgenerators
-- 20Khz Samplerate
-- 200Hz Ausgang
-- 100 Schritte für 200Hz

entity sinus is
    Port ( MEINECLOCK : in  STD_LOGIC;
           ANALOG : out  STD_LOGIC_VECTOR (7 downto 0));
end sinus;

architecture Behavioral of sinus is
    signal zaehler    : integer range 0 to 299 := 0; --20kHz
    signal zaehler2    : integer range 0 to 99 := 0; --200Hz
	 signal wort : std_logic_vector(7 downto 0);
    begin
        process begin
            wait until rising_edge(MEINECLOCK);
            if (zaehler<299) then
                zaehler <= zaehler+1;
            else
                zaehler <= 0;
					 ---- Beginn zähler 2
                if (zaehler2<99) then
                    zaehler2 <= zaehler2+1;
                else
                    zaehler2 <= 0;
                end if;					 
            end if;
        end process;
		  
        --- Zuordnungen zum Ausgang, Test Rechteckschwingung von 200Hz
        with zaehler2 select wort <=
            "11111111" when 0 to 50,
            "00000000" when others;		  
        ANALOG <= wort;
end Behavioral;

Code 0-17: 1. Testumsetzung: Tonausgabe über DA-Wandler R/2R-Netzwerk, nur Rechtecksignal

## GCLK6 ist auf FPGA-Chip Pin 56
NET "MEINECLOCK" LOC = "P56";
## IO_L05P_0 ist auf FPGA-Chip Pin 125
NET "MEINECLOCK" IOSTANDARD = LVCMOS25;

NET "ANALOG<0>"  LOC = "P58"  | IOSTANDARD = LVCMOS33 ;
NET "ANALOG<1>"  LOC = "P59"  | IOSTANDARD = LVCMOS33 ;
NET "ANALOG<2>"  LOC = "P93"  | IOSTANDARD = LVCMOS33 ;
NET "ANALOG<3>"  LOC = "P94"  | IOSTANDARD = LVCMOS33 ;
NET "ANALOG<4>"  LOC = "P96"  | IOSTANDARD = LVCMOS33 ;
NET "ANALOG<5>"  LOC = "P97"  | IOSTANDARD = LVCMOS33 ;
NET "ANALOG<6>"  LOC = "P103"  | IOSTANDARD = LVCMOS33 ;
NET "ANALOG<7>"  LOC = "P104"  | IOSTANDARD = LVCMOS33 ;

Code 0-18: Constraints zu 1. Testumsetzung.

  • Das R/R2 Netzwerk wurde bei IO0..IO7 angeschlossen.
  • Es wurden 1kOhm und 2kOhm Widerstände kombiniert.
  • Vorwiderstand beim Lautsprecher: 1kOhm.
Schaltung zum Tongebeber.

Bild 0-2: Schaltung zum Tongebeber.

Schaltungsaufbau zum Tongebeber (sehr leise).

Bild 0-3: Schaltungsaufbau zum Tongebeber (sehr leise).

2. Testumsetzung: Sinuston über DA-Wandler R/2R-Netzwerk

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

use IEEE.NUMERIC_STD.ALL;
-- Umsetzung eines DAC am Beispiel eines Sinusgenerators
-- 20Khz Samplerate
-- 200Hz Ausgang
-- 100 Schritte für 200Hz

entity sinus is
    Port ( MEINECLOCK : in  STD_LOGIC;
           ANALOG : out  STD_LOGIC_VECTOR (7 downto 0));
end sinus;

architecture Behavioral of sinus is
    signal zaehler    : integer range 0 to 299 := 0; --20kHz
    signal zaehler2    : integer range 0 to 99 := 0; --200Hz
	 signal wort : std_logic_vector(7 downto 0);
    begin
        process begin
            wait until rising_edge(MEINECLOCK);
            if (zaehler<299) then
                zaehler <= zaehler+1;
            else
                zaehler <= 0;
                ---- Beginn zähler 2
                if (zaehler2<99) then
                    zaehler2 <= zaehler2+1;
                else
                    zaehler2 <= 0;
                end if;
            end if;
        end process;
		  
        --- Zuordnungen zum Ausgang, Test Rechteckschwingung von 200Hz
        with zaehler2 select wort <=
            "00000000" when 0,
            "00000000" when 1,
            "00000001" when 2,
            "00000010" when 3,
            "00000100" when 4,
            "00000110" when 5,
            "00001000" when 6,
            "00001100" when 7,
            "00001111" when 8,
            "00010011" when 9,
            "00011000" when 10,
            "00011101" when 11,
            "00100010" when 12,
            "00101000" when 13,
            "00101110" when 14,
            "00110100" when 15,
            "00111011" when 16,
            "01000010" when 17,
            "01001001" when 18,
            "01010000" when 19,
            "01011000" when 20,
            "01011111" when 21,
            "01100111" when 22,
            "01101111" when 23,
            "01110111" when 24,
            "01111111" when 25,
            "10000111" when 26,
            "10001111" when 27,
            "10010111" when 28,
            "10011111" when 29,
            "10100110" when 30,
            "10101110" when 31,
            "10110101" when 32,
            "10111100" when 33,
            "11000011" when 34,
            "11001010" when 35,
            "11010000" when 36,
            "11010110" when 37,
            "11011100" when 38,
            "11100001" when 39,
            "11100110" when 40,
            "11101011" when 41,
            "11101111" when 42,
            "11110010" when 43,
            "11110110" when 44,
            "11111000" when 45,
            "11111010" when 46,
            "11111100" when 47,
            "11111101" when 48,
            "11111110" when 49,
            "11111110" when 50,
            "11111110" when 51,
            "11111101" when 52,
            "11111100" when 53,
            "11111010" when 54,
            "11111000" when 55,
            "11110110" when 56,
            "11110010" when 57,
            "11101111" when 58,
            "11101011" when 59,
            "11100110" when 60,
            "11100001" when 61,
            "11011100" when 62,
            "11010110" when 63,
            "11010000" when 64,
            "11001010" when 65,
            "11000011" when 66,
            "10111100" when 67,
            "10110101" when 68,
            "10101110" when 69,
            "10100110" when 70,
            "10011111" when 71,
            "10010111" when 72,
            "10001111" when 73,
            "10000111" when 74,
            "01111111" when 75,
            "01110111" when 76,
            "01101111" when 77,
            "01100111" when 78,
            "01011111" when 79,
            "01011000" when 80,
            "01010000" when 81,
            "01001001" when 82,
            "01000010" when 83,
            "00111011" when 84,
            "00110100" when 85,
            "00101110" when 86,
            "00101000" when 87,
            "00100010" when 88,
            "00011101" when 89,
            "00011000" when 90,
            "00010011" when 91,
            "00001111" when 92,
            "00001100" when 93,
            "00001000" when 94,
            "00000110" when 95,
            "00000100" when 96,
            "00000010" when 97,
            "00000001" when 98,
            "00000000" when 99,
            "00000000" when others;		  
        ANALOG <= wort;
end Behavioral;

Code 0-19: 2. Testumsetzung: Sinuston über DA-Wandler R/2R-Netzwerk

Contraints wie zuvor.

sinus.zip -- Xinlinx 14.7-Projekt.
public void setup()
{
     for(int i=0;i<100;i++)
     {
         double dt = 1.0/20000.0;
         double  t = (double)i*dt;
         double x = -Math.cos(2.0*Math.PI*200.0*t);
         double y = 255.0*((x+1.0)*0.5);
         int iy = (int)y;
         int a0 = iy%2; iy/=2;
         int a1 = iy%2; iy/=2;
         int a2 = iy%2; iy/=2;
         int a3 = iy%2; iy/=2;
         int a4 = iy%2; iy/=2;
         int a5 = iy%2; iy/=2;
         int a6 = iy%2; iy/=2;
         int a7 = iy%2;
         println("            \""+a7+""+a6+""+a5+""+a4+""+a3+""+a2+""+a1+""+a0+"\" when "+i+",");
        
     }
}

Code 0-20: Codegenerator mit Processing für when-statement.


Testen Sie das Projekt sinus.


4. Beispiel: Erzeugung einer "Obertonmusik" (ursprünglich Übung)

  • Auf IO0 bis IO7 sollen jeweils die Frequenzen 200, 400, 600, 800, 1000, 1200, 1400, 1600Hz als Rechteckschwingungen ausgegeben werden.
  • Jedoch nach einem zyklischen Muster, das einem Binärzähler entspricht:
  • erst 200Hz auf IO0, dann 400Hz auf IO1, dann beides, dann 600Hz auf IO2 usw.
  • Die Wechsel sollen im Tempo von 2Hz erfolgen.

Um das Geschehen akustisch wahrnehmbar zu machen, soll folgende Schaltung aufgebaut werden:

Schaltung für

Bild 0-4: Schaltung für "Obertonspiel".

Hinweise:

  • Es kann mehr als einen Prozess in einem VHDL-Programm geben.
  • Prozesse arbeiten "concurrent".
  • Es gibt aber auch Lösungen mit einem Prozess auszukommen.
  • Entscheiden Sie sich für eine Variante und setzen sie dann um.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;

use IEEE.NUMERIC_STD.ALL;


library UNISIM;
use UNISIM.VComponents.all;

entity ober is
    Port (MEINECLOCK : STD_Logic;
            aus : out STD_LOGIC_VECTOR (7 downto 0));
end ober;

architecture Behavioral of ober is
constant f0: integer := 29999;
constant f1: integer := 14999;
constant f2: integer := 9999;
constant f3: integer := 7499;
constant f4: integer := 5999;
constant f5: integer := 4999;
constant f6: integer := 4285;
constant f7: integer := 3749;

signal zaehler0 : integer range 0 to 29999 :=  0;
signal zaehler1 : integer range 0 to 14999 :=  0;
signal zaehler2 : integer range 0 to 9999 :=  0;
signal zaehler3 : integer range 0 to 7499 :=  0;
signal zaehler4 : integer range 0 to 5999 :=  0;
signal zaehler5 : integer range 0 to 4999 :=  0;
signal zaehler6 : integer range 0 to 4285 :=  0;
signal zaehler7 : integer range 0 to 3749 :=  0;
signal frequenz : integer range 0 to 2999999 := 0;

signal wort : integer range 0 to 256 := 0;

signal Ausgang: STD_LOGIC_VECTOR (7 downto 0) := "00000000";

signal takt0 : STD_LOGIC := '0';
signal takt1 : STD_LOGIC := '0';
signal takt2 : STD_LOGIC := '0';
signal takt3 : STD_LOGIC := '0';
signal takt4 : STD_LOGIC := '0';
signal takt5 : STD_LOGIC := '0';
signal takt6 : STD_LOGIC := '0';
signal takt7 : STD_LOGIC := '0';


begin
    process begin
        wait until rising_edge(MEINECLOCK);
        if(zaehler0<f0)then
            zaehler0 <= zaehler0 + 1;
        else
            zaehler0 <= 0;
            takt0 <= not takt0;
        end if;
    end process;
   
    process begin
        wait until rising_edge(MEINECLOCK);
        if(zaehler1<f1)then
            zaehler1 <= zaehler1 + 1;
        else
            zaehler1 <= 0;
            takt1 <= not takt1;
        end if;
    end process;
   
    process begin
        wait until rising_edge(MEINECLOCK);
        if(zaehler2<f2)then
            zaehler2 <= zaehler2 + 1;
        else
            zaehler2 <= 0;
            takt2 <= not takt2;
        end if;
    end process;
   
    process begin
        wait until rising_edge(MEINECLOCK);
        if(zaehler3<f3)then
            zaehler3 <= zaehler3 + 1;
        else
            zaehler3 <= 0;
            takt3 <= not takt3;
        end if;
    end process;
   
    process begin
        wait until rising_edge(MEINECLOCK);
        if(zaehler4<f4)then
            zaehler4 <= zaehler4 + 1;
        else
            zaehler4 <= 0;
            takt4 <= not takt4;
        end if;
    end process;
   
    process begin
        wait until rising_edge(MEINECLOCK);
        if(zaehler5<f5)then
            zaehler5 <= zaehler5 + 1;
        else
            zaehler5 <= 0;
            takt5 <= not takt5;
        end if;
    end process;
   
    process begin
        wait until rising_edge(MEINECLOCK);
        if(zaehler6<f6)then
            zaehler6 <= zaehler6 + 1;
        else
            zaehler6 <= 0;
            takt6 <= not takt6;
        end if;
    end process;
   
    process begin
        wait until rising_edge(MEINECLOCK);
        if(zaehler7<f7)then
            zaehler7 <= zaehler7 + 1;
        else
            zaehler7 <= 0;
            takt7 <= not takt7;
        end if;
    end process;

    process begin
        wait until rising_edge(MEINECLOCK);
        if(frequenz<2999999)then
            frequenz <= frequenz + 1;
        else
            frequenz <= 0;
            if(wort>255)then
                wort <= 0;
            else
                wort <= wort +1;
            end if;
        end if;
    end process;
       
Ausgang <= conv_std_logic_vector(wort,Ausgang'length);

aus(0) <= takt0 and Ausgang(0);
aus(1) <= takt1 and Ausgang(1);
aus(2) <= takt2 and Ausgang(2);
aus(3) <= takt3 and Ausgang(3);
aus(4) <= takt4 and Ausgang(4);
aus(5) <= takt5 and Ausgang(5);
aus(6) <= takt6 and Ausgang(6);
aus(7) <= takt7 and Ausgang(7);

end Behavioral;

Code 0-21: Studentische Lösung zu "Obertonmusik".

NET "aus<0>"  LOC = "P126"  | IOSTANDARD = LVCMOS33 ;
NET "aus<1>"  LOC = "P130"  | IOSTANDARD = LVCMOS33 ;
NET "aus<2>"  LOC = "P131"  | IOSTANDARD = LVCMOS33 ;
NET "aus<3>"  LOC = "P132"  | IOSTANDARD = LVCMOS33 ;
NET "aus<4>"  LOC = "P134"  | IOSTANDARD = LVCMOS33 ;
NET "aus<5>"  LOC = "P135"  | IOSTANDARD = LVCMOS33 ;
NET "aus<6>"  LOC = "P139"  | IOSTANDARD = LVCMOS33 ;
NET "aus<7>"  LOC = "P140"  | IOSTANDARD = LVCMOS33 ;

NET "MEINECLOCK" LOC = "P56" | IOSTANDARD = LVCMOS25;

Code 0-22: Zugehörige Constraint-Datei zu "Obertonmusik".

Aufbau zu

Bild 0-5: Aufbau zu "Obertonmusik"

https://youtu.be/ccnHqVTUeIA -- Video zu Obertonmusik.

5. Projektübung: Entwicklung eines elektronischen Musikinstruments

  1. Ideensammlung: Was wäre machbar? Was wäre interessant zu machen?
  2. Konkretisierung der Projektideen
  3. Beginn mit der Umsetzung

#10 Mo 02.05.2025


Ankündigung, nächster Termin: Probe-E-Test Montag, 16.06.


Themen

  1. Rückblick auf die praktische Verwendung der Xilinx IDE
  2. Rückblick auf den DSPFPGA und die FPGA-Familie Spartan 3E
  3. Vertiefung: Struktur von FPGA-Programmen, synchrone und asynchrone Schaltungen
  4. Vertiefung: Analyse von Programmen mit und ohne Prozess-Bereich
  5. Sprachelemente von VHDL -- Vorstellung einiger häufig verwendeter Datentypen und Programmstrukturen
  6. Vorstellung und Diskussion des Projektstandes bei der Entwicklung eines elektronischen Musikinstruments
  7. Fortsetzung: Entwicklung eines elektronischen Musikinstruments
1. Rückblick auf die praktische Verwendung der Xilinx IDE:
  • Wie wird die Entwicklungsumgebung gestartet?
  • Wie wird ein neues Projekt angelegt? (.vhd und .ucf-Datei)
  • Wozu dient die .ucf-Datei?
  • Was ist das besondere an der .vhd-Datei?
  • Was unterscheidet ein VHDL-Programm von beispielsweise einem C-Programm?
  • Können die Zeilen in einem VHDL-Programm (teilweise) vertauscht werden?
  • Wie aktiviert man die USB-Spannungsversorgung für das FPGA-Board?
  • Warum sollte man unbedingt den FPGA erst löschen, bevor man ein neues Programm flasht?
  • Wie wird die .bit-Datei erstellt und auf den FPGA übertragen?
2. Rückblick auf den DSPFPGA und die FPGA-Familie Spartan 3E
69_FPGA/03_DLP_FPGA
3. Vertiefung: Struktur von FPGA-Programmen, synchrone und asynchrone Schaltungen
69_FPGA/01_Einfuehrung
4. Vertiefung: Analyse von Programmen mit und ohne Prozess-Bereich
69_FPGA/05_Beispiele/03_Mustervergleich
69_FPGA/05_Beispiele/01_Blinkende_LED
5. Sprachelemente von VHDL -- Vorstellung einiger häufig verwendeter Datentypen und Programmstrukturen
69_FPGA/11_VHDL

#11 Mo 16.06.2025

Themen

  1. Probe-E-Test
  2. Besprechung

1. Probe-E-Test

  • Der Test besteht aus einem elektronischen Test und einer praktische Aufgabe.
  • Es ist nicht möglich beides parallel zu machen.
  • Zuerst ist der elektronische Test zu machen, danach die praktische Aufgabe.
  1. Booten Sie unter Xubuntu,
  2. Doppelklicken Sie ETEST kramann auf dem Desktop,
  3. Speichern Sie den Test unter Andere Orte--Rechner--mnt-system--htdocs-repository,
  4. Navigieren Sie dann mit dem Dateimanager an den Ort, wo der Test liegt,
  5. Gehen Sie mit der RECHTEN MAUSTASTE auf den Test und starten ihn mit startekp.
  6. Tragen Sie Ihren Namen und Ihre Matrikelnummer ein.
  7. Drücken Sie ab und an SPEICHERN.
  8. Wenn Sie fertig sind, drücken Sie bitte ABGEBEN.
  9. Im elektronischen Test ist eine Dummy-Aufgabe enthalten, über die später die Punkte der praktischen Aufgabe hinzu gerechnet werden.
  10. Für den elektronischen Test sind KEINE HILFSMITTEL zugelassen.
  11. Für die praktische Aufgabe kann die Webseite kramann.info hinzu gezogen werden.

Praktische Aufgabe

  • Nachfolgende Tabelle zeigt einen zeitlichen Verlauf an Zuständen an den angegebenen Ausgängen des FPGA-Bausteins.
  • Es handelt sich um eine Art Lauflicht.
  • Das heißt: Ist der letzte Zustand erreicht (letzte Zeile der Tabelle), beginnt es wieder mit dem ersten (erste Zeile in der Tabelle).
  • Bauen Sie auf dem FPGA-Board eine passende Schaltung auf, bei der LEDs an den in der Tabelle angegebenen Ausgängen angeschlossen sind.
  • Legen Sie in bekannter Weise ein Projekt mit dem Namen "Laufendeslicht" mit der Xilinx IDE an. Überlegen Sie sich dazu, welche Port Aus- und Eingänge es geben muss.
  • Entwicklen Sie in dem Projekt ein VHDL-Programm und eine zugehörige Constraints-Datei, mit deren Hilfe obige Tabelle umgesetzt wird.
  • Kompilieren Sie das Programm und übertragen die Bit-Datei auf das Board.
  • Testen und korrigieren Sie das Projekt.
Zustand Nr. Zeit/s P59 P93 P94 P96
0 0,0 HIGH LOW LOW LOW
1 0,2 LOW HIGH LOW LOW
2 0,4 LOW LOW HIGH LOW
3 0,6 LOW LOW LOW HIGH

Tabelle 0-2: Zeitliche Abfolge der Zustände auf den angegebenen Port-Ausgängen.

HINWEISE:

  • Im praktischen Teil ist es erlaubt, die Seite kramann.info zu Hilfe zu nehmen.
  • Weitere Hilfsmittel sind nicht erlaubt, insbesondere ist die Verwendung einer Suchmaschine oder einer KI wie chatGPT verboten.
  • Präsentieren Sie Ihr fertiges Projekt dem Dozenten.
  • Laden Sie Ihr Projekt als ZIP-File nach der Fertigstellung auf Moodle an der vorgesehenen Stelle hoch.

2. Besprechung

#12 Mo 23.06.2025


ACHTUNG: Wegen eines Zugausfalls verspäte ich mich heute um 10 Minuten. Bitte arbeiten Sie schon an der praktischen Aufgabe aus der Probeklausur weiter.


Themen

  1. Besprechung der praktischen Aufgabe des Probe-E-Tests
  2. Exkurs: Objektorientierte Programmierung mit Java/Processing
  3. Fragenbeantwortung zu den Inhalten des Kurses und zur anstehenden Prüfung
Laufendeslicht.zip -- studentische Lösung.
Processing Beispiel
import java.util.Random;
Random zufall = new Random();
Ball[] ball = new Ball[1000];
public void setup()
{
    size(500,500);
    frameRate(30);
    
    for(int i=0;i<ball.length;i++)
       ball[i] = new Ball();
}

public void draw()
{
    background(255);
    for(int i=0;i<ball.length;i++)
       ball[i].draw();
    
}

Code 0-23: Randomart003

public class Ball
{
     int x,y,d,t,r,g,b;
  
     public Ball()
     {
          x = zufall.nextInt(width);
          y = zufall.nextInt(height);
          d = zufall.nextInt(height/5);
          t = zufall.nextInt(256);
          r = zufall.nextInt(256);
          g = zufall.nextInt(256);
          b = zufall.nextInt(256);
     }
  
     public void draw()
     {
          fill(r,g,b,t);
          ellipse(x,y,d,d);
     }
}

Code 0-24: Tab Ball