¿Cuál será la síntesis de este pequeño fragmento de Verilog?

-2
always_comb begin

  for (index = 0; index < NUM_REQUESTORS; index++ ) begin

          if (valid[index]) begin

               grant = index;

               break ;

          end

  end

end

Mi conjetura es que sintetizará en una cadena de multiplexores tantos como NUM_REQUESTORS, y el más cercano a otorgar tendrá una línea de selección válida [0]. Pero seguramente esto no puede escalar bien con NUM_REQUESTORS grandes. ¿Qué piensas?

    
pregunta frank_010

2 respuestas

0

Simplemente, no se sintetizará.

La declaración break en Verilog es solo para fines de simulación, es decir, para hacer bancos de pruebas.

No se puede romper un bucle for en Verilog sintetizable, simplemente porque el bucle for no se "ejecuta" como un bucle for. El compilador la desenrolla en hardware. Por esta razón, el número de bucles debe ser una constante conocida en el punto de síntesis. No puede, por ejemplo, sintetizar:

for (idx = 0; idx < someVariable; idx = idx + 1) ...

Porque al igual que con una instrucción break, el número de bucles ya no se conocerá en el punto de síntesis.

En su lugar, debes pensar en esto en términos de hardware. Lo que su descripción parece ser un codificador de prioridad: establecerá la concesión igual al índice más bajo para el que valid es un 1. Puede lograr este resultado utilizando un bucle sin la necesidad de una declaración de interrupción. Si utilizamos asignaciones de bloqueo, podemos hacer:

grant = 0; //Default value if there are none valid
for (idx = NUM_REQUESTORS; idx > 0; idx = idx - 1) begin
    if (valid[idx-1]) begin
        grant = idx-1;
    end
end

Tenga en cuenta que aquí estamos haciendo una cuenta regresiva ya que todos los pases de bucle producirán hardware y queremos que el índice más bajo tenga la mayor prioridad.

Este circuito, como usted sospecha, se desenrollará en una cadena de multiplexores, similar a hacer una larga cadena de if-elseif-else . Ese es el precio que pagas por los codificadores de prioridad.

Si no necesita prioridad en su sistema (digamos que simplemente está tratando de arbitrar entre múltiples maestros que acceden a un esclavo) puede usar otros esquemas de arbitraje, como el round robin. En el round robin simplemente tendrías que la señal grant es un contador. Cada ciclo de reloj, el contador se mantendría igual si el maestro actual es válido, o si no lo fuera, se incrementaría al siguiente maestro.

    
respondido por el Tom Carpenter
0

Uno puede volver a escribir esto fácilmente sin una declaración break , una herramienta de síntesis también.

bit breakout;
always_comb begin
  breakout = 0;
  grant = some_value; // if there is no valid[index]
  for (index = 0; index < NUM_REQUESTORS; index++ ) begin
     if (!breakout)
          if (valid[index] ) begin
               grant = index;
               breakout = 1;
          end
  end
end

Esto se desenrolla como

grant = valid[0] ? 0 : valid[1] ? 1 : valid[2] ? 2 : ... : some_value
    
respondido por el dave_59

Lea otras preguntas en las etiquetas