Acabei de começar a aprender design de lógica digital com FPGAs e tenho construído muitos projetos. Na maioria das vezes (já que sou meio noob), tenho um design que simula perfeitamente (simulação comportamental), mas não é sintetizado adequadamente.
Portanto, minha pergunta é "quais são as etapas de design que posso incorporar no meu fluxo de trabalho, que garantirão que eu tenha um design funcional que funcione corretamente no meu FPGA?"
Eu tenho duas áreas principais em que espero aconselhar, mas isso é absolutamente baseado em um ponto de vista muito restrito para iniciantes, e mais são bem-vindos:
- O que todas as etapas (visualização do esquema RTL, simulação pós-síntese, ...) devem ser realizadas para a melhor prática.
- O que todas as coisas devo ter em mente ao projetar minha lógica (digamos FSM ou circuitos seqüenciais) para evitar resultados inesperados.
Estou usando um pacote Xilinx Spartan 6 FPGA e Xilinx ISE Design para o meu trabalho.
Respostas:
Em um local em que trabalhei, havia dois campos de designers de FPGA. Um campo que chamei de simular, simular, simular ou é dividido em cubos. O outro campo era sobre design.
Os caras em cubos usavam um simulador como o modelsim; eles apresentavam um design inicial através de métodos de codificação e \ ou blocos no conjunto de design. Em seguida, eles simulavam e encontravam as coisas que não funcionavam, depois mudavam o código. Esse processo foi repetido várias vezes até que eles apresentassem um design que funcionasse.
O campo de design (que eu preferia) projetaria a forma de onda em papel (ou papel digital como visio), exatamente o que era necessário. Em seguida, crie um diagrama lógico. Este é um processo de auto-documentação. Em seguida, o diagrama foi convertido em código (o código e o diagrama eram 1: 1, se havia algo no diagrama, havia um processo para ele no código). Em seguida, foi simulada, e a forma de onda da simulação foi comparada com a forma de onda projetada no papel e esperava-se que fosse a mesma.
Acabei fazendo as duas coisas, às vezes entrava no modo s em cubos e não era muito divertido. Descobri que às vezes perdi de vista meu objetivo. Por exemplo, eu mudaria um estado em uma máquina de estado, e a mudança seria reduzida para o próximo estado, então eu teria que consertar isso. Acabei passando mais tempo do que pensando sobre isso.
Em que campo você prefere estar? Acho que precisa haver um design rigoroso, fazer o que funciona para você, mas acho que quanto mais detalhado e rigoroso você estiver no design, menos problemas você terá a longo prazo. Dei alguns exemplos do que é possível, eles podem não se encaixar na estrutura organizacional do seu local de trabalho. A razão pela qual os detalhes do projeto e o planejamento cuidadoso são tão úteis, é que o força a pensar no que está fazendo. Isso facilita a depuração. Desenvolva um fluxo de trabalho de design que permita que isso aconteça. Além disso, familiarize-se com as ferramentas de simulação e escreva boas bancas de teste que testarão todas as condições que o dispositivo simulado pode enfrentar. É claro que isso precisa ser equilibrado com o tempo. Por exemplo, escreva o código ADC HDL que simulará o dispositivo em suas simulações.
A ferramenta mais valiosa para ter no design de FPGA (na minha opinião) é um bom procedimento de teste que permitirá que você teste completamente seu design e execute-o em seus ritmos. Não se pode esperar que um projeto de FPGA "funcione" apenas, é necessário um esforço para garantir que todas as peças funcionem. Se você encontrar erros, volte à simulação e ao design e aprenda quais são as diferenças entre um FPGA e RTL simulados. Isso vem principalmente da experiência, mas se o design funciona em simulação, mas não em hardware, você precisa descobrir por que há uma diferença.
Algumas coisas importantes que aprendi:
1) Desinfetar suas entradas, o relógio e os circuitos de redefinição precisam estar limpos ou você pode obter a metastablidade propagando-se pelo seu sistema. Saiba o que é um sincronizador de classificação dupla. Existem muitas topologias diferentes para os circuitos de redefinição, sei como usá-los (há um ótimo artigo na Web, eu ainda não o tenho em mãos).
2) Obtenha os requisitos do design antecipadamente e, em seguida, faça o design em torno deles. Se as pessoas ao seu redor não fornecerem requisitos definidos, crie alguns por conta própria.
3) A caixa de ferramentas de ponto fixo da Matlab é ótima para simular sistemas de controle e aplicativos DSP, mas você pode não ter acesso a isso. É uma ótima maneira de provar um design antes de codificar.
4) O design vem primeiro, depois codifica e depois simula.
5) Fortemente digitado, também mantenha os nomes dos sinais consistentes nos esquemas PCB e HDL. (é também por isso que prefiro o VHDL ao verilog.
fonte
As principais coisas são:
Eu tive vários projetos bastante complexos funcionando corretamente (ou pelo menos na maior parte corretamente) no primeiro teste em um FPGA real, seguindo o acima. Não é necessário verificar o esquema RTL, isso é extremamente complicado e é uma completa perda de tempo para projetos grandes. Uma simulação pós-síntese seria muito mais útil.
fonte
Todo o seu código sintetizável precisa ser expressável como:
As primitivas específicas do fornecedor são instanciadas explicitamente ou geradas pelo assistente do fornecedor ou inferidas por padrões de codificação muito específicos, portanto, não deve haver ambiguidade.
No VHDL, por exemplo, você não pode usar
wait for
no código sintetizável. Para entender o porquê, tente expressar de forma determinísticawait for 100 ns
usando LUTs ou chinelos. Você não pode.Isso não significa que você não pode implementá-lo configurando um contador com uma frequência de clock conhecida (com período que pode dividir 100 ns) e use sua contagem para saber quando o tempo acabou. Mas o mecanismo de síntese não criará esse esquema automaticamente. Você precisa ser explícito sobre a arquitetura em termos de lógica combinatória (gates / LUTs) e registros.
Portanto, o principal a ter em mente para gerar código sintetizável é ter uma imagem relativamente clara de como seu código se torna portas lógicas e chinelos. É isso mesmo.
fonte
wait until rising_edge(clk);
é certamente sintetizável, embora algumas ferramentas imponham restrições ao seu uso.O primeiro passo mais óbvio é verificar os avisos.
As ferramentas Xilinx produzem arquivos de log que alertam sobre algo que pode não ser o que o codificador pretendia. Às vezes, isso é irritante, quando você tem montes de avisos sobre sinais não utilizados que você sabe perfeitamente que não são utilizados. Mas, às vezes, ele pega bugs genuínos. Se você é um novato, as chances de cometer um erro são significativamente maiores.
Então você precisa configurar restrições de tempo. Com que rapidez, após uma borda crescente no relógio A, é necessário definir a linha de dados B? Ou por quanto tempo a linha de dados B precisa ser mantida antes de uma borda decrescente no relógio A? As restrições de tempo permitem especificar tudo isso. Se você não tiver restrições de tempo, o compilador pode assumir que você não se importa particularmente e pode direcionar seus sinais para qualquer lugar. Se você tiver restrições de tempo, o compilador funcionará para garantir que seus sinais atendam a essas restrições, movendo o posicionamento. E se não puder atender às restrições de tempo, será emitido um aviso.
Se o seu problema é que as saídas não estão fazendo o que você espera, observe em detalhes os blocos de E / S. Cada pino de E / S possui um pouco de lógica associada e um flip-flop. A ordem na qual você especifica suas variáveis lógicas e de estado no seu código pode não permitir que seu código se encaixe nessa arquitetura, para que você obtenha um atraso extra de onde quer que ele seja colocado. Os avisos sobre restrições de tempo informam se isso acontece (supondo que você configurou suas restrições de tempo), mas corrigi-lo exige que você compreenda o hardware e como o seu design será mapeado no hardware. Geralmente, esse é apenas um problema quando você começa a atingir altas taxas de clock, mas vale a pena mencionar.
fonte