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

Instancias del módulo Verilog

Como vimos en un artículo anterior, los diseños más grandes y complejos se construyen integrando múltiples módulos de manera jerárquica. Los módulos pueden ser instanciados dentro de otros módulos y puertos de estas instancias se puede conectar con otras señales dentro del módulo principal.

Estas conexiones de puertos se pueden realizar a través de una lista ordenada o por nombre.

Conexión de puertos por lista ordenada

Un método para establecer la conexión entre las expresiones de puerto enumeradas en una instanciación de módulo con las señales dentro del módulo principal es mediante la lista ordenada .

midiseño es un module instanciado con el nombre d0 en otro módulo llamado tb_top. Los puertos se conectan en un cierto orden que está determinado por la posición de ese puerto en la lista de puertos de la declaración del módulo. Por ejemplo, b en el banco de pruebas está conectado a y del diseño simplemente porque ambos están en la segunda posición en la lista de puertos.

  
  
	module mydesign ( input  x, y, z,     // x is at position 1, y at 2, x at 3 and
	                  output o);          // o is at position 4
	                  
	endmodule

	module tb_top;
		wire [1:0]  a;
		wire        b, c;
		
		mydesign d0  (a[0], b, a[1], c);  // a[0] is at position 1 so it is automatically connected to x
		                                  // b is at position 2 so it is automatically connected to y
		                                  // a[1] is at position 3 so it is connected to z
		                                  // c is at position 4, and hence connection is with o
	endmodule

  

Se debe conocer el orden de los puertos en el módulo de diseño para una conexión correcta.

Esto es muy inconveniente porque el orden puede cambiar si se agrega un nuevo puerto a la lista o cuando la cantidad de puertos en el diseño es muy grande.

Puerto de conexión por nombre

Una mejor manera de conectar puertos es vincular puertos explícitamente en ambos lados usando su nombre de puerto .

El punto . indica que el nombre del puerto que sigue al punto pertenece al diseño. El nombre de la señal a la que se debe conectar el puerto de diseño se proporciona a continuación entre paréntesis ( ) .

  
  
module design_top;
	wire [1:0]  a;
	wire        b, c;
	
	mydesign d0  ( .x (a[0]),    // signal "x" in mydesign should be connected to "a[0]" in this module (design_top)
	               .y (b),       // signal "y" in mydesign should be connected to "b" in this module (design_top)
	               .z (a[1]), 
	               .o (c));
endmodule

  

Se recomienda codificar cada conexión de puerto en una línea separada para que cualquier mensaje de error de compilación apunte correctamente al número de línea donde ocurrió el error. Esto es mucho más fácil de depurar y resolver en comparación con no saber qué puerto creó el error si todos estuvieran en la misma línea.

Debido a que estas conexiones se realizan por nombre, el orden en que aparecen es irrelevante. No se permiten conexiones de puerto de instancia de módulo múltiple.

  
  
	module design_top;
		mydesign d0 ( .x (a[0]),
		              .z (a[1]),     // z at second position is okay because of explicit connection
		              .y (a[1]),
		              .x (b),        // illegal - x is already connected to a[0]
		              .o (c));
	endmodule

  

Puertos no conectados/flotantes

Los puertos que no están conectados a ningún cable en el módulo de creación de instancias tendrán un valor de alta impedancia.

  
  
module design_top;
	mydesign d0   (              // x is an input and not connected, hence a[0] will be Z
	              .y (a[1]),
	              .z (a[1]),
	              .o ());        // o has valid value in mydesign but since
	                             // it is not connected to "c" in design_top, c will be Z
endmodule

  

Ejemplo

Tomemos el ejemplo del registro de desplazamiento que habíamos visto antes y dejemos algunos puertos sin conectar.

  
  
module shift_reg (   input   d,
                    input    clk,
                    input   rstn,
                    output   q);
 
  wire [2:0] q_net;
  
  dff u0 (.d(d),         .clk(clk), .rstn(rstn), .q(q_net[0]));
  dff u1 (.d(q_net[0]), .clk(clk), .rstn(rstn), .q()); 						// Output q is left floating
  dff u2 (.d(q_net[1]), .clk(clk), .rstn(rstn), .q()); 						// Output q is left floating
  dff u3 (.d(q_net[2]), .clk(clk), .rstn(rstn), .q(q));
 
endmodule

  

Tenga en cuenta que las salidas de las instancias u1 y u2 se dejan desconectadas en el esquema RTL obtenido después de la síntesis. Dado que la entrada d a las instancias u2 y u3 ahora está conectada a redes que no están siendo impulsadas por nada, está conectada a tierra.

unconnected-port-after-synthesis

En las simulaciones, dichos puertos no conectados se indicarán como de alta impedancia ('hZ), que normalmente se muestran en formas de onda como una línea naranja alineada verticalmente en el medio.

verilog-unconnected-port

Todas las declaraciones de puerto se declaran implícitamente como wire y, por lo tanto, la dirección del puerto es suficiente en ese caso. Sin embargo output los puertos que necesitan almacenar valores deben declararse como reg tipo de datos y se puede utilizar en un bloque de procedimiento como always y initial solo.

Puertos de tipo input o inout no se puede declarar como reg porque están siendo impulsados ​​​​desde el exterior continuamente y no deben almacenar valores, sino reflejar los cambios en las señales externas lo antes posible. Es perfectamente legal conectar dos puertos con diferentes tamaños de vectores, pero prevalecerá el que tenga un tamaño de vector más bajo y se ignorarán los bits restantes del otro puerto con un ancho mayor.

  
  

	// Case #1 : Inputs are by default implicitly declared as type "wire"
	module des0_1	(input wire clk ...); 		// wire need not be specified here
	module des0_2 	(input clk, ...); 			// By default clk is of type wire
		
	// Case #2 : Inputs cannot be of type reg
	module des1 (input reg clk, ...); 		// Illegal: inputs cannot be of type reg
	
	// Case #3: Take two modules here with varying port widths
	module des2 (output [3:0] data, ...);	// A module declaration with 4-bit vector as output
	module des3 (input [7:0] data, ...); 	// A module declaration with 8-bit vector as input
	
	module top ( ... );
		wire [7:0] net;
		des2  u0 ( .data(net) ... ); 		// Upper 4-bits of net are undriven
		des3  u1 ( .data(net) ... ); 		
	endmodule
	
	// Case #4 : Outputs cannot be connected to reg in parent module
	module top_0 ( ... );
		reg [3:0] data_reg;
		
		des2 ( .data(data) ...); 	// Illegal: data output port is connected to a reg type signal "data_reg"
	endmodule
		

  

Verilog

  1. Tutorial de Verilog
  2. Concatenación Verilog
  3. Verilog - En pocas palabras
  4. Asignaciones de Verilog
  5. Bloqueo y no bloqueo de Verilog
  6. Funciones de Verilog
  7. Tarea Verilog
  8. Ámbito de referencia jerárquica de Verilog
  9. Generador de reloj Verilog
  10. Funciones matemáticas de Verilog
  11. Formato de hora de Verilog