Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> Verilog

Lógica sequencial com sempre


Um artigo anterior mostrou diferentes exemplos de uso de um always bloco para implementar a lógica combinacional. Um always bloco também é usado principalmente para implementar sequencial lógica que tem elementos de memória como flip-flops que podem armazenar valores.

Flip Flop JK


Um flip-flop JK é um dos muitos tipos de flops usados ​​para armazenar valores e tem duas entradas de dados j e k junto com uma para reset rstn e outra para clock clk. A tabela verdade para um flop JK é mostrada abaixo e normalmente é implementada usando portas NAND.
rstn j k q Comentários
0 0 0 0 Quando o reset é ativado, a saída é sempre zero
1 0 0 Reter valor Quando j e k são 0, a saída permanece a mesma de antes
1 0 1 1 Quando k=1, a saída se torna 1
1 1 0 0 Quando k=0, a saída se torna 0
1 1 1 Alternar valor Quando j=1,k=1 a saída alterna o valor atual

O código comportamental Verilog para um flip-flop JK pode ser escrito como mostrado abaixo
  
  
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

  

Banco de teste


Primeiro declare todas as variáveis ​​usadas no testbench e inicie um relógio usando um simples always bloco que pode ser direcionado para o projeto. Em seguida, instancie o projeto e conecte suas portas com as variáveis ​​do testbench correspondentes. Observe que q é do tipo wire porque está conectado a uma saída do projeto que o conduzirá ativamente. Todas as outras entradas do projeto são do tipo reg para que possam ser conduzidos dentro de um bloco procedural como initial .

O estímulo primeiro inicializa todas as entradas do projeto para zero e, em seguida, desabilita a reinicialização após algum tempo. Um for loop é usado para direcionar valores diferentes para j e k que são direcionados em tempos aleatórios. Feito o loop, espere mais um pouco e finalize a simulação.
  
  
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

  

Observe a partir da onda de simulação que na posição do clock, a saída q muda de valor com base no estado das entradas j e k como dado na tabela verdade.

Contador Módulo-10


Os contadores de módulo (MOD) simplesmente contam até um certo número antes de voltar a zero. Um contador MOD-N contará de 0 a N-1 e depois voltará a zero e começará a contar novamente. Esses contadores geralmente exigem log2 N número de flops para manter o valor de contagem. Abaixo está o código Verilog para um contador MOD-10 que continua contando a cada clk do relógio enquanto reset rstn estiver desabilitado.

Os parâmetros Verilog podem ser usados ​​para fazer um contador MOD-N mais escalável.
  
  
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

  

Banco de teste


O testbench primeiro declara algumas variáveis ​​que podem ser atribuídas a alguns valores e direcionadas às entradas de projeto. O módulo contador é então instanciado e conectado com os sinais da bancada de teste que são posteriormente acionados com alguns valores no estímulo. Como o contador também requer um relógio, o relógio do testbench é modelado com um always quadra. O estímulo simplesmente define os valores padrão no tempo 0ns, então as desativações são redefinidas após 10ns e o projeto pode ser executado por algum tempo.
  
  
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

  

Veja que o módulo contador conta de zero a 9, passa para zero e começa a contar novamente.

Registro de deslocamento esquerdo de 4 bits


Abaixo é mostrado um registrador de deslocamento à esquerda de 4 bits que aceita uma entrada d em LSB e todos os outros bits serão deslocados para a esquerda em 1. Por exemplo, se d for igual a zero e o valor inicial do registrador for 0011, ele se tornará 0110 em a próxima borda do clk do relógio.
  
  
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

  

Banco de teste


O testbench segue um template similar ao mostrado antes onde algumas variáveis ​​são declaradas, o módulo de design é instanciado e conectado com os sinais do testbench. Em seguida, um relógio é iniciado e o estímulo é direcionado para o design usando um initial quadra. Neste exemplo do testbench, diferentes valores de d devem ser exercitados e, portanto, um for loop é usado para iterar 20 vezes e aplicar valores aleatórios ao projeto.
  
  
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

  

Observe que cada bit é deslocado para a esquerda em 1 e o novo valor de d é aplicado ao LSB.

Verilog

  1. Tutorial - Escrevendo Código Combinacional e Sequencial
  2. Circuito com interruptor
  3. Circuitos integrados
  4. Controladores lógicos programáveis ​​(PLC)
  5. Introdução à Álgebra Booleana
  6. Simplificação da lógica com mapas de Karnaugh
  7. Lógica digital com feedback
  8. Contador Verilog Mod-N
  9. Contador Verilog Cinza
  10. Sempre um acabamento suave com as retificadoras Okamoto