Fundamentos
Posted on sex 18 setembro 2020 in vhdl • 8 min read
Nest post falaremos das características fundamentais da linguagem VHDL. Quando aplicável, usaremos para indicar quais versões de VHDL suportam cada característica.
Elementos Léxicos
VHDL não diferencia maiúsculas de minúsculas. Os arquivos são todos arquivos de texto e a especificação da linguagem admite apenas caracteres ASCII. No entanto, sugiro usar codificação UTF-8, limitando-se aos caracteres que também existem no ASCII, pois isso maximiza a compatibilidade com editores e ferramentas de síntese. A extensão do arquivo não importa muito, mas as mais comuns são .vhd
e .vhdl
(não use .v
pois esta extensão é interpretada como Verilog pelas ferramentas).
Tome cuidado com acentos pois o código dos caracteres, mesmo em UTF-8, deve ser compatível com ASCII. Evite caracteres acentuados fora dos comentários. |
Comentários
Os comentários são parte importantíssima em engenharia de software e não é diferente em engenharia de hardware. São muito úteis para descrever as intenções do projetista, de forma que outro projetista entenda o que foi descrito quando, posteriormente, ler o arquivo.
O comentário básico em VHDL é --
. Após estes dois caracteres, todo o restante da linha se torna um comentário. Há também o comentário delimitado, que começa com /*
e termina com */
, útil para comentários multi-linhas. Os comentários não podem ser aninhados (comentário dentro de comentário), mas um comentário com --
no início da linha desativa qualquer delimitador de comentário.
Por motivos óbvios, os comentários não são sintetizáveis.
Os comentários com delimitadores /* */ são suportados a partir do VHDL-2008. |
Exemplo (VHDL<=2002)
1 2 3 4 5 6 7 8 9 |
|
Exemplo (VHDL>=2008)
1 2 3 4 5 6 7 8 9 |
|
Identificadores
Os identificadores são cadeias de caracteres usadas para dar nomes a variáveis, sinais e qualquer outro elemento da descrição. Em VHDL, o identificador pode ser uma cadeia de qualquer tamanho, desde que siga as seguintes restrições:
- Deve conter somente letras (
A-Z
ea-z
), dígitos (0-9
) ou o caractere_
- Deve começar com uma letra
- Não deve terminar com um
_
e não pode conter dois_
seguidos
Essas limitações existem para que seu identificador não entre em conflito com identificadores usados internamente pelas ferramentas.
Lembre-se que VHDL não diferencia maiúsculas de minúsculas, então `meu_sinal` é o mesmo que `MEU_SINAL` ou `MeU_sInAl`. |
Exemplo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Identificadores estendidos
VHDL também suporta o que chamamos de identificador estendido. Os identificadores estendidos não tem as limitações dos identificadores e pode-se usar qualquer coisa dentro deles. Para usar, basta colocar seu identificador entre dois \
.
Exemplo
-- Identificadores estendidos válidos
\5bola\
\_meusinal\
\meusinal_\
\MeuSinal_\
\meu__sinal\
\balbertini@usp\
\xo:xo\
\😊\
\saída\
Quando usamos identificadores estendidos, a linguagem interpreta o identificador exatamente como ele é, então neste caso a linguagem diferencia maiúsculas de minúsculas.
Os identificadores estendidos foram criados para serem usados pelas ferramentas de síntese, facilitando a troca de informações. Não recomendamos que utilize em suas descrições pois nem todas as ferramentas o suportam. | |
Os identificadores estendidos são suportados a partir do VHDL-1993. |
Palavras reservadas
Os comandos em VHDL são chamados de palavras reservadas. Todas tem um significado especial e devem ser evitadas como identificadores. A tabela abaixo tem uma lista de todas as palavras reservadas da linguagem, em ordem alfabética.
abs | else | map | range | unaffected |
---|---|---|---|---|
access | elsif | mod | record | units |
after | end | register | until | |
alias | entity | nand | reject | use |
all | exit | new | release | |
and | next | rem | variable | |
architecture | fairness | nor | report | vmode |
array | file | not | restrict | vprop |
assert | for | null | restrict_guarantee | vunit |
assume | force | return | ||
assume_guarantee | function | of | rol ror | wait |
attribute | on | when | ||
generate | open | select | while | |
begin | generic | or | sequence | with |
block | group | others | severity | xnor |
body | guarded | out | shared | xor |
buffer | signal | |||
bus | if | package | sla | |
impure | parameter | sll | ||
case | in | port | sra | |
component | inertial | postponed | srl | |
configuration | inout | procedure | strong | |
constant | is | process | subtype | |
context | property | |||
cover | label | protected | then | |
library | pure | to | ||
default | linkage | transport | ||
disconnect | literal | type | ||
downto | loop |
Algumas dessas palavras não são consideradas palavras reservadas em algumas versões de VHDL, mas para manter a compatibilidade entre as versões, considere esta lista como uma lista de palavras que você não deve usar como identificadores.
Símbolos Especiais
A linguagem VHDL usa a seguinte lista de símbolos, cada um com um significado específico na linguagem:
" # & ' ( ) * + - , . / : ; < = > ? @ [ ] \` |
Além desses, há símbolos com um único significado em VHDL, mas composto de dois caracteres:
1 |
|
Para funcionarem, você precisa escrevê-los sem nenhum espaço entre eles (e.g. <=
é um operador de atribuição, mas < =
são duas comparações, de menor e igual respectivamente). Nos próximos posts falarei sobre o significado de cada um destes operadores.
Literais
Números
Há dois tipos de literais numéricos em VHDL: os inteiros e os reais. Ambos podem ser expressos usando notação científica.
1 2 3 4 5 6 7 8 9 |
|
Note que -123
não é um número inteiro mas sim uma negação de um inteiro. Os número reais precisam de ao menos um dígito antes e outro depois do .
para serem considerados válidos.
Os literais numéricos também podem ser especificados em outras bases usando o operador #
com a base expressa em decimal:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
VHDL suporta as bases de 2 a 16 nativamente, mas sugerimos ater-se às bases 2, 8 e 16 pois nem todas as ferramentas suportam bases arbitrárias. |
Não há ponto (ou vírgula) de separação de milhares, mas é possível usar o caractere _
para melhorar e legibilidade dos literais numéricos, respeitando-se as regras de composição de identificadores (não se pode aparecer no início ou final de um número, e também não pode aparecer duas vezes seguidas):
1 2 3 |
|
O caractere _
em um literal é inerte e não tem significado algum, servindo apenas para melhorar a visualização.
Caracteres
Os caracteres em VHDL são expressos entre aspas simples '
e podem ser qualquer caractere ASCII imprimível.
1 2 3 4 5 |
|
Strings
As strings são vetores de caracteres e são representadas em VHDL entre aspas duplas "
:
1 2 3 4 5 6 |
|
Bit Strings
Como todo hardware no final das contas trabalha com zeros e uns, VHDL possui uma forma específica para representar cadeias de bits. As cadeias são tratadas de forma diferenciada pois sempre podem ser transformadas em bits sem ambiguidade. É possível especificar a base da cadeia usando os prefixos B
para binário, O
para octal, X
para hexadecimal e D
para decimal (este último só existe a partir de VHDL-2008).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
O número de bits da cadeia equivalente é sempre o número de bits mínimo necessário para representar o literal. Quando usamos octal, a cadeia resultante será um múltiplo de 3 bits pois cada dígito octal corresponde a 3 bits binários. Similarmente, as cadeias em hexadecimal correspondem a múltiplos de 4 bits binários. Os dígitos especificados devem ser válidos na base desejada (e.g. em octal só existem os dígitos de 0-7, em hexadecimal, de 0-9 e A-F (ou a-f)). Algumas letras tem significado especial dependendo do tipo binário por trás da conversão, como o Z
que significa alta impedância quando se usa lógica multi-variada.
A lógica multi-variada em VHDL é baseada no tipo std_logic , que aceita U , X , Z , W , L , H e - como dígitos, além dos tradicionais 0 e 1 .
|
Há ainda uma forma de controlar quantos bits queremos que a cadeia possua, que funciona com VHDL>=2008, colocando o número de bits antes do prefixo:
1 2 3 4 |
|
A cadeia será preenchida com 0
suficientes para completar o número de bits. Caso o número desejado seja menor, os zeros à esquerda serão cortados da cadeia, mas é um erro especificar um número de bits menor que o necessário para representar o número.
Também podemos especificar se o número representa um inteiro com sinal ou sem sinal, adicionando os prefixos S
e U
respectivamente. Esta especificação só é possível em VHDL>=2008 e não pode ser usada para números decimais (especificador D
), que são sempre considerados inteiros sem sinal.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
As versões de VHDL<2008 não suportam o especificador decimal D , nenhum especificador de tamanho (os números no prefixo), e nenhum especificador de sinal (U ou S ). Aconselho a evitá-los se deseja manter a compatibilidade da sua descrição com todas as ferramentas.
|