Menu

Opérateurs bitwise et de réduction en Verilog

Les opérateurs au niveau bit en Verilog - AND/OR/XOR bitwise, les formes d'inversion, et les opérateurs de réduction qui collapsent un vecteur entier à un seul bit.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Deux rôles pour le même symbole

&, |, ^, et leurs frères inversés apparaissent sous deux formes distinctes :

  • Forme binaire (deux opérandes) : a & b - opération bitwise entre vecteurs de même largeur.
  • Forme unaire (un opérande) : &a - réduction à travers tous les bits de a vers un seul bit.

Le compilateur les distingue en comptant les opérandes. La convention de nommage utilisée par les gens est « les opérateurs bitwise » pour la forme binaire et « les opérateurs de réduction » pour la forme unaire.

Bitwise : un bit à la fois

L'ensemble complet :

OpérateurNomBit de sortie en position N
a & bANDa[N] AND b[N]
a | bORa[N] OR b[N]
a ^ bXORa[N] XOR b[N]
a ~& bNANDNOT (a[N] AND b[N])
a ~| bNORNOT (a[N] OR b[N])
a ~^ bXNORNOT (a[N] XOR b[N])
~aNOTNOT a[N]

Note que ~&, ~|, ~^ s'écrivent avec le tilde en premier et l'opérateur en second. Ce sont des tokens uniques ; pas d'espace entre.

Quand les deux opérandes ont des largeurs différentes, la plus étroite est zero-étendue à gauche pour correspondre. Si tu veux une extension de signe, utilise des opérandes signés explicitement avec $signed().

Réduction : de plusieurs bits à un seul

Les formes unaires des mêmes opérateurs collapsent un vecteur à un seul bit :

Ce que chacun veut dire :

  • &data retourne 1 si tous les bits de data sont 1, sinon 0. Utile pour les checks « est-ce que c'est all-ones ? ».
  • |data retourne 1 si un bit quelconque de data est 1, sinon 0. Utile pour les checks « est-ce que c'est non-zéro ? ».
  • ^data retourne la parité - XOR de tous les bits. 1 si nombre impair de 1, 0 si pair.
  • ~&data, ~|data, ~^data sont les inverses des précédents.

Tu les verras partout dans le vrai code :

wire empty       = ~|fifo_count;       // vide si et seulement si count est zéro
wire all_ones    = &mask;              // tous bits mis
wire parity_bit  = ^data;              // parité d'un octet
wire any_request = |request_vector;    // y a-t-il une requête ?

Les formes réduction sont concises et se synthétisent en arbres de portes évidents : & se réduit à un AND multi-entrées, | à un OR multi-entrées, ^ à un arbre XOR (qui est aussi le générateur de parité en matériel).

Motifs courants

Mettre et effacer des bits

wire [7:0] data;
wire [7:0] mask = 8'b0000_1000;

wire [7:0] set     = data | mask;     // force le bit 3 à 1
wire [7:0] cleared = data & ~mask;    // force le bit 3 à 0
wire [7:0] toggled = data ^ mask;     // bascule le bit 3
wire [7:0] tested  = data & mask;     // zéro si bit 3 était 0, non-zéro sinon

Ce sont les mêmes idiomes de manipulation de bits que tu utiliserais en C. Ils se synthétisent en opérations de porte unique.

Vérifier si une valeur égale all-ones

wire is_max = &counter;       // 1 si chaque bit de counter est 1

Une réduction AND avec une porte, vs écrire counter == 8'hFF (qui marcherait aussi ; les synthétiseurs produisent généralement le même matériel).

Générer un bit de parité

Détecter un signal actif

wire any_pending = |request_vector;

Si request_vector est large (disons 64 requérants), la réduction OR collapse à un seul signal que tu peux alimenter dans un encodeur de priorité ou un arbitre.

Opérateurs de shift

Pendant qu'on est sur les opérateurs au niveau bit, les shifts :

  • a << N décale a à gauche de N positions de bits, remplit avec des zéros à droite.
  • a >> N décale a à droite de N positions de bits, remplit avec des zéros à gauche.
  • a <<< N shift arithmétique gauche (identique à << pour le non signé).
  • a >>> N shift arithmétique droit - remplit avec le bit de signe quand a est signé.

Les shifts par une puissance constante sont gratuits en matériel (juste du recâblage). Les shifts par une variable runtime produisent un barrel shifter, plus gros mais encore peu coûteux.

La suite

Tu as maintenant vu chaque opérateur qui retourne une valeur unique. Le prochain document - Concaténation et réplication - couvre la syntaxe {} et {N{...}} qui construit des vecteurs plus larges à partir de morceaux, que tu utiliseras constamment en interfaçant des modules de largeurs différentes.

Questions fréquentes

Que sont les opérateurs bitwise en Verilog ?

Les opérateurs bitwise combinent deux vecteurs de même largeur position par position. a & b fait le AND du bit 0 de a avec le bit 0 de b, du bit 1 avec le bit 1, etc., produisant un vecteur de même largeur que les entrées. L'ensemble complet est & (AND), | (OR), ^ (XOR), ~ (NOT), et les formes inverses ~&, ~|, ~^ (NAND, NOR, XNOR).

Qu'est-ce qu'un opérateur de réduction en Verilog ?

Un opérateur de réduction est une forme unaire d'un opérateur bitwise qui collapse un vecteur entier à un seul bit. &data retourne 1 seulement si chaque bit de data est 1. |data retourne 1 si un bit quelconque est 1. ^data retourne le XOR de tous les bits - la parité. Les formes réduction n'ont pas d'opérande à gauche, seulement à droite.

Quelle est la différence entre & et && en Verilog ?

& est le AND bitwise - il apparie les bits position par position et le résultat a la même largeur que les opérandes. && est le AND logique - il traite chaque opérande comme un booléen (zéro vs non-zéro) et retourne un résultat 1 bit. 4'b1100 & 4'b0011 est 4'b0000 ; 4'b1100 && 4'b0011 est 1.

Comment calculer la parité en Verilog ?

Utilise l'opérateur de réduction XOR : parity = ^data. Il fait le XOR de chaque bit de data. Pour un vecteur 8 bits c'est data[7] ^ data[6] ^ ... ^ data[0]. Le résultat est 1 si un nombre impair de bits est mis, 0 si pair. Inverser avec ~^ donne la parité paire.

Que fait ~ en Verilog ?

~ est le NOT bitwise - il inverse chaque bit de son opérande. ~4'b1100 est 4'b0011. Ne le confonds pas avec ! (NOT logique), qui collapse l'opérande à un booléen 1 bit et inverse ça. !4'b1100 est 1'b0 (l'opérande est non-zéro, NOT de la valeur de vérité donne 0).

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER