¿cómo resolver un gran retraso lógico combinacional?

-2

Soy nuevo en systemverilog. Recientemente estoy trabajando en un proyecto para decodificar un flujo de datos de un AVALON_ST. Utilizando systemverilog. Mi dispositivo de destino es Stratix V y el reloj es de 200Mz.

module decoder(
  // clk and reset
  input logic reset_n,
  input logic clk,

  // avalon st
  input logic in_vld,
  input logic in_sop,
  input logic in_eop,
  input logic[255:0] in_data,
  input logic[4:0] in_eop_pos,

  // output
  output logic trigger
  );

  // local logics
  shortint pos;
  shortint limit;
  shortint offset;
  logic[511:0] buffer;
  logic[255:0] remainning_data;
  business_object obj; // systemverilog struct for the packed data

  always_ff @(posedge clk or negedge reset_n) begin
    // (0)
    // handle reset_n

    // (1)
    // whenever in_vld, combine remainning_data (if any) and in_data
    // to buffer

    // (2)
    // update pos, limit and offset based on in_eop_pos

    // (3)
    // decode the buffer and populate business_object field by field

    // (4)
    // if a completed obj is decoded, applied the business rule to output trigger

    // (5)
    // if there are remainning data bits (either after a full decoded obj 
    // or remainning bits that are not enough to pouplate business_object),
    // store it in remainning_data

  end

endmodule

Uso la asignación sin bloqueo para las partes # 0 y # 4 y la asignación de bloqueo para # 1, # 2, # 3 y # 5.

Uso ModelSim para simular el decodificador. Funciona. Sin embargo, no funciona en hardware.

Después de la investigación, descubrí que hay algo resaltado en rojo en el Analizador de tiempo de Quartus que dice que:

"El diseño contiene rutas de instalación con errores con una holgura de -9.561ns en el peor de los casos"

Hay un gran retraso lógico combinacional que excede un período de reloj.

Mis preguntas son:

1) ¿Importa el retraso lógico combinacional si hay varias asignaciones de bloqueo (# 1, # 2, # 3, # 5) dentro del bloque always_ff?

Sé que no es la mejor práctica tener una asignación de bloqueo dentro de always_ff pero aprendí de alguna parte que está bien tener una asignación de bloqueo para variable local o en el caso de que solo haya un bloque always_ff en el módulo.

Si es importante, ¿puedo reducir el retraso moviendo estas lógicas de asignación de bloqueo a always_comb?

2) La interfaz de Avalon tiene 256 bits de ancho y ya estoy usando la forma de línea de pines en mi diseño. ¿Algún otro consejo que pueda reducir el retraso lógico?

Update@20180806

Observo el esquema RTL junto con el analizador de tiempo y traté de entender por qué hay tantos niveles lógicos y señales de salida. Descubrí que lo siguiente consume suficiente demora en la ruta de datos:

a) if / else statement / switch-case en pos , offset etc

b) cálculo matemático (por ejemplo, adder ) en pos , offset

Utilicé shortint general como tipo de datos para pos y limit , que eran señales locales para representar el número de bits leídos / pendientes de lectura / bits restantes, etc. El rango de datos de negocios de pos es 12k bits (1500 bytes) y offset 256 bits (32 bytes), así que el original usé shortint (16 bits). Fui demasiado generoso.

Ahora, cambié a bit[5:0] para offset y bit[9:0] para que pos represente el número de BYTES leídos / pendientes. Reduce el recuento de ALM del módulo de 3800 a 1900, reduce significativamente el retraso de los datos y ahora se cumple el requisito de tiempo.

Gracias a todos.

    
pregunta Ken Tsang

2 respuestas

0

Parece que falta el código que hace las asignaciones. Esperaría algo como "pos < = offset + 1", etc ... y sin el código es difícil decirle exactamente dónde dividir su código.

Pero aquí hay algunos consejos para ponerte en marcha: Primero, en virtud del hecho de que tiene "o negedge reset_n" en su lista de sensibilidad de proceso, implica que usará señales de reinicio asíncrono activo-bajo ... lo que significa que un pulso de reinicio tendrá efecto inmediatamente, Y no esperes hasta el próximo borde del reloj. Cuando incluya un reinicio asíncrono como este, deberá asegurarse de que el resto de su código incluya realmente una cláusula "if / else" que especifique QUÉ HACER cuando exista una condición de reinicio (entonces el sintetizador se conectará al reinicio asíncrono señal al pin "borrar / configurar" del Flip-Flop. Al omitir accidentalmente la cláusula "if! reset_n", se crea un circuito falso que no se puede sintetizar correctamente.

Segundo, los valores de #delay solo ocurren en la simulación. Este es un mal hábito para usarlos, ya que le permitirá crear y ver (falsamente) actualizaciones a un valor en la "memoria" del simulador en diferentes momentos, pero eso no es realmente cómo funcionará el hardware. En el hardware, todas las operaciones se compondrán y se sintetizará un gran circuito para hacer toda la aritmética, y el sintetizador puede mover las operaciones fuera de orden para un mejor rendimiento.

En tercer lugar, comenzar este "siempre bloque" con "always_ff @ (cliqueo de posición" significa que todo dentro de él funciona de manera síncrona a la señal de clk, y que todos los códigos / asignaciones deben ser sin bloqueo ... todo ocurrirá en paralelo sincrónico con el borde del reloj. Así que si realmente quieres algunas asignaciones de bloqueo, crea un bloque always_comb completamente separado y pon tu lógica combinatoria ahí ... veo que las personas hacen esto cuando están calculando un valor intermedio, por ejemplo, pero en general debería pensarse como una nube de lógica que probablemente (según el uso) se absorberá en los circuitos síncronos donde se usa en la síntesis.

Y finalmente, para resolver su problema de tiempo, necesita canalizar su diseño. Haga esto realizando las manipulaciones aritméticas / de bits en diferentes ciclos de reloj, no simplemente cambiando si están bloqueando o no bloqueando. Por ejemplo, la salida < = A B C D; puede ser un circuito muy grande, pero si crea un par de variables temporales (registros) y en el primer ciclo de reloj, haga lo siguiente: temp1 < = A B; temp2 < = C * D; luego, en el segundo ciclo de reloj, usted genera la salida < = temp1 * temp2, luego descompone con éxito un circuito enorme en tres circuitos más pequeños ... a costa de un reloj de latencia adicional. Normalmente, en una aplicación de transmisión por secuencias que es aceptable, pero tendrás que descubrir cómo debe cambiar el resto del diseño para adaptarse a la latencia.

    
respondido por el macman50
0

Después de días de investigación, todavía no puedo solucionar el problema. Sin embargo, encontré esta capacitación en línea de Intel Altera que puede ayudar.

enlace

Al menos puedo reconocer algunas características de tiempo de falla en mi diseño:

1) altas señales de salida

2) alto nivel lógico combinacional

3) codificadores de prioridad no deseados

    
respondido por el Ken Tsang

Lea otras preguntas en las etiquetas