Logique combinatoire avec toujours
Le bloc verilog always peut être utilisé à la fois pour la logique séquentielle et combinatoire. Quelques exemples de conception ont été montrés en utilisant un assign
déclaration dans un article précédent. Le même ensemble de conceptions sera ensuite exploré à l'aide d'un always
bloquer.
Exemple #1 :Logique combinatoire simple
Le code ci-dessous implémente une simple logique combinatoire numérique qui a un signal de sortie appelé z de type reg
qui est mis à jour chaque fois que l'un des signaux de la liste de sensibilité change de valeur. La liste de sensibilité est déclarée entre parenthèses après le @
opérateur.
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
Le module combo est élaboré dans le schéma matériel suivant à l'aide d'outils de synthèse et on peut voir que la logique combinatoire est implémentée avec des portes numériques.
Utilisez des affectations de blocage lors de la modélisation d'une logique combinatoire avec un bloc toujours
Banc de test
Le banc d'essai est une plate-forme pour simuler la conception afin de s'assurer que la conception se comporte comme prévu. Toutes les combinaisons d'entrées sont dirigées vers le module de conception à l'aide d'un for
boucle avec une instruction de retard de 10 unités de temps afin que la nouvelle valeur soit appliquée aux entrées après un certain temps.
module tb;
// Declare testbench variables
reg a, b, c, d, e;
wire z;
integer i;
// Instantiate the design and connect design inputs/outputs with
// testbench variables
combo u0 ( .a(a), .b(b), .c(c), .d(d), .e(e), .z(z));
initial begin
// At the beginning of time, initialize all inputs of the design
// to a known value, in this case we have chosen it to be 0.
a <= 0;
b <= 0;
c <= 0;
d <= 0;
e <= 0;
// Use a $monitor task to print any change in the signal to
// simulation console
$monitor ("a=%0b b=%0b c=%0b d=%0b e=%0b z=%0b",
a, b, c, d, e, z);
// Because there are 5 inputs, there can be 32 different input combinations
// So use an iterator "i" to increment from 0 to 32 and assign the value
// to testbench variables so that it drives the design inputs
for (i = 0; i < 32; i = i + 1) begin
{a, b, c, d, e} = i;
#10;
end
end
endmodule
Journal de simulation ncsim> run a=0 b=0 c=0 d=0 e=0 z=0 a=0 b=0 c=0 d=0 e=1 z=0 a=0 b=0 c=0 d=1 e=0 z=1 a=0 b=0 c=0 d=1 e=1 z=0 a=0 b=0 c=1 d=0 e=0 z=1 a=0 b=0 c=1 d=0 e=1 z=0 a=0 b=0 c=1 d=1 e=0 z=0 a=0 b=0 c=1 d=1 e=1 z=0 a=0 b=1 c=0 d=0 e=0 z=0 a=0 b=1 c=0 d=0 e=1 z=0 a=0 b=1 c=0 d=1 e=0 z=1 a=0 b=1 c=0 d=1 e=1 z=0 a=0 b=1 c=1 d=0 e=0 z=1 a=0 b=1 c=1 d=0 e=1 z=0 a=0 b=1 c=1 d=1 e=0 z=0 a=0 b=1 c=1 d=1 e=1 z=0 a=1 b=0 c=0 d=0 e=0 z=0 a=1 b=0 c=0 d=0 e=1 z=0 a=1 b=0 c=0 d=1 e=0 z=1 a=1 b=0 c=0 d=1 e=1 z=0 a=1 b=0 c=1 d=0 e=0 z=1 a=1 b=0 c=1 d=0 e=1 z=0 a=1 b=0 c=1 d=1 e=0 z=0 a=1 b=0 c=1 d=1 e=1 z=0 a=1 b=1 c=0 d=0 e=0 z=1 a=1 b=1 c=0 d=0 e=1 z=1 a=1 b=1 c=0 d=1 e=0 z=1 a=1 b=1 c=0 d=1 e=1 z=1 a=1 b=1 c=1 d=0 e=0 z=1 a=1 b=1 c=1 d=0 e=1 z=1 a=1 b=1 c=1 d=1 e=0 z=1 a=1 b=1 c=1 d=1 e=1 z=1 ncsim: *W,RNQUIE: Simulation is complete.
Notez que les deux méthodes, assign
et always
, sont implémentés dans la même logique matérielle.
Exemple n° 2 :demi-additionneur
Le demi-module additionneur accepte deux entrées scalaires a et b et utilise une logique combinatoire pour affecter la somme des signaux de sortie et le bit de retenue cout. La somme est pilotée par un OU exclusif entre a et b tandis que le bit de retenue est obtenu par un ET entre les deux entrées.
module ha ( input a, b,
output sum, cout);
always @ (a or b) begin
{cout, sum} = a + b;
end
endmodule
Banc de test
module tb;
// Declare testbench variables
reg a, b;
wire sum, cout;
integer i;
// Instantiate the design and connect design inputs/outputs with
// testbench variables
ha u0 ( .a(a), .b(b), .sum(sum), .cout(cout));
initial begin
// At the beginning of time, initialize all inputs of the design
// to a known value, in this case we have chosen it to be 0.
a <= 0;
b <= 0;
// Use a $monitor task to print any change in the signal to
// simulation console
$monitor("a=%0b b=%0b sum=%0b cout=%0b", a, b, sum, cout);
// Because there are only 2 inputs, there can be 4 different input combinations
// So use an iterator "i" to increment from 0 to 4 and assign the value
// to testbench variables so that it drives the design inputs
for (i = 0; i < 4; i = i + 1) begin
{a, b} = i;
#10;
end
end
endmodule
Journal de simulation 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
Un bloc toujours peut être utilisé pour décrire le comportement d'un additionneur complet pour piloter la somme et le cout des sorties.
module fa ( input a, b, cin,
output reg sum, cout);
always @ (a or b or cin) begin
{cout, sum} = a + b + cin;
end
endmodule
Banc de test
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
Journal de simulation ncsim> run a=0 b=0 cin=0 cout=0 sum=0 a=0 b=0 cin=1 cout=0 sum=1 a=0 b=1 cin=0 cout=0 sum=1 a=0 b=1 cin=1 cout=1 sum=0 a=1 b=0 cin=0 cout=0 sum=1 a=1 b=0 cin=1 cout=1 sum=0 a=1 b=1 cin=0 cout=1 sum=0 a=1 b=1 cin=1 cout=1 sum=1 ncsim: *W,RNQUIE: Simulation is complete.
Exemple n° 4 :multiplexeur 2x1
Le multiplexeur 2x1 simple utilise un opérateur ternaire pour décider quelle entrée doit être affectée à la sortie c. Si sel vaut 1, la sortie est pilotée par a et si sel vaut 0, la sortie est pilotée par b.
module mux_2x1 (input a, b, sel,
output reg c);
always @ ( a or b or sel) begin
c = sel ? a : b;
end
endmodule
Banc de test
module tb;
// Declare testbench variables
reg a, b, sel;
wire c;
integer i;
// Instantiate the design and connect design inputs/outputs with
// testbench variables
mux_2x1 u0 ( .a(a), .b(b), .sel(sel), .c(c));
initial begin
// At the beginning of time, initialize all inputs of the design
// to a known value, in this case we have chosen it to be 0.
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
Journal de simulation 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
Le démultiplexeur utilise une combinaison d'entrées sel et f pour piloter les différents signaux de sortie. Chaque signal de sortie est de type reg
et utilisé dans un always
bloc qui est mis à jour en fonction des modifications des signaux répertoriés dans la liste de 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
Banc de test
module tb;
// Declare testbench variables
reg f;
reg [1:0] sel;
wire a, b, c, d;
integer i;
// Instantiate the design and connect design inputs/outputs with
// testbench variables
demux_1x4 u0 ( .f(f), .sel(sel), .a(a), .b(b), .c(c), .d(d));
// At the beginning of time, initialize all inputs of the design
// to a known value, in this case we have chosen it to be 0.
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);
// Because there are 3 inputs, there can be 8 different input combinations
// So use an iterator "i" to increment from 0 to 8 and assign the value
// to testbench variables so that it drives the design inputs
for (i = 0; i < 8; i = i + 1) begin
{f, sel} = i;
#10;
end
end
endmodule
Journal de simulation ncsim> run f=0 sel=0 a=0 b=0 c=0 d=0 f=0 sel=1 a=0 b=0 c=0 d=0 f=0 sel=10 a=0 b=0 c=0 d=0 f=0 sel=11 a=0 b=0 c=0 d=0 f=1 sel=0 a=1 b=0 c=0 d=0 f=1 sel=1 a=0 b=0 c=1 d=0 f=1 sel=10 a=0 b=1 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
Banc de test
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
Journal de simulation ncsim> run en=0 in=0x0 out=0x0 en=0 in=0x1 out=0x0 en=0 in=0x2 out=0x0 en=0 in=0x3 out=0x0 en=0 in=0x4 out=0x0 en=0 in=0x5 out=0x0 en=0 in=0x6 out=0x0 en=0 in=0x7 out=0x0 en=0 in=0x8 out=0x0 en=0 in=0x9 out=0x0 en=0 in=0xa out=0x0 en=0 in=0xb out=0x0 en=0 in=0xc out=0x0 en=0 in=0xd out=0x0 en=0 in=0xe out=0x0 en=0 in=0xf out=0x0 en=1 in=0x0 out=0x1 en=1 in=0x1 out=0x2 en=1 in=0x2 out=0x4 en=1 in=0x3 out=0x8 en=1 in=0x4 out=0x10 en=1 in=0x5 out=0x20 en=1 in=0x6 out=0x40 en=1 in=0x7 out=0x80 en=1 in=0x8 out=0x100 en=1 in=0x9 out=0x200 en=1 in=0xa out=0x400 en=1 in=0xb out=0x800 en=1 in=0xc out=0x1000 en=1 in=0xd out=0x2000 en=1 in=0xe out=0x4000 en=1 in=0xf out=0x8000 ncsim: *W,RNQUIE: Simulation is complete.
Verilog
- Tutoriel - Écriture de code combinatoire et séquentiel
- Circuit avec interrupteur
- Introduction à l'algèbre booléenne
- arithmétique avec notation scientifique
- Q&R avec un architecte de solution Industrie 4.0
- Contrôle de la température avec Raspberry Pi
- Exemples de niveau de porte Verilog
- Format d'heure Verilog
- Toujours une finition lisse avec les rectifieuses Okamoto