Funções
Posted on sáb 17 outubro 2020 in vhdl • 3 min read
As funções em VHDL são bastante úteis para reaproveitar código. Elas funcionam como uma função em qualquer linguagem estruturada. Neste artigo, vamos ver o básico de como escrever funções em VHDL.
A sintaxe de uma função em VHDL é:
1 2 3 4 5 6 7 8 9 |
|
A classificação da função como pura ou impura é opcional e indica se a função pode alterar valores de entrada (impure
) ou não (pure
). Por padrão, as funções são puras, ou seja qualquer alteração nos parâmetros de entrada é considerada inválida. Os valores retornados por uma função impura podem depender de valores externos (e.g. variáveis compartilhadas).
O nome_da_funcao
pode ser o que o projetista desejar, seguindo a nomenclatura obrigatória de VHDL para identificadores. O mesmo se aplica para os parâmetros. Os tipos dos parâmetros podem ser qualquer tipo suportado em VHDL, lembrando que se for um tipo não-nativo, deve-se incluir a biblioteca correta no projeto. O valor padrão dos parâmetros é pouco utilizado e serve para preencher os parâmetros não especificados no momento da chamada. O tipo de retorno adere às mesmas regras dos parâmetros.
As declaracoes_internas
são todas as variáveis e constantes utilizadas, no mesmo formato utlizado em um processo ou arquitetura, mas as funções não suportam sinais.
O código de uma função é intrinsecamente sequencial, então pode-se usar qualquer comando de VHDL, incluindo os exclusivos para uso em processos. A única obrigatoriedade é que a função retorne um e somente um valor condizente com o tipo_de_retorno
. É possível usar comandos condicionais (e.g. if
), mas a todas as condições devem retornar um valor.
As funções podem ser declaradas em dois lugares distintos: em um pacote contendo funções e no preâmbulo das unidades em VHDL (e.g. arquitetura, processo, entidade, etc).
Exemplo (preâmbulo)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
No exemplo acima a função equal
compara dois bit_vector
bit a bit e retorna verdadeiro somente se ambos os vetores possuírem o mesmo conteúdo. A chave para a comparação é o aninhamento dos dois loops for
, que itera sobre os vetores comparando-os bit a bit.
Note que a função foi declarada no preâmbulo da arquitetura, mas chamada no corpo. A função não é sintetizável diretamente, mas o sintetizador irá produzir um comparador para calcular o valor da comparação e usá-lo para decidir sobre a atribuição condicional. Para efeitos de simulação, a função demora tempo zero.
A declaração da função usou a vírgula para separar os parâmetros pois eles são do emsmo tipo. A mesma função poderia ser reescrita como equal(a: bit_vector; b: bit_vector)
e a chamada continuaria exatamente igual.
Exemplo (package
)
No caso de um package
, a função é declarada dentro da biblioteca:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Temos agora uma biblioteca que pode ser usada em qualquer projeto, bastando para isso incluí-la no projeto como uma biblioteca normal. As bibliotecas do usuário, quando não especificado, ficam em um pacote chamado work
, que corresponde ao pacote de trabalho e sempre é importado por padrão. A cláusula use
no entanto não é opcional pois o sintetizador precisa saber qual(is) partes do pacote deseja usar.
1 2 3 4 5 6 7 8 9 10 11 |
|