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

Logique séquentielle avec toujours

Un article précédent montrait différents exemples d'utilisation d'un always bloc pour implémenter la logique combinatoire. Un always Le bloc est également principalement utilisé pour implémenter séquentiel logique qui a des éléments de mémoire comme des bascules qui peuvent contenir des valeurs.

Tongs JK

Une bascule JK est l'un des nombreux types de bascules utilisées pour stocker des valeurs et possède deux entrées de données j et k avec une pour la réinitialisation rstn et une autre pour l'horloge clk. La table de vérité d'un flop JK est illustrée ci-dessous et est généralement implémentée à l'aide de portes NAND.

rstn j k q Commentaires
0 0 0 0 Lorsque la réinitialisation est affirmée, la sortie est toujours zéro
1 0 0 Conserver la valeur Lorsque j et k valent 0, la sortie reste la même qu'avant
1 0 1 1 Lorsque k=1, la sortie devient 1
1 1 0 0 Lorsque k=0, la sortie devient 0
1 1 1 Basculer la valeur Lorsque j=1,k=1 la sortie bascule la valeur actuelle

Le code comportemental Verilog pour une bascule JK peut être écrit comme indiqué ci-dessous

  
  
module jk_ff ( input 			j, 				// Input J
               input 			k, 				// Input K
               input 			rstn, 		// Active-low async reset
               input 			clk, 			// Input clk
               output reg q); 			// Output Q

	always @ (posedge clk or negedge rstn) begin
		if (!rstn) begin
			q <= 0;
		end else begin
	  	q <= (j & ~q) | (~k & q);
	  end
  end
endmodule

  

Banc de test

Déclarez d'abord toutes les variables utilisées dans le testbench et démarrez une horloge en utilisant un simple always bloc qui peut être entraîné à la conception. Ensuite, instanciez la conception et connectez ses ports aux variables de banc de test correspondantes. Notez que q est de type wire car il est connecté à une sortie de la conception qui le pilotera activement. Toutes les autres entrées de la conception sont de type reg afin qu'ils puissent être pilotés dans un bloc procédural tel que initial .

Le stimulus initialise d'abord toutes les entrées de la conception à zéro, puis désactive la réinitialisation après un certain temps. Un for La boucle est utilisée pour conduire différentes valeurs à j et k qui sont pilotées à des moments aléatoires. Une fois la boucle terminée, attendez encore un peu et terminez la simulation.

  
  
module tb;
	// Declare testbench variables
	reg j, k, rstn, clk;
	wire q;
	integer i;
	reg [2:0] dly;
	
	// Start the clock 
	always #10 clk = ~clk;
	
	// Instantiate the design
	jk_ff 	u0 (	.j(j), .k(k), .clk(clk), .rstn(rstn), .q(q));
	
	// Write the stimulus
	initial begin
		{j, k, rstn, clk} <= 0;
		#10 rstn <= 1;
		
		for (i = 0; i < 10; i = i+1) begin
			dly = $random;
			#(dly) j <= $random;
			#(dly) k <= $random;
		end
		
		#20 $finish;
	end
endmodule

  

Notez à partir de l'onde de simulation qu'au bord posé de l'horloge, la sortie q change de valeur en fonction de l'état des entrées j et k comme indiqué dans la table de vérité.

Compteur modulo-10

Les compteurs de module (MOD) comptent simplement jusqu'à un certain nombre avant de revenir à zéro. Un compteur MOD-N comptera de 0 à N-1, puis reviendra à zéro et recommencera à compter. Ces compteurs nécessitent généralement log2 N nombre de flops pour contenir la valeur de comptage. Vous trouverez ci-dessous le code Verilog d'un compteur MOD-10 qui continue de compter à chaque clk d'horloge tant que reset rstn est désactivé.

Les paramètres Verilog peuvent être utilisés pour créer un compteur MOD-N plus évolutif.

  
  
module mod10_counter ( 	input		clk,
												input 	rstn,
												output	reg[3:0] out);
												
	always @ (posedge clk) begin
		if (!rstn) begin
			out <= 0;
		end else begin
			if (out == 10) 
				out <= 0;
			else
				out <= out + 1;
		end
	end
endmodule

  

Banc de test

Le testbench déclare d'abord certaines variables qui peuvent être affectées à certaines valeurs et pilotées vers les entrées de conception. Le module de compteur est ensuite instancié et connecté aux signaux du banc d'essai qui sont ensuite pilotés avec certaines valeurs dans le stimulus. Étant donné que le compteur nécessite également une horloge, l'horloge du banc de test est modélisée avec un always bloquer. Le stimulus définit simplement les valeurs par défaut au temps 0ns, puis désactive la réinitialisation après 10ns et la conception est autorisée à s'exécuter pendant un certain temps.

  
  
module tb;
	reg clk, rstn;
	reg [3:0] out;
	
	mod10_counter u0 ( .clk(clk), .rstn(rstn), .out(out));
	
	always #10 clk = ~clk;
	
	initial begin
		{clk, rstn} <= 0;
		
		#10 rstn <= 1;
		#450 $finish;
	end
endmodule

  

Vérifiez que le module compteur compte de zéro à 9, revient à zéro et recommence à compter.

Registre à décalage gauche 4 bits

Ci-dessous, un registre à décalage à gauche de 4 bits qui accepte une entrée d dans LSB et tous les autres bits seront décalés vers la gauche de 1. Par exemple, si d est égal à zéro et que la valeur initiale du registre est 0011, il deviendra 0110 à le bord suivant de l'horloge clk.

  
  
module lshift_4b_reg (  input d,                      
                        input clk,                    
                        input rstn,                   
                        output reg [3:0] out
                     );
 
   always @ (posedge clk) begin
      if (!rstn) begin
         out <= 0;
      end else begin
         out <= {out[2:0], d};
      end
   end
endmodule

  

Banc de test

Le testbench suit un modèle similaire à celui présenté précédemment où certaines variables sont déclarées, le module de conception est instancié et connecté aux signaux du testbench. Ensuite, une horloge est démarrée et le stimulus est dirigé vers la conception à l'aide d'un initial bloquer. Dans cet exemple de testbench, différentes valeurs de d doivent être exercées et donc un for boucle est utilisée pour itérer 20 fois et appliquer des valeurs aléatoires à la conception.

  
  
module tb;
	reg clk, rstn, d;
	wire [3:0] out;
  integer i;
	
  lshift_4b_reg u0 (  .d(d), .clk(clk), .rstn(rstn), .out(out));
	
	always #10 clk = ~clk;
	
	initial begin
    {clk, rstn, d} <= 0;
    
    #10 rstn <= 1;
	
    for (i = 0; i < 20; i=i+1) begin
      @(posedge clk) d <= $random; 
    end
    
    #10 $finish;
	end  
endmodule

  

Notez que chaque bit est décalé vers la gauche de 1 et la nouvelle valeur de d est appliquée au LSB.


Verilog

  1. Tutoriel - Écriture de code combinatoire et séquentiel
  2. Circuit avec interrupteur
  3. Circuits intégrés
  4. Contrôleurs logiques programmables (PLC)
  5. Introduction à l'algèbre booléenne
  6. Simplification de la logique avec Karnaugh Maps
  7. Compteur Verilog Mod-N
  8. Comptoir gris Verilog
  9. Toujours une finition lisse avec les rectifieuses Okamoto