1 Comentário

Procedures com Alocação Estática em VHDL

Esse vai deixar muita gente sem entender. Alocação dinâmica e estática em VHDL? Sim, dá para usar estes conceitos. Quase isso, na verdade…

Introdução

Muito pouca gente sabe, mas é possível adotar o conceito de variável estática e dinâmica em VHDL, aproximado-se do conceito de programação de software. Neste artigo, eu vou ensinar uma técnica bastante avançada para o uso de VHDL, que permite sistemas complexos serem criados com facilidade aliviando a complexidade presente na descrição de hardware. Por exemplo, esse paradigma facilita a criação de pipelines em alguns casos, permite pensar mais “algoritmo” e menos hardware em outros e, por fim, acaba aproximando o desenvolvedor de HDL (neste caso, VHDL) ao desenvolvedor de HLS (High Level Synthesis).

A ideia é usar procedures para isso. Mas antes é preciso recordar alguns conceitos, bem simplificados…

Mas se você já vem de HDL…

A ideia é usar a porta inout de uma procedure para gerar amostragem em FlipFlop. Você pode ler de onde veio a ideia caso queira. Se quer só mais uma técnica para o arsenal, pula direto para a implementação do FlipFlop D.

Um pouco sobre Alocação de Variável em Software

Para fazer o pessoal de C ficar nervoso, vou resumir em muito um conceito importantíssimo tomando toda a licença poética ao meu dispor.

Uma variável dinâmica é aquela criada durante a execução de uma função, em geral, alocada na pilha. Durante execução daquela função, uma porção da memória é alocada e utilizada e liberada automaticamente após o fim da execução desta função. Uma variável estática é uma variável que mantém o seu conteúdo mesmo quando a execução da função é finalizada, pois deve manter seu valor enquanto o programa estiver sendo executado. Resumindo mais ainda, em Firmware, ela deve manter o conteúdo até uma próxima chamada da função (ou seja, por toda a vida do programa, que no caso de Firmware, é ele mesmo).

Bom, há muito mais atrás disso, há muito mais a ser explicado. Talvez valha dar uma lida nestes artigos antes de prosseguir:

Mas para os propósitos deste artigo, é suficiente. Em VHDL, podemos implementar este raciocínio, mas é preciso fazer um pouco de ginástica mental. Em geral, estático é o que gera hardware de armazenamento (flip-flop ou RAM, mas para os fins deste artigo, pensaremos apenas em flip-flop) e dinâmico é o que é resolvido em tempo de síntese (tempo de síntese é, para os desenvolvedores de HDL, análogo ao tempo de compilação).

  • Todos os sinais em uma entidade VHDL, quando utilizados em processo com clock para armazenar valor, são comparáveis com variáveis estáticas globais dentro daquela entidade (sempre alocados em flip-flop durante toda a execução do “programa”);
  • Todas as variáveis são locais, sendo que as variáveis continuam apresentando problema: podem ser estáticas ou dinâmicas.

Components, Procedures e Funções

Antes de adentrar nas variáveis em VHDL, precisamos entender os formatos de “subprograma” que o VHDL possui.

  • Componentes: componentes (components) são hoje o mais próximo de “objeto” que se possui em VHDL. Um componente é sempre uma entidade VHDL declarada dentro de outra entidade VHDL. Podemos criar componentes que aglomerem funções dentro deles.
  • Functions: funções em VHDL servem, dentro do escopo sintetizável, servem para implementar lógica combinacional. Lógica combinacional é o que realmente faz alguma coisa em HDL: fora isso, temos apenas flip-flops ou memórias. Basicamente as funções tem entrada e uma única saída, o retorno.
  • Procedures: procedures são subprogramas tal qual as functions e também servem, primariamente, para implementar lógica combinacional. Porém, são mais poderosos pois os procedures podem ter portas de entrada e saída.

NOTA: Leitores mais atentos podem lembrar as construções BLOCK e também dos PROTECTED TYPES. Ambos em geral são desprezados pela ferramenta de síntese.

Variáveis em VHDL

Eu continuo desestimulando o uso de variáveis (variables) em processos, durante a descrição de hardware com VHDL, principalmente para iniciantes. Porém, nunca estendi essa regra para functions e procedures. Até porque é praticamente impossível usá-las sem trabalhar com variáveis e, se o desenvolvedor já está precisando deste tipo de construção, um pouco de variáveis não deve trazer grandes complicações.

Em VHDL, podemos entender que dentro de uma função, o uso de variáveis é sempre dinâmico, ou seja, não é possível armazenar o valor das variáveis internas entre chamadas da função. A única coisa que pode ser armazenada de uma função nem VHDL é o valor de retorno da mesma.

Nas procedures, a coisa não é diferente para as variáveis. Elas são criadas usadas e seu valor, a princípio, não pode ser armazenado. Porém, já mencionei que diferente das funções, uma procedure pode não só ter mais de uma entrada, como também mais de uma saída.

As Procedures Revisitadas

Uma procedure possui portas, tal qual uma entidade. Essas portas podem ser de entrada, saída e o mais interessante, entrada e saída.

Embora se possa entender as portas de entrada e saída de uma procedure como entrada de “ponteiros” (análogo a possibilidade de poder mudar valores de apontados. Contudo, como o conceito de ponteiro não faz muito sentido em HDL, é melhor entender que as procedures são funções com possibilidade de mais de uma saída, cada uma em uma porta out.

Nota: existe sim uma estrutura de ponteiros usada em simulação, o access. Porém, seu uso é bastante complicado e é possível passar uma vida sem precisar disso. Outro jeito de pensar em ponteiros em VHDL é através do endereçamento de memórias, mas isso é bastante diferente do conceito de ponteiros em C.

Porém, as procedures possuem a porta INOUT. Essa porta permite enviar valor para ser armazenado por um sinal ou variável para ser usado na próxima execução desta procedure (ou seja, no próximo ciclo de clock). Tem-se, portanto, o conceito de que, a cada ciclo de relógio haverá uma chamada da procedure e, portanto, a utilização de valores da chamada anterior.

Um Flip-Flop D

Ok. Bastante explicação. Show me the code! Vamos fazer um Flip-Flop tipo D (FFD). Seja o seguinte record:

E seja a seguinte procedure:

E, em algum lugar da entidade, temos o seguinte sinal sendo declarado, ligações das portas da entidade e o seguinte processo:

Pronto. Acabamos de criar um flip-flop D com esse novo estilo de codificação.

Dicas Finais

Enquanto eu pensava nesse novo estilo de enxergar minhas máquinas digitais, pude antecipar alguns problemas…

Multi Driver

Essa técnica é muito útil, mas há alguns poréns: lembra quando eu afirmei que todos os sinais são variáveis GLOBAIS? Isso quer dizer que um mesmo sinal pode ser utilizado por vários processos, gerando mais de um driver. Em HDL, sempre que um sinal tem mais de um driver, o resultado é ‘U’.

O ideal é que o sinal usado como variável estática seja sempre escrito (ou seja, tenha valores atribuídos a ele) dentro de um mesmo processo (ele pode ser lido por todos os outros, tal qual o uso “normal” dos sinais).

Você pode evitar isso codificando de tal forma que, quando não vai usar um sinal naquele processo, ele assume o valor de ‘Z’, ou seja, alta impedância. Faz anos que os FPGAs não possuem buffers tri-state internos e é bem provável que a ferramenta vá resolver isso com um monte de multiplexador. Mas você estaria a mercê do fabricante (isso até é aguentável), porém, na linha do funciona, mas é feio…

Variáveis continuam sendo um problema.

Sim, elas continuam sendo um problema. A ideia de alocação estática serve também para variáveis, contudo, prefiro usar sinais para isso.

Eu citei as variáveis neste artigo por fazerem parte das descrições em procedures e functions e, de certa forma, para mostrar mais uma vez que pode-se fazer VHDL muito avançado sem elas. Elas vão trazer toda a complicação usual das variáveis: hora vão gerar hardware, ora não.

Contudo, talvez elas possam ajudar… Por causa de temporização, ou seja, quando as coisas acontecem em HDL. Mais sobre isso no próximo item.

O Timing pode ficar complicado.

Toda vez que um sinal recebe um valor, ele só “adquire” aquele valor quando o processo acaba ou encontra um ‘wait until clock’ (ou quando encontra um ‘wait for time‘, mas isso é inválido na síntese).

Caso algo precise adquirir um valor imediato, pode ser necessário usar variáveis nas portas de entrada e saída da procedure (a porta de alocação estática eu recomendo que sempre seja um sinal).

Conclusão e Desafios

Acredito que, sendo uma técnica avançada, se não estiver fazendo muito sentido pode ser importante estudar um pouco mais de VHDL, FPGAs ou HDLs em geral. Talvez esse link ajude:

Ainda vale a pena salientar que é possível criar construções mais complexas do que o FFD. Exemplos:

  • Shift-Registers
  • Memórias (por limitação dos sintetizadores, talvez acabe implementada com FlipFlop e não com Blockram)
  • E também sistemas com pipeline mais complexo (Filtros, Corretores de Erro,…)

Mas por enquanto, que tal pegar os dois exemplos acima e codificar, para ver o que acontece?

Sem licença Creative Commons

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Hardware » Sistemas Digitais » Procedures com Alocação Estática em VHDL
Comentários:
Notificações
Notificar
guest
1 Comentário
recentes
antigos mais votados
Inline Feedbacks
View all comments
Dawood
Dawood
19/10/2020 14:58

obrigado pelo artigo

Last edited 10 dias atrás by Dawood
Talvez você goste:

Séries

Menu

WEBINAR
 

BlueNRG-LP – Bluetooth 5.2 de longo alcance para aplicações industriais

Data: 05/11 às 15:00h - Apoio: STMicroelectronics
 
INSCREVA-SE AGORA »



 
close-link