Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> Verilog

Lógica secuencial con siempre

Un artículo anterior mostró diferentes ejemplos del uso de un always bloque para implementar la lógica combinacional. Un always bloque también se utiliza principalmente para implementar secuencial lógica que tiene elementos de memoria como flip flops que pueden contener valores.

Chanclas JK

Un flip flop JK es uno de los muchos tipos de flops usados ​​para almacenar valores y tiene dos entradas de datos j y k junto con una para reset rstn y otra para clock clk. La tabla de verdad para un flop JK se muestra a continuación y normalmente se implementa mediante compuertas NAND.

rstn j k q Comentarios
0 0 0 0 Cuando se confirma el restablecimiento, la salida siempre es cero
1 0 0 Valor de retención Cuando tanto j como k son 0, la salida sigue siendo la misma que antes
1 0 1 1 Cuando k=1, la salida se convierte en 1
1 1 0 0 Cuando k=0, la salida se convierte en 0
1 1 1 Alternar valor Cuando j=1,k=1 la salida cambia el valor actual

El código Verilog de comportamiento para un flip-flop JK se puede escribir como se muestra a continuación

  
  
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 pruebas

Primero declare todas las variables utilizadas en el banco de pruebas e inicie un reloj usando un simple always bloque que se puede conducir al diseño. Luego cree una instancia del diseño y conecte sus puertos con las variables del banco de pruebas correspondientes. Tenga en cuenta que q es de tipo wire porque está conectado a una salida del diseño que lo impulsará activamente. Todas las demás entradas al diseño son del tipo reg para que puedan ser conducidos dentro de un bloque de procedimiento como initial .

El estímulo primero inicializa todas las entradas al diseño a cero y luego desactiva el reinicio después de un tiempo. Un for loop se usa para conducir diferentes valores a j y k que se manejan en momentos aleatorios. Una vez que se completa el ciclo, espere un poco más y finalice la simulación.

  
  
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

  

Tenga en cuenta de la onda de simulación que en el borde posterior del reloj, la salida q cambia de valor según el estado de las entradas j y k como se indica en la tabla de verdad.

Contador Módulo-10

Los contadores de módulo (MOD) simplemente cuentan hasta cierto número antes de retroceder a cero. Un contador MOD-N contará de 0 a N-1 y luego retrocederá a cero y comenzará a contar nuevamente. Dichos contadores normalmente requieren log2 N número de flops para mantener el valor de conteo. A continuación se muestra el código Verilog para un contador MOD-10 que continúa contando en cada reloj siempre y cuando se desactive el reinicio rstn.

Los parámetros de Verilog se pueden usar para hacer un contador MOD-N que sea más escalable.

  
  
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 pruebas

El banco de pruebas primero declara algunas variables a las que se les pueden asignar algunos valores y conducir a las entradas de diseño. Luego, se crea una instancia del módulo contador y se conecta con las señales del banco de pruebas que luego se controlan con algunos valores en el estímulo. Dado que el contador también requiere un reloj, el reloj del banco de pruebas se modela con un always bloquear. El estímulo simplemente establece los valores predeterminados en el tiempo 0ns, luego se desactiva después de 10ns y se permite que el diseño se ejecute durante algún tiempo.

  
  
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

  

Vea que el módulo de contador cuente de cero a 9, vuelva a cero y comience a contar nuevamente.

Registro de desplazamiento a la izquierda de 4 bits

A continuación se muestra un registro de desplazamiento a la izquierda de 4 bits que acepta una entrada d en LSB y todos los demás bits se desplazarán a la izquierda en 1. Por ejemplo, si d es igual a cero y el valor inicial del registro es 0011, se convertirá en 0110 en el siguiente borde del reloj.

  
  
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 pruebas

El banco de pruebas sigue una plantilla similar a la que se muestra antes, donde se declaran algunas variables, se crea una instancia del módulo de diseño y se conecta con las señales del banco de pruebas. Luego se inicia un reloj y el estímulo se dirige al diseño usando un initial bloquear. En este ejemplo de banco de pruebas, se deben ejercitar diferentes valores de d y, por lo tanto, un for loop se usa para iterar 20 veces y aplicar valores aleatorios al diseño.

  
  
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

  

Tenga en cuenta que cada bit se desplaza a la izquierda en 1 y el nuevo valor de d se aplica a LSB.


Verilog

  1. Tutorial - Escritura de código combinacional y secuencial
  2. Circuito con un interruptor
  3. Circuitos integrados
  4. Controladores lógicos programables (PLC)
  5. Introducción al álgebra booleana
  6. Simplificación lógica con mapas de Karnaugh
  7. Lógica digital con comentarios
  8. Una SRAM 4T integrada de RRAM con carga de conmutación resistiva autoinhibida mediante un proceso lógico CMOS puro
  9. Contador Verilog Mod-N
  10. Mostrador gris Verilog
  11. Siempre un acabado suave con las rectificadoras Okamoto