Je viens de commencer à apprendre la conception de la logique numérique avec les FPGA et j'ai construit de nombreux projets. La plupart du temps (puisque je suis une sorte de noob), j'ai un design qui simule parfaitement (simulation comportementale) mais ne synthétise pas correctement.
Donc, ma question est "quelles sont les étapes de conception que je peux incorporer dans mon flux de travail, qui assureront que j'ai une conception fonctionnelle qui fonctionnera directement sur mon FPGA?"
J'ai deux domaines principaux où je m'attends à conseiller, mais cela est absolument basé sur un point de vue très étroit du mien en tant que débutant, et d'autres sont les bienvenus:
- Quelles sont les étapes (visualisation du schéma RTL, simulation post-synthèse, ...) dois-je entreprendre un apprentissage pour les meilleures pratiques.
- Que dois-je garder à l'esprit lors de la conception de ma logique (disons FSM ou circuits séquentiels) pour éviter tout résultat inattendu.
J'utilise un FPGA Xilinx Spartan 6 et Xilinx ISE Design pour mon travail.
Réponses:
Dans un endroit où je travaillais, il y avait deux camps de concepteurs FPGA. Un camp que j'ai appelé simuler, simuler, simuler ou être cubé. L'autre camp était entièrement dédié au design.
Les gars en cubes ont utilisé un simulateur comme modelsim, ils proposeraient une conception initiale via des méthodes de codage et / ou des blocs dans la suite de conception. Ensuite, ils le simulaient et trouvaient les choses qui ne fonctionnaient pas, puis changeaient le code. Ce processus a été répété plusieurs fois jusqu'à ce qu'ils trouvent une conception qui fonctionne.
Le camp de conception (que j'ai préféré) concevrait la forme d'onde sur papier (ou papier numérique comme visio), exactement ce qui était nécessaire. Venez ensuite avec un diagramme logique. Il s'agit d'un processus d'auto-documentation. Ensuite, le diagramme a été traduit en code (le code et le diagramme étaient 1: 1 s'il y avait quelque chose dans le diagramme, il y avait un processus pour cela dans le code). Ensuite, il a été simulé, et la forme d'onde de simulation a été comparée à la forme d'onde conçue sur papier, et devait être la même.
J'ai fini par faire les deux, parfois je passais en mode cube, et ce n'était pas très amusant. J'ai trouvé que j'avais parfois perdu de vue mon objectif. Par exemple, je changerais un état dans une machine d'état, et le changement se répercuterait sur l'état suivant, alors je devrais corriger cela. J'ai fini par passer plus de temps que d'y penser.
Dans quel camp préféreriez-vous être? Je pense qu'il faut une conception rigoureuse, faites ce qui fonctionne pour vous, mais je pense que plus vous êtes détaillé et rigoureux dans la conception, moins vous aurez de problèmes à long terme. J'ai donné quelques exemples de ce qui est possible, ils peuvent ne pas correspondre à la structure organisationnelle de votre lieu de travail. La raison pour laquelle les détails de conception et une planification minutieuse sont si utiles, c'est qu'ils vous obligent à réfléchir à ce que vous faites. Cela facilite le débogage. Développer un flux de travail de conception qui permet que cela se produise. De plus, familiarisez-vous vraiment avec les outils de simulation et écrivez de bons bancs de test qui testeront toutes les conditions que le dispositif simulé pourrait rencontrer. Bien sûr, cela doit être équilibré avec le temps. Par exemple, écrivez le code ADC HDL qui simulera l'appareil dans vos simulations.
L'outil le plus précieux à avoir dans la conception de FPGA (à mon avis) est une bonne procédure de test qui vous permettra de tester pleinement votre conception et de la mettre à l'épreuve. On ne peut pas s'attendre à ce qu'une conception FPGA "fonctionne juste", il faut des efforts pour s'assurer que toutes les pièces fonctionnent. Si vous repérez des erreurs, revenez à la simulation et à la conception et découvrez les différences entre un FPGA simulé et un RTL. Cela vient principalement de l'expérience, mais si la conception fonctionne en simulation mais pas en matériel, vous devez savoir pourquoi il y a une différence.
Quelques éléments clés que j'ai appris:
1) Désinfectez vos entrées, l'horloge et les circuits de réinitialisation doivent être propres ou vous pouvez obtenir une métastabilité se propageant à travers votre système. Sachez ce qu'est un synchroniseur à double rang. Il existe de nombreuses topologies différentes pour les circuits de réinitialisation, sachez comment les utiliser (il y a un excellent article sur le Web, je ne l'ai pas sous la main cependant).
2) Obtenez les exigences de la conception à l'avance, puis concevez-les. Si les gens autour de vous ne vous donneront pas d'exigences précises, alors créez-en vous-même.
3) La boîte à outils à point fixe Matlab est idéale pour simuler des systèmes de contrôle et des applications DSP, mais vous pourriez ne pas y avoir accès. C'est un excellent moyen de prouver une conception avant de coder.
4) La conception vient en premier, puis le codage, puis la simulation.
5) Fortement typé, gardez également les noms de signal cohérents sur le schéma de la carte PCB et le hdl. (c'est aussi pourquoi je préfère de loin le VHDL au verilog.
la source
Les principales choses sont:
J'ai eu plusieurs conceptions assez complexes qui fonctionnent correctement (ou du moins pour la plupart correctement) lors du premier test sur un FPGA réel en suivant ce qui précède. Pas besoin de vérifier le schéma RTL, c'est juste extrêmement lourd et une perte de temps complète pour les grands modèles. Une simulation post-synthèse serait beaucoup plus utile.
la source
Tout votre code synthétisable doit pouvoir être exprimé comme:
Les primitives spécifiques au fournisseur sont soit instanciées explicitement, soit générées par l'assistant du fournisseur, soit inférées par des modèles de codage très spécifiques, il ne devrait donc y avoir aucune ambiguïté.
En VHDL par exemple, vous ne pouvez pas utiliser
wait for
de code synthétisable. Pour comprendre pourquoi, essayez d'exprimer de façon déterministe enwait for 100 ns
utilisant des LUT ou des tongs. Tu ne peux pas.Cela ne signifie pas que vous ne pouvez pas l'implémenter en configurant un compteur avec une fréquence d'horloge connue (avec une période qui peut diviser 100 ns) et en utilisant son compte pour savoir quand le temps est écoulé. Mais le moteur de synthèse ne proposera pas automatiquement ce schéma, vous devez être explicite sur l'architecture en termes de logique combinatoire (portes / LUT) et de registres.
Donc, la principale chose à garder à l'esprit afin de générer du code synthétisable est d'avoir une image relativement claire de la façon dont votre code devient des portes logiques et des bascules. C'est vraiment ça.
la source
wait until rising_edge(clk);
est certainement synthétisable, bien que certains outils imposent des restrictions à son utilisation.La première étape la plus évidente consiste à vérifier les avertissements.
Les outils Xilinx produisent des fichiers journaux qui avertissent de tout ce qui pourrait ne pas être ce que le codeur voulait. Parfois, cela est ennuyeux, lorsque vous avez des tonnes d'avertissements sur les signaux inutilisés que vous savez parfaitement bien inutilisés. Mais parfois, il détecte de véritables bogues. Si vous êtes un débutant, les chances que vous commettiez une erreur sont considérablement plus élevées.
Ensuite, vous devez configurer des contraintes de temps. À quelle vitesse après un front montant sur l'horloge A la ligne de données B doit-elle être définie? Ou combien de temps la ligne de données B doit-elle être maintenue avant un front descendant sur l'horloge A? Les contraintes de temps vous permettront de spécifier tout cela. Si vous n'avez pas de contraintes de temps, le compilateur peut supposer que vous ne vous en souciez pas particulièrement et pourrait acheminer vos signaux n'importe où. Si vous avez des contraintes de temps, le compilateur s'assurera que vos signaux respectent ces contraintes en déplaçant le placement. Et s'il ne peut pas respecter les contraintes de temps, il affichera un avertissement.
Si votre problème est que les sorties ne font pas ce que vous attendez, examinez en détail les blocs d'E / S. Chaque broche d'E / S a un peu de logique associée et une bascule. L'ordre dans lequel vous spécifiez vos variables de logique et d'état dans votre code peut ne pas permettre à votre code de s'intégrer dans cette architecture, vous obtenez donc un délai supplémentaire quel que soit l'endroit où il se trouve. Les avertissements sur les contraintes de temps vous diront si cela se produit (en supposant que vous avez configuré vos contraintes de temps), mais pour y remédier, vous devez comprendre le matériel et comment votre conception sera mappée en matériel. Généralement, ce n'est un problème que lorsque vous commencez à atteindre des taux d'horloge élevés, mais cela vaut la peine d'être mentionné.
la source