¿Puede un procesador hacer un bucle for dentro de 1 pulso de reloj?

0

Estoy en una clase de circuitos digitales. En esta clase estamos usando verilog para simular (pero no sintetizar físicamente) diferentes circuitos. Tenemos una asignación en la que se supone que simulamos un circuito y uno de los requisitos lo establece, por lo que debe haber un bucle for con un cálculo básico en un pulso de reloj:

always@(posedge clock)
    for (i=0; i<11; i=i+1) begin
        if (i*i == data)
            isPerfectSquare = 1;
    end

Lo que me pregunto es si este circuito es realmente posible de implementar en hardware real y no solo de simular. Para mí, parece imposible ajustar un bucle for completo dentro de un pulso de reloj porque un bucle for requeriría registros que se actualicen en el pulso de reloj. A mi modo de ver, necesitaría al menos 1 pulso de reloj por iteración. ¿Estoy en lo correcto o es posible construir un circuito que represente un bucle for dentro de un solo pulso de reloj?

    
pregunta Tyler H

3 respuestas

7

Cuando se sintetiza Verilog, los bucles se desenrollan. Así que el código

always @(posedge clock) begin
    isPerfectSquare = 0;
    for (i=0; i<11; i=i+1) begin
        if (i*i == data)
            isPerfectSquare = 1;
    end
end

se convertiría a

always @(posedge clock) begin
    isPerfectSquare = 0;
    if (0*0 == data)
        isPerfectSquare = 1;
    if (1*1 == data)
        isPerfectSquare = 1;
    if (2*2 == data)
        isPerfectSquare = 1;
    if (3*3 == data)
        isPerfectSquare = 1;
    if (4*4 == data)
        isPerfectSquare = 1;
    if (5*5 == data)
        isPerfectSquare = 1;
    if (6*6 == data)
        isPerfectSquare = 1;
    if (7*7 == data)
        isPerfectSquare = 1;
    if (8*8 == data)
        isPerfectSquare = 1;
    if (9*9 == data)
        isPerfectSquare = 1;
    if (10*10 == data)
        isPerfectSquare = 1;
end

que luego se implementa como un grupo de comparadores de N bits y una puerta OR de 10 entradas.

Esta es la ÚNICA manera en que se manejan los bucles en los lenguajes de descripción de hardware, incluidos tanto verilog como VHDL. El sintetizador debe poder desenrollarlos. Lo que significa que cosas como los límites de bucle deben determinarse en el momento de la síntesis, ya sea como constantes (como en su pregunta) o como parámetros que se evalúan en el momento de la síntesis.

Si desea extender la ejecución a lo largo de múltiples ciclos de reloj, debe implementar su bucle como una máquina de estados explícita.

    
respondido por el alex.forencich
8

En HDL, for loop no es algo que el hardware está ejecutando . Es algo que está generando la herramienta de síntesis. En su caso, solo se convertirá en un grupo de comparadores (11 de ellos) o hardware similar con la entrada de data y los números cuadrados de 0 a 10^2 . Y algo así como una puerta OR en sus salidas con una salida isPerfectSquare .

    
respondido por el Eugene Sh.
2

Antes de continuar con su pregunta principal, hay un par de problemas que veo con su código.

  1. Nunca inicializa "isPerfectSquare".
  2. Si usa "asignaciones de bloqueo" dentro de un bloque siempre secuencial, solo debe leer el resultado en el mismo bloque siempre. Leerlos desde otros bloques siempre puede llevar a un comportamiento impredecible y / o diferencias entre síntesis y simulación.

En particular, el primero de estos problemas puede significar que la herramienta de síntesis simplifica su código a algo como.

assign isPerfectSquare = 1;

Entonces, consideremos una versión fija de su código para que podamos continuar con su pregunta principal.

always@(posedge clock) begin
    isPerfectSquareInternal = 0
    for (i=0; i<11; i=i+1) begin
        if (i*i == data)
            isPerfectSquareInternal = 1;
    end
    isPerfectSquare <= isPerfectSquareInternal
end

Ahora juguemos a la herramienta de síntesis y veamos si podemos convertir esto en lógica combinatoria que alimente un registro final.

En general, podemos convertir una "declaración if" en un multiplexor, pero en este caso particular podemos mejorar y convertirlo en una operación lógica.

always@(posedge clock) begin
    isPerfectSquareInternal = 0
    for (i=0; i<11; i=i+1) begin
        isPerfectSquareInternal = isPerfectSquareInternal || (i*i == data)
    end
    isPerfectSquare <= isPerfectSquareInternal
end

Ahora para tratar con el bucle for. Notamos que el bucle tiene un número fijo de iteraciones, por lo tanto, podemos desenrollarlo.

always@(posedge clock) begin
    isPerfectSquareInternal0 = (0 == data)
    isPerfectSquareInternal1 = isPerfectSquareInternal0 || (1 == data)
    isPerfectSquareInternal2 = isPerfectSquareInternal1 || (4 == data)
    isPerfectSquareInternal3 = isPerfectSquareInternal2 || (9 == data)
    isPerfectSquareInternal4 = isPerfectSquareInternal3 || (16 == data)
    isPerfectSquareInternal5 = isPerfectSquareInternal4 || (25 == data)
    isPerfectSquareInternal6 = isPerfectSquareInternal5 || (36 == data)
    isPerfectSquareInternal7 = isPerfectSquareInternal6 || (49 == data)
    isPerfectSquareInternal8 = isPerfectSquareInternal7 || (64 == data)
    isPerfectSquareInternal9 = isPerfectSquareInternal8 || (81 == data)
    isPerfectSquareInternal10 = isPerfectSquareInternal9 || (100 == data)
    isPerfectSquare <= isPerfectSquareInternal10
end
    
respondido por el Peter Green

Lea otras preguntas en las etiquetas