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

Verilog User-Defined Primitives beheersen: Geavanceerde logica-modellering

Standaard Verilog-primitives zoals nand en not zijn niet altijd gemakkelijk of voldoende om complexe logica weer te geven. Nieuwe primitive-elementen genaamd UDP of user-defined primitives kunnen gedefinieerd worden om combinatorische of sequentiële logica te modelleren.

Alle UDPs hebben precies één output die 0, 1 of X kan zijn en nooit Z (niet ondersteund). Elke input met waarde Z wordt behandeld als X.

Verilog UDP Symbolen

Verilog user-defined primitives kunnen op hetzelfde niveau geschreven worden als module-definities, maar nooit tussen module en endmodule. Ze kunnen veel input-poorten hebben maar altijd één output-poort, en bidirectionele poorten zijn niet geldig. Alle poortsignalen moeten scalair zijn wat betekent dat ze 1-bit breed moeten zijn.

Hardwaregedrag wordt beschreven als een primitive staatstabel die de verschillende mogelijke combinaties van inputs en hun corresponderende output opsomt binnen table en endtable. Waarden van input- en output-signalen worden aangegeven met de volgende symbolen.

Symbool Opmerkingen
0 Logica 0
1 Logica 1
x Onbekend, kan logica 0 of 1 zijn. Kan als input/output of huidige toestand van sequentiële UDPs gebruikt worden
? Logica 0, 1 of x. Kan geen output van een UDP zijn
- Geen verandering, alleen toegestaan in output van een UDP
ab Waardeverandering van a naar b waar a of b 0, 1, of x is
* Hetzelfde als ??, duidt elke verandering in input-waarde aan
r Hetzelfde als 01 -> stijgende flank op input
f Hetzelfde als 10 -> dalende flank op input
p Potentiële positieve flank op input; 0->1, 0->x, of x->1
n Potentiële dalende flank op input; 1->0, x->0, 1->x

Combinatorische UDP Voorbeeld

// Output moet altijd het eerste signaal in poortlijst zijn
primitive mux (out, sel, a, b);
  output out;
  input sel, a, b;
  table
    // sel a b out
    0 1 ? : 1;
    0 0 ? : 0;
    1 ? 0 : 0;
    1 ? 1 : 1;
    x 0 0 : 0;
    x 1 1 : 1;
  endtable
endprimitive

Een ? geeft aan dat het signaal 0, 1 of x kan zijn en niet meeweegt bij de beslissing van de finale output.

Hieronder is een testbench-module die de UDP instantiëert en input-stimuli toepast.

module tb;
  reg sel, a, b;
  reg [2:0] dly;
  wire out;
  integer i;
  // Instantieer de UDP - let op dat UDPs niet
  // geïnstantieerd kunnen worden met poortnaamverbinding
  mux u_mux ( out, sel, a, b );
  initial begin
    a <= 0; b <= 0;
    $monitor("[T=%0t] a=%0b b=%0b sel=%0b out=%0b", $time, a, b, sel, out);
    // Stuur a, b, en sel na verschillende random vertragingen
    for (i = 0; i < 10; i = i + 1) begin
      dly = $random; #(dly) a <= $random;
      dly = $random; #(dly) b <= $random;
      dly = $random; #(dly) sel <= $random;
    end
  end
endmodule

Simulatie-log

xcelium> run
[T=0] a=0 b=0 sel=x out=0
[T=4] a=1 b=0 sel=x out=x
[T=5] a=1 b=1 sel=x out=1
[T=10] a=1 b=1 sel=1 out=1
[T=15] a=0 b=1 sel=1 out=1
[T=28] a=0 b=0 sel=1 out=0
[T=33] a=0 b=0 sel=0 out=0
[T=38] a=1 b=0 sel=0 out=1
[T=40] a=1 b=1 sel=0 out=1
[T=51] a=1 b=1 sel=1 out=1
[T=54] a=0 b=0 sel=1 out=0
[T=62] a=1 b=0 sel=1 out=0
[T=67] a=1 b=1 sel=1 out=1
[T=72] a=0 b=1 sel=1 out=1
[T=80] a=0 b=1 sel=0 out=0
[T=84] a=0 b=0 sel=0 out=0
[T=85] a=1 b=0 sel=0 out=1
xmsim: *W,RNQUIE: Simulation is complete.

Sequentiële UDP Voorbeeld

Sequentiële logica kan level-sensitive of edge-sensitive zijn en dus zijn er twee soorten sequentiële UDPs. De output-poort moet ook gedeclareerd worden als reg-type binnen de UDP-definitie en kan optioneel geïnitialiseerd worden binnen een initial-statement.

Sequentiële UDPs hebben een extra veld tussen de input- en output-velden wat gescheiden wordt door een : wat de huidige staat vertegenwoordigt.

Level-Sensitive UDPs

primitive d_latch (q, clk, d);
  output q;
  input clk, d;
  reg q;
  table
    // clk d q q+
    1 1 : ? : 1;
    1 0 : ? : 0;
    0 ? : ? : -;
  endtable
endprimitive

In de bovenstaande tabel geeft een streepje - op de laatste rij aan dat er geen waardeverandering is voor q+.

module tb;
  reg clk, d;
  reg [1:0] dly;
  wire q;
  integer i;
  d_latch u_latch (q, clk, d);
  always #10 clk = ~clk;
  initial begin
    clk = 0;
    $monitor ("[T=%0t] clk=%0b d=%0b q=%0b", $time, clk, d, q);
    #10;
    // Om effect van X te zien
    for (i = 0; i < 50; i = i+1) begin
      dly = $random; #(dly) d <= $random;
    end
    #20 $finish;
  end
endmodule

Simulatie-log

xcelium> run
[T=0] clk=0 d=x q=x
[T=10] clk=1 d=1 q=1
[T=13] clk=1 d=0 q=0
[T=14] clk=1 d=1 q=1
[T=17] clk=1 d=0 q=0
[T=20] clk=0 d=1 q=0
[T=28] clk=0 d=0 q=0
[T=30] clk=1 d=1 q=1
[T=38] clk=1 d=0 q=0
[T=39] clk=1 d=1 q=1
[T=40] clk=0 d=1 q=1
[T=42] clk=0 d=0 q=1
[T=47] clk=0 d=1 q=1
[T=50] clk=1 d=0 q=0
[T=55] clk=1 d=1 q=1
[T=59] clk=1 d=0 q=0
[T=60] clk=0 d=0 q=0
[T=61] clk=0 d=1 q=0
[T=64] clk=0 d=0 q=0
[T=67] clk=0 d=1 q=0
[T=70] clk=1 d=0 q=0
[T=73] clk=1 d=1 q=1
[T=74] clk=1 d=0 q=0
[T=77] clk=1 d=1 q=1
[T=79] clk=1 d=0 q=0
[T=80] clk=0 d=0 q=0
[T=84] clk=0 d=1 q=0
[T=86] clk=0 d=0 q=0
[T=87] clk=0 d=1 q=0
[T=90] clk=1 d=1 q=1
[T=91] clk=1 d=0 q=0
[T=100] clk=0 d=0 q=0
[T=110] clk=1 d=0 q=0
Simulation complete via $finish(1) at time 111 NS + 0

Edge-Sensitive UDPs

Een D flip-flop wordt gemodelleerd als een Verilog user-defined primitive in het onderstaande voorbeeld. Let op dat de stijgende flank van de klok gespecificeerd wordt door 01 of 0?.

primitive d_flop (q, clk, d);
  output q;
  input clk, d;
  reg q;
  table
    // clk d q q+
    // verkrijg output op stijgende flank van clk (01)
    0 : ? : 0;
    (01) 1 : ? : 1;
    (0?) 1 : 1 : 1;
    (0?) 0 : 0 : 0;
    // negeer dalende flank van clk
    (?0) ? : ? : -;
    // negeer data-veranderingen op vaste clk
    ? (??): ? : -;
  endtable
endprimitive

In de testbench wordt de UDP geïnstantieerd en aangedreven met random d-inputwaarden na random aantal klokken.

module tb;
  reg clk, d;
  reg [1:0] dly;
  wire q;
  integer i;
  d_flop u_flop (q, clk, d);
  always #10 clk = ~clk;
  initial begin
    clk = 0;
    $monitor ("[T=%0t] clk=%0b d=%0b q=%0b", $time, clk, d, q);
    #10;
    // Om effect van X te zien
    for (i = 0; i < 20; i = i+1) begin
      dly = $random;
      repeat(dly) @(posedge clk);
      d <= $random;
    end
    #20 $finish;
  end
endmodule

Uit de afbeelding is te zien dat de output q de input d volgt na 1 klokvertraging wat het gewenste gedrag is voor een D flip-flop.

Simulatie-log

xcelium> run
[T=0] clk=0 d=x q=x
[T=10] clk=1 d=1 q=x
[T=20] clk=0 d=1 q=x
[T=30] clk=1 d=1 q=1
[T=40] clk=0 d=1 q=1
[T=50] clk=1 d=1 q=1
[T=60] clk=0 d=1 q=1
[T=70] clk=1 d=0 q=1
[T=80] clk=0 d=0 q=1
[T=90] clk=1 d=1 q=0
[T=100] clk=0 d=1 q=0
[T=110] clk=1 d=1 q=1
[T=120] clk=0 d=1 q=1
[T=130] clk=1 d=1 q=1
[T=140] clk=0 d=1 q=1
[T=150] clk=1 d=0 q=1
[T=160] clk=0 d=0 q=1
[T=170] clk=1 d=0 q=0
[T=180] clk=0 d=0 q=0
[T=190] clk=1 d=0 q=0
[T=200] clk=0 d=0 q=0
[T=210] clk=1 d=1 q=0
[T=220] clk=0 d=1 q=0
[T=230] clk=1 d=1 q=1
[T=240] clk=0 d=1 q=1
[T=250] clk=1 d=1 q=1
[T=260] clk=0 d=1 q=1
[T=270] clk=1 d=1 q=1
[T=280] clk=0 d=1 q=1
[T=290] clk=1 d=1 q=1
[T=300] clk=0 d=1 q=1
[T=310] clk=1 d=1 q=1
[T=320] clk=0 d=1 q=1
[T=330] clk=1 d=1 q=1
[T=340] clk=0 d=1 q=1
[T=350] clk=1 d=1 q=1
[T=360] clk=0 d=1 q=1
[T=370] clk=1 d=0 q=1
[T=380] clk=0 d=0 q=1
[T=390] clk=1 d=0 q=0
[T=400] clk=0 d=0 q=0
[T=410] clk=1 d=1 q=0
[T=420] clk=0 d=1 q=0
[T=430] clk=1 d=1 q=1
[T=440] clk=0 d=1 q=1
[T=450] clk=1 d=1 q=1
[T=460] clk=0 d=1 q=1
[T=470] clk=1 d=1 q=1
[T=480] clk=0 d=1 q=1
Simulation complete via $finish(1) at time 490 NS + 0

Verilog

  1. Verilog beheersen: Complete tutorial voor digitale schakelingontwerp
  2. Verilog concatenatie beheersen: Een praktische gids
  3. Verilog-toewijzingen begrijpen: types, syntax en best practices
  4. Verilog Blocking vs. Non-Blocking: belangrijkste verschillen uitgelegd
  5. Verilog-functies beheersen voor efficiënt RTL-ontwerp
  6. Verilog Tasks begrijpen: Functions vs Tasks, Syntax en Gebruik
  7. Verilog Clock Generator: Ontwerp & Implementatie Gids
  8. Verilog Math Functions beheersen voor efficiënt Hardware-ontwerp
  9. Verilog $timeformat beheersen: Precisie en Weergave-controle
  10. Verilog Timescales begrijpen en printen in elke Scope
  11. Verilog File I/O onder de knie: Openen, Lezen, Schrijven en Sluiten