Comportamiento errático en el loopback I2s basado en FPGA (Verilog + Spartan6)

0

Estoy trabajando en un proyecto personal que involucra un Xilinx Spartan6 FPGA que programo en Verilog. No soy un usuario avanzado, es mi tercer proyecto de tamaño razonable y realmente no me gusta el trabajo con los diseñadores de FPGA, así que básicamente aprendí todo solo con libros e internet. Dicho esto, solicitaré indulgencia si alguien encuentra mi diseño inadecuado.

Está bien, por lo que encuentro un problema en mi diseño que me parece bastante fascinante. Básicamente, después de cada reinicio, mi diseño se comporta de manera diferente. A veces funciona, otras veces no, y el resto del tiempo casi funciona.

El proyecto

Mi objetivo es hacer un procesador de sonido basado en FPGA. Completé la PCB y la mayoría del software y ahora estoy empezando a construir el diseño de FPGA. Aquí hay un resumen del objetivo final:

MiFPGA(XC6SLX9-3TQG144C)estáconectadoconuncódigo TLV320AIC23 . El audio se envía a través de I2S a mi FPGA y se envía a este mismo chip a través de la misma línea I2S (en contradicción con el diagrama que proporcioné, ADC y DAC son parte del mismo IC).

He escrito el módulo I2S y he hecho un paso sencillo entre la entrada y la salida para que la señal de salida de línea sea la misma que para la entrada de línea. Obtengo buena calidad de sonido en la salida cuando funciona. Cuando no es así, no recibo ningún sonido o señal distorsionada. Cuando eso sucede, se reinician 2 o 3 y los sonidos vuelven bien, otro se reinicia y comienza a distorsionarse, y así sucesivamente.

Los síntomas

Hice mucha simulación de comportamiento, todo parecía bien. Luego procedo a conectar un núcleo de Chipscope a mi diseño para averiguar qué estaba pasando, con la esperanza de encontrar algo obvio, pero encontré un comportamiento cambiante. Lo que puedo ver es que algunos DFF no cierran lo que se supone que deben hacer. Por ejemplo:

  • El registro de desplazamiento de 16 bits funciona, pero ocasionalmente se pierde un poco
  • El contador de 5 bits funciona, pero cada 2 o 3 pulsos.

Estos dos síntomas aparecen y desaparecen cuando reinicio mi dispositivo y se pueden ver en diferentes lugares del diseño. Aquí hay una captura de pantalla.

Enlaprimeraimagen,puedeverunaejecuciónfuncionalconuncontadorqueseincrementaencadabordedeBCLK.Enlasegundaimagen,sepierde1pulsode2.

Vertambién: LasúltimasimágenesmuestranunregistrodedesplazamientoqueestásiendoarrastradopordatosenlaentradaDIN,muestreadosenunbordeascendenteBCLK.Simiraconcuidadolosbordesamarillos,veráqueelregistrodedesplazamientonopudomoverelMSB.

Másdetalles

Ahoraquesehanenumeradolossíntomas,intentarédartodoslosdetallesposiblessobreloquehice.

  • Eldiseñocompletotiene1dominiodetiempo,con100MHZprovenientesdelFPGAPLL,queesimpulsadoporunosciladorexternode32MHz.
  • DetectolosbordesBCLKalcompararelvalorrealconelvaloranteriorparamantenerunsolodominiodetiempo.
  • Pongounarestriccióndetiempoencadaseñaldereloj,elmapanodaningunaadvertenciadetiempo.
  • NormalmenteconfiguroelFPGAconunmicrocontroladorSTM32incorporado.TengoelmismocomportamientoconunJTAG.
  • Elreinicioessíncrono,bajoactivo.UtilizaelmismopinquelaseñalINIT_B(notengootralíneadisponibleporahora).
  • Elcódecestácronometradoa12.288MHz,quetambiénesgeneradoporelFPGAPLL
  • Elrelojde12.288MHznotieneunalíneaderelojdedicada.SealimentadirectamenteaunOBUF.Desafortunadamente,cometíunerrordediseñodehardwareylocorregiréenunaversiónposterior.NoconduzconingúnDFFconél,directamenteaunasalida.

HecompartidoelmódulosuperioryelcódigoI2S.Veráunbuclederetornoenelnivelsuperior.

  • ElcódigoparaelmóduloI2Sestáaquí: enlace
  • El código para el módulo superior está aquí: enlace

Eso resume el problema que veo. Creo que hay un problema de tiempo en alguna parte. La depuración con Chipscope es lo más lejos que sé hacer para depurar este tipo de problema.

La pregunta

  • ¿Qué puedo mirar?
  • ¿Cuál sería el siguiente paso de depuración aquí?
  • ¿Alguien ve algo mal que yo no?

Por supuesto, puedo proporcionar más detalles a solicitud.

Gracias

    

1 respuesta

2

Esto se parece mucho a los problemas asociados con no sincronizar todas sus entradas en el dominio del reloj principal. Siempre debe estar ejecutando todas las señales de entrada a través de flip-flops antes de usarlas para cualquier cosa.

En cuanto a su reloj de 12,288 MHz; use un elemento ODDR2 para conducirlo de esta manera:

ODDR2 #(
    .DDR_ALIGNMENT("C0"),
    .SRTYPE("ASYNC")
)
oddr_inst (
    .Q(clk_out),
    .C0(clk),
    .C1(~clk),
    .CE(1'b1),
    .D0(1'b0),
    .D1(1'b1),
    .R(1'b0),
    .S(1'b0)
);

Tenga en cuenta que los pines del reloj global solo son necesarios para que los relojes entren en el FPGA. Los relojes de conducción pueden realizarse en cualquier pin, y la forma recomendada de hacerlo es con un flip flop DDR para que pueda generar con precisión un reloj invertido que se alinee exactamente con los datos de los flip flops IOB controlados por el mismo reloj.

    
respondido por el alex.forencich

Lea otras preguntas en las etiquetas