top of page

Programando FPGAs com AHDL

O uso de processadores e de outros chips é muito comum na implementação de projetos eletrônicos. Esses dispositivos podem ter custo de desenvolvimento bastante elevado, mas pela grande demanda em diferentes aplicações, o preço de venda é reduzido até valores factíveis. Ainda assim, certos projetos têm necessidades específicas, que não são atendidas pelos dispositivos comuns. Nesse caso, a solução mais comum é o uso das FPGAs, sigla para Field-Programmable Gate Array ou, em português, Arranjo de Portas Programável em Campo. Neste artigo, serão apresentadas informações sobre a tecnologia FPGA, incluindo suas vantagens e suas desvantagens, além de uma introdução à intuitiva linguagem AHDL, usada para programar chips FPGA da empresa Altera.

1. Um pouco sobre as FPGA


Comercializadas desde 1984, majoritariamente pelas empresas Xilinx e Altera, as FPGAs pertencem ao grupo dos Dispositivos Lógicos Programáveis de Alta Capacidade (HCPLD), que por sua vez se englobam entre os Circuitos Integrados de Aplicação Específica (ASIC). Basicamente, uma FPGA é composta por milhões de blocos lógicos interconectados, totalmente configuráveis. Assim, diferentemente de um processador, cujas configurações e funcionalidades são determinadas durante a fabricação, uma FPGA é configurada pelo próprio projetista, o que permite desenvolver as operações de controle desejadas. É por essa razão que esses dispositivos são programáveis em campo, ou seja, os chips são configurados no âmbito do projeto, e não na indústria. A Figura 1 mostra um esquema básico da construção de uma FPGA.


Figura 1 – Esquema simplificado de um chip FPGA: blocos lógicos, interconexões programáveis e pinos de entrada e de saída. Fonte: referência [3].

Os microprocessadores padrão necessitam, em geral, de 50 ms para executar uma tarefa e, portanto, necessitam de 5 s para executar cem tarefas. Um dispositivo ASIC (como as FPGAs), no entanto, precisa em torno de 5 ms para executar uma tarefa, totalizando cem tarefas em 0,5 s. Assim, FPGAs são, no mínimo, dez vezes mais rápidas que um microprocessador. Além de maiores velocidades, as FPGA também possuem menor volume físico, garantindo melhor alocação de espaço, e consumem menos energia que os processadores. Todavia, como já dito anteriormente, a demanda reduz consideravelmente o preço dos dispositivos, e as FPGAs, por sua demanda menor que a demanda dos microprocessadores, são mais caras a que os chips comuns, o que pode ser financeiramente inviável para o desenvolvimento de certos projetos.

A programação de FPGAs é feita em um Ambiente de Desenvolvimento Integrado (IDLE), como o Quartus Prime Lite Version da Altera e o ISE WebPACK da Xilinx, ambos gratuitos para download. Nesses IDLES, existem as opções de programação gráfica, feita com “bloquinhos” que simulam dispositivos digitais, e de programação usual, feita com comandos de texto. Essas linguagens textuais são chamadas linguagens de descrição de hardware (HDLs), que para projetos com FPGAs podem ser a Verilog, a VHDL (cujo V é a sigla para VHSIC, a tecnologia dos Circuitos Integrados de Velocidade Muito Alta) e a AHDL (cujo A significa Altera). As linguagens Verilog e VHDL, aplicáveis a todos chips FPGA, são padronizadas pelo Institute of Electrical and Electronic Engineering (IEEE), e a AHDL, embora limitada às FPGAs da Altera, é amplamente utilizada pelos desenvolvedores e seus códigos podem ser convertidos para outras HDLs facilmente.

A seguir, serão apresentadas as instruções básicas para programação em AHDL, com a criação de novos projetos no Quartus Prime e a apresentação de códigos que simulam circuitos digitais.


2. Criando arquivos AHDL


Antes de iniciar a programação, é necessário abrir um novo projeto. Com o Quartus Prime instalado no computador, clique em File, no canto superior esquerdo, e depois selecione New Project Wizard..., conforme mostra a Figura 2. Também é possível clicar no ícone New Project Wizard no centro da tela.


Figura 2 – Criando um projeto no Quartus Prime. Fonte própria.


Aparecerá, a seguir, uma tela com o título Introduction, que fala sobre a criação de projetos. Depois de clicar em Next, será vista a tela na Figura 3, na qual serão especificados o diretório (isto é, a pasta) e o nome do novo projeto. Na primeira seção (caixa vermelha), escreva o diretório do projeto (que aparece inicialmente como o diretório padrão do Quartus Prime), e na segunda seção (caixa azul), digite o nome do projeto. Não é necessário, no momento, conhecer ou escrever qualquer texto nas demais seções (a seção abaixo da caixa azul é preenchida automaticamente com o mesmo nome do projeto).


Figura 3 – Especificação do diretório (caixa vermelha) e do nome (caixa azul) do novo projeto. Fonte própria.


Será vista, após clicar em Next, uma tela com o título Project Type, na qual é possível selecionar as opções Empty project (opção já selecionada e que cria um projeto novo) e Project template (que abre um projeto-exemplo do Quartus Prime). Mantenha a opção Empty project selecionada e clique em Next; surgirá uma tela com título Add Files, que no momento não precisa ser utilizada e, portanto, pode passada com o Next. A próxima tela, vista na Figura 4, permite inserir a família e o dispositivo FPGA que será usado. Como neste tutorial o foco será o desenvolvimento de códigos em AHDL, e não implementação desses código em uma FPGA, a opção padrão (família Cyclone V) será deixada, sem seleção do chip usado. No entanto, é possível alterar essas configurações mesmo após a criação do projeto.

Figura 4 – Seleção da família e do dispositivo FPGA que será usado. Fonte própria.


Clique em Next na tela da Figura 4 e na próxima tela também. Então, aparecerá a tela Summary, com os dados gerais do novo projeto, que será criado após selecionar o botão Finish. A tela inicial do Quartus Prime aparecerá momentaneamente, enquanto o programa carrega o novo projeto. Após o carregamento, selecione a opção Files e depois a opção New..., que pode ser vista também na Figura 2, acima da opção New Project Wizard... Surgirá a tela apresentada na Figura 5, na qual deve ser selecionada a opção AHDL File, para a criação de um arquivo em branco. Nesses arquivos são escritos os códigos em AHDL, que serão tratados na próxima seção.

Figura 5 – Abrindo um arquivo AHDL em branco. Fonte própria.

3. Programando em AHDL


Como na maioria das linguagens de programação, a estrutura básica dos algoritmos em AHDL é composta por início, declaração das variáveis, declaração da(s) função(ões) e encerramento. A declaração das variáveis é feita no preâmbulo do código, enquanto as funções são definidas entre o início e o encerramento do algoritmo. Na sintaxe da AHDL, as declarações são finalizadas com pontos e vírgulas, e espaços em branco entre as declarações não são significantes.

Para declarar as variáveis, é usado o comando SUBDESIGN, seguido do nome do algoritmo e de parênteses fechados, como é visto na Figura 7. Entre esses parênteses, são declaradas as variáveis de entrada e de saída, definidas pelas declarações INPUT e OUTPUT, respectivamente. Para cada variável é definida um símbolo (no caso da Figura 7, as letras E e S), seguida de dois pontos e INPUT, se for uma variável de entrada, ou OUTPUT, se for uma variável de saída.


Figura 6 – Estrutura básica de um código em AHDL. Fonte própria.

O início e o encerramento do código são feitos pelos comandos BEGIN e END, respectivamente. Entre esses comandos são escritas as funções que o algoritmo executa, relacionando as variáveis de saída com as variáveis de entrada. No exemplo da Figura 7, o valor da saída é igual ao valor da entrada. Ademais, os comentários podem ser inseridos no código digitando dois traços seguidos (--).


3.1. Análise do algoritmo

Para compilar um código em AHDL, é necessário estar conectado a um dispositivo FPGA, que não é o caso trabalhado neste tutorial. No entanto, é possível checar a sintaxe do algoritmo selecionando o atalho Processing e clicando em Analyze Current File, como apresenta a Figura 7. Também é possível clicar no ícone na caixa vermelha menor para realizar essa análise.

Figura 7 – Análise do código em AHDL. Fonte própria.

Para uma análise sem erros, é necessário que código não apenas esteja sintaticamente correto, mas também que o nome do projeto, escrito após SUBDESIGN, tenha o mesmo nome do arquivo salvo do código. Se não existirem erros, aparecerá a mensagem mostrada na Figura 7, dentro da caixa azul.

3.2. Operações booleanas


Expressões booleanas são amplamente utilizadas em algoritmos em AHDL, já que correspondem ao funcionamento dos circuitos digitais. Utiliza-se os símbolos

  • &, para a função AND;

  • #, para a função OR;

  • !, para a função NOT.

Embora existam comandos para as demais funções de Boole nas bibliotecas do AHDL, com as operações listadas acima, é possível construir as demais funções facilmente.

A Figura 8 mostra um sistema digital simples, de entradas A e B e formado por uma porta AND, uma porta OR, uma porta NOT, uma porta NAND e uma porta NOR, com as respectivas saídas S0, S1, S2, S3 e S4. A Figura 9 apresenta um código em AHDL que simula esse sistema digital.


Figura 8 – Desenho esquemático de um sistema digital simples. Fonte própria.

Figura 9 – Algoritmo em ADHL equivalente ao sistema da Figura 7. Fonte própria.

3.3. Nós internos

Muitas vezes, circuitos digitais apresentam diversos estágios antes das saídas. Um exemplo é ilustrado na Figura 10, cuja saída da porta AND, que executa a operação A·B, é entrada da porta OR, cuja saída, que é a saída do circuito, é A·B+C. Em AHDL, essa saída intermediária é chamada de nó interno, e é definida através das declarações VARIABLE e NODE, conforme é visto na Figura 11. A atribuição de uma variável a um nó é feita de maneira similar à declaração das variáveis de entrada e de saída.

Figura 10 – Circuito digital cuja saída da porta AND é uma das entradas da porta OR. Fonte própria.

Figura 11 – Exemplo de uso dos nós internos em AHDL. O código simula o circuito da Figura 10. Fonte própria.

3.4. Tabela Verdade

É possível implementar um código em AHDL utilizando a tabela verdade de um sistema digital. Para isso, conforme mostra o exemplo na Figura 12, são inseridas as declarações TABLE e END TABLE entre BEGIN e END. Depois, são escritas as entradas e seus valores entre parênteses, seguidas dos símbolos => e, em seguida, as saídas e seus valores.

Figura 12 – Código em AHDL utilizando a tabela verdade de um sistema digital. Fonte própria.

3.5. Circuitos sequenciais: latches e flip-flops

A dependência tanto dos valores das entradas como dos valores anteriores da saída torna os circuitos sequenciais bastante interessantes, especialmente como elementos de memória. Entre os circuitos sequenciais biestáveis, capazes de guardar um bit de informação por unidade, existem os circuitos assíncronos, chamados de "latches" e cujas saídas pode ser alteradas a qualquer instante, e os circuitos síncronos, denominados "flip-flops" (FF) e cujas saídas são alteradas somente pela variação de um sinal de clock.

É possível escrever códigos em AHDL capazes de simularem latches e FF. A Figura 13 mostra o bloco lógico e a tabela verdade do latch D. Na Figura 14, é visto o código em AHDL desse dispositivo. Usa-se a declaração LATCH para definir o funcionamento da saída q, seguida das definições q.ena=ena e q.d=d. Essas variáveis precisam ter esses mesmos nomes (d, ena e q, ou ainda a versão com letras maiúsculas), pois esses comandos estão definidos nas bibliotecas da AHDL.


Figura 13 – Latch D: circuito digital e tabela verdade. Fonte: <www.allaboutcircuits.com>.

Figura 14 – Algoritmo em AHDL de um latch D. Fonte própria.

O latch SR, cujos circuito e tabela verdade são mostrados na Figura 15, tem sua operação definida em uma estrutura if-else, conforme a Figura 16, na qual o nível lógico alto é a declaração VCC e o nível lógico baixo é a declaração GND.

Os códigos em AHDL sobre FF trabalham com declarações similares ao LATCH, como DFF ou DFFE para FF D e JKFF ou JKFFE para FF JK. Exemplos com FF serão apresentados nas seções 3.6 e 3.7, que abordarão os registradores de deslocamento e os contadores, respectivamente.


Figura 15 – Circuito digital e tabela verdade de um latch SR. Fonte: <electronics.stackexchange.com>.

Figura 16 – Latch SR em AHDL. Fonte própria.

3.6. Registradores de deslocamento

Os registradores de deslocamento (RD) são circuitos formados por FF D ou JK, controlados pelo mesmo sinal de clock e cujas saídas conectam-se com as entradas dos FF seguintes. Nesses circuitos, em cada variação do clock (subida ou descida), os estados das saídas de cada FF são deslocados para saída do FF seguinte, como sugere o esquema da Figura 17.

Figura 17 – Esquema de funcionamento de um registrador de deslocamento. Fonte: <www.newtoncbraga.com.br>.

A Figura 18 mostra um algoritmo de um RD de 8 bits, formado por oito FF D. Na declaração PARAMETERS, seguida de parênteses fechados, escreve-se WIDTH para definir a largura do RD, isto é, o número de bits. Note que como PARAMETERS é uma declaração, é necessária a inclusão de um ponto e vírgula após o segundo parêntese. Depois, são declaradas clock e data[WIDTH-1..0] como a entrada de clock e as oitos entradas dos FF, respectivamente, seguidas das oitos saídas q[WIDTH-1..0]. Como todos os FF são do tipo D, é preciso declará-los no campo VARIABLE, escrevendo ff[WIDTH-1..0]:DFFE. Após isso, declara-se ff[].clk=clock e ff[].d=data[] para relacionar as variáveis de entrada em SUBDESIGN às entradas dos FF definidos em VARIABLE, e escreve-se q[]=ff[].q para que as variáveis de saída recebam os valores assumidos pelas saídos do RD.


Figura 18 – Código em AHDL de um registrador de deslocamento de 8 bits. Fonte própria.

3.7. Contadores assíncronos e síncronos


Não é preciso discutir a importância dos contadores, tanto para projetos técnico-científicos, como para aplicações cotidianas, como os relógios, por exemplo. Resumidamente, nos contadores assíncronos, as saídas dos FF atuam como clock do FF seguinte, existindo apenas um sinal de clock externo no primeiro FF do circuito. Já nos contadores síncronos, um sinal de clock externo controla todos os FF, simultaneamente.

Na Figura 19, um algoritmo de um contador assíncrono de 3 bits, ou seja, que conta de zero a sete, é apresentado. Utiliza-se a declaração JKFF em VARIABLE para definir saídas de FF JK ao circuito, cujos Preset e Clear estão pré-definidos no nível lógico alto (VCC). As declarações q[2..0].j=VCC e q[2..0].k=VCC habilitam todas as entradas J e K em nível lógico alto. Já as declarações q[0].clk=!clock, q[1].clk=!q[0].q e q[2].clk=!q[1].q definem a configuração de contador assíncrono, com o sinal externo de clock no primeiro FF e a saída de cada FF na entrada de clock do FF seguinte. Como no padrão da AHDL a transição dos estados da saída ocorre na subida do clock, o sinal de negação “!” altera para a transição de estados durante a descida do sinal.


Figura 19 – Código de um contador assíncrono de 3 bits. Fonte própria.

Como exemplo de contador síncrono, é mostrado o código de um contador em anel de 4 bits na Figura 20. Nesse circuito, formado por FF D, cada saída conecta-se à entrada D seguinte, tal que a saída do último FF se ligue à entrada do primeiro FF. Essa configuração garante uma contagem cíclica, com o retorno ao valor inicial após o processo atingir o valor máximo.

O nó interno ser_in, visto na Figura 20, reinicia a contagem ao receber o nível lógico alto, o que ocorre quando os bits mais significativos, isto é, as saídas q3, q2 e q1, são iguais a 000, em binário (por isso a notação B“000”).


Figura 20 – Algoritmo em AHDL de um contador síncrono em anel, de 4 bits. Fonte própria.

4. Conclusão


Para a execução de projetos eletrônicos mais complexos, ainda é necessário aprender diversos tópicos da eletrônica digital (como decodificadores, multiplexadores e outros mais) e outros elementos mais avanços da programação de FPGAs. No entanto, sem os conceitos-base, apresentados neste artigo, é bastante difícil a qualquer projetista, em especial o iniciante, desenvolver um algoritmo em AHDL (ou mesmo em outra HDL) com sucesso. Dessa maneira, é essencial que os “guerreiros projetistas” (termo usado na referência [2], em tradução livre) tenham os conhecimentos básicos sobre FPGAs bastante fundamentados, pois só assim poderão implementar projetos com praticidade e competência.


5. Referências


As informações abaixo foram usadas para a elaboração deste artigo, e podem ser utilizados para aqueles que quiserem se aprofundar mais no assunto das FPGAs. A referência [1] contém toda a documentação sobre o Quartus Prime e a referência [2] é um excelente guia, tanto para os iniciantes como para os projetistas já envolvidos com a tecnologia FPGA.

[1] ALTERA. Quartus Prime Help version 15.1. Disponível em: <http://quartushelp.altera.com>. Acesso em: 18 jan 2016.

[2] MAXFIELD, C. The design warrior'sguide to FPGAs. Burlingtion: Elsevier, 2004. ISBN: 0-7506-7604-3

[3] NATIONAL INSTRUMENTS. Fundamentos da tecnologia FPGA. Disponível em: <http://www.ni.com/white-paper/6983/pt/>. Acesso em: 4 jan. 2016.

[4] SCHAFFER, K. Advanced AHDL. Disponível em: <http://www.cs.kent.edu/~walker/classes/vlsi.s06/lectures/L14-15.pdf>. Acesso em: 14 jan. 2016.



bottom of page