Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Verilog

Maîtriser les Primitives Définies par l'Utilisateur Verilog : Modélisation Logique Avancée

Les primitives Verilog standard comme nand et not ne sont pas toujours faciles ou suffisantes pour représenter une logique complexe. De nouveaux éléments primitifs appelés UDP ou primitives définies par l'utilisateur peuvent être définis pour modéliser la logique combinatoire ou séquentielle.

Tous les UDPs ont exactement une sortie qui peut être 0, 1 ou X et jamais Z (non supporté). Toute entrée qui a la valeur Z sera traitée comme X.

Symboles Verilog UDP

Les primitives définies par l'utilisateur Verilog peuvent être écrites au même niveau que les définitions de module, mais jamais entre module et endmodule. Elles peuvent avoir plusieurs ports d'entrée mais toujours un port de sortie, et les ports bidirectionnels ne sont pas valides. Tous les signaux de port doivent être scalaires ce qui signifie qu'ils doivent faire 1 bit de large.

Le comportement matériel est décrit comme un tableau d'états primitif qui liste les différentes combinaisons possibles d'entrées et leur sortie correspondante dans table et endtable. Les valeurs des signaux d'entrée et de sortie sont indiquées en utilisant les symboles suivants.

Symbole Commentaires
0 Logique 0
1 Logique 1
x Inconnu, peut être soit logique 0 ou 1. Peut être utilisé comme entrée/sortie ou état courant des UDPs séquentiels
? Logique 0, 1 ou x. Ne peut pas être sortie d'un UDP
- Pas de changement, seulement autorisé en sortie d'un UDP
ab Changement de valeur de a vers b où a ou b est soit 0, 1, ou x
* Identique à ??, indique tout changement de valeur d'entrée
r Identique à 01 -> front montant sur l'entrée
f Identique à 10 -> front descendant sur l'entrée
p Front montant potentiel sur l'entrée ; soit 0->1, 0->x, ou x->1
n Front descendant potentiel sur l'entrée ; soit 1->0, x->0, 1->x

Exemple d'UDP Combinatoire

// La sortie doit toujours être le premier signal dans la liste des ports
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

Un ? indique que le signal peut être 0, 1 ou x et n'a pas d'importance pour décider la sortie finale.

Voici un module de banc de test qui instancie l'UDP et applique des stimuli d'entrée.

module tb;
  reg sel, a, b;
  reg [2:0] dly;
  wire out;
  integer i;
  // Instancier l'UDP - noter que les UDPs ne peuvent pas
  // être instanciés avec connexion de port par nom
  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);
    // Piloter a, b, et sel après différents délais aléatoires
    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

Journal de Simulation

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.

Exemple d'UDP Séquentiel

La logique séquentielle peut être soit sensible au niveau, soit sensible au front et donc il y a deux types d'UDPs séquentiels. Le port de sortie doit aussi être déclaré comme type reg dans la définition de l'UDP et peut être optionnellement initialisé dans une instruction initial.

Les UDPs séquentiels ont un champ additionnel entre le champ d'entrée et de sortie qui est délimité par un : qui représente l'état courant.

UDPs Sensibles au Niveau

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

Dans le tableau ci-dessus, un tiret - sur la dernière ligne du tableau indique pas de changement de valeur pour 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; // Pour voir l'effet de X
    for (i = 0; i < 50; i = i+1) begin
      dly = $random;
      #(dly) d <= $random;
    end
    #20 $finish;
  end
endmodule

Journal de Simulation

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

UDPs Sensibles au Front

Un bascule D est modélisé comme une primitive définie par l'utilisateur Verilog dans l'exemple montré ci-dessous. Notez que le front montant de l'horloge est spécifié par 01 ou 0?.

primitive d_flop (q, clk, d);
  output q;
  input clk, d;
  reg q;
  table
  // clk d q q+
  // obtenir la sortie sur front montant de clk (01)
  0 : ? : 0;
  (01) 1 : ? : 1;
  (0?) 1 : 1 : 1;
  (0?) 0 : 0 : 0;
  // ignorer front descendant de clk
  (?0) ? : ? : -;
  // ignorer changements de données sur clk stable
  ? (??): ? : -;
  endtable
endprimitive

Dans le banc de test, l'UDP est instancié et piloté avec des valeurs d aléatoires après un nombre aléatoire de cycles d'horloge.

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; // Pour voir l'effet de X
    for (i = 0; i < 20; i = i+1) begin
      dly = $random;
      repeat(dly) @(posedge clk);
      d <= $random;
    end
    #20 $finish;
  end
endmodule

On peut voir sur l'image que la sortie q suit l'entrée d après 1 cycle d'horloge de délai ce qui est le comportement souhaité pour une bascule D.

Journal de Simulation

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. Maîtriser Verilog : Tutoriel complet pour la conception de circuits numériques
  2. Maîtriser la concaténation Verilog : Guide pratique
  3. Comprendre les affectations Verilog : Types, Syntaxe et Bonnes Pratiques
  4. Verilog Blocking vs Non-Blocking : Différences Clés Expliquées
  5. Maîtriser les Fonctions Verilog pour une Conception RTL Efficace
  6. Comprendre les Tasks Verilog : Fonctions vs Tasks, Syntaxe et Utilisation
  7. Générateur d'Horloge Verilog : Guide de Conception et d'Implémentation
  8. Maîtriser les Fonctions Mathématiques Verilog pour une Conception Matérielle Efficace
  9. Maîtriser Verilog $timeformat : Contrôle de Précision et d'Affichage