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

Sequentiële logica met altijd

Een vorig artikel toonde verschillende voorbeelden van het gebruik van een always blok om combinatorische logica te implementeren. Een always blok wordt ook voornamelijk gebruikt om sequentiële . te implementeren logica met geheugenelementen zoals flip-flops die waarden kunnen bevatten.

JK-teenslipper

Een JK-flip-flop is een van de vele soorten flops die worden gebruikt om waarden op te slaan en heeft twee data-ingangen j en k, samen met een voor reset rstn en een andere voor klok clk. De waarheidstabel voor een JK-flop wordt hieronder getoond en wordt meestal geïmplementeerd met behulp van NAND-poorten.

rstn j k q Opmerkingen
0 0 0 0 Als reset wordt uitgevoerd, is de output altijd nul
1 0 0 Waarde vasthouden Als zowel j als k 0 zijn, blijft de uitvoer hetzelfde als voorheen
1 0 1 1 Als k=1, wordt de output 1
1 1 0 0 Als k=0, wordt de output 0
1 1 1 Toggle waarde Als j=1,k=1 uitgang wisselt van huidige waarde

De gedragscode van Verilog voor een JK-flip-flop kan worden geschreven zoals hieronder weergegeven

  
  
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

  

Testbank

Declareer eerst alle variabelen die in de testbench worden gebruikt en start een klok met een simpele always blok dat naar het ontwerp kan worden gereden. Instantieer vervolgens het ontwerp en verbind de poorten met de bijbehorende testbench-variabelen. Merk op dat q van het type wire . is omdat het is verbonden met een uitgang van het ontwerp die het actief zal aansturen. Alle andere inputs voor het ontwerp zijn van het type reg zodat ze kunnen worden gereden binnen een procedureel blok zoals initial .

De stimulus initialiseert eerst alle invoer naar het ontwerp naar nul en wordt vervolgens na enige tijd opnieuw ingesteld. Een for lus wordt gebruikt om verschillende waarden naar j en k te sturen die op willekeurige tijden worden aangestuurd. Als de lus klaar is, wacht je nog even en voltooi je de simulatie.

  
  
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

  

Merk op uit de simulatiegolf dat op het moment van de klok, output q van waarde verandert op basis van de status van inputs j en k zoals gegeven in de waarheidstabel.

Modulo-10-teller

Modulus (MOD)-tellers tellen gewoon tot een bepaald aantal voordat ze teruggaan naar nul. Een MOD-N-teller telt van 0 tot N-1 en keert dan terug naar nul en begint opnieuw te tellen. Dergelijke tellers vereisen doorgaans log2 N aantal flops om de telwaarde vast te houden. Hieronder wordt de Verilog-code weergegeven voor een MOD-10-teller die bij elke klokklok blijft optellen zolang reset rstn niet is bevestigd.

Verilog-parameters kunnen worden gebruikt om een ​​MOD-N-teller te maken die beter schaalbaar is.

  
  
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

  

Testbank

De testbench declareert eerst enkele variabelen waaraan enkele waarden kunnen worden toegewezen en die naar de ontwerpinvoer kunnen worden gestuurd. De tellermodule wordt dan geïnstantieerd en verbonden met de testbanksignalen die later worden aangestuurd met enkele waarden in de stimulus. Omdat de teller ook een klok nodig heeft, is de testbankklok gemodelleerd met een always blok. De stimulus stelt eenvoudig de standaardwaarden in op tijd 0ns, wordt vervolgens na 10ns opnieuw ingesteld en het ontwerp mag enige tijd worden uitgevoerd.

  
  
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

  

Zie dat de tellermodule telt van nul tot 9, rolt naar nul en begint opnieuw te tellen.

4bit Left Shift Register

Hieronder wordt een 4-bit linker schuifregister weergegeven dat een invoer d in LSB accepteert en alle andere bits worden met 1 naar links verschoven. Als d bijvoorbeeld gelijk is aan nul en de beginwaarde van het register 0011 is, wordt het 0110 bij de volgende rand van de klok klikt.

  
  
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

  

Testbank

De testbench volgt een soortgelijk sjabloon als het eerder getoonde, waar enkele variabelen worden gedeclareerd, de ontwerpmodule wordt geïnstantieerd en verbonden met de testbench-signalen. Vervolgens wordt een klok gestart en wordt de stimulus naar het ontwerp gestuurd met behulp van een initial blok. In dit testbench-voorbeeld moeten verschillende waarden van d worden uitgeoefend en dus een for lus wordt gebruikt om 20 keer te herhalen en willekeurige waarden toe te passen op het ontwerp.

  
  
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

  

Merk op dat elk bit met 1 naar links wordt verschoven en dat de nieuwe waarde van d wordt toegepast op LSB.


Verilog

  1. Tutorial - Combinatie- en sequentiële code schrijven
  2. Circuit met een schakelaar
  3. Geïntegreerde circuits
  4. Programmable Logic Controllers (PLC)
  5. Inleiding tot Booleaanse algebra
  6. Logische vereenvoudiging met Karnaugh-kaarten
  7. Digitale logica met feedback
  8. Een RRAM-geïntegreerde 4T SRAM met zelfremmende resistieve schakelbelasting door puur CMOS logisch proces
  9. Verilog Mod-N-teller
  10. Verilog grijze toonbank
  11. Altijd een gladde afwerking met Okamoto-slijpmachines