Generar puerta con un número parametrizado de entradas

5

Estoy intentando generar una puerta de entrada múltiple para la cual se pueden seleccionar las entradas cuando se elabora el diseño.

Déjame dar un ejemplo para (con suerte) aclarar esto:

module selectable_xor(input [7:0] in, output out);

parameter [7:0] SELECT = 8'b10010100;

// this should be generated for the default value of SELECT:
assign out = in[7] ^ in[4] ^ in[2]

endmodule

Entonces, out debería ser la salida de una puerta XOR que tiene esos bits de in como entrada para la cual se establece el bit correspondiente en SELECT .

Estoy intentando algo como lo siguiente:

generate
  genvar gen_i;
  assign out = 1'b0;

  for (gen_i = 0; gen_i < 8; gen_i = gen_i + 1)
    if (SELECT[gen_i])
      assign out = out ^ in[gen_i];
endgenerate

Pero esto produce valores no definidos para la señal out .

¿Hay alguna buena manera de generar una puerta con un número variable de entradas en Verilog?

PS: Sobre el caso de uso: estoy intentando implementar un LFSR para el cual el polinomio es un parámetro.

Editar: El consenso parece ser que debo usar la siguiente expresión equivalente y confiar en el sintetizador para optimizarlo al circuito que quiero:

assign out = ^(in & SELECT);

Aunque confío en que cualquier sintetizador decente podrá hacer esto, me gustaría saber si Verilog puede codificar este circuito en realidad en una forma en que Verilog pueda hacerlo.

Considere que, en lugar de la puerta XOR anterior, quería codificar una puerta OR. La expresión equivalente es:

assign out = |(in & SELECT);

Ok, eso es prácticamente lo mismo que para la puerta XOR. Para una puerta AND, sin embargo, la expresión es diferente:

assign out = &(in | ~SELECT);

Mi punto es que para cada tipo de puerta, podría tener que encontrar una expresión equivalente diferente. Prefiero tener una forma general de codificar una puerta para la cual se puedan parametrizar las entradas porque entonces puedo usar la misma técnica para cualquier tipo de puerta.

Editar 2: Como mi recompensa vence mañana, editaré esta pregunta una vez más para eliminarla. Este es un comentario que dejé para explicar lo que quiero, que espero sea más visible en el cuerpo de la pregunta:

  

Lo que quiero no tiene nada que ver con los recursos físicos. Cuando hablo   sobre "puertas" me refiero al concepto Verilog. Quiero ser capaz de definir   Una puerta con entradas en función de algún parámetro. Más específicamente, yo   desea que esta puerta tenga in[i] como entrada si se establece SELECT[i] . yo    no desea una expresión equivalente que podría estar optimizada para la puerta que deseo. Como he dicho antes, esta expresión equivalente podría   así como implementarse como 8 puertas AND y una puerta XOR de 8 entradas porque    eso es lo que realmente está codificado . Espero que esto aclare las cosas :-)

    
pregunta Job

4 respuestas

2

Si entendí tu pregunta correctamente, creo que el siguiente módulo hace lo que quieres. Puede simplemente especificar la puerta por su operador ( ^ , & , | , etc.) y nada más. Además, solo se generan las asignaciones deseadas (que es lo que estoy buscando).

'timescale 1 ns / 1 ps

module selectable_gate(input [7:0] in, output out);

parameter [7:0] SELECT = 8'b10010100;

function integer count_ones;
  input [7:0] v;
  integer ret;
  integer i;
  begin
    ret = 0;
    for(i=0;i<8;i=i+1) begin
      if (v[i]) begin
        ret = ret+1;
      end
    end
    count_ones = ret;
  end
endfunction

function integer nth_one;
  input integer n;
  input [7:0] v;
  integer i,ret,cnt;
  begin
    ret = -1;
    cnt = 0;
    for(i=0;i<8;i=i+1) begin
      if (v[i]) begin
        if (cnt == n) begin
          ret = i;
        end
        cnt = cnt+1;
      end
    end    
    nth_one = ret;
  end
endfunction

localparam integer w = count_ones(SELECT);
wire [w-1:0] y;

generate
  genvar i;
  for(i=0 ; i<w ; i=i+1) begin
    assign y[i] = in[nth_one(i,SELECT)];
  end
endgenerate

assign out = ^y; // specify gate here (e.g. ^y, &y, |y, etc)

endmodule;  

El módulo anterior para el SELECT = 8'b10010100 predeterminado debería terminar generado como:

assign y[0] = in[2];
assign y[1] = in[4];
assign y[2] = in[7];
assign out  = ^y;

Que es lo mismo que xor(in[2],in[4],in[7]) .

Dado que los genvars siempre se desenrollan como constantes dentro de genera, el truco consistió en encontrar constantes que permitan las condiciones adecuadas para generar y usar funciones para cualquier manipulación de variable temporal necesaria para calcularlas.

    
respondido por el apalopohapa
5

Probar

assign out = ^(in & parameter);

El & selecciona aquellos bits que son 1 en el parámetro, y luego ^ los XORARÁN todos juntos. Aquellos bits que son 0 en el parámetro serán ignorados.

    
respondido por el pjc50
1

Lo siguiente es equivalente a lo que quiero:

assign out = ^(in & SELECT);

Y me di cuenta de que Xilinx ISE sintetiza esto en una puerta XOR de 3 entradas para el valor predeterminado de SELECT , que es exactamente lo que quiero.

Sin embargo, como esto podría sintetizarse en 8 puertas AND y una puerta XOR de 8 entradas, todavía estoy muy interesado en otras respuestas. Me gustaría tener una forma de codificar esto en Verilog en lugar de tener que confiar en la herramienta de síntesis.

    
respondido por el Job
0
generate
  genvar gen_i;
  assign out = 1'b0;

  for (gen_i = 0; gen_i < 8; gen_i = gen_i + 1)
    if (SELECT[gen_i])
      assign out = out ^ in[gen_i];
endgenerate

El problema con este código es que tiene varias declaraciones de asignación que se van a enviar. Creo que lo siguiente debería funcionar.

wire [8:0] tmp;
generate
  genvar gen_i;
  assign tmp[0] = 1'b0;

  for (gen_i = 0; gen_i < 8; gen_i = gen_i + 1)
    if (SELECT[gen_i])
      assign tmp[i+1] = temp[i] ^ in[gen_i];
    else
      assign tmp[i+1] = temp[i]
endgenerate
assign out = tmp[8]
    
respondido por el Peter Green

Lea otras preguntas en las etiquetas