Concevoir de la logique combinatoire en Verilog avec assign
L'instruction assign Verilog pilote continûment un signal de type wire et se synthétise en logique combinatoire. Voici plus d'exemples de conception avec assign.
Exemple #1 : Logique combinatoire simple
Code implémentant logique combinatoire simple avec sortie z pilotée par assign pour réaliser équation numérique.
module combo (input a, b, c, d, e, output z);
assign z = ((a & b) | (c ^ d) & ~e);
endmodule
Module combo élaboré en schéma matériel suivant :

Testbench
Plateforme de simulation pour vérifier comportement. Toutes combinaisons d'entrées pilotées via boucle for avec 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 scalaires a, b, sorties sum (XOR) et cout (AND).
module ha (input a, b, output sum, cout);
assign sum = a ^ b; assign cout = a & b;
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
Additionneur complet avec assign pour sorties sum et cout.
module fa (input a, b, cin, output sum, cout);
assign sum = (a ^ b) ^ cin;
assign cout = (a & b) | ((a ^ b) & cin);
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 sum=%0b cout=%0b", a, b, cin, sum, cout);
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 sum=0 cout=0 ... a=1 b=1 cin=1 sum=1 cout=1 ncsim: *W,RNQUIE: Simulation is complete.

Exemple #4 : Multiplexeur 2x1
Utilise opérateur ternaire : si sel=1 sortie = a, sinon b.
module mux_2x1 (input a, b, sel, output c);
assign c = sel ? a : b;
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 pilotée par assign séparé (généralement non recommandé de piloter même signal par différents assign).
module demux_1x4 (input f, input [1:0] sel, output a, b, c, d);
assign a = f & ~sel[1] & ~sel[0];
assign b = f & sel[1] & ~sel[0];
assign c = f & ~sel[1] & sel[0];
assign d = f & sel[1] & sel[0];
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 [15:0] out);
assign out = en ? 1 << in: 0;
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
- Circuits intégrés : fondamentaux des portes logiques numériques
- 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