Comprendre les Instructions Case Verilog : Implémentation Efficace de Multiplexeurs
L'instruction case vérifie si l'expression donnée correspond à l'une des autres expressions dans la liste et se ramifie en conséquence. Elle est généralement utilisée pour implémenter un multiplexeur. La construction if-else peut ne pas convenir s'il y a de nombreuses conditions à vérifier et se synthétiserait en un encodeur de priorité au lieu d'un multiplexeur.
Syntaxe
Une instruction case Verilog commence avec le mot-clé case et se termine avec le mot-clé endcase. L'expression entre parenthèses sera évaluée exactement une fois et comparée avec la liste des alternatives dans l'ordre où elles sont écrites, et les instructions pour lesquelles l'alternative correspond à l'expression donnée sont exécutées. Un bloc de plusieurs instructions doit être groupé et se trouver entre begin et end.
// Ici 'expression' doit correspondre à l'un des éléments (élément 1,2,3 ou 4)
case (<expression>)
case_item1 : <instruction_simple>
case_item2, case_item3 : <instruction_simple>
case_item4 : begin
<instructions_multiples>
end
default : <instruction>
endcase
Si aucun des éléments case ne correspond à l'expression donnée, les instructions dans l'élément default sont exécutées. L'instruction default est optionnelle, et il ne peut y avoir qu'une seule instruction default dans une instruction case. Les instructions case peuvent être imbriquées.
L'exécution quittera le bloc case sans rien faire si aucun des éléments ne correspond à l'expression et qu'une instruction default n'est pas donnée.
Exemple
Le module de conception montré ci-dessous a un signal de sélection 2 bits pour router l'une des trois autres entrées 3 bits vers le signal de sortie appelé out. Une instruction case est utilisée pour affecter l'entrée correcte à la sortie basée sur la valeur de sel. Puisque sel est un signal 2 bits, il peut avoir 22 combinaisons, 0 à 3. L'instruction default aide à mettre la sortie à 0 si sel est 3.
module my_mux (
input [2:0] a, b, c, // Trois entrées 3 bits
[1:0] sel, // Signal de sélection 2 bits pour choisir parmi a, b, c
output reg [2:0] out // Signal de sortie 3 bits
);
// Ce bloc always est exécuté chaque fois que a, b, c ou sel change de valeur
always @ (a, b, c, sel) begin
case(sel)
2'b00 : out = a; // Si sel=0, sortie est a
2'b01 : out = b; // Si sel=1, sortie est b
2'b10 : out = c; // Si sel=2, sortie est c
default : out = 0; // Si sel est autre chose, out est toujours 0
endcase
end
endmodule
Schéma Matériel
Le code RTL est élaboré pour obtenir un schéma matériel qui représente un multiplexeur 4 vers 1.
On voit que la sortie est zéro quand sel est 3 et correspond aux entrées assignées pour les autres valeurs.
Journal de Simulation
ncsim> run [0] a=0x4 b=0x1 c=0x1 sel=0b11 out=0x0 [10] a=0x5 b=0x5 c=0x5 sel=0b10 out=0x5 [20] a=0x1 b=0x5 c=0x6 sel=0b01 out=0x5 [30] a=0x5 b=0x4 c=0x1 sel=0b10 out=0x1 [40] a=0x5 b=0x2 c=0x5 sel=0b11 out=0x0 ncsim: *W,RNQUIE: Simulation is complete.
Dans une instruction case, la comparaison ne réussit que lorsque chaque bit de l'expression correspond à l'une des alternatives incluant 0, 1, x et z. Dans l'exemple montré ci-dessus, si l'un des bits dans sel est soit x soit z, l'instruction default sera exécutée car aucune des autres alternatives n'a correspondu. Dans un tel cas, la sortie sera tout zéros.
Journal de Simulation
ncsim> run [0] a=0x4 b=0x1 c=0x1 sel=0bxx out=0x0 [10] a=0x3 b=0x5 c=0x5 sel=0bzx out=0x0 [20] a=0x5 b=0x2 c=0x1 sel=0bxx out=0x0 [30] a=0x5 b=0x6 c=0x5 sel=0bzx out=0x0 [40] a=0x5 b=0x4 c=0x1 sel=0bxz out=0x0 [50] a=0x6 b=0x5 c=0x2 sel=0bxz out=0x0 [60] a=0x5 b=0x7 c=0x2 sel=0bzx out=0x0 [70] a=0x7 b=0x2 c=0x6 sel=0bzz out=0x0 [80] a=0x0 b=0x5 c=0x4 sel=0bxx out=0x0 [90] a=0x5 b=0x5 c=0x5 sel=0bxz out=0x0 ncsim: *W,RNQUIE: Simulation is complete.
Si l'instruction case dans la conception a x et z dans les alternatives d'éléments case, les résultats seraient très différents.
module my_mux (
input [2:0] a, b, c,
[1:0] sel,
output reg [2:0] out
);
// Les éléments case ont x et z et sel doit correspondre à la valeur exacte pour
// que la sortie soit assignée avec l'entrée correspondante
always @ (a, b, c, sel) begin
case(sel)
2'bxz : out = a;
2'bzx : out = b;
2'bxx : out = c;
default : out = 0;
endcase
end
endmodule
Journal de Simulation
ncsim> run [0] a=0x4 b=0x1 c=0x1 sel=0bxx out=0x1 [10] a=0x3 b=0x5 c=0x5 sel=0bzx out=0x5 [20] a=0x5 b=0x2 c=0x1 sel=0bxx out=0x1 [30] a=0x5 b=0x6 c=0x5 sel=0bzx out=0x6 [40] a=0x5 b=0x4 c=0x1 sel=0bxz out=0x5 [50] a=0x6 b=0x5 c=0x2 sel=0bxz out=0x6 [60] a=0x5 b=0x7 c=0x2 sel=0bzx out=0x7 [70] a=0x7 b=0x2 c=0x6 sel=0bzz out=0x0 [80] a=0x0 b=0x5 c=0x4 sel=0bxx out=0x4 [90] a=0x5 b=0x5 c=0x5 sel=0bxz out=0x5 ncsim: *W,RNQUIE: Simulation is complete.
En quoi un case diffère-t-il de if-else ?
L'instruction case diffère de if-else-if de deux manières :
- Les expressions données dans un bloc
if-elsesont plus générales alors que dans un bloccase, une seule expression est comparée avec plusieurs éléments casefournira un résultat définitif lorsque il y a des valeurs X et Z dans une expression
Verilog
- Maîtriser l'instruction Switch C# : Syntaxe, exemples et bonnes pratiques
- Instruction Break C# : Comment et quand l'utiliser
- Maîtriser l'instruction Continue C# : Comment ignorer efficacement les itérations de boucle
- Maîtriser le switch-case en C++ : Syntaxe, utilisation et exemples pratiques
- Maîtriser Verilog : Tutoriel complet pour la conception de circuits numériques
- Maîtriser la concaténation Verilog : Guide pratique
- Comprendre les affectations Verilog : Types, Syntaxe et Bonnes Pratiques
- Verilog Blocking vs Non-Blocking : Différences Clés Expliquées
- Maîtriser les Fonctions Verilog pour une Conception RTL Efficace