Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> Verilog

Combinatorische logica ontwerpen in Verilog met continue assign-statements

Het Verilog assign statement wordt typisch gebruikt om een signaal van wire datatype continu te drijven en wordt gesynthetiseerd als combinatorische logica. Hier zijn meer ontwerpvoorbeelden met assign.

Voorbeeld #1: Eenvoudige combinatorische logica

De onderstaande code implementeert een simpele digitale combinatorische logica met een uitvoer wire z die continu gedreven wordt door een assign statement om de digitale vergelijking te realiseren.

module combo ( input a, b, c, d, e, output z);
assign z = ((a & b) | (c ^ d) & ~e);
endmodule

De module combo wordt geëlaboreerd in het volgende hardwareschema met synthetise-tools, waar de combinatorische logica geïmplementeerd is met digitale gates.

Testbench

De testbench is een platform voor het simuleren van het ontwerp om te verzekeren dat het zich gedraagt zoals verwacht. Alle combinaties van invoeren worden aangedreven met een for lus met een vertraging van 10 tijdseenheden.

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=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. 

Let op: zowel assign als always methodes worden geïmplementeerd in dezelfde hardwarelogica.

Voorbeeld #2: Half Adder

De half adder module accepteert twee scalaire invoeren a en b en gebruikt combinatorische logica om de uitgangen sum en carry-bit cout toe te wijzen. De som wordt gedreven door een XOR tussen a en b, de carry-bit door een 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. 

Voorbeeld #3: Full Adder

Een full adder kan gebouwd worden met de half adder module of de volledige combinatorische logica direct met assign statements voor sum en 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=0 b=0 cin=1 sum=1 cout=0
a=0 b=1 cin=0 sum=1 cout=0
a=0 b=1 cin=1 sum=0 cout=1
a=1 b=0 cin=0 sum=1 cout=0
a=1 b=0 cin=1 sum=0 cout=1
a=1 b=1 cin=0 sum=0 cout=1
a=1 b=1 cin=1 sum=0 cout=1
ncsim: *W,RNQUIE: Simulation is complete. 

Voorbeeld #4: 2x1 Multiplexer

De eenvoudige 2x1 multiplexer gebruikt een ternaire operator om te beslussen welke invoer aan de uitvoer c toegewezen wordt. Als sel 1 is, wordt uitvoer gedreven door a, anders door 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. 

Voorbeeld #5: 1x4 Demultiplexer

De demultiplexer gebruikt een combinatie van sel en f om de verschillende uitvoersignalen te drijven. Elk uitvoersignaal wordt gedreven door een apart assign statement. Let op: het is niet aan te bevelen hetzelfde signaal door verschillende assign statements te drijven.

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=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. 

Voorbeeld #6: 4x16 Decoder

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=0 in=0x1 out=0x0
...
en=1 in=0xf out=0x8000
ncsim: *W,RNQUIE: Simulation is complete. 

Verilog

  1. Accurate temperatuurbewaking in een serverkast met Raspberry Pi
  2. Circuit met een schakelaar: Praktische gids voor basis elektrische circuits
  3. Geïntegreerde Schakelingen: Fundamenten van Digitale Logische Poorten
  4. Programmeerbare Logische Controllers (PLC's): Moderne Digitale Besturing voor Industriële Systemen
  5. Booleaanse Algebra Begrijpen: Van Logica Fundamenten tot Digitale Schakelingen
  6. Logica Vereenvoudiging Beheersen met Karnaugh-kaarten
  7. Vermenigvuldigen en delen met wetenschappelijke notatie beheersen
  8. Industry 4.0 Inzichten: Q&A met Verena Majuntke van Bosch.IO over IoT, Automatisering en de Toekomstfabriek
  9. VHDL & Verilog Meesteren: Schone Combinatoire en Sequentiele Logica Schrijven
  10. Praktisch Verilog Gate-Level Ontwerp: AND, OR, NOT Gates & 2x1 Multiplexer
  11. Verilog $timeformat beheersen: Precisie en Weergave-controle