Zum Hauptinhalt springen

Logikfunktionen

Boolsche Operationen

Boolsche Variablen oder Signale können nur 2 Zustände annehmen, die je nach Kontext mit verschiedenen Mnemonics beschrieben werden können

01
falsetrue
noyes
offon
lowhigh

Im Folgenden wird darüber hinaus das Symbol X für "don't care" angenommen, d.h. der Wert spielt für das Ergebnis keine Rolle. Flanken werden durch die entsprechende Notation 0->1 oder 1->0 angegeben.

Zum Vergleich wird an vielen Stellen die Verbindung zu den klassischen Logikgatter-ICs der 74-er Serie aufgezeigt (z.B. 74HC147). Die im Math Modul implementierte Funktion hat bei den komplexen Bausteinen meist noch mehr Optionen als das bezeichnete Vorbild.

Die einfachste, elementare Logikfunktion ist das invertierende Element "NOT":

NOT A
A(74HC04)
01
10

Werden zwei boolsche Variablen oder Signale miteinander verknüpft, kommen 2 elementare Logikfunktionen AND und OR zur Anwendung:

A AND BA OR BA XOR B
AB(74HC21)(74HC32)(74HC86)
00000
01011
10011
11110

Das XOR-Element (Exklusive-OR) ist durch eine komplexe Kombination aus AND, OR, und NOT realisierbar und wird hier als eigenes Element aufgeführt, um die Funktion im Folgenden leichter zu verdeutlichen.

XOR(A,B)=AND(OR(A,B),NOT(AND(A,B))XOR(A, B) = AND(OR(A,B), NOT(AND(A,B))

Durch die Kombination mit einer NOT Stufe erhält man jeweils

A NAND BA NOR BA NXOR B
AB(74HC00)(74HC02)(74HC266)
00111
01100
10100
11001

Entsprechend der Datentypen kommen folgende logische Operatoren und Funktionen zur Anwendung, wobei die 64 bits des numerischen Typs <uint> (unsigend integer) jeweils einzeln den Logikfunktionen zugeführt werden:

<bool> A, B<uint> A, B
NOT!AbNot(A)
ANDA && BbAnd(A,B)
ORA || BbOr(A,B)
XORA ^^ BbXOr(A,B)
NAND!(A && B)bNAnd(A,B)
NOR!(A || B)bNOr(A,B)
NXOR!(A ^^ B)bNXOr(A,B)

Bit-orientierte Funktionen

vorsicht

Diese bit-Funktionen sind keine logischen Operatoren! Sie arbeiten immer auf der internen Darstellung als <uint> und wandeln deshalb auch alle Parameter zunächst in den <uint> Typ. Dies wird zum Beispiel an der Funktion bNot() deutlich, die alle Bits des Eingangswerts invertiert.

  • bNot(false) => bNot(0x00) => 0xFFFFFFFFFFFFFFFF => logic: true
  • bNot(true) => bNot(0x01) => 0xFFFFFFFFFFFFFFFE => logic: true

Auch wenn der XOR Operator ^^ im Ergebnis dem != (ungleich) ähnelt, erzwingt der erste für seine Operanden den Datentyp <bool>, wohingegen != oder ==die bestmögliche Darstellung für beide Datentypen sucht und damit bei einer Vermischung unterschiedlicher Datentypen in der Regel den boolschen Operanden in einen numerischen Wert 0 oder 1 (<uint>, <int>, <dbl>) für den Vergleich umwandelt.

FunktionBeschreibung
bNot(x)bit-orientierte Inversion von x (siehe auch Operator ~)
Für ein logisches NOT auf ein <bool> Term ist der Operator ! zu verwenden.
bAnd(x1, ..., xN)bitweise Konjuktion (AND) sämtlicher Ausdrücke x1, ..., xN
bNAnd(x1, ..., xN)bitweise Konjuktion (AND) sämtlicher Ausdrücke x1, ..., xN mit anschließender Inversion
bOr(x1, ..., xN)bitweise Disjuktion (OR) sämtlicher Ausdrücke x1, ..., xN
bNOr(x1, ..., xN)bitweise Disjuktion (OR) sämtlicher Ausdrücke x1, ..., xN mit anschließender Inversion
bXor(x1, ..., xN)exklusive bitweise Disjuktion (OR) sämtlicher Ausdrücke x1, ..., xN
bNXor(x1, ..., xN)exklusive bitweise Disjuktion (OR) sämtlicher Ausdrücke x1, ..., xN mit anschließender Inversion
bShift(x,n)bitweise Verschiebung (SHIFT) von x um n Positionen nach links, bei negativem n nach rechts
bCount(x)Anzahl gesetzter Bits in x
bTest(x,n)Abfrage, ob in x das n-te Bit gesetzt ist, n entspricht der Wertigkeit des Bits 2n,n[0..63]2^n, n \in [0 ..63]
bSet(x,n,v)Setzen (v=true) oder Löschen (v=false) des Bits 2n,n[0..63]2^n, n \in [0 ..63] in x

Logikelemente

Flanken-Erkennung "posedge", "negedge", "onchange"

Für die Elemente der Flankenerkennung kann das Eingangssignal ein beliebiger numerischer, skalarer Wert vom Typ <bool>, <uint>,<int> oder <dbl> sein.

FunktionBeschreibung
posedge(x)liefert für eine Nano-Sekunde true zurück, wenn der aktuelle Wert des Signals y größer ist, als sein vorheriger Wert
negedge(x)liefert für eine Nano-Sekunde true zurück, wenn der aktuelle Wert des Signals y kleiner ist, als sein vorheriger Wert
onchange(x)liefert für eine Nano-Sekunde true zurück, wenn der aktuelle Wert des Signals y sich gegenüber dem vorherigen Wert geändert hat

Flanken Erkennung

hinweis

Durch die extrem kurze Dauer des Signals von nur 1 ns, wird so ein Signal in der Regel von der MQTT Übertragung übersehen. Zur Kontrolle oder Visualisierung eignet sich somit nur die Aufzeichnungen in OSF-Dateien.

RS-Flip-Flop "rsFF"

Mit true am Eingang reset fällt der Ausgang auf false und mit true am Eingang set wird der Ausgang auf true gesetzt. reset hat Priorität.

Die Eingänge reset und set werden als <bool> interpretiert.

Q  = rsFF(reset, set);
// Optionale Konfiguration
Qx = rsFF(..., { storage: <str>
});
EigenschaftWertBeschreibung
storage<str>Name eines persistenten Speichers für den internen Zustand. Damit bekommt nach einem Neustart des Systems der Ausgang den zuletzt gespeichert Wert. Der Inhalt dieses Speichers ist an keiner anderen Stelle im smartCORE nutzbar.
resetsetAusgang
00Letzter Zustand wird gehalten
011
1X0

JK-Flip-Flop "jkFF"

Mit steigender Flanke am clock Eingang entscheiden die Vorbereitungseingänge j und k wie der Ausgang verändert wird (74HC73).

Mit true am Eingang reset fällt der Ausgang auf false und mit true am Eingang set wird der Ausgang auf true gesetzt. reset hat Priorität.

Alle Eingänge werden als <bool> interpretiert.

Q1 = jkFF(clock, j, k);
Q2 = jkFF(clock, j, k, reset);
Q3 = jkFF(clock, j, k, reset, set);
// Optionale Konfiguration für alle Varianten
Qx = jkFF(..., { storage: <str>
});
EigenschaftWertBeschreibung
storage<str>Name eines persistenten Speichers für den internen Zustand. Damit bekommt nach einem Neustart des Systems der Ausgang den zuletzt gespeichert Wert. Der Inhalt dieses Speichers ist an keiner anderen Stelle im smartCORE nutzbar.
clockjkresetsetAusgang
0XX00Letzter Zustand wird gehalten
1XX00Letzter Zustand wird gehalten
0->10000Letzter Zustand wird gehalten
0->101000
0->110001
0->11100Ausgang wechselt den Zustand
XXX1X0
XXX011

D-Flip-Flop "dFF"

Mit steigender Flanke an Eingang clock wird der Wert am Eingang data gespeichert (74HC74).

Mit true am Eingang reset fällt der Ausgang auf false und mit true am Eingang set wird der Ausgang auf true gesetzt. reset hat Priorität.

Dieses Flip-Flop kann alle Datentypen speichern. Bis auf data werden alle Eingänge als <bool> interpretiert.

Q1 = dFF(clock, data);
Q2 = dFF(clock, data, reset);
Q3 = dFF(clock, data, reset, set);
// Optionale Konfiguration für alle Varianten
Qx = dFF(..., { storage: <str>
});
EigenschaftWertBeschreibung
storage<str>Name eines persistenten Speichers für den internen Zustand. Damit bekommt nach einem Neustart des Systems der Ausgang den zuletzt gespeichert Wert. Der Inhalt dieses Speichers ist an keiner anderen Stelle im smartCORE nutzbar.
clockdataresetsetAusgang
0X00Letzter Ausgabewert wird gehalten
1X00Letzter Ausgabewert wird gehalten
0->1<var>00Ausgabe und Speicherung des Wertes an data
XX1XDer Ausgang wird auf <false> gesetzt
XX01Der Ausgang wird auf <true> gesetzt

D-Latch "dLatch"

Mit true an Eingang hold wird der letzte Wert am Eingang data gespeichert, sonst folgt der Ausgang unmittelbar dem Eingang data (74HC75) . Dieses Flip-Flop kann alle Datentypen speichern. Der Eingang hold wird als <bool> interpretiert.

Q = dLatch(hold, data);
// Optionale Konfiguration
Qx = dLatch(..., { storage: <str>
});
EigenschaftWertBeschreibung
storage<str>Name eines persistenten Speichers für den internen Zustand. Damit bekommt nach einem Neustart des Systems der Ausgang den zuletzt gespeichert Wert. Der Inhalt dieses Speichers ist an keiner anderen Stelle im smartCORE nutzbar.
holddataAusgang
0<var>Folgt dem Wert an data
1XLetzter Ausgabewert wird gehalten
info

Wenn sich hold und data gleichzeitig ändern, wird der neue data-Wert bereits nicht mehr verwendet.

Multiplexer "select"

Multiplexer (74HC151), Über den Index i wird ein Signal s0, s1, ... ausgewählt und weiter geleitet. Ist i negativ oder größer oder gleich der Anzahl der Eingänge (n+1), wird false ausgegeben. Die Signale können beliebige Datentypen abbilden, der Ausgang wechselt dementsprechend auch den Datentyp.

y = select(i, s0, s1, ...sn);
is0s1...snAusgang
< 0XX...Xfalse
0<var>X...Xfolgt s0
1X<var>...Xfolgt s1
nXX...<var>folgt sn
> nXX...Xfalse
info

In der Programmiersprache C würde dies der folgenden Anweisung entsprechen:

switch(i)
{
case 0: return s0;
case 1: return s1;
// ...
case n: return sn;
default: return false;
}
tipp

Wenn die einzelnen Signale bereits gruppiert als Vektor vorliegen, kann einfacher die Index-Syntax für Vektoren verwendet werden:

VSig = [s0, s1, ...sn];      // eventually result of calculation or buffering
yi = VSig[i];

Dann sollte allerdings darauf geachtet werden, dass i in einem gültigen Wertebereich [0 .. n] bleibt.

Prioritäts Encoder "prioEnc"

Prioritäts Encoder (ähnlich 74HC147 oder 74HC148), zählend in aufsteigender Reihenfolge wird der Index des ersten aktiven Eingangs ausgegeben. Durch das optionale Konfigurationsobjekt können Varianten in der Funktionalität eingestellt werden. Alle Eingänge werden als <bool> interpretiert.

enc1 = prioEnc(e0, e1, ...);
// Optionale Konfiguration
encX = prioEnc(..., { none: <int>
, active: <bool>
, edge: <bool>
, map: [<int>]
, latch: <bool>
, startup: inf|<bool>
});
EigenschaftWertBeschreibung
none<int>Ist kein Eingang aktiv, wird dieser Wert ausgegeben (def.: -1)
active<bool>Der als aktiv zu erkennende Pegel (mit edge: false) kann hiermit eingestellt werden (def.: true).
edge<bool>Mit true werden nur positive (active: tue) oder negative Flanken (active: false) zur Auslösung verwendet.
map[<int>]Tabelle zur Zuordnung von Ausgabewerten für die Steuereingänge e0, e1, ... z.B.
[1, 10, 100, 1000]
latch<bool>Mit true wird der Index des letzten aktiven Eingangs gehalten (Radio-Button).
startupinf/<bool>Definition eines Referenz-Pegels für die Eingänge bei Software-Start

In der folgenden Tabelle ist ein Eingang aktiv, wenn der durch die Eigenschaften active und edge festgelegte Zustand zutreffend ist. Sonst inaktiv.

e0e1...enAusgang
inaktivinaktiv...inaktivlatch = false: -1 oder Wert der Eigenschaft none
latch = true: der zuletzt aktivierte Wert (Radio-Button)
aktivX...X0 oder der mit map[0] definierte Wert
inaktivaktiv...X1 oder der mit map[1] definierte Wert
inaktivinaktiv...aktivn oder der mit map[n] definierte Wert

Für den Systemstart muss festgelegt werden, wie mit der Vergangenheit der Eingänge umgegangen wird und ob damit beim Start unmittelbar Flanken erkannt werden sollen. Dafür dient die Eigenschaft startup:

  • inf: das erste Signal-Sample bestimmt den Wert in der Vergangenheit vor Systemstart, eine Flanke wird damit nicht mit dem ersten Sample ausgelöst.

  • <bool>: Die Eingänge werden mit diesem Signalwert (true, false) in der Vergangenheit vor Systemstart angenommen. Damit kann möglicherweise eine Flanke mit dem ersten Sample eines Eingangs ausgelöst werden.

Eigenschaft startup

info

In der Programmiersprache C würde dies (ohne edge, latch oder startup) der folgenden Anweisung entsprechen:

if (e0 == active)
return map.size() > 0 ? map[0] : 0;
else if (e1 == active)
return map.size() > 0 ? map[1] : 1;
// ...
else if (en == active)
return map.size() > 0 ? map[n] : n;
else
return none; // by default -1;