Aller au contenu principal

Fonctions logiques

Opérations booléennes​

Les variables ou signaux booléens ne peuvent prendre que 2 états, qui peuvent être désignés par différents mnémoniques selon le contexte

01
falsetrue
noyes
offon
lowhigh

Dans la suite, le symbole X est en outre utilisé pour « don't care » (indifférent), c'est-à-dire que la valeur n'a aucune influence sur le résultat. Les fronts sont indiqués par la notation correspondante 0->1 ou 1->0.

À titre de comparaison, le lien avec les circuits intégrés logiques classiques de la série 74 est indiqué à de nombreux endroits (par ex. 74HC147). Pour les composants complexes, la fonction implémentée dans le module Math offre le plus souvent encore plus d'options que le modèle cité.

La fonction logique élémentaire la plus simple est l'élément inverseur « NOT » :

NOT A
A(74HC04)
01
10

Lorsque deux variables ou signaux booléens sont combinés, 2 fonctions logiques élémentaires AND et OR sont utilisées :

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

L'élément XOR (OR exclusif) peut être réalisé par une combinaison complexe de AND, OR et NOT ; il est présenté ici comme élément à part afin de faciliter l'illustration de la fonction dans la suite.

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

En combinant avec un étage NOT, on obtient respectivement

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

Selon les types de données, les opérateurs et fonctions logiques suivants sont utilisés, les 64 bits du type numérique <uint> (unsigned integer) étant soumis individuellement aux fonctions logiques :

<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)

Fonctions orientées bit​

attention

Ces fonctions de bits ne sont pas des opérateurs logiques ! Elles travaillent toujours sur la représentation interne en <uint> et convertissent donc d'abord tous les paramètres en type <uint>. Cela apparaît clairement, par exemple, avec la fonction bNot(), qui inverse tous les bits de la valeur d'entrée.

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

Même si le résultat de l'opérateur XOR ^^ ressemble à celui de != (différent), le premier impose le type de données <bool> à ses opérandes, alors que != ou == recherchent la meilleure représentation commune aux deux types de données et, en cas de mélange de types différents, convertissent généralement l'opérande booléen en une valeur numérique 0 ou 1 (<uint>, <int>, <dbl>) pour la comparaison.

FonctionDescription
bNot(x)inversion orientée bit de x (voir aussi l'opérateur ~)
Pour un NOT logique sur un terme <bool>, utiliser l'opérateur !.
bAnd(x1, ..., xN)conjonction bit à bit (AND) de toutes les expressions x1, ..., xN
bNAnd(x1, ..., xN)conjonction bit à bit (AND) de toutes les expressions x1, ..., xN, suivie d'une inversion
bOr(x1, ..., xN)disjonction bit à bit (OR) de toutes les expressions x1, ..., xN
bNOr(x1, ..., xN)disjonction bit à bit (OR) de toutes les expressions x1, ..., xN, suivie d'une inversion
bXor(x1, ..., xN)disjonction exclusive bit à bit (OR) de toutes les expressions x1, ..., xN
bNXor(x1, ..., xN)disjonction exclusive bit à bit (OR) de toutes les expressions x1, ..., xN, suivie d'une inversion
bShift(x,n)décalage bit à bit (SHIFT) de x de n positions vers la gauche, vers la droite si n est négatif
bCount(x)nombre de bits positionnés dans x
bTest(x,n)test visant à déterminer si le n-ième bit de x est positionné, n correspond au poids du bit 2n,n∈[0..63]2^n, n \in [0 ..63]
bSet(x,n,v)positionnement (v=true) ou effacement (v=false) du bit 2n,n∈[0..63]2^n, n \in [0 ..63] dans x

Éléments logiques​

Détection de fronts « posedge », « negedge », « onchange »​

Pour les éléments de détection de fronts, le signal d'entrée peut être n'importe quelle valeur numérique scalaire de type <bool>, <uint>, <int> ou <dbl>.

FonctionDescription
posedge(x)renvoie true pendant une nanoseconde lorsque la valeur actuelle du signal y est supérieure à sa valeur précédente
negedge(x)renvoie true pendant une nanoseconde lorsque la valeur actuelle du signal y est inférieure à sa valeur précédente
onchange(x)renvoie true pendant une nanoseconde lorsque la valeur actuelle du signal y a changé par rapport à la valeur précédente

Détection de fronts

remarque

En raison de la durée extrêmement courte du signal, de 1 ns seulement, un tel signal est en général manqué par la transmission MQTT. Seuls les enregistrements dans des fichiers OSF conviennent donc pour le contrôle ou la visualisation.

Bascule RS « rsFF »​

Avec true sur l'entrée reset, la sortie passe à false ; avec true sur l'entrée set, la sortie est mise à true. reset est prioritaire.

Les entrées reset et set sont interprétées comme <bool>.

Q = rsFF(reset, set);
// Optionale Konfiguration
Qx = rsFF(..., { storage: <str>
});
PropriétéValeurDescription
storage<str>Nom d'une mémoire persistante pour l'état interne. Après un redémarrage du système, la sortie reprend ainsi la dernière valeur enregistrée. Le contenu de cette mémoire n'est utilisable à aucun autre endroit dans smartCORE.
resetsetSortie
00Le dernier état est conservé
011
1X0

Bascule JK « jkFF »​

Sur front montant de l'entrée clock, les entrées de préparation j et k déterminent comment la sortie est modifiée (74HC73).

Avec true sur l'entrée reset, la sortie passe à false ; avec true sur l'entrée set, la sortie est mise à true. reset est prioritaire.

Toutes les entrées sont interprétées comme <bool>.

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>
});
PropriétéValeurDescription
storage<str>Nom d'une mémoire persistante pour l'état interne. Après un redémarrage du système, la sortie reprend ainsi la dernière valeur enregistrée. Le contenu de cette mémoire n'est utilisable à aucun autre endroit dans smartCORE.
clockjkresetsetSortie
0XX00Le dernier état est conservé
1XX00Le dernier état est conservé
0->10000Le dernier état est conservé
0->101000
0->110001
0->11100La sortie change d'état
XXX1X0
XXX011

Bascule D « dFF »​

Sur front montant de l'entrée clock, la valeur présente sur l'entrée data est mémorisée (74HC74).

Avec true sur l'entrée reset, la sortie passe à false ; avec true sur l'entrée set, la sortie est mise à true. reset est prioritaire.

Cette bascule peut mémoriser tous les types de données. À l'exception de data, toutes les entrées sont interprétées comme <bool>.

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>
});
PropriétéValeurDescription
storage<str>Nom d'une mémoire persistante pour l'état interne. Après un redémarrage du système, la sortie reprend ainsi la dernière valeur enregistrée. Le contenu de cette mémoire n'est utilisable à aucun autre endroit dans smartCORE.
clockdataresetsetSortie
0X00La dernière valeur de sortie est conservée
1X00La dernière valeur de sortie est conservée
0->1<var>00Sortie et mémorisation de la valeur présente sur data
XX1XLa sortie est mise à <false>
XX01La sortie est mise à <true>

Verrou D « dLatch »​

Avec true sur l'entrée hold, la dernière valeur de l'entrée data est mémorisée ; sinon, la sortie suit directement l'entrée data (74HC75). Cette bascule peut mémoriser tous les types de données. L'entrée hold est interprétée comme <bool>.

Q = dLatch(hold, data);
// Optionale Konfiguration
Qx = dLatch(..., { storage: <str>
});
PropriétéValeurDescription
storage<str>Nom d'une mémoire persistante pour l'état interne. Après un redémarrage du système, la sortie reprend ainsi la dernière valeur enregistrée. Le contenu de cette mémoire n'est utilisable à aucun autre endroit dans smartCORE.
holddataSortie
0<var>Suit la valeur présente sur data
1XLa dernière valeur de sortie est conservée
info

Si hold et data changent simultanément, la nouvelle valeur de data n'est déjà plus prise en compte.

Mémoire indexée « memory » 1​

La fonction memory est un dLatch() ou un dFF() adressable, doté de fonctionnalités étendues. La valeur de retour est le vecteur de données mémorisé. Le type de données est défini par le paramètre preset.

MEM1 = memory(control, index, data, {...});
MEM2 = memory(control, index, data, reset, {...});
// mandatory configuration
MEMx = memory(..., { mode: <enum> // mandatory
, size: <uint> // mandatory
                   , preset: <var> // recommended
, weight: <dbl>
, storage: <str>
});
PropriétéValeurDescription
mode<enum>latch : avec true sur l'entrée control, la dernière valeur de l'entrée data est mémorisée dans l'élément index ; sinon, l'élément suit directement l'entrée data (comme dLatch())
set : mem[index] = data, sur front montant de l'entrée control, la valeur de l'entrée data est mémorisée dans l'élément index (comme dFF())
add : mem[index] += data, sur front montant de l'entrée control, la valeur de l'entrée data est ajoutée à l'élément index :
mult : mem[index] *= data, sur front montant de l'entrée control, la valeur de l'entrée data est multipliée par l'élément index
weight : mem[index] = (1-weight)*mem[index] + weight*data, sur front montant de l'entrée control, la valeur de l'entrée data est multipliée par ce facteur de pondération et ajoutée à l'élément index pondéré inversement.
sizeNombre d'emplacements mémoire réservés (indexés à partir de 0 jusqu'à size-1) et taille du vecteur de sortie.
presetInitialisation de la mémoire (avec reset = true) et définition du type de données, par ex. 0.0 pour <dbl> ou 0 pour <int>.
weightFacteur de pondération pour le mode weight, plage de valeurs valide [0..1.0][0 .. 1.0]
storage<str>Nom d'une mémoire persistante pour le vecteur de données. Après un redémarrage du système, la sortie reprend ainsi la dernière valeur enregistrée. Le contenu de cette mémoire n'est utilisable à aucun autre endroit dans smartCORE.
astuce

Un élément du vecteur « mémoire » peut être lu avec la syntaxe d'indexation [...] ou la fonction GetCol(), y compris à différents endroits du texte de la formule :

e1 = MEMx[rdIndex];
e2 = GetCol(MEMx, rdIndex);
astuce

Un cas d'usage fréquent de la fonction memory() est, par exemple, la mémorisation de relevés de compteurs d'énergie. Dans ce cas, on obtiendrait en mode latch l'index à partir de la fonction decodeTime(), par ex. comme jour de la semaine, et l'on injecterait comme data le relevé cumulé du compteur d'énergie. L'entrée control est maintenue constamment à false afin de suivre les valeurs du compteur d'énergie.

Une seconde mémoire conserve de manière analogue les valeurs de la veille, de sorte que la consommation journalière résulte de la différence entre les vecteurs.

Une implémentation se trouve dans l'exemple 1c).

Multiplexeur « select »​

Multiplexeur (74HC151). L'index i sélectionne un signal s0, s1, ... qui est ensuite transmis. Si i est négatif ou supérieur ou égal au nombre d'entrées (n+1), false est émis. Les signaux peuvent représenter n'importe quel type de données ; la sortie change donc également de type de données en conséquence.

y = select(i, s0, s1, ...sn);
is0s1...snSortie
< 0XX...Xfalse
0<var>X...Xsuit s0
1X<var>...Xsuit s1
nXX...<var>suit sn
> nXX...Xfalse
info

En langage C, cela correspondrait à l'instruction suivante :

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

Si les différents signaux sont déjà regroupés sous forme de vecteur, il est plus simple d'utiliser la syntaxe d'indexation pour les vecteurs :

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

Il convient alors toutefois de veiller à ce que i reste dans une plage de valeurs valide [0 .. n].

Encodeur de priorité « prioEnc »​

Encodeur de priorité (similaire au 74HC147 ou 74HC148). En comptant par ordre croissant, l'index de la première entrée active est émis. L'objet de configuration facultatif permet de régler des variantes de fonctionnement. Toutes les entrées sont interprétées comme <bool>.

enc1 = prioEnc(e0, e1, ...);
// Optionale Konfiguration
encX = prioEnc(..., { none: <int>
, active: <bool>
, edge: <bool>
, map: [<int>]
, latch: <bool>
, startup: inf|<bool>
});
PropriétéValeurDescription
none<int>Si aucune entrée n'est active, cette valeur est émise (déf. : -1)
active<bool>Permet de régler le niveau à reconnaître comme actif (avec edge : false) (déf. : true).
edge<bool>Avec true, seuls les fronts positifs (active : true) ou négatifs (active : false) sont utilisés pour le déclenchement.
map[<int>]Table d'affectation des valeurs de sortie aux entrées de commande e0, e1, ... par ex.
[1, 10, 100, 1000]
latch<bool>Avec true, l'index de la dernière entrée active est conservé (bouton radio).
startupinf/<bool>Définition d'un niveau de référence pour les entrées au démarrage du logiciel

Dans le tableau suivant, une entrée est active lorsque l'état défini par les propriétés active et edge est vérifié. Sinon, elle est inactive.

e0e1...enSortie
inactiveinactive...inactivelatch = false : -1 ou valeur de la propriété none
latch = true : la dernière valeur activée (bouton radio)
activeX...X0 ou la valeur définie avec map[0]
inactiveactive...X1 ou la valeur définie avec map[1]
inactiveinactive...activen ou la valeur définie avec map[n]

Pour le démarrage du système, il faut définir comment traiter le passé des entrées et si des fronts doivent ainsi être détectés immédiatement au démarrage. La propriété startup sert à cela :

  • inf : le premier échantillon du signal détermine la valeur dans le passé avant le démarrage du système ; aucun front n'est donc déclenché avec le premier échantillon.

  • <bool> : les entrées sont supposées avoir cette valeur de signal (true, false) dans le passé avant le démarrage du système. Un front peut ainsi éventuellement être déclenché avec le premier échantillon d'une entrée.

Propriété startup

info

En langage C, cela correspondrait (sans edge, latch ni startup) à l'instruction suivante :

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;

Footnotes​

  1. Disponible à partir de la version 13 du catalogue. ↩