Implémenter la logique combinatoire avec le bloc always de Verilog
Le bloc always Verilog sert pour logique séquentielle et combinatoire. Quelques exemples avec assign vus précédemment. Même ensemble exploré avec always.
Exemple #1 : Logique combinatoire simple
Code implémentant logique combinatoire simple avec sortie z de type reg mise à jour quand signaux liste sensibilité changent. Liste déclarée entre parenthèses après @.
module combo (input a, b, c, d, e, output reg z);
always @ (a or b or c or d or e) begin
z = ((a & b) | (c ^ d) & ~e);
end
endmodule
Module combo élaboré en schéma matériel :

Utilisez affectations bloquantes (=) pour modéliser logique combinatoire avec bloc always
Testbench
Plateforme simulation pour vérifier comportement. Toutes combinaisons entrées pilotées via boucle for délai 10 unités.
module tb; reg a, b, c, d, e; wire z; integer i;
combo u0 (.a(a), .b(b), .c(c), .d(d), .e(e), .z(z));
initial begin a <= 0; b <= 0; c <= 0; d <= 0; e <= 0;
$monitor ("a=%0b b=%0b c=%0b d=%0b e=%0b z=%0b", a, b, c, d, e, z);
for (i = 0; i < 32; i = i + 1) begin {a, b, c, d, e} = i; #10; end end
endmodule
Simulation Log :
ncsim> run a=0 b=0 c=0 d=0 e=0 z=0 ... a=1 b=1 c=1 d=1 e=1 z=1 ncsim: *W,RNQUIE: Simulation is complete.

Les deux méthodes assign et always donnent même logique matérielle.
Exemple #2 : Demi-additionneur
Module ha : 2 entrées a, b, sorties sum (XOR) et cout (AND).
module ha (input a, b, output sum, cout);
always @ (a or b) begin {cout, sum} = a + b; end
endmodule

Testbench
module tb; reg a, b; wire sum, cout; integer i;
ha u0 (.a(a), .b(b), .sum(sum), .cout(cout));
initial begin a <= 0; b <= 0; $monitor("a=%0b b=%0b sum=%0b cout=%0b", a, b, sum, cout);
for (i = 0; i < 4; i = i + 1) begin {a, b} = i; #10; end end
endmodule
Simulation Log :
ncsim> run a=0 b=0 sum=0 cout=0 a=0 b=1 sum=1 cout=0 a=1 b=0 sum=1 cout=0 a=1 b=1 sum=0 cout=1 ncsim: *W,RNQUIE: Simulation is complete.

Exemple #3 : Additionneur complet
Bloc always pour additionneur complet pilotant sum et cout.
module fa (input a, b, cin, output reg sum, cout);
always @ (a or b or cin) begin {cout, sum} = a + b + cin; end
endmodule

Testbench
module tb; reg a, b, cin; wire sum, cout; integer i;
fa u0 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));
initial begin a <= 0; b <= 0; $monitor("a=%0b b=%0b cin=%0b cout=%0b sum=%0b", a, b, cin, cout, sum);
for (i = 0; i < 8; i = i + 1) begin {a, b, cin} = i; #10; end end
endmodule
Simulation Log :
ncsim> run a=0 b=0 cin=0 cout=0 sum=0 ... a=1 b=1 cin=1 cout=1 sum=1 ncsim: *W,RNQUIE: Simulation is complete.

Exemple #4 : Multiplexeur 2x1
Opérateur ternaire : si sel=1 sortie = a, sinon b.
module mux_2x1 (input a, b, sel, output reg c);
always @ (a or b or sel) begin c = sel ? a : b; end
endmodule

Testbench
module tb; reg a, b, sel; wire c; integer i;
mux_2x1 u0 (.a(a), .b(b), .sel(sel), .c(c));
initial begin a <= 0; b <= 0; sel <= 0; $monitor("a=%0b b=%0b sel=%0b c=%0b", a, b, sel, c);
for (i = 0; i < 3; i = i + 1) begin {a, b, sel} = i; #10; end end
endmodule
Simulation Log :
ncsim> run a=0 b=0 sel=0 c=0 a=0 b=0 sel=1 c=0 a=0 b=1 sel=0 c=1 ncsim: *W,RNQUIE: Simulation is complete.

Exemple #5 : Démultiplexeur 1x4
Combinaison sel et f pour piloter sorties. Chaque sortie type reg dans bloc always mis à jour selon signaux liste sensibilité.
module demux_1x4 (input f, input [1:0] sel, output reg a, b, c, d);
always @ (f or sel) begin
a = f & ~sel[1] & ~sel[0];
b = f & sel[1] & ~sel[0];
c = f & ~sel[1] & sel[0];
d = f & sel[1] & sel[0];
end
endmodule

Testbench
module tb; reg f; reg [1:0] sel; wire a, b, c, d; integer i;
demux_1x4 u0 (.f(f), .sel(sel), .a(a), .b(b), .c(c), .d(d));
initial begin f <= 0; sel <= 0; $monitor("f=%0b sel=%0b a=%0b b=%0b c=%0b d=%0b", f, sel, a, b, c, d);
for (i = 0; i < 8; i = i + 1) begin {f, sel} = i; #10; end end
endmodule
Simulation Log :
ncsim> run f=0 sel=0 a=0 b=0 c=0 d=0 ... f=1 sel=11 a=0 b=0 c=0 d=1 ncsim: *W,RNQUIE: Simulation is complete.

Exemple #6 : Décodeur 4x16
module dec_3x8 (input en, input [3:0] in, output reg [15:0] out);
always @ (en or in) begin out = en ? 1 << in: 0; end
endmodule

Testbench
module tb; reg en; reg [3:0] in; wire [15:0] out; integer i;
dec_3x8 u0 (.en(en), .in(in), .out(out));
initial begin en <= 0; in <= 0; $monitor("en=%0b in=0x%0h out=0x%0h", en, in, out);
for (i = 0; i < 32; i = i + 1) begin {en, in} = i; #10; end end
endmodule
Simulation Log :
ncsim> run en=0 in=0x0 out=0x0 ... en=1 in=0xf out=0x8000 ncsim: *W,RNQUIE: Simulation is complete.

Verilog
- Maîtriser VHDL et Verilog : écrire une logique combinatoire et séquentielle propre
- Circuit avec interrupteur : guide pratique des circuits électriques de base
- Comprendre l'algèbre de Boole : des fondements logiques aux circuits numériques
- Maîtriser multiplication et division en notation scientifique
- Industrie 4.0 : Questions-réponses avec Verena Majuntke de Bosch.IO sur l'IoT, l'automatisation et l'usine du futur
- Surveillance précise de la température dans un placard serveur avec Raspberry Pi
- Conception Pratique Verilog Niveau Portes : Portes ET, OU, NON & Multiplexeur 2x1
- Maîtriser Verilog $timeformat : Contrôle de Précision et d'Affichage
- Obtenir des finitions parfaites avec les machines de rectification de précision Okamoto