Mudanças entre as edições de "Predefinição:DiegoMedeiros-SST20707"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 1 822: Linha 1 822:
 
Em duas equipes de 3 pessoas, estudar as seções abaixo do livro [1] e fazer uma apresentação da solução adotada.
 
Em duas equipes de 3 pessoas, estudar as seções abaixo do livro [1] e fazer uma apresentação da solução adotada.
  
; Equipe A (Kamila, Leonardo O., Rogério):
+
; [[Avaliação 1 - SST | Equipe A (Kamila, Leonardo O., Rogério)]]:
  
 
:* 22.2 - Debouncer para chave
 
:* 22.2 - Debouncer para chave

Edição das 19h26min de 16 de abril de 2015

Ementa e referências bibliográficas

Informações da disciplina

Diário de aula

2015-1 - Clicar no "+" para expandir
Aula Data Horas Conteúdo Recursos
1 06/02 2 Apresentação da disciplina
2 10/02 2 Dispositivos lógicos programáveis - PLD
3 13/02 2 Tecnologia de FPGA
4 20/02 2 Projetos em FPGA
5 24/02 2 Sem aula devido a reunião com a reitoria. Resolver exercício
6 27/02 2 Correção do exercício e utilização do Kit DE2-115 e Introdução ao VHDL
7 03/03 2 Introdução ao VHDL e Objetos e atribuições
8 06/03 2 Aula livre para a execução dos exercícios de VHDL
9 10/02 2 Abordagens e Atribuições de variáveis em simulações
10 13/03 2 Tópicos em VHDL
11 17/03 2 Uso do Modelsim - Aula prejudicada devido à problemas no laboratório
12 20/03 2 Abordagem estrutural
13 24/03 2 Aula livre para realização da Avaliação 1
14 27/03 2 Aula livre para realização da Avaliação 1
15 31/03 2 Continuação da Avaliação 1: Implementação em FPGA
16 07/04 2 Circuitos sequenciais em VHDL
TOTAL '

Aulas

Apresentação da disciplina

Roteiro
  • Apresentação do professor;
  • Apresentação da disciplina (Plano de Ensino);
  • Avaliações: Trabalhos e Projeto Final
  • Grupo da disciplina: IFSCTeleSST
Atividade
Ler capítulo 18 do Livro do Pedroni

Dispositivos lógicos programáveis - PLD

PLDs em sistemas digitais

Sistema digital: Saída digital definida em função de processamento realizado em entrada digital.

Sistema digital. Fonte: [1]


Os sistemas digitais foram por muito tempo projetados usando a chamada lógica fixa, composta por CIs (circuitos integrados) TTL que implementavam portas lógicas. Em meados de 1970, foram introduzidos os PLDs (Programmable Logic Devices), chips de uso geral cujo hardware pode ser configurado para atender especificações. Com os PLDs, sistemas digitais poderiam ser projetados a partir de CIs genéricos, com funções definidas a partir de configurações armazenadas em memórias. Desta forma, os PLDs possuem as seguintes vantagens sobre sistemas de lógica fixa [2]:

  • Redução de custos de projeto, chamados de custos NRE (nonrecurring engineering cost - custo de engenharia não recorrente), com a abolição de desenvolvimentos complexos de placas
  • Rapidez de desenvolvimento
  • Flexibilidade no desenvolvimento: a adição de funcionalidades é feita por simples mudanças no arquivo de configuração
  • Rapidez de produção do CI: por serem padronizados, os PLDs possuem entrega imediata
  • Atualização de hardware em tempo real

Uma alternativa de projeto é o uso de microcontroladores, dispositivos programáveis a nível de software. Porém, mesmo nesses casos, os PLDs possuem vantagens [3]:

  • PLDs são mais simples de desenvolver, pois alterações no projeto são feitas instantaneamente
  • Sistemas com processadores customizados possuem desenvolvimento lento e oneroso
  • Sistemas mais genéricos tendem a ter custos menores pela possibilidade de uso em diversas aplicações, facilitando o estoque de itens
Tempo de desenvolvimento entre sistema com microprocessador (ASIC) ou PLD (FPGA). Fonte: [3]


Em função da arquitetura e tecnologia empregada, os PLDs foram classificados em SPLDs (simple PLDs) ou CPLDs (complex PLDs).

SPLDs

São denominados SPLDs os seguintes dispositivos:

PAL - Programmable Array Logic

Um arranjo programável de portas AND seguido por um arranjo fixo de portas OR.

Arquitetura PAL. Fonte: [4]


Essa foi a primeira implementação de PLDs, e se baseia no fato de que qualquer função lógica pode ser reescrita como uma soma de produtos (SOP - sum of products) [4]. Por exemplo, sendo abaixo a tabela verdade da soma aritmética de um bit u de uma posição de um circuito somador, como função de x e y e do carry ci

ci x y u(ci,x,y)
0 0 0 0
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 0
1 1 0 0
1 1 1 1

Sendo as linhas 2, 3, 5 e 8, as que possuem saída 1, podemos escrever u como [5]:


Os PAL tem, porém, como limitação, a implementação apenas em circuitos combinacionais.


PLA - Programmable Logic Array

Muito semelhante aos PALs, os PLA diferenciam-se no fato de que tanto as ligações AND quanto OR são programáveis.

Arquitetura PLA. Fonte: [4]



GAL - Generic Array Logic

Características adicionais com relação aos PALs:

  • Célula de saída (chamada de OLMC - output logic macrocell) com flip-flop, porta XOR, multiplexadores
  • Inclusão de um sinal de retorno (feedback)
  • Utilização de memórias EEPROM na programação do circuito

Um exemplo dessa arquitetura pode ser visto na figura abaixo:

Arquitetura GAL no chip GAL 16V8. Fonte: [4]


CPLDs

Como o próprio nome já adianta, os CPLDs possuem arquitetura muito mais complexa que os SPLDs. De fato, os primeiros CPLDs eram formados pela interconexão programável de vários SPLDs, além de outros avanços. Na figura abaixo, a arquitetura básica de um CPLD:

Arquitetura de CPLDs. Fonte: [4]



FPGAs - Field programmable gate arrays - Arranjo de portas programável em campo

Os FPGAs estendem as capacidades dos CPLDs, sendo diferentes em arquitetura, tecnologia, características embutidas e custo. Por serem voláteis, precisam de uma memória de configuração não volátil para armazenar a programação do hardware. Uma simplificação da arquitetura de FPGAs pode ser vista na figura abaixo. No caso, CLBs (configurable logic blocks) e LABs (logic array blocks) são blocos semelhantes à SPLDs GAL.

Arquitetura de FPGAs Xilinx (a) e Altera (b). Fonte: [4]


Além desses blocos, FPGAs costumam possuir também:

  • Blocos RAM: Possibilitam o uso direto de memória, sem a necessidade de projetá-las
  • Blocos DSP: Muito utilizados em aplicações de processamento de áudio e vídeo digitais, o bloco DSP implementa operações de soma, multiplicação e variáveis.

Comparação entre dispositivos

Uma comparação entre os dispositivos vistos nesta aula pode ser vista na figura abaixo:

Comparação entre DLPs. Fonte: [6]


onde as características de armazenamento do programa são:

  • Fusível e antifusível - Configurado uma única vez
  • (E)EPROM - Configurado um número limitado de vezes, mantida com o chip desconectado da alimentação (não volátil)
  • SRAM - Configuração realizada cada vez que o sistema é alimantado (volátil)


Referências

[1] Midorikawa, Edson. Projeto de sistemas digitais. Disponível em Link. Acesso em 09/02/2015.
[2] Xilinx. What is Programmable Logic? Disponível em Link. Acesso em 09/02/2015.
[3] Parnell, Karen & Bryner, Roger. Comparing and contrasting FPGA and microprocessor system design and development. Disponível em Link. Acesso em 09/02/2015.
[4] Pedroni, Volnei A. Eletrônica digital moderna e VHDL. Disponível em Link. Acesso em 09/02/2015.
[5] Wikipedia. Canonical normal form. Disponível em Link. Acesso em 09/02/2015.
[6] Matos, Roberto de. Apresentação da disciplina de SST. Disponível em Link.

Tecnologia de FPGA

Os FPGAs são compostos por três tipos de componentes:

  • Bloco de entrada e saída (Input/Output Block - IOB): Circuitos responsáveis pela interface de entrada e saída do FPGA. Compostos basicamente de buffers.
  • Bloco de configuração lógica (Configurable Logic Block - CLB): Circuitos construídos usando flip-flops e lógica combinacional. Onde são construídas as funções lógicas do sistema.
  • Chaves de interconexões: Trilhas configuráveis usadas para conectar os blocos de funções com os blocos de saída. O processo de escolha das interconexões é chamado de roteamento.

Os 3 blocos são interconectados em duas dimensões, otimizando as conexões entre os blocos

Arquitetura simplificada de um FPGA. Fonte: [1]


IOB

São usados para fazer a interface de entrada e saída do FPGA. Consiste em um buffer de entrada e um de saída, ambos com flip-flops, permitindo que saídas com clocks sejam disponibilizadas sem encontrar atrasos significantes e reduzindo a necessidade de manter sinais de entrada por muito tempo.

IOB. Fonte: [2]


  • Entrada e saída são concentradas num único pino descrito como Pad.
  • Flip-flops realizam a sincronização dos dados, mas caminhos diretos, sem atrasos, são configuráveis
  • Entrada do dado pelo flip-flop inferior.
  • Saídas não utilizadas necessitam ser mantidas em tri-state.
  • Slew rate controla a velocidade de mudança de polaridade. Valores menores reduzem ruídos.

CLB [3]

Contêm a lógica do FPGA, como mostra a simplificação abaixo:

CLB. Fonte: [2] e [3]


Neste bloco:

  • Disponíveis 3 elementos configuráveis, dois com 4 entradas (F e G) e um com 3 entradas (H). Estes elementos podem construir qualquer função lógica a partir de suas entradas.
  • Com os multiplexadores M1 a M3, é possível combinar os elementos para criar funções de mais de 4 entradas.
  • Com os multiplexadores M4 a M7, a saída das funções lógicas podem ser enviadas diretamente para as saídas X e Y ou podem ser capturadas pelos flip-flops F1 e F2.
  • Saída dos flip-flops nas saídas XQ e YQ, podendo os pinos serem "desativados" para simplesmente copiar sinais de entrada.
  • O clock dos flip-flops pode ser configurado para a borda de subida ou descida.
  • Os flip-flops podem também usar sinal de Enable.
  • Os multiplexadores superiores permitem escolher a função dos sinais C1 a C4, para a entrada da função H ou outros sinais internos.
  • Blocos S/R Control configuram o estado inicial dos flip-flops.

As funções lógicas são implementadas a partir de suas tabelas verdade nos elementos lógicos usando uma memória chamada de Lookup Table (LUT). Com isso, um bloco de configuração lógica também pode ser usado como uma memória, em diferentes configurações dependendo dos multiplexadores. Nesses casos, as entradas F1 a F4 e G1 a G4 fornecem endereços, e as entradas C1 a C4 fornecem os dados e sinais de enable.

Chaves de interconexões

Os CLBs estão imersos numa rede de interconexões configuráveis. As conexões possíveis por cada bloco lógico podem ser vistas na figura abaixo.

Esquema de conexão de cada CLB. Fonte: [3]


Um FPGA com 64 blocos de configuração lógica seriam a repetição dessa figura numa matriz de 8x8

Um FPGA com 64 CLBs. Fonte: [3]


Para fazer a ligação entre CLBs vizinhos, o caminho unidirecional direct pode ser utilizado. Porém, para o roteamento de dados em maiores "distâncias", 3 outros caminhos são disponíveis, dispostos como a figura abaixo:

Caminhos indiretos de interligação num FPGA. Fonte: [4]


Na figura, uma Matriz de Comutação Programável (Programmable Switch Matrix - PSM) pode ser vista, além dos 3 caminhos indiretos:

  • Single: ideal para conexão entre CLBs vizinhos, pois é conectado a todos os blocos PSM.
  • Double: conectado intercaladamente nos blocos PSM
  • Long: não é conectado nos blocos PSM

Os blocos PSM introduzem atraso na propagação do sinal no FPGA. Os 3 caminhos introduzem versatilidade ao balancear atrasos e propagação em longas distâncias.

O bloco PSM efetua a conexão entre pinos seguindo o esquema da figura abaixo. No esquema, os círculos vermelhos são chamados de Elementos de Comutação Programável (Programmable Switch Element - PSE).

Conexão numa PSM. Fonte: [5]


Com isso, várias formas de conexão são possíveis, como exemplifica a figura a seguir:

Exemplo de conexão. Fonte: [4]



Várias tecnologias podem ser usadas para realizar a conexão num PSE:

  • Antifusível: Realiza a função oposta de um fusível. Inicia com uma grande resistência, e cria um caminho condutivo ao ser aplicada uma voltagem maior do que um certo limite.
  • Ocupam uma pequena área, permitindo um maior número de conexões em estruturas chamadas de Fully Populated
  • Aumentam a flexibilidade
  • Não podem ser reprogramados
PSM com PSE de antifusíveis. Fonte: [4]


  • Transistores de passagem: Transistores controlados por posições de memória realizam a passagem do sinal entre os pinos.
  • Ocupam uma grande área no chip, resultando num menor número de conexões
  • Menor flexibilidade
  • Pode ser reprogramado
PSE com transistor de passagem. Fonte: [4]



O trabalho de roteamento de sinais dentro de um FPGA é realizado por ferramentas de Placement & Routing, que buscam otimizar a propagação de sinais.

Antes e depois de um processo de Placement e routing. Fonte: [6]


NOTA: Os nomes dos blocos disponíveis nesta aula seguem os termos utilizados pela Xilinx, e os blocos referem-se a
      uma família específica, a XC4000E. Para fabricantes diferentes, ou mesmo famílias diferentes, mudanças podem
      ser observadas. Para informações sobre a arquitetura dos FPGAs da Altera, consultar [7].

Tabela comparativa entre FPGAs

A tabela a seguir é um exemplo de dados de fabricantes, no caso, da Xilinx.

Comparação FPGAs. Fonte: [3]


  • Max user I/O: Número de entradas e saídas por FPGA. Devido aos diferentes encapsulamentos possíveis, nem todos os pinos de entrada e saída podem estar disponíveis
  • Flip-flops: Número total de flip-flops disponíveis, sendo 2 por CLB e 2 por IOB
  • Max RAM bits (no logic): Número de bits de RAM disponíveis no caso de todos os CLBs estarem configurados como RAM
  • Max gates (no RAM): Número total de portas disponíveis quando nenhum CLB estiver configurado como RAM

Referências

[1] Oskin, Mark. Apresentação sobre FPGAs da disciplina Advanced Digital Design. Disponível em Link. Acesso em 12/02/2015.
[2] Zeidman, bob. All about FPGAs. Disponível em Link. Acesso em 12/02/2015.
[3] Wakerly, John. Digital Design: Principles & practices. Disponível (versão para demonstração) em Link. Acesso em 12/02/2015.
[4] Wang, Haibo. FPGA Programmable Interconnect and I/O Cells. Disponível em Link. Acesso em 13/02/2015.
[5] Wikipedia. Field-programmable gate array. Disponível em Link. Acesso em 13/02/2015.
[6] Wong, William. FPGA Design Suite Generates Global Minimum Layout. Disponível em Link. Acesso em 13/02/2015.
[7] Altera. White Paper: FPGA architecture. Disponível em Link. Acesso em 13/02/2015.


Projetos em FPGA

Altera

A Altera é uma das maiores fabricantes de FPGAs e CPLDs. Há no seu portfólio PLDs dos mais baixo custo até dos mais avançados do mercado. O Quartus II é o software de desenvolvimento de PLDs da Altera.

Dispositivos da Altera. Fonte: [1]



Licença

A licença de uso é dada da seguinte forma:

  • Web Edition: de uso livre, com limitações quanto ao número de DLPs disponíveis
  • Full Edition - Fixed License: pago, com licença nativa no computador
  • Full Edition - Float License: pago, com licença em rede
Edições do Quartus II da Altera. Fonte: [1]


Uma comparação entre as edições Web e Full está disponível em Link.

Para configurar uma licença, acessar Link. A licença Web é gerada em Link. Alguns laboratórios do IFSC possuem computadores com licenças flutuantes, como pode ser visto no Link. Além disso, o IFSC possui licenças flutuantes para acesso remoto via Cloud. O tutorial para acesso pode ser acessado em Acesso ao IFSC-CLOUD - Quartus II - Modelsim - QSIM.


Como obter informações

A Altera preparou uma série de materiais sobre o desenvolvimento usando o Quartus II. Existem cursos on-line e presenciais, pagos e gratuitos:

  • A página de cursos pode ser acessada em Link.
  • O treinamento completo (muito material!) está disponível em Link.
  • Um bom material escrito pode ser acessado em Link.

Quartus II

Abaixo, um roteiro para o reconhecimento do software da Altera:

  • Abrir o Quartus II
  • Getting Started
  • Janelas:
  • Project Navigator
  • Message Window
  • Tool View Window
  • Tasks Window
  • Custom Tasks Flow

Fluxo de desenvolvimento em PLDs

Fluxo de desenvolvimento em PLDs. Fonte: [1]


  • RTL: nível de abstração usado para descrever o circuito, dentre 3:
  • Behavioural: mais alto nível de abstração, descreve o comportamento do circuito (entradas e saídas)
  • RTL - Register Transfer Level: descrição do Hardware a partir de lógica, indicando como dados são transferidos entre registradores
  • Gate Level: usa componentes como portas lógicas, flip-flops e multiplexadores
  • Synthesis: processo em que o comportamento de um circuito numa forma abstrata (por exemplo, em RTL) é convertido para uma implementação em termos de portas lógicas.
  • Netlist: descreve a conectividade dos terminais para o desenvolvimento do circuito.
  • Place & Route - Fitting: otimiza a localização dos elementos e o roteamento dos dados entre eles.


Projeto no Quartus II

Wizard
  • Selecionar como dispositivo o Cyclone IV EP4CE30F23, ou o mais próximo disponível. É esse o modelo que será utilizado nas nossas aulas.


Arquivos [2]
  • .QPF - Quartus II Project File: informação da versão do Quartus 2 e da data. Traz as revisões efetuadas no projeto.
  • .QDF - Quartus II Defaults File: configurações padrão de todo novo projeto criado
  • .QSF - Quartus II Settings File: configurações específicas do projeto, como arquivos, dispositivo escolhido, etc.
  • Pasta dB: informação do projeto compilado
  • .SDC - Synopsys Design Constraint: restrições temporais do projeto
O Quartus também oferece ferramentas para controle de versão de projetos a partir de arquivos .QAR - Quartus II Compressed Archive File. Disponível no menu Project. Com revisões, é possível fazer testes com outros parâmetros sem perder resultados anteriores.

Formas de desenvolvimento

Ir em File -> New, e selecionar um dos Design Files disponíveis.

Formas de desenvolvimento no Quartus II. Fonte: [1]


Nesta aula, usaremos o desenvolvimento via Esquemático - Block File.


Desenvolvimento via esquemático

Um exemplo de sistema será usado para apresentar a ferramenta. O sistema que será desenvolvido está disponível na figura abaixo:

Sistema a ser desenvolvido. Fonte: [3]


O desenvolvimento é feito a partir dos seguintes passos:

  • Criar novo arquivo do tipo Schematic
  • Importar portas lógicas
  • Importar sinais de entrada e saída
  • Atribuir nomes aos pinos
  • Conectar os componentes
  • Compilar
  • Atribuir pinos físicos do FPGA aos pinos do sistema (Pin planner)
  • Pinos atribuídos podem ser exportados para futuros desenvolvimentos
  • Descrever sinais de entrada (criar arquivo VWF - Vector Waveform File)
  • Simular (Tool -> Simulation)

Utilizando o FPGA

O kit DE2-115

O Kit Altera DE2-115 pode ser visto na figura abaixo.

Kit Altera DE2-115. Fonte: [4]


Algumas características do kit:

  • FPGA Altera Cyclone IV EP4CE115F29C7
  • 2 MB de SRAM
  • 64 MB de SDRAM
  • 8 MB de Flash
  • Interfaces:
  • Botões
  • Switch
  • Leds
  • Módulo LCD


Para ligar o kit, seguir os passos:

  1. Conectar o cabo USB no computador e no kit na porta USB Blaster. Talvez seja necessário instalar o driver específico para o USB da Altera. Para instalar, consultar Link e Link.
  2. Desligar o kit soltando o botão ON/OFF vermelho.
  3. Conectar o adaptador 12V.
  4. Selecione a posição RUN no switch RUN/PROG (SW19).
  5. Ligue o kit pressionando o botão ON/OFF vermelho.


Para mais informações, consultar a página Software e equipamentos recomendados para programação de FPGAs, e a página Preparando para gravar o circuito lógico no FPGA

Exercício 1 - Esquemático

Executar o roteiro disponível em Link. São informações complementares ao roteiro:

  • Para atribuir os pinos usando o arquivo .qsf fornecido pela Altera, usar o menu Assignments → Import Assignments.
  • Uma outra referência para o processo de programação do FPGA pode ser vista em Link.

Referências

[1] Altera Training Courses. Using the Quartus II Software: An Introduction. Disponível em Link. Acesso em 19/02/2015.
[2] Altera. Quartus II Volume I: Design and Synthesis. Disponível em Link. Acesso em 19/02/2015.
[3] Altera. Quartus II Introduction Using Schematic Designs. Disponível em Link. Acesso em 27/02/2015.
[4] Altera. DE2-115 User Manual. Disponível em Link.

Introdução ao VHDL

VHDL vem de VHSIC (Very High Speed Integrated Circuito) Hardware Description Language. É a linguagem padrão IEEE para a descrição de hardware na indústria.

  • Características:
  • Linguagem de descrição de hardware, não de programação
  • Maior parte da linguagem não é Case Sensitive
  • Expressões são terminadas com ponto-e-vírgula
  • É Space Insensitive
  • Comentários feitos com um "--" no início da linha. Não há comentários em bloco


Unidades do código VHDL

O código VHDL é inicialmente dividido em 3 seções:

PACKAGE
ENTITY
ARCHITECTURE
PACKAGE

Declara as bibliotecas utilizadas no sistema. Usa o formato:

LIBRARY nome1, nome2;
USE nome1.pack_name1.object;
USE nome2.pack_name2.ALL;

Duas LIBRARYs disponibilizadas automaticamente:


  • STD: tipos básicos de dados:
  • BIT: dois valores ('0' e '1')
  • BIT_VECTOR: deve indicar a ordem dos bits
SIGNAL s1 : BIT_VECTOR (3 DOWNTO 0);
SIGNAL s2 : BIT_VECTOR (0 TO 3);
  • BOOLEAN: dois valores (False, true)
  • INTEGER: Valores positivos e negativos em decimal
SIGNAL s3 : INTEGER;                  -- Número de 32 bits
SIGNAL s4 : INTEGER RANGE 0 TO 255    -- Número de 8 bits
  • NATURAL: Inteiro sem sinal
  • CHARACTER: ASCII
  • STRING: Array de ASCII
  • TIME: Valores com unidades de tempo (ps, ms, min, hr)
  • REAL: Número de ponto flutuante de precisão dupla


  • WORK: indica onde estão armazenados os arquivos do projeto


Um pacote frequentemente incluído é STD_LOGIC_1164, da LIBRARY IEEE, que define os tipos:

  • STD_LOGIC: bit com 3-state (Z) e "não importa" (-)
  • STD_ULOGIC: tipo lógico com 9 valores Link

A declaração do pacote IEEE ficaria assim:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY

define a visão externa do modelo (símbolo). Usa o formato:

ENTITY <entity_name> IS
   GENERIC
   PORT
END ENTITY <entity_name>

onde:

  • PORT: descreve entradas e saídas
PORT (
   nome1, nome2 : <mode> <type>;
   nome3, nome4 : <mode> <type>
);
  • <mode>:
  • in (input): sinais de entrada - São apenas lidos
  • out (output): sinais de saída - São apenas escritos
  • inout (bidirecional): podem ser lidos e escritos
  • <type>: tipo do dado
  • GENERIC: passa informações globais (constantes) ao modelo
GENERIC (
   nome1, nome2 : <type> (:= <initial value>);
   nome2, nome4 : <type> (:= <initial value>)
);
  • <type>: tipo do dado
  • <initial value>: opcional
ARCHITECTURE

Define a função do modelo (esquemático). Segue o formato:

ARCHITECTURE <identifier> OF <entity_identifier> IS
   <declaration>
BEGIN
   <body>
END ARCHITECTURE <identifier>

onde:

  • <entity_identifier>: nome da ENTITY a qual pertence a ARCHITECTURE
  • <identifier>: nome da ARCHITECTURE, que deve ser único dentre as ARCHITECTUREs da ENTITY
  • <declaration>: identificadores locais usados na ARCHITECTURE que não são PORTs nem GENERICs. Devem ser declarados antes de usados.
  • <body>: corpo da ARCHITECTURE

Nomes para identificadores

Os identificadores das entidades, arquiteturas e portas devem ser compactos e informativos. Abaixo, exemplos de nomes bons e ruins.

Exemplos de nomes de identificadores. Fonte: [4]


Desenvolvimento via VHDL

Um exemplo de sistema será usado para apresentar o Quartus II e o VHDL. O sistema que será desenvolvido está disponível na figura abaixo:

Sistema a ser desenvolvido. Fonte: [2]


O desenvolvimento é feito a partir dos seguintes passos:

  • Criar novo arquivo do tipo VHDL File
  • Escrever o código
  • Templates podem ser usados (Edit -> Insert Template)
Código VHDL


  • Compilar
  • Atribuir pinos físicos do FPGA aos pinos do sistema (Pin planner)
  • Pinos atribuídos podem ser exportados para futuros desenvolvimentos
  • Descrever sinais de entrada (criar arquivo VWF - Vector Waveform File)
  • Simular (Tool -> Simulation)


Concorrência do código

Os código VHDL tem uma característica importante que é a concorrência. Assim, todas as instruções tem a mesma procedência, diferentemente das linguagens de programação. O exemplo abaixo demonstra isso:

Multiplexador com buffer de 3 estados. Fonte: [3].


A solução do problema pode ser vista abaixo:

Solução do exercício.


Erros clássicos

Em desenvolvimento com VHDL, são comuns os seguintes erros [3]:

  1. Tipos de dados diferentes (um lado é BIT e outro é BOOLEAN)
  2. Tamanhos não são iguais
  3. Valor ou representação inválido (BIT não aceita valor 'Z', vetor de bits requer aspas duplas)
  4. Indexação incorreta (ordem)
  5. Operador de atribuição incorreto (para sinais é "<="; para variáveis e constantes é ":="

Tarefa - Introdução ao VHDL

Ler os capítulos 1, 2 e 3 do livro [4], resolvendo os exercícios do capítulo 3.

Referências

[1] Altera Training Courses. VHDL Basics. Disponível em Link. Acesso em 27/02/2015.
[2] Altera. Quartus II Introduction Using VHDL Designs. Disponível em Link. Acesso em 27/02/2015.
[3] Pedroni, Volnei A. Eletrônica Digital Moderna e VHDL. Rio de Janeiro: Elsevier, 2010.
[4] Mealy, B. Tappero, F. Free Range VHDL. Free Range factory. Disponível em Link. Acesso em 27/02/2015.


Objetos e atribuições

Objetos

Há quatro tipos de objetos em VHDL: CONSTANT, SIGNAL, VARIABLE e FILE. Vamos ver agora os dois primeiros [1].

CONSTANT

É uma forma de atribuir um valor constante a um nome. Não pode então ser alterada durante a execução. É utilizada para melhorar:

  • Legibilidade
  • Flexibilidade

A declaração segue o formato:

CONSTANT <nome> : <tipo> := <valor>;


O escopo é definido pela localização da sua declaração:

  • GENERIC: Global
  • ARCHITECTURE: Local
Código com CONSTANTs declaradas.



SIGNAL

Representa a interconexão entre blocos. É declarada da seguinte forma:

SIGNAL <nome> : <tipo>;

Um valor inicial é opcionalmente passado ao objeto, da seguinte forma:

SIGNAL <nome> : <tipo> := <valor_inicial>;
Código com um SIGNAL declarado.



Bit e múltiplos bits

Na atribuição de valores binários, há diferenças de declaração entre um único bit ou múltiplos bits:

  • Um único bit: aspas simples:
x <= '1';
  • Múltiplos bits: aspas duplas:
x <= "10101010";
Indexação

É possível atribuir valores à membros específicos de um barramento (vetor). Abaixo, alguns exemplos ilustrativos:

x(3)          <= '0';
x(0)          <= '1';
x(7 DOWNTO 4) <= "1010";

É possível ainda usar vírgulas e os operadores OTHERS e => para fazer atribuições específicas [2]:

  • Nominal:
x <= (7 => '0', 5 => '0', OTHERS => '1');
  • Posicional:
x <= ('0', '1', '0', OTHERS => '1');
Bases numéricas

É possível atribuir à barramentos valores em bases numéricas diferentes. Para isso, o seguinte formato pode ser usado:

y <= [<tamanho>][<preenchimento>]<base>"<valor>";
  • <valor>: valor a ser atribuído
  • <base>: b (binário), x (hexadecimal) ou o (octal)
  • <tamanho>: número de sinais atribuídos (opcional)
  • <preenchimento>: caso o número de sinais atribuídos (<tamanho>) seja maior que o número de sinais gerados no <valor>, os demais sinais são preenchidos com 1's (s) ou 0's (u)

Atribuições simultâneas

Uma das maiores diferenças de VHDL para linguagens de programação de software é que as atribuições do código VHDL são simultâneas. De fato, todas as atribuições dentro de uma arquitetura representam processos implícitos que executam em paralelo. Quando um sinal de entrada do processo é alterado, o novo valor é imediatamente atribuído à variável.

São três os tipos de atribuições simultâneas no VHDL:

Simples

São da forma:

<nome> <= <expressão>;

No exemplo abaixo, há dois processos implícitos, cujas atribuições de sinais são feitas simultaneamente:

x1 <= a1 OR b1;
x2 <= a2 AND b2;
Condicional

São da forma:

<nome> <= <valor> WHEN <condição_1> ELSE
       <valor> WHEN <condição_2> ELSE
                      .
                      .
                      .
       <valor> WHEN <condição_3> ELSE
       <valor>;

O exemplo abaixo representa dois multiplexadores (A e B) em série, onde:

  • Sinal sel_A seleciona a saída do multiplexador A, entre x e y, que é conectada na entrada do multiplexador B
  • Sinal sel_B seleciona a saída do multiplexador B ('saida'), entre a saída do A e z
saida <= z WHEN sel_B = '1' ELSE
         y WHEN sel_A = '1' ELSE
         x;

De certa forma, o operador condicional é semelhante ao operador if em linguagens de programação de software.

De seleção

São da forma:

WITH <expressão> SELECT
   <nome> <= <valor> WHEN <condição_1>,
             <valor> WHEN <condição_2>,
                          .
                          .
                          .
             <valor> WHEN OTHERS;

No exemplo abaixo, um multiplexador de 4 entradas (a, b, c, d) e uma seleção de 2 elementos sel é desenvolvido:

WITH sel SELECT
   y <= a  WHEN "00",
        b  WHEN "01",
        c  WHEN "10",
        d  WHEN "11",
       '0' WHEN OTHERS;

Operadores

Abaixo, um resumo dos operadores utilizados nas expressões:

Lógicos
  • NOT
  • AND
  • NAND
  • OR
  • NOR
  • XOR
  • XNOR
Aritméticos
  • Adição: +
  • Subtração: -
  • Multiplicação: *
  • Divisão: /
  • Exponenciação: **
  • Valor absoluto: ABS
Comparação
  • Igual: =
  • Diferente: /=
  • Maior: >
  • Menor: <
  • Maior igual: >=
  • Menor igual: <=
Concatenação

Para concatenar valores, usa-se o operador &:

x <= '1' & "0001";         -- x <= "10001"


Desta forma, a ordem das atribuições dentro de uma arquitetura não importa!.

Exercícios - Objetos e atribuições

Resolver os seguintes exemplos do livro [3]:

  • Exemplo 2: pg 36
Exemplo 2. Fonte: [3].


Exemplo 2 usando sinais intermediários. Fonte: [3].


  • Exemplo 3: pg 39
Exemplo 3. Fonte: [3].


  • Exemplo 4: pg 40
Exemplo 4. Fonte: [3].


Exemplo 4 com elementos separados. Fonte: [3].


  • Exemplo 5: pg 42
Exemplo 5. Fonte: [3].


  • Exemplo 6: pg 43
Exemplo 6. Fonte: [3].


  • Exemplo 7: pg 44
Exemplo 7. Fonte: [3].


  • Exemplo 8: pg 46
Exemplo 8. Fonte: [3].


Resolver os exercícios do capítulo 4 do livro [3].

Referências

[1] Altera Training Courses. VHDL Basics. Disponível em Link. Acesso em 27/02/2015.
[2] Pedroni, Volnei A. Eletrônica Digital Moderna e VHDL. Rio de Janeiro: Elsevier, 2010.
[3] Mealy, B. Tappero, F. Free Range VHDL. Free Range factory. Disponível em Link. Acesso em 27/02/2015.

Abordagens

Há 3 tipos de abordagens para escrever arquiteturas em VHDL: Data-flow, Behavioral e Structural.

Data-flow (fluxo de dados)

Especifica o circuito como uma representação do fluxo de dados através do circuito. São informadas as relações entre as entradas que geram as saídas do modelo, ou como o dado de entrada "flui" até a saída, a partir das operações descritas. As atribuições simples, condicional e de seleção fazem parte da abordagem Data-flow.

Vantagens:

  • Dá uma visão do fluxo dos sinais no circuito diretamente do código
  • Indica como o sistema será implementado no FPGA

Desvantagens:

  • Se torna difícil de ser utilizado à medida que os circuitos ficam mais complexos

Behavioral (comportamental)

Não traz detalhes de como o sistema será quando sintetizado. Modela como as saídas do sistema irão reagir às entradas do sistema, e os detalhes de implementação são deixados para a ferramenta de sintetização.

Enquanto a abordagem Data-flow descreve como o circuito deve ser, a abordagem behavioral descreve o seu comportamento. Assim, a abordagem comportamental é considerada de um nível de abstração maior.

Process

É o coração da abordagem behavioral, pois seu corpo possui instruções sequenciais. Possui a forma:

<label>: process (<sinal1>,<sinal2>) is
   <declaração>
begin
   <instruções sequenciais>
end process <label>

onde:

  • <label>: rótulo do processo. É opcional mas recomendado para melhorar a legibilidade do código
  • <sinal1>,<sinal2>: lista de sinais que compõem a lista de sensibilidade, parte fundamental da estrutura process (mais detalhes abaixo)
  • <declaração>: declaração de variáveis com escopo local ao process
  • <instruções sequenciais>: corpo da estrutura, onde a lógica é descrita
Lista de sensibilidade

Temos abaixo duas formas diferentes de descrever a mesma função, uma operação de XOR entre as portas de entrada A e B.

XOR com Data-flow. Fonte: [1].
XOR com Behavioral. Fonte: [1].


Na abordagem Data-flow, a cada vez que um sinal (A ou B) é alterado, a expressão é avaliada e o sinal do lado esquerdo do operador de atribuição (F) é atualizado. Na abordagem Behavioral, para o corpo da função ser executado, é necessário que haja alteração num dos sinais presentes da lista de sensibilidade. É importante ter em mente no entanto que embora seja composta por instruções sequenciais, a estrutura process é executada simultaneamente com instruções Data-flow dentro da mesma arquitetura.

Execução sequencial

As instruções no corpo de um process são sintetizadas de forma a serem executadas sequencialmente, como numa programação de software comum. Abaixo, serão demonstrados os 3 tipos de instruções sequenciais do VHDL.

Instrução de atribuição de sinal

São as instruções vistas nas aulas anteriores, com o operador de atribuição "<=".

Instrução de teste

É a versão sequencial para a atribuição condicional vista anteriormente. Segue a forma:

if (<condição>) then
   <instruções>;
elsif (<condição>) then
   <instruções>;
else
   <instruções>;
end if;

Considerações:

  • Os parênteses são opcionais
  • Instruções de teste podem ser aninhadas para obter testes mais complexos
  • A instrução pode ser escrita em uma única linha se isso melhorar a legibilidade
Uso do IF - Exemplo 9, pg 58. Fonte: [1].



Instrução de seleção

Versão sequencial para a atribuição de seleção vista anteriormente. Segue a forma:

case (<expressão>) is
   when <resultado> =>
      <instruções>;
   when <resultado> =>
      <instruções>;
   when others =>
      <instruções>;
end case

Considerações:

  • Os parênteses são opcionais
  • Somente um conjunto de instruções é executado
  • A instrução pode ser escrita em uma única linha se isso melhorar a legibilidade
Uso do CASE - Exemplo 12, pg 64. Fonte: [1].


Referências

[1] Mealy, B. Tappero, F. Free Range VHDL. Free Range factory. Disponível em Link. Acesso em 27/02/2015.


Atribuições de variáveis em simulações

As atribuições de sinais podem ser agendadas usando a instrução AFTER:

x <= A or B AFTER 0.5 ns;
 
y <= a AFTER 1 s WHEN z = 0 ELSE
     b;

Mesmo quando não há um agendamento explícito, as atribuições de sinais não são executadas imediatamente após a instrução. Tanto em processos implícitos (atribuições simples, condicionais e de seleção) quanto em processos explícitos (instrução PROCESS), as atribuições são realizadas após um tempo chamado de Delta Delay. O Delta Delay é definido como o tempo necessário para que todos os processos simultaneamente em execução sejam encerrados. Após esse tempo, todas as atribuições sem agendamento indicado são realizadas. Isso significa que as atribuições realizadas dentro de processos explícitos só serão efetuadas após a conclusão do processo.

A necessidade deste fato pode ser confirmada no exemplo a seguir [1].

Circuito combinacional. Fonte: [1].


Para o circuito apresentado, duas formas de avaliação podem ser utilizadas:

Formas de avaliação do circuito. Fonte: [1].


Se esse comportamento não for bem definido, erros graves podem ser gerados na fase de compilação. Por isso, os Delta Delays são utilizados, e o problema é resolvido da seguinte forma:

Circuito avaliado com o Delta Delay. Fonte: [1].


Nos códigos abaixo, três formas aparentemente semelhantes são exibidas. Você consegue confirmar se os códigos são funcionalmente iguais?

Códigos e Delta Time. Fonte: [2].


PENSE A RESPEITO e depois clique no "+" para expandir

Repare que há diferenças no número de processos envolvidos. No caso, os códigos esquerdo e direito são funcionalmente iguais. O código central é diferente dos outros pois o c usado na segunda atribuição não terá o valor atualizado da operação a AND b.

Simulação

A simulação do modelo VHDL segue duas fases: inicialização e ciclos de simulação.

  • Inicialização:
  • Valores iniciais são atribuídos aos sinais
  • Processos sensíveis aos sinais são executados
  • Atribuição de sinais são agendadas
  • Ciclo de simulação:
  • Tempo de simulação é avançado ao próximo tempo em que há uma atribuição de sinal agendada
  • São realizadas as atribuições
  • Processos sensíveis aos sinais são executados
  • Atribuição de sinais são agendadas
  • Quando todos os processos terminam sua execução, o ciclo atual de simulação é encerrado, e um novo ciclo é executado
  • Quando todos os processos forem executados e não houver mais alterações nos sinais, a simulação é encerrada
Fluxo de simulação de um modelo VHDL. Fonte: [2].


O objeto VARIABLE

Dentro de processos explícitos (instrução PROCESS) o objeto VARIABLE pode ser utilizado. Sua declaração é igual à declaração de objetos SIGNAL, mas há algumas diferenças:

  • Atribuição de valores: Enquanto objetos SIGNAL usam o operador "<=", objetos VARIABLE usam ":=".
  • Atualização: Enquanto objetos SIGNAL são atualizados ao final do Delta Time, objetos VARIABLE são atualizados imediatamente.

Além disso, como objetos VARIABLE só podem ser declarados dentro de instruções PROCESS, eles são de escopo local. Uma forma de alterar isso é utilizar um objeto SHARED VARIABLE, normalmente declarado na arquitetura. Uma SHARED VARIABLE possui escopo global, mas só pode ser modificada em códigos sequenciais (dentro de um PROCESS, por exemplo). A passagem do seu valor à um SIGNAL pode ser feita em qualquer lugar [4].

SHARED VARIABLE x : BIT;

Assim como variáveis globais em linguagens de programação de software, é recomendado que objetos SHARED VARIABLE sejam usados apenas em casos muito específicos.

A tabela abaixo resume as diferenças entre objetos SIGNAL e VARIABLE [4]:

Regra SIGNAL VARIABLE
1. Local de declaração Proibido declarar em código sequencial Somente em código sequencial (PROCESS ou subprograma)
2. Escopo Pode ser global Sempre local (visível somente no código sequencial correspondente)
3. Atualização Ao final do DELTA TIME Atualização imediata
4. Atribuição sig <= 5 var := 5

Tarefas

  • Resolver exercícios do Capítulo 5 (pg 68) do livro [3].

Referências

[1] Perry, Douglas L. VHDL Programming by example. 4ª Edição. McGrw-Hill.
[2] Altera Training Courses. VHDL Basics. Disponível em Link. Acesso em 27/02/2015.
[3] Mealy, B. Tappero, F. Free Range VHDL. Free Range factory. Disponível em Link. Acesso em 27/02/2015.
[4] Pedroni, Volnei A. Eletrônica Digital Moderna e VHDL. Rio de Janeiro: Elsevier, 2010.

Outros tópicos em VHDL

Tipos de dados definidos pelo usuário

O projetista pode também criar seus próprios tipos de dados. Eles podem ser declarados na entidade, arquitetura, entre outros. Tipos de dados devem ser definidos sempre que possível, pois melhora a legibilidade do código [1].

Tipos baseados em inteiros

São declarados usando a forma:

TYPE <nome do tipo> IS RANGE <faixa de valores>;

onde <faixa de valores> define a faixa de valores que o tipo de dado pode assumir. Usa as palavras chaves TO ou DOWNTO.

Exemplos:

type scores is range 0 to 100;
type years is range -3000 to 3000;
type apples is range 0 to 15;
type oranges is range 0 to 15;
Tipos enumerados

Definem uma lista de valores. Seguem o formato:

TYPE <nome do tipo> IS (<lista de nomes ou números>);

onde <lista de nomes ou números> define os valores possíveis, separados por vírgula.

Exemplos:

type machine_state is (idle, forward, backward);
type counter is (zero, one, two, three);
Tipos baseados em arranjos

Seguem a forma:

TYPE <nome do tipo> IS ARRAY (<faixa de valores>) OF <tipo do dado>;

Exemplos [2]:

  • Arranjos linha:
type vector is array (7 downto 0) of std_logic;
  • Arranjos 1D x 1D (conjunto de linhas):
type array1D1D is array (1 to 4) of bit_vector (7 downto 0);
type vector_array is array (1 to 4) of vector;
  • Arranjos matriciais
type array2D is array (1 to 8, 1 to 16) of std_logic;


NOTA: Todos os tipos de dados declarados acima poderiam ter sido criados com o uso da palavra SUBTYPE. A vantagem de definir subtipos é a possibilidade de fazer atribuições entre os tipos de origem e novo.

Laços de repetição

No corpo de processos explícitos é possível criar laços de repetição. São normalmente utilizados para atribuição de valores à múltiplas portas, contagem, etc.

FOR

Usado quando o desenvolvedor sabe o número de iterações a serem realizadas. Segue a forma:

<rotulo>: FOR <indice> IN <faixa de valores> LOOP
   <instruções sequenciais>;
END LOOP <rotulo>;

onde:

  • <indice>: Variável que receberá o valor incrementado a cada iteração. Possui as seguintes características:
  • Não precisa ser declarada previamente.
  • Não pode receber valores dentro do laço.
  • Somente incrementos de 1 unidade são permitidos.
  • <faixa de valores>: Pode ser declarada de duas formas:
  • Explicitamente, com as palavras-chave TO e DOWNTO
  • Implicitamente, a partir de tipos definidos pelo usuário

Exemplos:

for cnt_val in 0 to 24 loop
   -- sequential_statements
end loop;
for cnt_val in 24 downto 0 loop
   -- sequential_statements
end loop;
type my_range is range 0 to 24;
--
for cnt_val in my_range loop
   -- sequential_statements
end loop;
type my_range is range 24 downto 0;
--
for cnt_val in my_range loop
   -- sequential_statements
end loop;
WHILE

Usado quando o desenvolvedor não conhece o total de iterações necessárias, pois elas são realizadas até uma condição determinada ser atingida.

<rotulo>: WHILE (<condição>) LOOP
   <instruções sequenciais>;
END LOOP <rotulo>;
Controle de iterações

O VHDL fornece também instruções para controle de iterações

NEXT

Pula o restante da iteração atual do laço, passando para a próxima. Duas formas são disponíveis, como pode ser visto nos exemplos abaixo:

variable my_sum : integer := 0;
--
for cnt_val in 0 to 50 loop
   if (my_sum = 20) then
      next;
   end if;
   my_sum := my_sum + 1;
end loop;
variable my_sum : integer := 0;
--
while (my_sum < 300) loop
   next when (my_sum = 20);
   my_sum := my_sum + 1;
end loop;
EXIT

Encerra toda a estrutura de repetição. As duas formas disponíveis ao NEXT podem ser utilizadas.

Repetição de código

Assim como linguagens de programação de software, VHDL também traz ferramentas para evitar a repetição de códigos. No caso, são utilizadas as estruturas FUNCTION, PROCEDURE e COMPONENT. As duas primeiras serão vistas agora.

FUNCTION

São blocos de código que podem ser chamados para realizar tarefas determinadas. Características:

  • Assim como processos explícitos, FUNCTIONs são sequenciais.
  • Todos os parâmetros recebidos são de entrada.
  • Retornam apenas um valor.

São declaradas da forma:

FUNCTION <nome> (<argumentos de entrada>)
RETURN <tipo do dado de retorno> IS
   <declarações>
BEGIN
   <instruções sequenciais>
   <rotulo>: RETURN <expressao>;
END FUNCTION <nome>

onde:

  • <argumentos de entrada>: Opcionais, é a lista de sinais de entrada da função
  • <rotulo>: Opcional.
  • <expressao>: Expressão a ser calculada para definir o dado de retorno. Normalmente, apenas a variável de retorno é indicada.

Funções podem ser declaradas na parte declarativa da ARCHITECTURE, e podem ser chamadas em qualquer lugar do código

Função de exemplo. Fonte: [3].


PROCEDURE

Assim como as FUNCTIONs, PROCEDUREs são usados para evitar a repetição de código. Características:

  • Assim como PROCESS e FUNCTION, PROCEDUREs são sequenciais.
  • Podem ter qualquer número de parâmetros de entrada, saída, ou entrada e saída (inout)
  • Funções normalmente fazem parte de uma expressão, enquanto que PROCEDUREs compõem uma instrução em si

São da forma:

PROCEDURE <nome> (<argumentos>) IS
   <declarações>
BEGIN
   <instruções sequenciais>
END PROCEDURE <nome>

onde <argumentos> define a lista de sinais de entrada e saída do PROCEDURE, e cada argumento necessita do seu modo (in, out, inout).


Tarefas

Resolver os exercícios abaixo usando ao menos um tipo de dado definido, uma estrutura de repetição e uma função ou componente.

  • Desenvolva um modelo VHDL para uma porta AND com 12 entradas
  • Desenvolva uma função VHDL para converter um vetor binário de 10 elementos para um número inteiro


Referências

[1] Mealy, B. Tappero, F. Free Range VHDL. Free Range factory. Disponível em Link. Acesso em 27/02/2015.
[2] Pedroni, Volnei A. Eletrônica Digital Moderna e VHDL. Rio de Janeiro: Elsevier, 2010.
[3] Perry, Douglas L. VHDL Programming by example. 4ª Edição. McGrw-Hill.

Abordagem estrutural

Das três abordagens para escrever arquiteturas em VHDL (Data-flow, Behavioral e Structural) nos falta a última, que será vista agora com a introdução de uma nova estrutura: COMPONENT. Para isso, o projeto de um sistema específico será usado como exemplo ilustrativo. Toda esta aula segue o "Capítulo 8 - VHDL Modularity with Components" de [1].

Em VHDL, a abordagem Estrutural é obtida a partir do uso de uma estrutura chamada COMPONENT. O desenvolvimento de uma COMPONENT pode ser dividido nas etapas abaixo:

  1. Dar nome ao módulo a ser descrito (entidade)
  2. Descrever o que o módulo irá fazer (arquitetura)
  3. Fazer o programa saber que o módulo existe e pode ser utilizado (declaração do componente)
  4. Usar o módulo no código (instanciação do componente ou mapeamento)

Assim, a estrutura COMPONENT é semelhante à criação de bibliotecas próprias na programação de software, com a criação de pequenos módulos (ou funções) e sua posterior declaração e utilização no código principal. Esta semelhança pode ser vista na tabela abaixo:

Linguagem C VHDL
Descrever a interface da função ENTITY do módulo
Descrever o que a função faz ARCHITECTURE do módulo
Provê um protótipo da função para o programa principal (main) Declaração da COMPONENT na Top-level Entity
Chamar a função no programa principal (main) Instanciação ou mapeamento do COMPONENT na Top-level Entity

O exemplo: Comparador de 3 bits

O exemplo que será utilizado para demonstrar a abordagem estrutural pode ser visto na figura abaixo. São características:

  • As 3 portas A_IN e B_IN compõem dois barramentos de entrada
  • EQ_OUT é um BIT, que indica que as entradas são iguais (1) ou não (0)
  • Os sinais p1_out, p2_out e p3_out são internos ao sistema
Exemplo - Comparador de 3 bits. Fonte: [1].


Desenvolvendo o sistema usando a abordagem Estrutural

A partir do sistema, a abordagem Estrutural segue os 5 passos abaixo:

  1. Implementar os módulos do circuito
  2. Declarar a entidade de nível mais alto
  3. Declarar os módulos de mais baixo nível
  4. Declarar os sinais internos usados para conectar os módulos
  5. Instanciar as unidades
Implementar os módulos do circuito

Como pode ser visto, o sistema faz uso de dois sistemas menores: a porta XNOR de 2 entradas e a porta AND de 3 entradas. Assim, é necessário implementar essas duas entidades.

No Quartus II, criar um projeto novo com o nome da entidade de nível mais alto my_compare. Após isso, criar os dois arquivos abaixo:

Módulo 1: big_xnor.vhd. Fonte: [1].
Módulo 2: big_and3.vhd. Fonte: [1].


Repare que os arquivos são desenvolvidos da mesma forma que sistemas como um todo.

Declarar a entidade de nível mais alto

Agora o comparador começará a ser desenvolvido, no arquivo my_compare.vhd. Como todo sistema, inicia-se pela entidade. A partir do diagrama acima e com base nas considerações apresentadas, a entidade será:

Entity. Fonte: [1].


Declarar os módulos de mais baixo nível

A declaração das portas desenvolvidas (XNOR e AND3) no código principal são feitas usando as COMPONENTs. Para isto, basta copiar as ENTITYs criadas nos outros arquivos para a parte declarativa da ARCHITECTURE, alterando a palavra-chave ENTITY para COMPONENT.

Declaração dos módulos com as COMPONENTs. Fonte: [1].


Declarar os sinais internos usados para conectar os módulos

Os sinais internos presentes no diagrama são declarados na arquitetura. Eles são utilizados para a interligação dos módulos criados.

Instanciar as unidades

O último passo é criar as instâncias dos módulos. Isto é feito mapeando os sinais de entrada e saída das componentes no corpo da arquitetura. É usada a palavra-chave PORT MAP.

Instanciação dos módulos. Fonte: [1].


No caso acima, é usado o chamado mapeamento direto. Nele, a associação dos sinais da entidade de nível mais alto com os sinais internos das componentes é feito usando o operador "=>". Uma alternativa é usar o mapeamento implícito, onde os sinais da entidade de nível mais alto são associados pela ordem da declaração:

Mapeamento implícito. Fonte: [1].


Sistema finalizado

O código completo pode ser visto na figura abaixo:

Comparador finalizado. Fonte: [1].


Mapeamento de constantes

O mapeamento pode ser realizado para, além das portas, as GENERICs. Com isto, sistemas genéricos podem ser criados, facilitando futuras implementações.

A entidade abaixo realiza a checagem de paridade de um número genérico de bits. Repare na declaração de n como um GENERIC.

Checagem de paridade. Fonte: [1].


Essa entidade é utilizada numa entidade de nível maior, como pode ser visto abaixo. Repare na instrução GENERIC MAP, que assim como o PORT MAP, faz o mapeamento do número de sinais de entrada a serem utilizados.

Checagem de paridade. Fonte: [1].


Tarefas

Resolver exercícios do capítulo 8, pg 129, do livro [1].

Referências

[1] Mealy, B. Tappero, F. Free Range VHDL. Free Range factory. Disponível em Link. Acesso em 27/02/2015.

Avaliação 1 - Sistemas combinacionais

Desenvolver os sistemas abaixo em VHDL, em dois grupos de 3 pessoas. O arquivo do QSIM deve ser gerado para realização dos testes. Escrever um relatório explicando a solução adotada, tanto para o desenvolvimento do código quanto para o arquivo de testes do QSIM.

Os relatórios dois dois grupos formados estar disponíveis nas páginas:


1 - Cruzamento de duas ruas

Desenvolver um sistema automático para os semáforos em um cruzamento de duas ruas, com as seguintes características:

  1. Quando houver carros somente na rua B, o semáforo 2 deverá permanecer verde
  2. Quando houver carros somente na rua A, o semáforo 1 deverá permanecer verde
  3. Quando houver carros nas duas ruas, o semáforo 1 deverá permanecer verde
Cruzamento de duas ruas.


2 - Um amplificador e três aparelhos

Desenvolver um sistema que comuta a utilização de um amplificador para três aparelhos, obedecendo as seguintes prioridades:

  1. Toca-discos
  2. Toca-fitas
  3. Rádio FM
3 - Intercomunicadores

Desenvolver um sistema que comuta intercomunicadores em uma empresa, obedecendo as seguintes prioridades:

  1. Presidente
  2. Vice-presidente
  3. Engenharia
  4. Chefe de seção
4 - Display de 7 segmentos

Desenvolver um sistema que mostra um número hexadecimal num display de 7 segmentos

5 - Tanque com fluido

Desenvolver um sistema para controlar o nível de fluido em um tanque por meio de uma válvula de entrada e uma válvula de saída, de igual vazão. O nível de fluído deve ser mantido entre dois níveis, medidos com dois sensores, um de mínimo e outro de máximo. Um botão para total esvaziamento do tanque (equivalente à um botão de liga/desliga do tanque) deve ser previsto.

6 - Cruzamento de três ruas

Desenvolver um sistema para controlar semáforos em um cruzamento de 3 ruas, com as seguintes características:

  1. Fechamento dos semáforos:
  1. Quando o semáforo 1 abrir para a rua A, automaticamente os semáforos 2 e 3 devem fechar
  2. Quando o semáforo 2 abrir para a rua B, automaticamente os semáforos 1 e 3 devem fechar
  3. Quando o semáforo 3 abrir para a rua C, automaticamente os semáforos 1 e 2 devem fechar
  1. Prioridades:
  1. O motorista que está na rua A tem prioridade sobre o que está na rua B
  2. O motorista que está na rua B tem prioridade sobre o que está na rua C
  3. O motorista que está na rua C tem prioridade sobre o que está na rua A
  4. Quando houver carros nas três ruas, a rua A é preferencial
  5. Quando não houver nenhum carro na rua, o sinal para a rua A deverá ser aberto
7 - Tanque de dois níveis, com sensor de temperatura

Desenvolver um sistema para controlar o nível de água em dois tanques por meio de duas válvulas, com as seguintes características:

  1. O tanque 2:
  1. Possui saída para a distribuição, por isso seu nível está sempre em redução
  2. Possui dois sensores, que indicam o nível mínimo (válvula 2 deve ser acionada) e o máximo (válvula 2 deve ser desligada)
  1. O tanque 1:
  1. É alimentado pela rede pública de abastecimento
  2. Possui os mesmos sensores do tanque 2
  3. Além desses dois, tendo em vista as oscilações presentes na rede de abastecimento, um sensor de segurança está disponível, indicando um nível intermediário (válvula 1 deve ser acionada se a válvula 2 estiver acionada)
  1. Sempre que chegar no nível mínimo, os tanques devem ser enchidos até o nível máximo

O sensor de temperatura é composto por dois sensores, um que indica se a água está muito fria e outro que indica se a água está muito quente.

Para todos os sensores do sistema, casos de falhas devem acionar um alarme.

Tanque de dois níveis, com sensor de temperatura.


8 - Circuito aritmético

Desenvolver um circuito somador completo de 8 bits


Adendo - Uso do FPGA

Das questões anteriores, implementar as discriminadas abaixo no Kit DE2-115. Em todas as questões, defina como as entradas e saídas serão simuladas no Kit (um botão, uma chave, um display, um led, etc).

1 - Cruzamento de duas ruas
3 - Intercomunicadores
4 - Display de 7 segmentos
5 - Tanque com fluido
7 - Tanque de dois níveis, com sensor de temperatura

Circuitos sequenciais em VHDL

Muitos sistemas precisam armazenar valores por períodos de tempo determinados. Nesta aula, vamos estudar como desenvolver esse tipo de sistema em VHDL. Baseados no capítulo 6 do livro [1], vamos desenvolver um Flip-Flop do tipo D, elemento de armazenamento de 1 bit.

Flip Flop tipo D

A figura abaixo apresenta o diagrama de um flip flop tipo D;

Flip Flop tipo D


Abaixo, os estados possíveis do Flip Flop.

Estados possíveis - Clicar no "+" para expandir
SST FlipFlop D2.png

Flip Flop tipo D em VHDL

  • Exercício: Desenvolva um modelo VHDL para um Flip Flop tipo D como mostrado na seção anterior. Visando já sua aplicação como memória em um sistema maior, fazer com que a entrada D seja síncrona, ou seja, só tenha influência na saída durante a borda de subida do sinal de clock.

Abaixo, a solução do problema.


Flip Flop tipo D em VHDL


Comentários:

  • O armazenamento de informação no Flip Flop é feito através das seguintes características no código:
  • Sendo o processo sensível apenas à CLK, a informação de entrada será avaliada apenas em casos de alteração nesse sinal
  • A função rising_edge() certifica que o corpo da instrução IF será executado apenas na borda de subida do clock
  • A ausência de uma instrução ELSE evita que outras operações sejam executadas dentro do bloco
  • Foi usada a abordagem behavioral ao invés da data-flow.
  • A função rising_edge() poderia ser substituída pelo teste abaixo:
if CLK = '1' then

Entrada set síncrona e ativo-baixo

Flip Flop tipo D com entrada set

Neste caso, o Flip Flop tem as seguintes características:

  • A entrada set (S) fará com que a saída do Flip Flop seja "1", independente da sua entrada D.
  • Por ser síncrona, essa alteração será realizada apenas na borda de subida do clock.
  • Por ser ativo-baixo, essa alteração será realizada apenas quando S for igual à "0".

A solução para o problema pode ser vista abaixo:

Flip Flop tipo D com entrada set em VHDL


Comentários:

  • A porta S foi incluída através de um novo teste dentro do processo
  • A prioridade da porta S sobre a porta D é implementada pela ordem dos IFs utilizada.

Entrada reset assíncrona e clock na borda de descida

Flip Flop tipo D com entrada reset

Neste caso, o Flip Flop tem as seguintes características:

  • A entrada reset (R) fará com que a saída do Flip Flop seja "0", independente da sua entrada D.
  • Por ser assíncrona, essa alteração será realizada sempre que R for alterado.

A solução para o problema pode ser vista abaixo:

Flip Flop tipo D com entrada reset em VHDL


Comentários:

  • Como a entrada R é assíncrona, ela não depende do clock. Por isso, R foi incluída na lista de sensitividade do processo.
  • A prioridade da porta R sobre a porta D é implementada pela ordem dos IFs utilizada.

Flip Flop tipo T

A figura abaixo apresenta o diagrama de um flip flop tipo T;

Flip Flop tipo T


Abaixo, os estados possíveis do Flip Flop.

Estados possíveis - Clicar no "+" para expandir
SST FlipFlop T2.png

Flip Flop tipo T em VHDL

  • Exercício: Desenvolva um modelo VHDL para um Flip Flop tipo T como mostrado na seção anterior. Visando já sua aplicação como memória em um sistema maior, fazer com que a entrada D seja síncrona, ou seja, só tenha influência na saída durante a borda de subida do sinal de clock.

Abaixo, a solução do problema.


Flip Flop tipo T em VHDL


Comentários:

  • Enquanto a saída do Flip Flop D depende apenas de sua entrada, no caso do Flip FLop T ela depende também da saída anterior.

Tarefas

Fazer exercícios 1 a 6 do capítulo 6 (pg 86) do livro [1].

Referências

[1] Mealy, B. Tappero, F. Free Range VHDL. Free Range factory. Disponível em Link. Acesso em 27/02/2015.

Avaliação 2 - Sistemas sequenciais

Em duas equipes de 3 pessoas, estudar as seções abaixo do livro [1] e fazer uma apresentação da solução adotada.

Equipe A (Kamila, Leonardo O., Rogério)
  • 22.2 - Debouncer para chave
  • 22.1 - Registrador de deslocamento com data-load
Equipe B (Nicole, Renan, Leonardo)
  • 22.3 - Temporizador
  • 22.5 - Medidor de frequência

Referências

[1] Pedroni, Volnei A. Eletrônica Digital Moderna e VHDL. Rio de Janeiro: Elsevier, 2010.

Pacotes

Os pacotes são utilizados para realizar operações comuns. Podem ser utilizados para fazer declarações gerais ou descrever subprogramas. Segue a forma:

PACKAGE <nome> IS
   <declarações>
END PACKAGE <nome>;
 
PACKAGE BODY <nome> IS
   <corpo do subprograma>
   <especificação de constantes>
END PACKAGE BODY <nome>;

A seguir, algumas das estruturas que podem ser descritas nos pacotes.

Macetário

Abaixo, as estruturas da linguagem VHDL:

LIBRARY nome1, nome2;
USE nome1.pack_name1.object;
USE nome2.pack_name2.ALL;
ENTITY <entity_name> IS
   PORT (
      nome1, nome2 : <mode> <type>;
      nome3, nome4 : <mode> <type>
   );
   GENERIC (
      nome1, nome2 : <type> (:= <initial value>);
      nome2, nome4 : <type> (:= <initial value>)
   );
END ENTITY <entity_name>
ARCHITECTURE <identifier> OF <entity_identifier> IS
   <declaration>
BEGIN
   <body>
END ARCHITECTURE <identifier>
CONSTANT <nome> : <tipo> := <valor>;
SIGNAL <nome> : <tipo> := <valor_inicial>;
VARIABLE <nome> : <tipo> := <valor_inicial>;
SHARED VARIABLE <nome> : <tipo> := <valor_inicial>;
-- Simples
<nome> <= <expressão>;

-- Condicional
<nome> <= <valor> WHEN <condição_1> ELSE
          <valor> WHEN <condição_2> ELSE
                     .
                     .
                     .
          <valor> WHEN <condição_3> ELSE
          <valor>;

-- De seleção
WITH <expressão> SELECT
    <nome> <= <valor> WHEN <condição_1>,
              <valor> WHEN <condição_2>,
                         .
                         .
                         .
              <valor> WHEN OTHERS;
<label>: process (<sinal1>,<sinal2>) is
   <declaração>
begin
   <instruções sequenciais>
end process <label>
-- Teste
if (<condição>) then
   <instruções>;
elsif (<condição>) then
   <instruções>;
else
   <instruções>;
end if;

-- Seleção
case (<expressão>) is
   when <resultado> =>
      <instruções>;
   when <resultado> =>
      <instruções>;
   when others =>
      <instruções>;
end case
-- Baseados em inteiros
TYPE <nome do tipo> IS RANGE <faixa de valores>;

type scores is range 0 to 100;
type years is range -3000 to 3000;
type apples is range 0 to 15;
type oranges is range 0 to 15;

-- Tipos enumerados
TYPE <nome do tipo> IS (<lista de nomes ou números>);

type machine_state is (idle, forward, backward);
type counter is (zero, one, two, three);

-- Tipos baseados em arranjos
TYPE <nome do tipo> IS ARRAY (<faixa de valores>) OF <tipo do dado>;

type vector is array (7 downto 0) of std_logic;
type array1D1D is array (1 to 4) of bit_vector (7 downto 0);
type vector_array is array (1 to 4) of vector;
type array2D is array (1 to 8, 1 to 16) of std_logic;
-- For
<rotulo>: FOR <indice> IN <faixa de valores> LOOP
   <instruções sequenciais>;
END LOOP <rotulo>;

-- While
<rotulo>: WHILE (<condição>) LOOP
   <instruções sequenciais>;
END LOOP <rotulo>;
-- NEXT
variable my_sum : integer := 0;

for cnt_val in 0 to 50 loop
    if (my_sum = 20) then
        next;
    end if;
    my_sum := my_sum + 1;
end loop;

variable my_sum : integer := 0;

while (my_sum < 300) loop
    next when (my_sum = 20);
    my_sum := my_sum + 1;
end loop;

-- EXIT
variable my_sum : integer := 0;

for cnt_val in 0 to 50 loop
    if (my_sum = 20) then
        exit;
    end if;
    my_sum := my_sum + 1;
end loop;

variable my_sum : integer := 0;

while (my_sum < 300) loop
    exit when (my_sum = 20);
    my_sum := my_sum + 1;
end loop;
FUNCTION <nome> (<argumentos de entrada>)
RETURN <tipo do dado de retorno> IS
   <declarações>
BEGIN
   <instruções sequenciais>
   <rotulo>: RETURN <expressao>;
END FUNCTION <nome>
PROCEDURE <nome> (<argumentos>) IS
   <declarações>
BEGIN
   <instruções sequenciais>
END PROCEDURE <nome>
<rótulo>: <nome_da_componente>
   GENERIC MAP (
      <gen1> => <genA>,
      <gen2> => <genB>)
   PORT MAP (
      <por1> => <porA>,
      <por2> => <parB>);

Referências

Sites

Livros, artigos, apostilas