Esta pregunta está en el contexto del uso de verilog / systemverilog para RTL sintetizable.
Tengo algunas señales vectoriales que van a través de los límites de los módulos que actualmente están definidos como puertos de entrada. La razón por la que están en los puertos de salida es que algunos de los índices vectoriales se asignan en algunos lugares dentro de la jerarquía, mientras que otros se asignan en otros lugares. Sin embargo, es enormemente beneficioso poder considerarlos como un gran autobús compartido que puede dirigir a muchos lugares.
El problema es que estoy usando estos puertos de entrada en RTL sintetizado y algunas de las herramientas de back-end tienen problemas con estas entradas cuando se trata de síntesis de baja potencia y comprobación de equivalencia lógica.
En realidad, solo hay un controlador para estas señales, por lo que nunca es necesario que entren. El problema es que algunos índices se marcarían idealmente como entrada, mientras que otros se marcarán como salida.
En el pasado, una solución ha sido utilizar vectores dispersos, uno para cada ubicación jerárquica que podría estar asignando uno de estos índices. Luego, todos se combinan, utilizando bloques de generación y máscaras de ubicación para determinar cómo asignar cada uno de los posibles controladores a la señal final.
Este enfoque termina siendo una gran sobrecarga y requiere hacer algún nivel de enmascaramiento / mapeo en cada ubicación jerárquica, y todo esto es solo para evitar tener puertos controlados individualmente como direcciones internas.
Dado que el flujo de mi herramienta de back-end no requiere el uso de puertos de entrada en este escenario, ¿alguien tiene otro enfoque que pueda ser más eficiente en la codificación?
Aquí hay un código de ejemplo para ilustrar (no probado):
Mi código ideal es el siguiente:
module driver0(inout [1:0] sig);
assign sig[0] = 'b1; // drive with some real value
endmodule
module driver1(inout [1:0] sig);
assign sig[1] = 'b1; // drive with some real value
endmodule
module top();
wire sig[1:0];
driver0 u0(.sig(sig));
driver1 u1(.sig(sig));
endmodule
Ningún bit del sig
vector es multi-accionado, solo son manejados en diferentes módulos.
Mi solución no inout es la siguiente:
module driver0(output [1:0] sig);
assign sig[0] = 'b1; // drive with some real value
assign sig[1] = 'b0; // clear unused indices
endmodule
module driver1(output [1:0] sig);
assign sig[1] = 'b1; // drive with some real value
assign sig[0] = 'b0; // clear unused indices
endmodule
module top();
wire [1:0] sig, sig0, sig1;
driver0 u0(.sig(sig0));
driver1 u1(.sig(sig1));
assign sig = sig0 | sig1;
endmodule
Requiere tener un vector disperso temporal para cada controlador posible y luego combinarlos. Esto fue solo un ejemplo con un vector de 2 bits y dos controladores. Puede imaginar que requiere bastante más esfuerzo y desperdicio de código cuando el vector es grande, ya que requiere un bucle sobre cada índice y luego tener algún mecanismo para determinar qué bits se activan en cada nivel jerárquico.