Página 1 de 1

Crear módulos combinacionales con IF-ELSE incompletos de forma que no generen latches

Publicado: 15 Ago 2018, 13:46
por mcleod_ideafix
Esta es una traducción de un post/pregunta que hice hace ya tiempo en Stack Overflow. El texto original y las respuestas que me dieron están aquí:
https://stackoverflow.com/q/20084928/3011009

Digamos que quiero escribir un módulo combinacional que usa 4 entradas y 3 salidas. Para modelar mi lógica, hago algo como esto:

Código: Seleccionar todo

module ifelse (
      input wire a,
      input wire b,
      input wire c,
      input wire d,
      output reg y1,
      output reg y2,
      output reg y3
      );

     always @* begin

       if (a==1'b1 && b==1'b0) begin
         y1 = 1'b0;
         y3 = 1'b1;
         end
       else if (a==1'b0 && c==1'b1 && d==1'b0) begin
         y2 = 1'b1;
         y1 = 1'b1;
         end
       else if (a==1'b0 && c==1'b0) begin
         y3 = 1'b0;
         y2 = 1'b0;
       end
   end
endmodule
Por supuesto, sé que este código va a inferir latches para y1,y2 e y3, y que la forma de evitarlo es asignar siempre un valor a todas las variables en cada una de las ramas del if-else, tal que así:

Código: Seleccionar todo

module ifelse (
      input wire a,
      input wire b,
      input wire c,
      input wire d,
      output reg y1,
      output reg y2,
      output reg y3
      );

     always @* begin

       if (a==1'b1 && b==1'b0) begin
         y1 = 1'b0;
         y3 = 1'b1;
         y2 = 1'bx;
         end
       else if (a==1'b0 && c==1'b1 && d==1'b0) begin
         y2 = 1'b1;
         y1 = 1'b1;
         y3 = 1'bx;
         end
       else if (a==1'b0 && c==1'b0) begin
         y3 = 1'b0;
         y2 = 1'b0;
         y1 = 1'bx;
       end
       else begin
         y1 = 1'bx;
         y2 = 1'bx;
         y3 = 1'bx;
       end
   end
endmodule
Pero ahora imaginemos que hay un montón de bloques if-else (estoy intentando describir la unidad de control para un microprocesador didáctico) y que hay un montón de salidas que provienen de este módulo (las lineas de control para todos los registros de la ruta de datos del procesador). Tener que asignar un valor a todas las salidas en todas y cada una de las ramas del bloque if-else múltiple no es una opción, ya que da lugar a código ilegible e inmantenible. Cada vez que quiera añadir una nueva salida, tengo que replicarla en todos los if-else!!

Entonces la cuestión es: cómo dar un valor "por defecto" a las salidas cuando alguna de ellas no se usa en alguno de los bloques if-else.¿Hay algo parecido a un "default" para todas aquellas señales que no se actualizan en el bloque, de forma que una vez evaluado, si alguna salida no se ha actualizado, tome el valor "por defecto" o a un valor "don't care"?

Hasta ahora, lo que se me ha ocurrido hacer es esto:

Código: Seleccionar todo

module ifelse(
    input wire a,
    input wire b,
    input wire c,
    input wire d,
    output reg y1,
    output reg y2,
    output reg y3
    );

   always @* begin
      // default values
      y1 = 1'bx;
      y2 = 1'bx;
      y3 = 1'bx;

      if (a==1'b1 && b==1'b0) begin
         y1 = 1'b0;
         y3 = 1'b1;
      end
      else if (a==1'b0 && c==1'b1 && d==1'b0) begin
         y2 = 1'b1;
         y1 = 1'b1;
      end
      else if (a==1'b0 && c==1'b0) begin
         y3 = 1'b0;
         y2 = 1'b0;
      end
   end
endmodule
Pero querría saber si existe algo máas elegante en Verilog. Algo como esto (que no es Verilog)

Código: Seleccionar todo

module ifelse(
    input wire a,
    input wire b,
    input wire c,
    input wire d,
    output reg y1,
    output reg y2,
    output reg y3
    );

   always @* begin
      if (a==1'b1 && b==1'b0) begin
         y1 = 1'b0;
         y3 = 1'b1;
      end
      else if (a==1'b0 && c==1'b1 && d==1'b0) begin
         y2 = 1'b1;
         y1 = 1'b1;
      end
      else if (a==1'b0 && c==1'b0) begin
         y3 = 1'b0;
         y2 = 1'b0;
      end
      @* = x;  // esto no existe en Verilog. Sería para indicar que todas las salidas no actualizadas toman el valor "dont care"
   end
endmodule
Entonces... ¿existe algo parecido a esto? ¿Es lo que yo hago lo habitual, o hay una solución más elegante?

La respuesta que me dieron es que lo que yo hago es lo correcto, salvo por un detalle: que no puedo asignar un valor "x" a una variable porque "x" significa "desconocido", no "don't care". Resulta que el valor "x" sólo significa "don't care" cuando se usa como expresión en un case (realmente cuando se usa en un casex)