Aubau einer Speicherzelle

Logik

Logik_FF

Ein FF besteht aus logischer Sicht aus zwei Invertern. Durch die zwei Inverter, erscheint der Eingangswert wieder am Ausgang. Der Wert wurde gespeichert. Tiefer betrachtet, ist die Basis eines FF ein Latch. Das Latch ist der Baustein, der durch Set-Reset am Ausgang ein Wert behält. Das Latch ist aber asynchron und deshal kein FF im engen Sinn. Das FF hat zusätzlich einen Clock. Dadurch werden erst (bei steigender Flanke) die Ausgänge gesetzt.

Hardware (mit Transistoren)

Hardware_FF

Pro Speicherzelle (FF) hat es zwei Bit-Lines. Eine ist die Inversion der anderen.
Auf der Bit-Line wird das aktuelle Bit gesetzt (siehe erstes Bild für Logik).
Die Word-Linien, ist die Verbindung einer Reihe von Speicherzellen.
Unterschied Transistoren <-> Kondensatoren als Speicherelement
FF können mit Transistoren (z.B. in SRAM, s = static = stabil) oder mit Kondensatoren (z.B. DRAM, d = dynamisch = instabil) aufgebaut sein. Die Transistoren behalten ihren Wert (Zustand ‚1‘ oder ‚0‘), sind sie einmal geschalten, was bei den Kondensatoren nicht gilt. Die Kondensatoren entladen sich (‚1‘ – > ‚0.7‘ -> ‚0.5‘), weshalb ihr Wert immer wieder neu gesetzt (refresh) werden muss.
Das Refrehen wird zeilenweise gemacht.
Bsp. Bei einem 16-Bit-Memory, wird in einem Refresh-Zyklus 16 FF neu gesetzt.

Gute Website zu detaillierteren Informatioenen zum digitalen Speichern („How RAM works“).

Memory an Prozesssor anbinden

Takt anpassen
Die Geschwindigkeit des Prozessors ist oft langsamer als der Speicher.
Hier braucht es eine Synchronisation durch einen Takt-Generator.
Das Timing (einhalten der Setup und Holdzeit) war traditionell die grösste Fehlerquelle für ungültige Daten.

Word Grösse
Bei 32-Bit Prozessoren ist ein Word 32 Bit breit. Der Bus hat dieselbe Breite. Am einfachsten ist es, wennd der Speicher ebenfalls 32 breit ist. Dann entspricht ein Word einer Speicher-Zeile. Ansonsten braucht es Anpassungen (siehe Byte-enable).

Schreib- und Leserichtung
Traditionell hat der Prozessor nur ein Bus, der in beide Richtungen kommuniziert.
Bei FPGAs hat es immer zwei Busse, einer fürs Lesen und einer fürs Schreiben.

Zugriffe auf Speicher (Port)
Normalerweise gibt es einen Port. Über diesen gehen die Lese- wie auch die Schreibzyklen.
Im FPGA hat es zwei Ports. Beide können für beides gebraucht werden und können unterschiedliche Busbreiten haben.

 

VHDL IO Debuggen

Signalüberprüfung
Zum Debuggen können den Top-Level-Ports spezifische Wert zugewiesen werden:

GPIO_0 <= '0';
GPIO_0 <= '1';

Am KO kann dann der Wert überprüft werden oder man kann die Pins ausläuten, um zu sehen, ob sie funktionieren. Problem: Pins können auch sonst auf ‚0‘ oder ‚1‘ per default sein.

Besser: Clock-Zuweisung. (Problem auch hier: ClK könnte per default herauskommen.) Am sichersten: CLK auf eigene Frequenz einstellen, so ist man sicher, dass es der gewünschte Pin ist.

GPIO_0 <= CLK_50;


Instanzen anpassen

Im Top-Level könnendie IO der Instanzen mit open auf inaktiv gesetzt werden.

inst_counter: counter
    PORT MAP( clk          => CLOCK_50,
              verification => open,   -- GPIO_0   
              zero_out      => open   -- GPIO_1                
        );

 

 

 

 

 

.gitignore Hilfe

.gitignore bezieht sich nur auf <untracked files>.  Sie sind rot.
New Files (grün) sind bereits <add> und gitignore sieht sie nicht mehr.

File aus add-Liste nehmen

git reset HEAD <file>
git reset HEAD **/**/db/*

Die Files werden wieder rot und gelten als ausserhalb des commits.

Test Funktionsweise .gitignore
Ordner und Endungen, die in .gitignore stehen, sollten unter den <untracked files> erscheinen.
Wichtig: Änderungen in .gitignore müssen zuerst <add> werden, damit sie wirken.

Ordner ignorieren
In gitignore: <bla>/<bli>/<blo>/
Git kann Ordner nicht ignorieren, nur Dateien. Deshalb ist / am Ende zwingend.

Ordner relativ ignorieren

**/**/<blo>/

Die Anzahl Stufen müssen stimmen.
Achtung:
Bei allgemeinen Namen, können ungewollt andere Ordner betroffen sein. Deshalb lieber zwei Namen angeben, sodass es eindeutig wird.

Etwas aus ignoriertem Ordner hinzufügen

Cyclone_IV/synthese/db/*
! Cyclone_IV/synthese/db/<datei.xxx>

Ordner/* der Stern ist zwingend, damit nicht alles per se ignoriert wird. Nur so können unterhalb Dateien wieder zugefügt werden.

Git: wichtigste Befehle

Herunterladen

git fetch upstream

Herunterladen und zusammenführen mit local

git pull [origin master]  // fetch und merge


Dateien auf Github hochladen

git push [origin master]   // origin  bedeutet remote auf github
git push [ <ziel> <von wo>]

Unterscheidung remote/local
Github ist ein entferntes Verzeichnis auf dem Internet. Deshalb bezieht sich der Begriff remote auf Github. Steht nichts vor dem Branch-Name, so ist es local.

$git branch -a
*master     // local branch
develop     // local branch
remotes/origin/HEAD  -> origin/master
remotes/origin/master
remotes/origin/develop


Ordner umbenennen

git mv <old name> <new name>

 

Lokale Datei aus aktuellem Verzeichnis nehmen

Das Git-Verzeichnis befindet sich immer in einem Zustand. Dies ist eine spezifische Commit-Nummer. Will man eine Datei nicht mehr nachverfolgen, bedeutet dies, dass man die Datei aus diesem Arbeitsverzeichnis nimmt.

git remove <file>   Dieser Befehl ist das Gegenteil von

git add <file>

Git remove  bezieht sich nur auf das aktuelle Verzeichnis. Ist die Datei bereits eingechecked, so ist sie in alten Versionen noch da.

git_remove


Push auf Repository rückgängig machen

git log
git revert <beginn der aktuellen commit-nummer>

Der aktuelle Commit findet man mit git log. Danach kann man diesen commit mit revert rückgängig machen. Es besteht wieder der Zustand vor diesem commit.
git_log

Add  rückgängig machen

git reset HEAD <Verzeichnis>

Hat man lokal zuviel zum Committen getan, geht mit diesem Befehl die Datei zurück in untracked (und wird wieder rot).

Ordner aus Repository entfernen   (remote)

git rm -r --cached <directory>       
git commit -m "Ordner aus Github genommen" 
git push origin master

Hier wird der Ordner aus dem Repository genommen (dort gelöscht), aber lokal gelassen. Grund dafür ist die Zeile –cached.


Ordner aus Git entfernen (lokal und remote)

git rm -r <directory>
git status: deleted  <directory>
git add <directory>
git commit -m "löschen eines Ordners lokal und auf Github" 

Der Ordner existiert lokal nicht mehr. Soll er auch auf Github nicht mehr existieren, muss die Lösch-Meldung gepushed werden.


Alte Datei von Repository holen

git checkout <commit-nr> <pfad>/<file>

Achtung: Die Datei wird lokal genau nach Pfad abgelegt. Liegt dort eine aktuelle Datei, wird diese überschrieben. Man muss zuerst die akutelle Datei umbenennen.


Website mit wichtigsten Befehlen

C++: Fehlerhandling

Errorfunktion selber schreiben

void error( std::string message){
    std::cout << message << "\n";
} 


// im code anderer Funktion
if (input < 0) {
   error("ungültiger Wert. \n");
}

Dient zum Überprüfen falscher Argumente
.

Exceptions (Klasse verarbeitet Fehler)
Exceptions trennen den Fehlererkennung  (in Funktion) vom  Verarbeitungsort (main).

– Es wird ein Klasse pro Fehlertyp definiert
.  Aufgabe der Klasse: Fehlermeldung werfen
– Im main werden die Fehlermeldungen global gesamelt

// Notwendige Infrastruktur: Leere Fehlerklasse
class Zero_Input{  };

// Fehlerdetektion in Funktion
int get_value(){
     if (cin == ""  || cin == "0"){
         throw Zero_Input{};
     }
}

// Fehlerbehandlung aufgrund der Klassen
int main()
try{ 
      <code main>
   }
catch( Zero_Input ){
      std::cerr<< "Ops. Leerer Input \n";
      return 1;
}

– main() ist ohne geschweifte Klammern !
– Fehlerausgabe auf std:cerr nicht auf std::cout
– Returnwert hat einen Wert unterschiedlich von 0

c++: vector as new type in -std=c++11

Eine sichere Alternative zum Array!

#include <vector>
std::vector <int> messungen = { 12, 10, 11, 12, 10 };
std::vector <string> klasse_1b = { "eva", "tim", "lin", "noe" };
std::vecrot <Class> token_table = { "n", 5, "+", 2, "*", 4 };


Wertzuweisung

messungen[1] = 11;
token_table[2] = { "*", 3 }

 

Vektor per Referenz übergeben
Damit nicht alle Werte des Vektors übergeben werden müssen, wird nur die Adresse übergeben (siehe Pointer).

void print( const vektor <int>& messungen){
.   // code
}

Zur Referenzübergabe gehört sowohl das & (Adresse mitgeben).

Mit 0 oder leeren Strings initialisieren

std::vector <int> messungen( 5 );
std::vector <string> klasse_1b( 4 );

Achtung: geht nur, wenn man mit -std=c++11 kompiliert.

for eines Vektors

for (int i : messungen){
.    (if i = 5 ) {
.        //
.     }
}

Das verkürzte For für einen Vektor gibt zu Beginn den Datentyp an und nach dem Doppelpunkt die Länge des Vekorts. Dann geht das For durch jedes Elements des Vektors.

for eines Vektors aus einem Klassen-Datentyp

for (Token t: token_table){
.    (if t.nummer == 5) {
.        //
.     }
}

Wieder zuerst der Datentyp (Token) und dann den Vektor.
Bei der interenen Auswertung, muss gesagt werden, auf welchen Variabelntyp der Klasse sich die Auswertung bezieht. (Bei der Klasse Token hat jeder Index zwei Variablen: string operation und int nummer.)

 

Funktionen für Vektorbearbeitung

int anzahl = messungen.size();
messungen.sort();


Daten in Vector einlesen

vector <int> data;
int current_element;

while ( cin ){
    cin >> current_element
     data.push_back ( current_element );
}

– Die Funktion push_back() hängt neue Daten hinten an.
– Sie vergrössert die Vektorgrösse damit immer um 1

 

c++: Ausgabe Konsole: cout <<

Allgemein cout und cin
– Aufgrund von Operator Overloading kann cout  alle Datentypen ausgeben
– Standardformat für Zahlen ist hex
– #include <iostream> ist notwendig
– Die Eingabe über Konsole wird wortweise  in cin gespeichert.
– Gibt man mehrere Wörter (mit Leerschlag getrennt) ein, so wird
.  wenn cin nur 1 Varibale folgt, nur das erste Wort übernommen. Ansonsten
.  braucht es nach cin mehrere Variablen.
– Wert = 0 wird nicht ausgegeben. Es erscheint ein Loch.
Es scheint, wie wenn kein Wert da ist.

Ausgabe dezimal

std::cout << std::dec << (int) var_1 << std::endl;
std::cout << std::dec << (int) treeMemy[0] << std::endl;


Ausgabe bitwise
Es braucht zwei Schritte. Typcast vor dem Output direkt funktioniert nicht.

char var_1 = 5;
std::bitset<8> bits(var_1);   /funktion vor output
std::cout << bits << std::endl;

– bitset muss als Library eingefügt werden
#indlucde <bitset >

Ausgabe char
– Char-Werte werden teilweise wie die 0-Werte nur mit einem Loch ausgegeben. Die Konversion zum Datentyp short hilft, dass man die Werte auf der Konsole sieht.

std::cout << (short) bitReadOut << std::endl;

Führende Nullen anzeigen

std::cout << setfill('0') << setw(5) << var_2<< std::endl;

-setw() sagt, wie viele Stellen man insgesamt ausdruckt

.