Estou aprendendo a usar um FPGA (placa de desenvolvimento Papilio, que possui um xilinx spartan3e, usando vhdl).
Preciso dividir um pulso recebido por um número (codificado).
Eu posso ver três opções - aproximadamente, como pseudocódigo (usando 10 contagens como exemplo):
- Inicialize para 0, no aumento da borda crescente da entrada em 1, compare com 10; se forem iguais, redefina para 0 e acione o pulso de saída
- Inicialize para 10, ao diminuir a borda crescente da entrada em 1, compare com 0; se forem iguais, redefina para 10 e acione o pulso de saída
- Inicialize para 9, mas verifique se há pelo menos 1 bit "0" inicial, que é o meu bit de saída. Na borda ascendente da entrada, diminua em 1. Na borda ascendente do bit de saída, redefina.
O ciclo de serviço não é importante.
Um deles é melhor que os outros? Existe um método ainda melhor que eu não pensei?
Existe uma maneira "padrão" que dará ao compilador a melhor chance de otimizar?
Respostas:
A otimização para esse nível partirá seu coração. O resultado pode mudar devido à tecnologia do FPGA que você está usando, outros fatores no FPGA, mas também devido a fatores fora do seu controle, incluindo a semente de números aleatórios do instalador.
Dito isto, acredito que a opção 3 será a melhor. As opções 1 e 2 têm um comparador / porta OR entre os contadores, para que possa sinalizar que o número de destino foi atingido. A opção 2 pode ser um pouco mais rápida que 1, pois tudo pode ser reto OU juntos sem inversores, mas novamente você encontra pequenas diferenças de tecnologia nas quais pode ser mais rápido para AND ou XOR.
A opção 3 ignora a comparação pelo baixo custo de um bit extra no contador. Isso deve valer a pena, a menos que você seja severamente restringido em chinelos.
Um fato interessante sobre os contadores é que eles tendem a ser agrupados em um tamanho específico de dispositivo dentro de um bloco lógico, e você verá o tempo mudar mais do que o esperado se esse bit extra o afastar desse grupo.
fonte
Uma outra opção seria inicializar o contador para 6 (= 2 4 - 10), contar e reiniciar quando a saída de transporte for ativada (ou seja, os FFs são todos iguais).
A vantagem disso é que ele não requer um FF extra, e muitos FGPAs têm lógica auxiliar dedicada para acelerar esse tipo de operação de transporte em um circuito de contador ou somador.
fonte
Depende. Por exemplo: o atraso de propagação de flip-flop para 0 → 1 e 1 → 0 pode ser diferente e, portanto, os atrasos de transição de um contador para 000 → 001 e 001 → 000 podem ser ligeiramente diferentes. Pode ser maior ou menor, dependendo da tecnologia CMOS usada no FPGA. Então você precisa sintetizar e descobrir qual deles possui melhor desempenho de tempo.
fonte
Da perspectiva de um escritor de compilador: se você usar
integer
, a representação interna é indefinida e o compilador é livre para escolher a implementação mais eficiente.Se você forçar uma representação interna específica, o otimizador ainda tentará melhorá-la, mas começará de um ponto de vista um pouco pior.
A menos que você conheça a estrutura interna, os recursos alocados para outra lógica (muitos FPGAs têm lógica de adição múltipla de ponto flutuante dedicada que você também pode usar para implementar um contador se houver unidades restantes) e tem certeza absoluta de que não trocará para um modelo diferente, a resposta é "não pense nisso".
fonte