Lógica de transferencia de registros (RTL) es el resultado de la primera fase de traducción, antes de ser mapeado a los recursos específicos del proveedor, que no son portables entre proveedores o incluso entre diferentes FPGA del mismo proveedor. Esencialmente, la RTL muestra tanto la lógica combinacional como los registros síncronos (flip flops D), por lo que las máquinas de estado son reconocibles. La RTL es bastante consistente entre Altera y Xilinx, y es probablemente la fase más interesante y útil para inspeccionar. Los problemas de síntesis se hacen visibles por primera vez en la fase RTL, y el diseño sigue siendo reconocible. Una vez que pasa al mapeo específico del proveedor, se trocea y se desordena. Tratar de decodificar un flujo de bits específico de un chip es muy costoso y poco beneficioso, y será inútil cuando se cambie de proveedor o incluso de tamaño de FPGA de la misma familia. Puedes ver lo que necesitas ver en el nivel RTL.
Siempre es una buena práctica probar tu código Verilog o VHDL recién desarrollado instanciándolo dentro de un banco de pruebas o un simple módulo de nivel superior, e inspeccionando el código RTL. Xilinx ISE es muy bueno para inspeccionar la RTL como un esquema (aunque a veces se le escapan cosas.) Los problemas más comunes son:
- Redes de 1 bit donde estaba previsto un bus
- trozos de lógica que son eliminados inesperadamente por el optimizador... de forma similar a como un simple bucle de retardo spinlock es eliminado silenciosamente por la optimización del código.
- salidas no completamente especificadas, debido al enfoque procedimental en lugar del enfoque de tabla de verdad. Si la herramienta piensa que la salida termina siempre en 0 o siempre en 1, abandonará toda la lógica que genera ese resultado.
- la lógica del módulo se recorta porque uno de los submódulos se ha optimizado para que sea siempre 0 o siempre 1; esto puede ocurrir en cascada hasta el nivel superior
Esta inspección RTL se vuelve muy difícil de manejar a menos que mantenga sus módulos pequeños y simples. El uso de un banco de pruebas es una herramienta importante.
Yo también vengo de la programación de sistemas embebidos primero y de verilog después, y el mayor peligro para la gente como nosotros al aprender la codificación HDL es que mira como un lenguaje de programación procedimental, y se siente como un lenguaje de programación procedimental (durante la simulación), pero luego todo salta por los aires cuando se intenta sintetizar el código de trabajo. Realmente hay que pensar en lo que el hardware tiene que ser, y asegúrese de que el código RTL incluye todo el hardware que espera.
Aparte del hecho de que Verilog/VHDL implican teclear un código fuente en un archivo informático, no hay realmente mucho parecido con el C/C++/etc. tradicional. Se transferirá muy poco de su experiencia en programación. Céntrate en dividir los grandes problemas en pequeños problemas, documentar todo con gran detalle y escribir bancos de pruebas. Invierte también en un buen osciloscopio de muestreo digital si no tienes ya uno. Echa un vistazo a algunos de los códigos de ejemplo publicados en opencores.org, ya que con C/C++ puedes aprender mucha técnica (tanto buena como mala) leyendo el código de otras personas.
Una cosa que me vuelve loco sobre el desarrollo de FPGAs es que el control de fuentes no es algo que los vendedores de cadenas de herramientas parecen pensar que es una característica importante. Xilinx Vivado es particularmente malo en este sentido, su consejo parece ser volver a generar los archivos del proyecto desde cero al hacer un nuevo checkout. Tratar de hacer un traspaso de proyecto con archivos zip de más de 100Mb es desalentador.
La otra cosa que me vuelve loco sobre el desarrollo de FPGAs es que las herramientas Quartus/ISE/Vivado no tienen realmente una forma satisfactoria de sofocar la avalancha de mensajes de advertencia. Cuando escribo programas en C/C++, espero ser capaz de abordar cada mensaje de advertencia individualmente y arreglarlo o sancionarlo, de modo que finalmente pueda obtener una compilación limpia con cero advertencias. Nunca he visto a nadie lograr eso en el desarrollo de FPGAs; otros desarrolladores de FPGAs (que son más inteligentes que yo) parecen simplemente aceptar que un proyecto normal tiene un montón de mensajes de diagnóstico, que a menudo simplemente ignoran, dejándolo para hacer el trabajo de laboratorio y verificar en el hardware real.
Si alguna vez desarrollas tu propia placa FPGA (cosa que no recomiendo), asegúrate de sacar todos los pines de E/S que no utilices a una cabecera en algún lugar - tantos como puedas manejar - porque eso va a ser tu salvación cuando tengas que depurar el código de la FPGA, o implementar algún parche de última hora.
Has mencionado la programación en lenguaje ensamblador como una forma de ejercer un control preciso sobre lo que hace el ordenador, y es posible ejercer un control igualmente preciso sobre el código de la FPGA utilizando primitivas no portables y específicas del proveedor. Esto será diferente para cada proveedor y cada FPGA, al igual que el lenguaje ensamblador es diferente para diferentes CPUs. En el caso de Xilinx, se escribiría un archivo de restricciones (diferente para la cadena de herramientas ISE o Vivado). El archivo de restricciones llamaría a instancias específicas o redes específicas, y especificaría los requisitos de sincronización. Normalmente, los CLBs/LUTs/lo que sea de las unidades de bajo nivel están organizados en una cuadrícula, por lo que se puede fijar una primitiva de bajo nivel específica para vivir en una ubicación específica de la cuadrícula X,Y. Busca el antiguo "FPGA Editor" de Xilinx para la serie Spartan 3, solían animar a la gente a usarlo así. Creo que los nuevos chips de la serie 7 y Zynq no están soportados. Al igual que el ensamblaje, es muy específico para la tecnología, y por lo tanto es un tipo de habilidad volátil.
Al igual que con el ensamblaje, para cualquier cosa que no sea un ejercicio trivial de "deberes", realmente quieres minimizar la cantidad de ensamblaje que escribes; utiliza C/C++ para el 98%-99% y sólo escribe ensamblaje para el 1% que es sensible al rendimiento. Si, por ejemplo, tienes un diseño de FPGA que requiere que algún subproceso se ejecute a 200MHz, vale la pena sumergirse en el mapeo de bajo nivel para ver qué hacen las herramientas. La mejor recompensa para la optimización es si puedes eliminar las etapas de trabajo innecesarias. Sólo después de haber reducido los elementos calientes al mínimo, merece la pena empezar a enrutar manualmente qué IOBs pertenecen a qué ubicaciones de la rejilla. Deje que la máquina haga la mayor parte del trabajo, para que usted pueda concentrar sus esfuerzos.