Compresión de bits en Verilog

1

Estoy tratando de escribir un código Verilog para un multiplicador basado en el principio del ábaco. Quiero comprimir una matriz de 8X15 bits a las filas más bajas. Por ejemplo para una matriz de

    p0 = 0000000000000000
    p1 = 1111111111111111
    p2 = 0000000000000000
    p3 = 1111111111111111
    p4 = 0000000000000000
    p5 = 1111111111111111
    p6 = 0000000000000000
    p7 = 1111111111111111

Quiero que mi salida sea:

    pp[0] = 000000000000000
    pp[1] = 000000000000000
    pp[2] = 000000000000000
    pp[3] = 000000000000000
    pp[4] = 111111111111111
    pp[5] = 111111111111111
    pp[6] = 111111111111111
    pp[7] = 111111111111111

He escrito el siguiente código para lograr esto:

    always @ (p0 or p1 or p2 or p3 or p4 or p5 or p6 or p7)
 begin
 pp[1] = p0;
 pp[2] = p1;
 pp[3] = p2;
 pp[4] = p3;
 pp[5] = p4;
 pp[6] = p5;
 pp[7] = p6;
 pp[8] = p7;

for (i=1; i<=15; i=i+1)
 begin
    for (j=8; j>=1; j=j-1)
    begin
       for (k=j-1; k>=1; k=k-1)
          begin
          if ((!pp[j][i]) && (pp[k][i]))
            begin
            pp[j][i] <= pp[k][i];
            pp[k][i] <= pp[j][i];
            end
          end
      end
  end
end

pero la salida que estoy obteniendo es la siguiente:

    pp[0] = 000000000000000
    pp[1] = 000000000000000
    pp[2] = 111111111111111
    pp[3] = 000000000000000
    pp[4] = 111111111111111
    pp[5] = 000000000000000
    pp[6] = 111111111111111
    pp[7] = 111111111111111

¿Puede alguien decir dónde está la falla?

    
pregunta titan

2 respuestas

1

Puede hacer que esto funcione si reemplaza las asignaciones no bloqueadas con las asignaciones de bloqueo. Todavía no es fácilmente sintetizable, pero estaría bien como banco de pruebas. Ejemplo a continuación.

Las asignaciones no bloqueadas que usan <= no surten efecto inmediatamente, sino que se retrasan hasta un punto posterior en el tiempo, que se puede considerar como el final del paso de tiempo actual. Dado que todos los bucles for están dentro del mismo paso de tiempo, si usan asignaciones no bloqueantes, programan una serie de eventos para que ocurran al final del paso de tiempo actual. Por lo tanto, los bucles for j y for k siempre ven los valores iniciales de la matriz. A medida que se expresa este algoritmo, es necesario que estos dos bucles trabajen con los datos después de que se haya producido el intercambio.

module compressMe();

  reg [15:0] p0;
  reg [15:0] p1;
  reg [15:0] p2;
  reg [15:0] p3;
  reg [15:0] p4;
  reg [15:0] p5;
  reg [15:0] p6;
  reg [15:0] p7;

  reg [15:0] pp [7:0];

  integer i,j,k;

  reg swapTemp;

  initial
    begin
      p0 <= 16'b0000000000000000;
      p1 <= 16'b1111111111111111;
      p2 <= 16'b0000000000000000;
      p3 <= 16'b1111111111111111;
      p4 <= 16'b0000000000000000;
      p5 <= 16'b1111111111111111;
      p6 <= 16'b0000000000000000;
      p7 <= 16'b1111111111111111;
  end

  always @ (p0 or p1 or p2 or p3 or p4 or p5 or p6 or p7)
    begin
    pp[0] = p0;
    pp[1] = p1;
    pp[2] = p2;
    pp[3] = p3;
    pp[4] = p4;
    pp[5] = p5;
    pp[6] = p6;
    pp[7] = p7;

    for (i=0; i<=15; i=i+1)
      begin
          for (j=7; j>=1; j=j-1)
          begin
            for (k=j-1; k>=1; k=k-1)c
                beginc
                if (    ( !pp[j][i] )     &&    (  pp[k][i]  )    )   
                  begin
                  swapTemp = pp[j][i];
                  pp[j][i] = pp[k][i];
                  pp[k][i] = swapTemp;
                  end
                end
            end
        end
  end


  initial
    begin
    #100 for (i=0; i<=7; i=i+1)
        $display("pp[%d] = %16b ", i, pp[i]);
    end


endmodule

Esto producirá:

 ncsim> run
 pp[          0] = 0000000000000000 
 pp[          1] = 0000000000000000 
 pp[          2] = 0000000000000000 
 pp[          3] = 0000000000000000 
 pp[          4] = 1111111111111111 
 pp[          5] = 1111111111111111 
 pp[          6] = 1111111111111111 
 pp[          7] = 1111111111111111 
    
respondido por el Ken Boorom
2

El problema es que estás escribiendo un código que sería apropiado para un lenguaje de programación de software en un lenguaje de descripción de hardware.

Recuerde, en un HDL, un bucle for describe construcciones de hardware paralelas, no pasos de procesamiento secuencial.

En su caso, el bucle for externo es apropiado, ya que desea construir una lógica que maneje cada columna de forma independiente. Pero dentro de cada columna, desea contar el número de unos y luego generar un vector de bits que tenga tantos bits establecidos en una fila. La forma más fácil de especificar esto podría ser simplemente enumerar todas las posibilidades con una declaración case o una tabla de búsqueda.

Si realmente quieres hacerlo con lógica, esta respuesta puede ofrecer una pista. (Básicamente, está ordenando una lista de valores de 1 bit.)

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas