i
CARLOS CAETANO DE ALMEIDA
61/2015
CAMPINAS
2015
ARQUITETURA DO MÓDULO DE CONVOLUÇÃO PARA
VISÃO COMPUTACIONAL BASEADA EM FPGA
ii
iii
UNIVERSIDADE ESTADUAL DE CAMPINAS
FACULDADE DE ENGENHARIA MECÂNICA
CARLOS CAETANO DE ALMEIDA
Orientador: Prof. Dr. Eurípedes Guilherme de Oliveira Nóbrega
Assinatura do Orientador
CAMPINAS 2015
Dissertação apresentada à Faculdade de
Engenharia Mecânica da Universidade
Estadual de Campinas como parte dos
requisitos exigidos para a obtenção do
título de Mestre em Engenharia
Mecânica, na Área de Mecânica dos
Sólidos e Projeto Mecânico.
ESTE EXEMPLAR CORRESPONDE À VERSÃO FINAL DA
DISSERTAÇÃO DEFENDIDA PELO ALUNO CARLOS CAETANO
DE ALMEIDA E ORIENTADO PELO PROF. DR. EURÍPEDES
GUILHERME DE OLIVEIRA NÓBREGA.
ARQUITETURA DO MÓDULO DE CONVOLUÇÃO PARA VISÃO
COMPUTACIONAL BASEADA EM FPGA
iv
v
vi
vii
Resumo
Esta dissertação apresenta o estudo de uma arquitetura para o processamento digital de
imagens, desenvolvido através de dispositivos de hardware programável, no caso FPGA, para a
implementação eficiente no domínio do tempo do algoritmo da convolução discreta, que permita
sua integração em redes neurais de convolução com múltiplas camadas, conhecidas como
ConvNets, visando sua aplicação na área de visão computacional.
A implementação em software pode acarretar elevado custo computacional de muitos
algoritmos, o que pode não atender às restrições de aplicações em tempo real, logo o uso de
implementações em FPGA torna-se uma ferramenta atraente. A convolução 2D na área de visão
computacional é um desses algoritmos. O uso de FPGA permite a adoção de execução
concorrente para os algoritmos, por ser em hardware, possibilitando que as redes de convolução
possam vir a ser adotadas em sistemas embarcados de visão computacional.
Neste trabalho de pesquisa foram estudadas duas soluções. Na primeira foi implementado
no FPGA o processador soft core NIOS II®
, e programado o algoritmo. Na segunda solução, foi
desenvolvida uma configuração em que o algoritmo foi implementado diretamente em hardware,
sem a necessidade de um microprocessador tradicional. Os resultados mostram que uma redução
expressiva do tempo de processamento pode ser esperada em aplicações reais. Na continuidade
do trabalho, deverá ser implementado e testado o algoritmo completo como parte de uma
aplicação de redes ConvNets.
Palavras-Chave: Convolução Discreta, Processamento de Imagens, Visão Computacional,
FPGA.
viii
Abstract
This research work presents a study of the architecture applied to image processing, using
programmable hardware devices, in this case FPGA, to an efficient implementation of the time
domain discrete convolution algorithm, which enables its integration into multiple layers
networks, known as ConvNets, aiming applications of computational vision.
For some algorithms, the software implementation can imply high computational costs,
which may not satisfy specific real time restrictions, which turns FPGA adoption an attractive
solution. Image processing application of 2D convolution is one of these algorithms. Hardware
implementation using FPGA can adopt algorithm concurrency, habilitating convolution nets to be
adopted in embedded systems for computer vision applications.
In this research work, two different solutions were studied. In the first solution, a soft core
NIOS II®
processor was implemented in a FPGA, and the convolution algorithm programmed. In
the second solution, a complete hardware implemented algorithm was developed, exempting the
need for a regular processor. Results show that an expressive processing time reduction may be
expected in real applications. In the continuity of the research work, a complete ConvNet will be
implemented and the convolution algorithm application tested in a more realistic condition.
Keywords: Discrete Convolution, Image Processing, Computer Vision, FPGA.
ix
SUMÁRIO
Resumo ......................................................................................................................................................... vii
Abstract ....................................................................................................................................................... viii
Agradecimentos .......................................................................................................................................... xiii
Lista de Ilustrações ....................................................................................................................................... xv
Lista de Tabelas .......................................................................................................................................... xvii
Lista de Abreviaturas, Siglas e Termos em Inglês ....................................................................................... xix
Lista de Símbolos ......................................................................................................................................... xxi
1. INTRODUÇÃO E JUSTIFICATIVA .......................................................................................................... 1
1.1 OBJETIVOS .................................................................................................................................. 3
1.1.1 Objetivo Geral .................................................................................................................... 3
1.1.2 Objetivos Específicos .......................................................................................................... 3
1.2 ESTRUTURA DA DISSERTAÇÃO ................................................................................................... 4
2. REVISÃO BIBLIOGRÁFICA .................................................................................................................... 5
2.1 Introdução .................................................................................................................................. 5
2.2 FPGA (Field Programmable Gate Array) ..................................................................................... 5
2.2.1 Ferramentas de Desenvolvimento ..................................................................................... 7
2.3 Linguagens de Descrição de Hardware e VHDL ......................................................................... 7
2.4 Amostragem e Quantização ....................................................................................................... 9
2.5 Arquitetura do Hardware .........................................................................................................10
2.6 Processador (RNC) ....................................................................................................................11
2.7 Análise dos Tempos da Solução em Software ..........................................................................14
2.8 Implementação em Hardware do Algoritmo para Aceleração do Tempo de Resposta ..........15
2.9 Resultado do Algoritmo em Software e em Hardware ............................................................17
3. MATERIAIS E MÉTODOS ...................................................................................................................22
3.1 Aplicação do ACD .....................................................................................................................23
3.1.1 Formulação Matemática ..................................................................................................24
3.1.2 O Fluxo de Dados ..............................................................................................................25
3.1.2.1 Processamentos Realizados usando o MATLAB®: ............................................................26
3.1.2.2 Processamento no FPGA usando o NIOS II®: ....................................................................27
3.1.2.3 Processamento no FPGA usando VHDL:...........................................................................27
x
3.2 Implementação no MATLAB® ...................................................................................................28
3.3 Implementação do NIOS II® ......................................................................................................30
3.3.1 Análise das Conexões .......................................................................................................32
3.3.2 Diagrama Esquemático do Microcontrolador ..................................................................35
3.3.3 O Fluxo de Dados e Módulo de Convolução ....................................................................36
3.4 Implementação em VHDL .........................................................................................................39
3.4.1 Hardware ACD e Periféricos .............................................................................................39
3.4.2 Módulo de Processamento de Imagens ...........................................................................40
4. RESULTADOS E DISCUSSÕES .............................................................................................................46
4.1 Implementação no MATLAB® ...................................................................................................46
4.2 Implementação do NIOS II® ......................................................................................................50
4.3 Implementação do VHDL..........................................................................................................50
4.4 Análise de Recursos usando o FPGA ........................................................................................51
4.5 Justificativa da Solução Proposta para Acelerar os Tempos de Resposta ...............................52
4.6 Análise de Desempenho Usando a Implementação em Software e em Hardware .................52
4.7 Comparação das Imagens de Saída Lena no MATLAB®, NIOS II® e VHDL ................................53
5. CONCLUSÕES E SUGESTÕES PARA TRABALHOS FUTUROS ..............................................................55
REFERÊNCIAS ............................................................................................................................................57
APÊNDICE A - QUARTUS E HARDWARE ACD ............................................................................................65
APÊNDICE B - CÓDIGOS EM VHDL ............................................................................................................72
APÊNDICE C - CÓDIGOS EM C/C++ .........................................................................................................102
APÊNDICE D - CÓDIGOS EM MATLAB® ...................................................................................................111
xi
A Deus
Aos meus pais Clotilde Caetano e José Carlos de Almeida (in memoriam)
Aos amigos e companheiros que confiaram em meu trabalho
Dedico
xii
xiii
Agradecimentos
A Deus que esteve presente em minha vida me orientando e guiando com sua sabedoria.
Ao meu orientador, Prof. Dr. Eurípedes Guilherme de Oliveira Nóbrega, por seus conselhos, apoio e
orientação durante minha formação acadêmica. Sua confiança e dedicação permitiram transpor os desafios
deste trabalho de pesquisa e promover meu crescimento pessoal, acadêmico e profissional.
À minha mãe Clotilde Caetano de Almeida pelo apoio e carinho, fundamentais para facilitar os desafios
que a vida me impôs.
À Coordenação de Pós-Graduação, professores e funcionários da Faculdade de Engenharia Mecânica da
Universidade Estadual de Campinas.
Aos amigos que me acompanharam, entre eles, Adriano Gonçalves, Alexander Denarelli, Almiro Franco,
Ana Paula Caetano, Angela Elias, Antônio Cunha, Caio Elias, Cristian Pimenta, Cristiano Emidio, Dalia
Gallardo, Daniela Gabeloni, Diogo Pereira Costa, Edson Espósito, Guilherme Saldanha, Ivone Setti, Joel
Oliveira, Jonatas Miranda, Jonathan Gazzola, José Francisco Lopes da Silva, Lucineia Ribeiro, Luiz Paulo
Oliveira, Maira Costa, Marcelo Nery, Maricélia Roberta Jimenez, Mayra Cristina Monteiro (in
memoriam), Michael dos Santos, Misael Victor, Paulo Roberto Delfino, Pedro Henrique Oliveira, Rafael
Baccaglini, Renato Kuteken, Rita de Cássia Silva, Rose Burgon, Sílvia Helena Allane Franchetti, Sônia
Lima, Sueli Santos, Tânia Margareth Silva e Wellington Gomes.
Em especial, gostaria de agradecer aos amigos de grupo de pesquisa Alexandre Tomazati, Danilo Morais
Pagano, Fernando Ortolano, Frank Alexis Canahuire Cabello, Helói Genari, Klaus Raizer, Nilson
Inocente, Vornei Augusto Grella, Wendell Diniz e Wilson Prates.
Por fim gostaria de agradecer à CAPES pela concessão da bolsa de estudos, o que permitiu que eu me
dedicasse ao mestrado e contribuísse, mesmo que um pouco, com o processo de desenvolvimento
científico do Brasil.
xiv
xv
Lista de Ilustrações
Figura 1. Estrutura de um FPGA (BROWN; VRANESIC, 2000) Adaptado .................................. 6
Figura 2. Imagem com Diferentes Níveis de Cinza. Da Esquerda para Direita, de Cima para
Baixo: 16, 8, 4 e 2 Níveis de Cinza. Fonte: (GONZALEZ e WOODS, 2001).............................. 10
Figura 3. Convolução 2D para K=3, onde K é a Largura do Kernel e W é a Largura da Imagem.
Diagrama adaptado de (FARABET; POULET; LECUN, 2011) .................................................. 11
Figura 4. Arquitetura de um RNC adaptada de (FAREBET ET AL, 2011).................................. 12
Figura 5. Exemplo de ConvNet ..................................................................................................... 13
Figura 6. Instrução Lógica Customizada no NIOS II®
adaptado de (LIAO; ZHOU; FAN, 2010) 15
Figura 7. Exemplo do Processador de Stream (Farabet et al. 2009). ............................................ 16
Figura 8. Tempo de Processamento (ms) por Número de Conexões no ConvNet (em milhões)
para RNC e Computadores Normais (Farabet et al. 2009). ........................................................... 18
Figura 9. Tempo de Processamento (ms) pelo Tamanho do Kernel Utilizado para RNC e
Computadores Normais (Farabet et al. 2009). ............................................................................... 19
Figura 10. Frames por Segundo em Função do Tamanho da Imagem Quadrada para Programas
em CPU, FPGA e ASIC (Farabet et al. 2009). .............................................................................. 20
Figura 11. Frames por Segundo em Função do Tamanho do Kernel para Programas em CPU,
FPGA e ASIC (Farabet et al. 2009). .............................................................................................. 20
Figura 12. Vista Superior FPGA Terasic Cyclone IV De2i-150 (Altera® co.) ............................. 22
Figura 13. Vista Inferior FPGA Terasic Cyclone IV De2i-150 (Altera® co.) ............................... 23
Figura 14. Convolução 2D............................................................................................................. 24
Figura 15. Funcionamento do Sistema: Fluxo de Dados da Aquisição à Visualização. ............... 25
Figura 16. Procedimento para o Desenvolvimento das Implementações ...................................... 26
Figura 17. Matriz da Imagem Gray ............................................................................................... 29
Figura 18. Matriz de Convolução Gerada a partir da Convolução da Imagem Gray com o Kernel
....................................................................................................................................................... 30
Figura 19. Kernels: K1 para Detecção de Bordas e K2 para Destacar Relevo .............................. 30
Figura 20. Diagrama em Blocos com Todos os Módulos do Microcontrolador, Módulo ACD
implementado em Linguagem C/C++ e MATLAB® e Barramento Avalon ................................. 31
Figura 21. Desenvolvimento do Microcontrolador no QSYS. ...................................................... 32
xvi
Figura 22. Implementação do Microcontrolador no QSYS. .......................................................... 34
Figura 23. Microcontrolador Desenvolvido no QSYS .................................................................. 35
Figura 24. Microcontrolador Desenvolvido no QSYS e Conexões com NIOS II ®
...................... 36
Figura 25. Diagrama de Blocos com Processador, Módulo ACD Implementado em NIOS II® e o
Barramento Avalon........................................................................................................................ 37
Figura 26. Diagrama em Blocos do Hardware ACD e Periféricos ............................................... 39
Figura 27. Dados da Imagem na Memória MIF ............................................................................ 41
Figura 28. Módulo de Memória MIF do Hardware ACD ............................................................. 42
Figura 29. Modelsim: Waveform da Aquisição de Dados da Imagem .......................................... 42
Figura 30. Imagem Processada pelo Hardware de Aquisição de Dados ....................................... 43
Figura 31. Módulo de Processamento de Imagens em Hardware ................................................. 43
Figura 32. Processamento Hardware ACD no FPGA ................................................................... 44
Figura 33. Módulo de Filtragem e UART do Hardware ACD ..................................................... 45
Figura 34. Imagem de Entrada Colorida RGB .............................................................................. 46
Figura 35. Obtenção da Imagem Gray a partir da Imagem RGB de Entrada no MATLAB®
....... 47
Figura 36. Imagem Convertida para Gray ..................................................................................... 47
Figura 37. Transformação da Imagem de Entrada RGB para Gray e Posterior Tratamento com os
Kernels K1 e K2 ............................................................................................................................ 48
Figura 38. Imagem Filtrada com o Kernel para Detecção de Bordas K1 ...................................... 49
Figura 39. Imagem Filtrada com o Kernel para Destacar Relevo K2 ........................................... 49
Figura 40. Recursos Utilizados com o NIOS II®
no FPGA .......................................................... 50
Figura 41. Recursos Utilizados com o VHDL no FPGA .............................................................. 51
Figura 42. Tempo de Processamento de Imagens em Software X Hardware ............................... 53
Figura 43. Imagens de Saída no MATLAB®, NIOS II
® e VHDL ................................................. 54
xvii
Lista de Tabelas
Tabela 1. Comparação entre a implementação por Software e por Instrução Customizada ......... 17
Tabela 2. Performance e Recursos Utilizados ............................................................................... 52
xviii
xix
Lista de Abreviaturas, Siglas e Termos em Inglês
ACD Algoritmo de Convolução Discreta
ASIC Circuito Integrado de Aplicação Específica (Application Specific Integrated Circuit)
CHIP Circuito Integrado (Circuit High Integrating Process)
CNC Controle Numérico Computadorizado
CNN Rede Neural Convolucional (Convolutional Neural Network)
CONVNETS Redes Neurais de Convolução (Convolutional Neural Networks)
CPU Unidade Central de Processamento (Central Processing Unit)
DMC Departamento de Mecânica Computacional
DSP Processamento de Sinal Digital (Digital Signal Processing)
FEM Faculdade de Engenharia Mecânica
FPGA Arranjo de Porta Programável em Campo (Field Programmable Gate Array)
GPU Unidade de Processamento Gráfico (Graphics Processing Unit)
MIF Arquivo de Inicialização de Memória (Memory Initialization File)
PIPELINE Busca de uma ou mais instruções além da próxima a ser executada
QSYS Ferramenta de Integração de Sistemas da Altera® (Altera
®’s System Integration Tool)
RAM Memória de Acesso Aleatório (Random Access Memory)
RCP Processador de Rede de Convolução Programável
RNAs Redes Neurais Artificiais
RNC Rede Neural de Convolução
SDRAM Memória Síncrona de Acesso Dinâmico Randômico (Synchronous Dynamic Random
Access Memory)
SIMD Múltiplos Dados com Instrução Única (Single Instruction, Multiple Data)
UART Receptor Transmissor Assíncrono Universal (Universal Asynchronous Receiver-
Transmitter)
ULA Unidade Lógica e Aritmética
VALU Vetor de Unidade Lógica e Aritmética (Vector Arithmetic and Logic Unit)
VHDL Linguagem de Descrição de Hardware VHSIC
(VHSIC Hardware Description Language)
VHSIC Circuito Integrado de Velocidde Muito Alta (Very High Speed Integrated Circuits)
xx
xxi
Lista de Símbolos
Kernel do filtro utilizado
Valor da posição (m,n) da matriz W referente ao filtro de Kernel K x K
Valor da posição ij da matriz referente à imagem de entrada
Valor da posição ij da matriz referente à imagem de saída
Posição da matriz Z referente ao plano de saída
Função não-linear
xxii
1
1. INTRODUÇÃO E JUSTIFICATIVA
A partir do século XVIII, pode-se observar que a ciência ingressou em um processo de
evolução constante, culminando no desenvolvimento de novas tecnologias que transformaram
a vida da humanidade e a forma de produção de mercadorias. Durante a 1ª revolução
industrial, o carvão utilizado como fonte de energia permitiu o desenvolvimento da máquina a
vapor e da locomotiva, sendo determinantes no transporte de insumos, pessoas e produtos
acabados. Na 2ª revolução industrial houve o desenvolvimento técnico, científico e de trabalho
que ocorreu principalmente na Segunda Guerra Mundial, tendo como base para o
desenvolvimento tecnológico desse período o aço, a eletricidade, o petróleo, a metalurgia, a
eletromecânica, o motor a explosão e a petroquímica, possibilitando grande expansão da
indústria, principalmente a automobilística. Durante a 3ª revolução industrial, a partir da
década de 1970, tem-se como base a alta tecnologia através da informática, microeletrônica,
telecomunicações, robótica, da máquina CNC (Controle Numérico Computadorizado) e da
biotecnologia (RIFKIN, 2012; MELLO, COSTA, 1993).
Recentes passos na evolução dos dispositivos eletrônicos têm trazido grande avanço na
fabricação de chips, possibilitando o surgimento do DSP (Digital Signal Processing) em
sistemas sofisticados de comunicação, aplicados na detecção de sinais sísmicos e
processamento de imagens (ANTONIOU, 2006) e também na implementação de circuitos
integrados reconfiguráveis ou programáveis, entre os quais os FPGA's (Field-Programmable
Gate Arrays), que são compostos de uma grande quantidade de módulos programáveis, que
podem ser configurados no campo, emulando o comportamento de qualquer circuito digital,
permitindo o desenvolvimento de sistemas extremamente complexos (BAILEY, 2011). Por
serem circuitos eletrônicos, permitem assim que algoritmos sejam embarcados e prototipados
de maneira concorrente, incrementando o desempenho em oposição à regra de uma instrução
de cada vez por processador, conhecida como "gargalo" de Von Neumann (SEBESTA, 2012).
A literatura referente ao processamento de imagem utilizando-se FPGA's está bastante
difundida atualmente, devido à importância deste tipo de tecnologia em sistemas
embarcados.O uso de FPGA’s em sistemas embarcados permite combinar a flexibilidade do
software com a velocidade do hardware, no que se chama de computação reconfigurável,
podendo implementar desde processamentos simples, até circuitos como controlador de vídeo,
2
incluindo memória RAM e elementos de apoio, ou ainda incorporar processamentos
complexos e exigentes computacionalmente (RUSSO ET AL. 2012).
Através do FPGA é possível desenvolver algoritmos de processamento de imagem de
alto desempenho (CROOKES ET AL, 2002), podendo unir o processamento paralelo no
desenvolvimento de circuitos dedicados como decodificadores de áudio e vídeo (ZONGQING,
2008).
O processamento de imagem refere-se a qualquer processo pelo qual as entradas e as
saídas são imagens (GONZALEZ e WOODS, 2001), visando a sua melhoria e a extração de
determinadas características (ACHARYA e RAY, 2005). O processamento de imagens e a
visão computacional evoluiram muito nas últimas décadas e as aplicações comerciais dessas
tecnologias estão se tornando economicamente atraentes, mas a complexidade de aplicações,
como a análise de cena por exemplo, dirigiu a pesquisa para implementação de um algoritmo
eficiente, com a adoção de FPGA's no uso do processamento concorrente, ou de GPU
(Unidade de Processamento Gráfico), buscando o paralelismo do processamento em software
(CROOKES ET AL, 2002; RAIZER ET AL, 2009).
Uma metodologia que tem se revelado eficiente para diversas aplicações de
processamento digital de sinais são as redes neurais de convolução (RNC), conhecidas como
ConvNets (KIM e CASPER, 2013). São redes com múltiplas camadas, que implementam
filtros baseados na convolução discreta, adicionados de funções sigmodais, permitindo o
processamento não linear de sinais (HAYES, 1999).
As redes neurais de convolução são similares às redes neurais artificiais (RNA), que
utilizam técnicas computacionais apresentando um modelo matemático baseado na estrutura
neural de organismos inteligentes, adquirindo conhecimento através da experiência. No
entanto uma RNC apresenta algoritmos com algumas diferenças fundamentais se comparada
com uma RNA (LECUN; KAVUKCUOGLU; FARABET, 2011). Suas funções podem
abranger uma ampla gama de aplicações, como análise de alteração genética (NING ET AL,
2005), detecção e reconhecimento de faces (SOCHER ET AL 2011; GARCIA e DELAKIS
2004, LAWRENCE ET AL, 1997), conversão de texto manuscrito (LECUN; BOTTOU;
BENGIO, 1998), a análise de cena (FARABET ET AL, 2012), geoprocessamento, controle de
qualidade em processos industriais, meteorologia e pesquisas em astronomia (AIZAWA;
SAKAUE; SUENAGA, 2004). Na área da Medicina, o uso de imagens tornou-se de grande
3
importância no diagnóstico médico, através de técnicas avançadas como a tomografia
computadorizada, ressonância magnética (ASSUMPÇÃO, 2013) e outros.
No processamento de imagens, os algoritmos são em geral implementados em software
e assim o desempenho computacional pode não ser adequado ou não atender requisitos de
aplicações em tempo real. Neste caso, a convolução 2D pode ser aplicada de forma
concorrente e/ou paralela, o que pode ser conseguido explorando-se o potencial dos FPGA’s,
obtendo-se assim desempenho potencialmente muito superior. Métodos implementados em
FPGA com aplicações de visão computacional para as RNC's têm sido publicados nos últimos
anos, desde o trabalho de FARABET ET AL. (2009).
Em diversas aplicações nas áreas de processamento digital de imagens e visão
computacional, a etapa de filtragem é um componente essencial, sendo uma das primeiras
etapas de processamento (ROSTEN e DRUMMOND, 2006).
Esta dissertação tem como objetivo apresentar um estudo da arquitetura para uma
implementação digital eficiente da parte central das RNC's, que é o algoritmo de convolução
discreta (ACD).
1.1 OBJETIVOS
1.1.1 Objetivo Geral
O presente trabalho de pesquisa tem como objetivo o estudo de uma arquitetura de
hardware, através de FPGA, que implemente o algoritmo discreto de convolução visando
futuras aplicações em tempo real da visão computacional.
1.1.2 Objetivos Específicos
Para atingir o objetivo geral, foi necessário:
Levantar o referencial teórico aplicado processamento de imagens em FPGA.
Propor uma solução paralela baseada em hardware para um Algoritmo de Convolução
Discreta.
Desenvolver a programação em MATLAB®, NIOS II
® e VHDL.
4
Implementar o projeto em FPGA.
Validar o design através de simulação.
Comparar os resultados obtidos pelo FPGA com os resultados obtidos pelo
MATLAB® como forma de avaliação da confiabilidade do método desenvolvido.
Realizar comparações de desempenho entre implementações em FPGA e em
MATLAB®.
1.2 ESTRUTURA DA DISSERTAÇÃO
Este trabalho de pesquisa está estruturado da seguinte forma: o primeiro capítulo trata
da contextualização do tema, apontando os objetivos geral e específicos. No segundo capítulo,
será apresentada a revisão bibliográfica necessária ao desenvolvimento do projeto, sendo
descritos conceitos relacionados ao FPGA e processamento de imagens. No terceiro capítulo
tem-se a descrição da solução proposta detalhada, a metodologia e materiais utilizados. Os
resultados e discussões serão apresentados no quarto capítulo, por fim, no quinto capítulo,
serão apresentadas as conclusões e sugestões para trabalhos futuros desta dissertação.
5
2. REVISÃO BIBLIOGRÁFICA
2.1 Introdução
As ConvNets são baseadas nas Redes Neurais Biológicas, tendo sua arquitetura
desenvolvida através de filtros de convolução intercalados, com a finalidade de segmentação,
detecção e reconhecimento de padrões de acordo com a aplicação. O projeto pode ser aplicado
para sistemas de visão, robôs de pequeno porte e outras aplicações embarcadas que requerem
baixo consumo de energia (FARABET ET AL. 2012).
A configuração implementada explora o paralelismo e com isso pode-se obter grande
eficiência na execução dos algoritmos através do FPGA. É normalmente necessário o uso de
um módulo de memória externa para o carregamento (PAGANO, 2012).
O sistema desenvolvido é baseado em uma rede neural de convolução (RNC),
apresentada por (FARABET ET AL. 2009). Ele pode ser analisado como um processador
SIMD (Single Instruction, Multiple Data). Possui um vetor de instruções que contém as
operações elementares de um algoritmo de convolução.
Tais instruções são otimizadas ao nível de hardware, assim a implementação de uma
RNC consiste em reprogramar as camadas do processador, sem a necessidade de mudar a
configuração lógica do FPGA.
2.2 FPGA (Field Programmable Gate Array)
FPGA é um dispositivo lógico programável que utiliza uma rede de portas lógicas e
chaves programáveis organizadas em forma de matriz e respectivas interligações, que podem
ser configurados possibilitando a criação de uma grande quantidade de circuitos digitais
através da conexão desses componentes, cuja programação é realizada pelo cliente e não pelo
fabricante (WOODS ET AL, 2008).
O FPGA permite implementar desde uma simples lógica combinacional até blocos de
memórias e estruturas mais complexas, como um microcontrolador, sendo capaz de rotear
cada bloco lógico de forma a conectá-los da melhor maneira possível, garantindo assim o
funcionamento do circuito projetado (PEDRONI, 2004; WOODS ET AL. 2008).
6
A Figura 1 apresenta a estrutura básica do FPGA, que pode variar conforme o
fabricante, contudo é composta, basicamente, dos seguintes recursos:
Blocos lógicos programáveis de n entradas (blocos lógicos), onde n varia conforme
fabricante e família do FPGA.
Amplificadores de corrente de entrada e saída.
Chaves de conexão que funcionam como uma rede para interligar os diversos
blocos lógicos existentes.
Memória RAM interna em alguns dispositivos.
Registradores (blocos lógicos) ou flip-flops para o armazenamento de informações.
Figura 1. Estrutura de um FPGA (BROWN; VRANESIC, 2000) Adaptado
De acordo com (ALTERA®, 2011D, 2010A), o FPGA moderno possibilita a utilização
de circuitos adicionais com funções específicas que são comumente encontradas no
desenvolvimento de circuitos digitais, tais como performance counter, barramento de dados,
Jtag, PLL (Phased Locked Loop) e memórias.
Sistemas reconfiguráveis em um único chip são cada vez mais utilizados de forma
embarcada, devido ao aumento de desempenho e velocidade que esses dispositivos
7
apresentam, bem como na facilidade em sua programação através de linguagens de descrição
de hardware (PERRY, 2002; ORDONEZ; PENTEADO e SILVA, 2006).
Processadores embarcados em FPGA´s podem ser utilizados conforme a necessidade
de uma aplicação específica e com fácil personalização, unindo o hardware e software para
redução de custos, maior desempenho e flexibilidade (RAIZER, 2010; TOMAZATI, 2009).
2.2.1 Ferramentas de Desenvolvimento
O trabalho aqui descrito foi desenvolvido através do kit de desenvolvimento Terasic
DE2i-150 que utiliza o FPGA Cyclone IV da Altera®. Esta placa apresenta diversos
dispositivos, periféricos e acessórios, como RS232, HDMI, Entrada de Som, SD, Memória,
VGA, Ethernet (ALTERA®, 2011d, 2010a), facilitando assim o desenvolvimento de sistemas
embarcados.
Para a programação do kit Terasic DE2i-150, foram utilizados os seguintes softwares,
todos fornecidos pela Altera®:
Quartus II v13.1 SP1: Utilizado na implementação dos códigos em VHDL para a
descrição e síntese do hardware.
NIOS II® Software Build Tools for Eclipse: Ambiente de programação em C/C++,
que permite criar o software que será executado pelo processador NIOS II®
,
desenvolvido no Quartus 13.1.
Qsys (ALTERA®, 2011f): Utilizado para o desenvolvimento e configuração do
processador NIOS II®
e seus periféricos.
2.3 Linguagens de Descrição de Hardware e VHDL
A linguagem VHDL (Very High Speed Integrated Circuit Hardware Description
Language) foi desenvolvida inicialmente como uma forma para documentar os projetos de
circuitos integrados de altíssima velocidade (VHSIC), com o objetivo de descrever a estrutura
e funcionalidade dos circuitos integrados, possibilitando a simulação dos circuitos projetados.
O Departamento de Defesa Norte Americano investiu nessa linguagem de forma a
possibilitar os avanços tecnológicos na área, contribuindo em meados de 1990 na
8
padronização do VHDL pelo IEEE, passando a ser chamado de VHSIC Hardware Description
Language (LIPSETT; SCHAEFER; USSERY, 1989).
A sintaxe do VHDL tem origem da linguagem ADA que, por sua vez, teve origem do
PASCAL. O VHDL é uma linguagem com descrições de operações executadas de forma
concorrente, exceto no sequenciamento das instruções em blocos especiais.
Um projeto escrito em VHDL é dividido em duas partes: a descrição do
comportamento (Architecture) e da interface (Entity), juntamente com a declaração das
bibliotecas e pacotes utilizados, conforme destacada abaixo:
Entidades: É qualquer componente VHDL que tenha um conjunto de portas de
comunicação, com entradas e saídas, sendo descrita por palavras reservadas, como
por exemplo: IN, OUT, INOUT, ENTITY, PORT. Uma entidade descreve e/ou
declara entradas e saídas de um circuito (interfaces).
Arquitetura: É um conjunto de primitivas em VHDL que farão a descrição do
hardware, isto é, o modo como o circuito deve operar (relação entre interfaces),
definindo estrutura (conexões) ou comportamento (ações).
Pacotes e Bibliotecas: Possibilitam agregar, em um determinado projeto, funções e
definições de tipos de dados previamente definidos.
Processos: Podem ser síncronos ou assíncronos, dependentes ou não de um sinal de
clock e utiliza palavras reservadas como: PROCESS, BEGIN e END PROCESS.
Consiste no modelo de um componente que possui uma lista de sensitividade, isto
é, possui uma lista de sinais dos quais depende. Os processos descritos em uma
arquitetura são sempre concorrentes, porém o fluxo dentro de um processo é
sequencial.
Dentre as vantagens da utilização de uma linguagem de descrição de hardware
(CARRO, 2001), pode-se destacar:
A codificação serve como documentação explicitando os objetivos do projeto.
Possuem regras sintáticas e semânticas bem definidas, não permitindo dupla
interpretação.
Padronização da linguagem resulta em portabilidade, tornando o código reutilizável
em outros ambientes de desenvolvimento.
9
2.4 Amostragem e Quantização
De acordo com (ACHARYA e RAY, 2005), o entendimento dos processos de
amostragem e quantização é de suma importância em processamento de imagens. Entende-se
como amostragem a discretização no espaço, enquanto a quantização se refere à discretização
em amplitude, de acordo com (GONZALEZ e WOODS,2009).
Para que uma imagem possa ser tratada computacionalmente, ela deve ser digitalizada,
e para isso, faz-se necessário a realização de quantização e amostragem da imagem analógica.
O processo de amostragem consiste na conversão da imagem analógica em uma matriz de
imagem com M x N pontos (pixels), definindo a resolução da imagem. A amostragem mais
frequente é chamada de uniformemente espaçada, sendo cada amostra tomada em intervalos
iguais, porém existem também outras técnicas de amostragem que utilizam espaçamento de
tamanhos direfentes, sendo menos comuns (ASSUMPÇÃO, 2013).
Quanto maiores os valores de M e N maior será a resolução da imagem, estando
diretamente relacionada à qualidade da imagem, que também depende fortemente dos
requisitos de determinada aplicação. Contudo, uma maior resolução implica em uma maior
complexidade computacional, necessária para realizar tratamentos na imagem e também um
maior custo de armazenamento (FILHO e NETO, 1999).
De acordo com a Figura 2 é possível comparar uma mesma imagem com diferentes
quantizações, ilustrando os efeitos da redução do número de níveis de cinza sobre a qualidade
da imagem. Quanto menor o número de níveis de cinza, mais perceptível é o surgimento de
uma imperfeição na imagem, conhecida como falso contorno (FILHO e NETO, 1999).
Na quantização, cada valor de pixel assume um valor inteiro, na faixa de 0 a 2n -1
,
sendo n é o número de tons de cinza. A imagem resultante terá 2n possíveis tons de cinza,
desta forma n é o número de bits necessários para representar cada pixel.
10
Figura 2. Imagem com Diferentes Níveis de Cinza. Da Esquerda para Direita, de Cima para Baixo: 16, 8, 4
e 2 Níveis de Cinza. Fonte: (GONZALEZ e WOODS, 2001)
A quantização mais frequente consiste em tomar o valor mínimo e o valor máximo dos
pixels da imagem, e dividir este segmento em intervalos iguais de acordo com o número de
bits definido para armazenar uma amostra. Utiliza-se normalmente o valor de n igual a 8, o
que equivale a um byte, representando uma variação de 0 a 255 nos tons da imagem
(ASSUMPÇÃO, 2013).
2.5 Arquitetura do Hardware
A arquitetura do hardware está representada na Figura 3 cujo diagrama mostra a
implementação do algoritmo da convolução, conforme será exemplificada posteriormente.
11
Figura 3. Convolução 2D para K=3, onde K é a Largura do Kernel e W é a Largura da Imagem. Diagrama
adaptado de (FARABET; POULET; LECUN, 2011)
Na Figura 3 pode-se observar que as multiplicações são realizadas em paralelo, com o
uso de nove multiplicadores simultâneos, e os valores dos resultados são somados e guardados
em acumuladores. A implementação de operações de processamento de imagens no FPGA
tem como ênfase as operações de vizinhança na aplicação de um kernel, que tem a função de
um determinado filtro. Com isto a realização da convolução 2D se torna mais rápida e prática
(SRIRAM e KEARNEY, 2007) obtendo-se cada linha da matriz de imagem final ao mesmo
tempo (BENKRID, 1999).
2.6 Processador (RNC)
A ConvNet é uma rede neural que consiste em várias etapas que têm módulos de
processamento repetitivos envolvendo basicamente duas funções, respectivamente, uma
convolução e uma subamostragem. Em cada fase há um módulo de banco de filtros, um
cálculo de função não-linear e um módulo de agrupamento espacial (LECUN;
KAVUKCUOGLU; FARABET, 2010).
12
O banco de filtros e a função não-linear correspondem à seguinte transformação, muito
semelhante a uma rede neural artificial tradicional.
(2.1)
Cada entrada e saída é uma matriz 2D de dimensões e ,
incluindo o filtro e a função não-linear e é o kernel do filtro utilizado na operação de
convolução representado por “*”.
A convolução é a unidade de processamento base de filtro, responsável pelo principal
custo computacional de todo o processo. Para se familiarizar com uma arquitetura completa
para uma aplicação de RNC, um processador de rede de convolução programável (RCP),
desenvolvido por (FARABET ET AL. 2009), é apresentado na Figura 3.
Este tipo de arquitetura pode ser analisado como um processador SIMD (Single
Instruction, Multiple Data) e tem um vetor de instruções contendo operações elementares de
uma ConvNet. Tais instruções são hardwares otimizados, de modo que a aplicação de uma
RCP consiste em reprogramar os elementos das camadas do processador, sem a necessidade
de alterar a configuração lógica do FPGA. A Figura 4 mostra os módulos que compõem um
RCP.
Figura 4. Arquitetura de um RNC adaptada de (FAREBET ET AL, 2011)
13
O sistema utilizado é uma rede neural de convolução (RNC), apresentado por
FARABET ET AL. (2009). Para programar as operações elementares de uma RCP, suas
instruções determinam o software layer do processador, sem a necessidade de mudar a
configuração lógica do FPGA.
Pode-se notar na Figura 4 que a RCP possui uma câmera como entrada de dados, e a
tela como saída de informações. A memória externa é usada para entrada e saída dos dados e
também pelo sistema de processamento. Para tanto, há uma interface que utiliza um árbitro
que seleciona a prioridade de cada módulo, tanto para a leitura como escrita de dados na
memória, controlando assim o múltiplo acesso aos dados (ALTERA® , 2011D, 2010A).
O driver de Entrada/Saída da memória providencia a latência de acesso requerida para
a memória externa, o que permite a RCP a ter completo acesso de leitura/escrita na mesma
memória utilizada pela VALU (Video Arithmetic Logic Unit), conforme visto na Figura 4.
A unidade de controle da RCP é baseada em uma máquina de estados. A diferença
dessa para uma unidade de controle complexa é que os cálculos não são realizados pela
unidade de processamento central, mas pela VALU que pode ler/escrever dados de/para a
interface de dados, de forma assíncrona.
O programa funciona com a utilização de oito camadas, sendo três de convolução, três
de subamostragem e duas de finalização. Seu funcionamento está ilustrado na Figura 5.
Figura 5. Exemplo de ConvNet
14
A rede convolucional é formada por múltiplos estágios e composta de várias fases. A
entrada e saída de cada etapa são conjuntos de matrizes chamados mapas de características
(LECUN; KAVUKCUOGLU; FARABET, 2011).
De acordo com FARABET ET AL (2010), A primeira camada (C1) recebe a imagem a
ser processada, após sua normalização, e gera seis convoluções diferentes utilizando kernels
desejados na imagem de entrada, produzindo assim seis mapas de características.
A segunda camada (S2), gera um agrupamento e subamostragem de cada mapa da
camada anterior.
A terceira camada (C3), computa características de níveis mais altos usando novos
filtros de convolução e somando os resultados, gerando assim novos mapas.
A próxima camada (S4), faz o mesmo procedimento de S2, mas agora para os mapas
gerados por C3.
A camada (C5) faz o mesmo procedimento de C3, mas agora utilizando os mapas
gerados por S4. Em (F6), o mapa gerado representa um mapa de picos de ativação para cada
categoria. O (F7) é fixo e simplesmente combina as categorias anteriores em um resultado
simples.
2.7 Análise dos Tempos da Solução em Software
Utilizando o processador embarcado NIOS II®
da Altera®, LIAO, ZHOU e FAN (2010)
fizeram o reconhecimento de folhas utilizando implementação por software (FARABET ET
AL. 2009), com isto obteve-se o como resultado:
Elementos Lógicos Utilizados: 6973
Registradores Utilizados: 4474
Tempo de Processamento: 991 ms
Assim o resultado em tempo de processamento da solução obtido foi superior ao
encontrado com a utilização de outras implementações, diferentes da realizada por software.
15
2.8 Implementação em Hardware do Algoritmo para Aceleração do Tempo de
Resposta
Como justificativa da solução proposta para acelerar os tempos de resposta e análise
em tempo da solução usando a implementação em hardware do algoritmo, LIAO, ZHOU e
FAN (2010) propuseram a utilização de instruções customizadas para a realização da mesma
experimentação, com o reconhecimento de folhas. A utilização de tais instruções foi possível
devido ao NIOS II®
que apresenta tal opção além de blocos lógicos customizados. A utilização
dessa estrutura foi pensada a fim de reduzir uma sequência complexa de instruções padrões em
uma única instrução de software implementada em hardware. A instrução customizada é
mostrada na Figura 6.
Figura 6. Instrução Lógica Customizada no NIOS II®
adaptado de (LIAO; ZHOU; FAN, 2010)
FARABET ET AL. (2009, 2013) apresentaram uma arquitetura desenhada para
aumentar o data throughput pela adição de unidades de vetor de processamento paralelo
múltiplo e permitindo fluxos de dados individuais para operar sem problemas dentro de blocos
de processamento. Um exemplo do Processador de Stream é mostrado na Figura 7.
16
Figura 7. Exemplo do Processador de Stream (Farabet et al. 2009).
Assim, a implementação através de FPGA e ASIC é o caminho mais fácil para gerar
um software compatível com redes de reconhecimento de objeto. A arquitetura de hardware
apresentada pode ser usada para acelerar a execução dos algoritmos de visão.
FARABET ET AL. (2009, 2012) demonstraram também que há um limite com o
bandwidth para a memória externa da implementação em FPGA. Assim, gerando uma placa
própria customizada consegue-se velocidades maiores de execução do reconhecimento. Pois
há uma limitação do bandwidth em 1 GB/s, fazendo o programa rodar com uma taxa de 6
frames por segundo. Utilizando a própria placa customizada, o bandwidth aumenta para 7,2
GB/s, a frequência pode ser maior e a taxa de frame é multiplicada por 2.
A sugestão da implementação de um RNC é devido à utilização de um vetor de
instruções que contém as operações elementares de um algoritmo de convolução. Tais
instruções são muito otimizadas no nível de hardware, assim a implementação de uma RNC
consiste em apenas reprogramar o software layer do processador, sem a necessidade de mudar
a configuração lógica do FPGA.
Utilizando apenas implementações de convolução, comparando a RNC com a
implementação em um computador normal, para Kernels pequenos (7x7) a RNC é 7 vezes
mais rápida e para Kernels maiores (17x17 aproximadamente) ela é trinta vezes mais rápida.
A RNC é cerca de cem vezes mais rápida se comparada com uma implementação
padrão em software. Toda análise foi feita com uma imagem em escala de cinza para a mesma
análise com uma monoescala, o tempo pode ser dividido por um fator de 1,5.
17
Existem outros fatores que podem ser analisados, segundo FARABET ET AL. (2009,
2011) para melhorar ainda mais a velocidade do reconhecimento. Esses fatores são:
1. Transformar o gerador de convolução em uma rede de unidades
elementares (como multiplicadores, mapeadores não lineares) flexível e
programável para poder gerar várias convoluções de diferentes tamanhos
ao mesmo tempo;
2. Transformar as operações na VALU cascateadas, criando diferentes
caminhos nesta rede, o que reduz a latência;
3. Colocar os filtros kernels em um cache na rede antes do processamento e
realizar a leitura antecipada do fluxo de dados durante o processamento.
2.9 Resultado do Algoritmo em Software e em Hardware
Pode-se analisar o tempo de execução e comparar com diversos fatores. A Tabela 1
mostra a diferença de tempo na utilização da implementação por software e por instrução
customizada.
Tabela 1. Comparação entre a implementação por Software e por Instrução Customizada
Tipo Total de Elementos
Lógicos
Total de
Registradores
Tempo de Processamento
(ms)
Custom Instruction 10.808 4.545 140
Software 6.973 4.474 991
18
Na Figura 8 e na Figura 9 pode-se observar a variação da velocidade de processamento
comparada entre a utilização de computadores normais (otimizados e não otimizados) e a
utilização do RNC. A Figura 8 mostra também a diferença do tempo para computar um
ConvNet comparada com número de conexões no ConvNet (em milhões), sendo que o
tamanho da entrada é fixo em 512x384, o Kernel é fixo em 7x7 e o pooling é fixo em 2x2,
observa-se que o tempo aumenta diretamente com o número de conexões.
Figura 8. Tempo de Processamento (ms) por Número de Conexões no ConvNet (em milhões) para RNC e
Computadores Normais (Farabet et al. 2009).
A Figura 9 mostra a variação do tempo para fazer a convolução de uma imagem de
640x480 com o tamanho do kernel utilizado, nota-se também que é diretamente proporcional,
mas um ponto interessante a notar é que para kernel muito pequeno (1x1) o resultado teórico
do computador normal é mais interessante que o RNC.
19
Figura 9. Tempo de Processamento (ms) pelo Tamanho do Kernel Utilizado para RNC e Computadores
Normais (Farabet et al. 2009).
Na Figura 10 e na Figura 11 pode-se analisar a comparação dos quadros por segundo
para o processamento em CPU, FPGA e ASIC. A Figura 10 relaciona os frames por segundo
com o tamanho das imagens processadas, mantendo um kernel constante de 9x9, já a Figura
11 relaciona os frames por segundo com o tamanho dos filtros de kernel, para figuras de
tamanho fixo de 500x500 pixels.
20
Figura 10. Frames por Segundo em Função do Tamanho da Imagem Quadrada para Programas em CPU,
FPGA e ASIC (Farabet et al. 2009).
Figura 11. Frames por Segundo em Função do Tamanho do Kernel para Programas em CPU, FPGA e
ASIC (Farabet et al. 2009).
21
A utilização da ConvNet proporciona a oportunidade de trabalhar com o
reconhecimento de imagens em tempo real, o que significa um salto muito grande no
desenvolvimento de trabalhos de veículos autônomos.
A implementação da nova tecnologia de ASIC pode, ainda, gerar uma diminuição na
potência, já que ela pode funcionar utilizando 1W e o FPGA utiliza 15W de pico, com isto,
trabalhos de visão inteligente e robôs de baixo custo tornam-se possíveis, já que utiliza pouca
energia, e tem o reconhecimento em tempo real. As ConvNets podem ser programadas ainda
para realizarem uma grande variedade de tarefas, como visão baseada em obstáculos
(FARABET ET AL. 2009, 2013).
22
3. MATERIAIS E MÉTODOS
Este capítulo apresenta a metodologia para os ensaios experimentais incluídos nesta
dissertação.
Como a meta deste projeto é o estudo de uma arquitetura para sistemas embarcados, o
trabalho de pesquisa foi implementado em um FPGA Altera® Cyclone IV GX no kit DE2i-
150, que pode ser observado em sua vista superior na Figura 12 e inferior na Figura 13.
Figura 12. Vista Superior FPGA Terasic Cyclone IV De2i-150 (Altera® co.)
É comum no processamento de imagens a manipulação da informação desejada através
da convolução entre o kernel respectivo e a matriz de dados que representa a imagem. O
kernel pode ser entendido como uma matriz de ordem muito menor do que a matriz da
imagem, o qual deve ser aplicado sucessivamente até processar toda a imagem.
23
Figura 13. Vista Inferior FPGA Terasic Cyclone IV De2i-150 (Altera® co.)
Entre os requisitos deste trabalho está o desenvolvimento de um projeto de arquitetura
de hardware de baixo custo e baixo consumo de energia, flexível e com um bom desempenho
computacional para possíveis aplicações em tempo real.
Para avaliar o desempenho, será feita a comparação no processamento de imagens
entre o software MATLAB® e os hardwares em FPGA com uma versão implementada através
da programação do processador NIOS II®
e uma versão completamente em VHDL.
O algoritmo de convolução será assim testado com duas implementações diferentes: a
primeira com o desenvolvimento de um processador dedicado que funcionará com as
instruções através de linguagem C/C++ e plataforma Eclipse, a segunda será utilizar todas as
instruções desenvolvidas em hardware através da linguagem VHDL.
3.1 Aplicação do ACD
Como evidenciado no capítulo anterior, a aplicação de algoritmos eficientes para a
convolução é de grande importância no processamento de imagens pelas redes neurais de
convolução, principalmente no que se refere ao desenvolvimento dos diversos kernels que têm
a função de filtragem da imagem, isolando assim regiões que apresentam determinadas
características como, por exemplo, detecção de bordas e nitidez. Neste caso, para testar os
24
algoritmos desenvolvidos, serão usados filtros tradicionais e bem conhecidos, evitando assim
o trabalho fora do escopo de treinar redes neurais com diferentes funções.
3.1.1 Formulação Matemática
A maior parte do esforço computacional de uma RNC é, portanto, relativo ao cálculo
da convolução 2D (Algoritmo de convolução discreta). Assim, para maior eficiência, adota-se
o cálculo das multiplicações da convolução em paralelo, realizando-se a seguir a soma das
multiplicações.
Adotou-se, portanto, a seguinte formulação digital para o cálculo da convolução, que é
um pouco diferente da formulação tradicional, porém está de acordo com o processamento de
uma RNC (FARABET ET AL, 2009), incorporando ao mesmo tempo a parte mais exigente
em termos de eficiência:
(3.1)
Onde xij é o valor da posição ij da matriz referente à imagem de entrada, wmn representa a
matriz referente ao kernel, yij é um viés que será combinado com o resultado e zij é o
valor de saída na matriz respectiva. Note que a variação dos índices i e j dependem do
tamanho original da matriz 2D da imagem respectiva a ser processada.
Apresenta-se na Figura 14 um esclarecimento para o processo da convolução conforme
foi usada na implementação do algoritmo respectivo.
Figura 14. Convolução 2D
25
A Figura 14 ilustra a convolução entre uma imagem e um dado kernel. Considerando-
se que o kernel é representado por uma matriz de dimensão 3 , a imagem será
completamente processada como várias submatrizes de mesma dimensão, retiradas
sucessivamente da matriz de dados da imagem. Cada submatriz será multiplicada pelo kernel
respectivo conforme apresentado na Figura 14. A convolução é completada através da
repetição do processo até que o kernel tenha passado sobre todos os possíveis pixels da matriz
de origem. O resultado final da convolução é uma versão filtrada da matriz da imagem. Não é
usual o uso de complementação das bordas para o processo, perdendo-se assim um certo
número de pixels a cada transformação.
3.1.2 O Fluxo de Dados
A Figura 15 apresenta o diagrama do fluxo de dados para o sistema desenvolvido, em
uma visão global. Inicialmente o sinal de vídeo ou imagem é capturado e armazenado na
memória de um computador tradicional, passando para a memória do sistema implementado
para o algoritmo da convolução, onde os dados serão processados e posteriormente reenviados
para serem exibidos.
Figura 15. Funcionamento do Sistema: Fluxo de Dados da Aquisição à Visualização.
A Figura 16 apresenta um diagrama de blocos detalhado para o processamento de
imagens nas duas implementações desenvolvidas usando FPGA (respectivamente baseada no
NIOS II®
e programada através de VHDL) e também no código desenvolvido no software
MATLAB®.
26
Figura 16. Procedimento para o Desenvolvimento das Implementações
As imagens aplicadas neste trabalho de pesquisa, foram obtidas por meio de banco de
dados de imagens padronizadas (COMPUTER VISION GROUP, 2014) e também através de
máquina fotográfica digital de 14 Megapixels.
Conforme a Figura 16 pode-se destacar o seguinte fluxo de dados no design do
hardware e software:
3.1.2.1 Processamentos Realizados usando o MATLAB®:
Desenvolvimento de código para converter a matriz de imagem RGB para uma
matriz de imagem com níveis de cinza (GRAY). Isso permite trabalhar com
apenas uma camada ao invés de três camadas no sistema RGB, diminuindo o
tempo de processamento.
Geração do arquivo de imagem em níveis de cinza no formato TXT para ser
processado no FPGA, nas duas implementações.
Aplicação do operador de suavização gaussiano na imagem, que corresponde a
um kernel convoluído com a matriz de imagem convertida em cinza, o que
27
serve como pré-processamento para as imagens a serem processadas, conforme
Apêndice D.
3.1.2.2 Processamento no FPGA usando o NIOS II®:
Configuração do processador NIOS II® no ambiente QSYS com os demais
dispositivos essenciais ao processamento.
Compilação da configuração do NIOS II® gerando um arquivo de extensão QIP
que representa o projeto do microncontrolador desenvolvido e que será
utilizado no ambiente QUARTUS®.
O projeto é convalidado através da simulação do seu funcionamento no
MULTISIM®.
Codificar o algoritmo de convolução em linguagem C/C++ visando a aplicação
do kernel de suavização de imagens gaussiano à matriz da imagem gerada no
MATLAB®.
Compilar a codificação no Eclipse a ser usada no microcontrolador no
QUARTUS® para ser utilizado no FPGA.
É gerada então pelo NIOS II®
a imagem processada. Essa matriz será
comparada com a matriz respectiva gerada pelo MATLAB® para verificação
dos resultados, conforme Apêndice C.
3.1.2.3 Processamento no FPGA usando VHDL:
Inicialmente, o arquivo da matriz de imagem em níveis de cinza deve ser
transformado em um vetor de dados para ser compatível com o armazenamento
na memória interna do FPGA.
Codificar em VHDL o operador de suavização gaussiano usando o kernel
respectivo.
Compilar o algoritmo descrito em VHDL no ambiente computacional
QUARTUS®
28
Simular no MULTISIM® o sistema desenvolvido, fazendo uso da ferramenta
waveform editor para criar estímulos que permitam a compreensão completa
dos aspectos eletrônicos de baixo nível envolvidos, por exemplo sincronização.
Após o funcionamento regular esperado ser constatado, o código é transmitido
ao FPGA e usado para realizar a filtragem respectiva.
A matriz da imagem processada é então comparada com a matriz de imagem
gerada pelo MATLAB® para verificação dos resultados, conforme Apêndice B.
3.2 Implementação no MATLAB®
Há diversas aplicações na engenharia e na ciência que exigem a identificação correta
de bordas, como por exemplo, nos processos de manufatura automatizados equipados com
câmeras para detectar componentes na montagem do produto, bem como o reconhecimento de
padrões.
Na robótica, um robô pode se comportar de uma certa maneira em resposta a estímulos
visuais. Pode-se também processar e extrair características relevantes em um conjunto de
imagens, através da detecção de bordas antes da utilização do algoritmo de reconhecimento de
padrões e assim alcançar resultados superiores de desempenho.
Pode-se utilizar vários tipos de kernel no ACD de acordo com a finalidade e
característica que se deseja analisar.
Através do software MATLAB®, diversos tipos de filtros e suas aplicações, podem ser
testados de acordo com o objetivo desejado. No desenvolvimento do projeto, a imagem GRAY
foi transformada em uma matriz de pixels que representa essa imagem através de números,
que varia de 0 a 255 conforme ilustra a Figura 17.
29
Figura 17. Matriz da Imagem Gray
Na sequência a matriz de imagem GRAY passa pelo processo de convolução com a
matriz de kernel do filtro pré-definido para a extração de uma determinada característica
desejada, nesse caso extração de bordas e suavização da imagem, o que pode ser visto na
Figura 18 e na Figura 19.
30
Figura 18. Matriz de Convolução Gerada a partir da Convolução da Imagem Gray com o Kernel
Figura 19. Kernels: K1 para Detecção de Bordas e K2 para Destacar Relevo
3.3 Implementação do NIOS II®
A arquitetura interna detalhada do periférico desenvolvido é representada na Figura 20.
Pode-se observar a presença dos periféricos no barramento Avalon e o ACD desenvolvido em
31
software com linguagem de programação C/C++, juntamente com o barramento Avalon para
comparações quanto ao desempenho e processamento de imagens.
Figura 20. Diagrama em Blocos com Todos os Módulos do Microcontrolador, Módulo ACD implementado
em Linguagem C/C++ e MATLAB® e Barramento Avalon
É importante a escolha adequada do barramento e de seus componentes para melhor
desempenho do sistema como um todo. O barramento Avalon permite que as informações
sejam lidas, processadas e escritas nos componentes vinculados ao barramento e entrarão na
memória interna a medida que o processador fizer uso do hardware desenvolvido.
Para a leitura das informações processadas, o processador irá retirar os dados da
memória SDRAM, que estão ordenados segundo o algoritmo de convolução.
A discussão dos resultados consistirá na análise comparativa do desempenho e
qualidade da imagem de um ACD desenvolvido em software através do MATLAB®
, em
hardware através do FPGA usando NIOS II®
e através do FPGA usando VHDL.
32
3.3.1 Análise das Conexões
O processador desenvolvido foi projetado com a finalidade de controlar todos os
periféricos necessários ao funcionamento do sistema.
Utilizando a ferramenta QSYS, os elementos presentes no processador são instanciados
um a um e conectados de forma coerente, conforme podemos observar na Figura 21 e na
Figura 22 que representam as janelas de criação do processador e sua conexão com os demais
periféricos.
Figura 21. Desenvolvimento do Microcontrolador no QSYS.
33
O processador ALTERA® NIOS II
® (ALTERA
®, 2010b) é um soft core que possui
arquitetura de 32 bits, contendo três versões que estão disponíveis para serem utilizadas:
econômico, padrão e rápido. A versão utilizada neste trabalho de pesquisa foi a padrão.
O processador desenvolvido foi projetado com a finalidade de controlar todos os
periféricos necessários ao funcionamento do sistema.
Após adição à biblioteca de periféricos, deve-se instanciar um periférico do tipo criado
e realizar a sua conexão com o barramento desejado, que neste caso foi o barramento de dados
do processador NIOS II®
.
Utilizando o software QSYS, uma extensão do Quartus II (ALTERA®, 2011f), os
elementos presentes no processador (sysid, jtag_uart, onchip_memory, sdram_controller,
pll_DE2115, performance_counter) são instanciados um a um e conectados de forma
coerente, conforme pode-se observar na Figura 22 que ilustra a janela de criação do
processador e sua conexão com os demais periféricos, possibilitando ao usuário personalizar
sua lógica diretamente na unidade lógica aritmética (ULA) do processador.
As conexões de desenvolvimento do hardware no QSYS não são feitas de maneira
intuitiva, havendo necessidade de conhecimento sobre o funcionamento de todos os
dispositivos disponíveis no software.
34
Figura 22. Implementação do Microcontrolador no QSYS.
Após adicionado no QSYS e gerado o sistema, há necessidade de compilação no
QUARTUS® para ser utilizado no FPGA. O próximo passo é criar o modelo de software em
linguagem C/C++ que irá acessar este periférico do processador através de comandos diretos
de escrita e leitura de dados em endereços de memória.
O algoritmo ACD desenvolvido funciona juntamente com o processador que foi
personalizado através do QSYS no FPGA, cuja função é realizar cálculos de convolução
necessários para se obter um filtro gaussiano, com a função de suavizar a imagem.
35
3.3.2 Diagrama Esquemático do Microcontrolador
Após compilação do hardware desenvolvido no QSYS é gerado o microcontrolador
representado na Figura 23. Esta forma de visualização é possível através do software
QUARTUS II®
onde podemos ver as entradas e saídas utilizadas na arquitetura desenvolvida.
Figura 23. Microcontrolador Desenvolvido no QSYS
A Figura 24 representa o microcontrolador desenvolvido no QSYS com as conexões
com o NIOS II®
36
Figura 24. Microcontrolador Desenvolvido no QSYS e Conexões com NIOS II ®
3.3.3 O Fluxo de Dados e Módulo de Convolução
Inicialmente o sinal de vídeo ou imagem é adquirido e armazenado na memória do
periférico desenvolvido, passando para o sistema de processamento do ACD onde os dados
serão processados através da rede de convolução, na sequência, os dados processados são
exibidos.
O pipeline desenvolvido para o processamento do ACD foi realizado utilizando
estágios, representando a descrição genérica de um conjunto de elementos lógicos e
componentes genéricos, ou seja, a técnica de hardware que permite a busca de uma ou mais
instruções além da próxima a ser executada, sendo colocadas em uma fila de memória dentro
do processador onde aguardam o momento de serem executadas.
A Figura 25 apresenta a implementação do módulo personalizado para o cálculo do
ACD. A utilização do algoritmo de convolução discreta é possível, após a sua integração ao
37
processador NIOS II®
, sendo realizado através da criação de interfaces para o barramento
Avalon.
Figura 25. Diagrama de Blocos com Processador, Módulo ACD Implementado em NIOS II® e o
Barramento Avalon
No desenvolvimento do circuito, foram utilizados vários periféricos, sendo o
barramento Avalon o meio pelo qual o processador NIOS II®
e todos os demais periféricos
utilizam para se comunicar.
Para melhor compreensão, é importante fazer a seguir uma descrição rápida de cada
periférico existente no microcontrolador:
ACD é o módulo responsável pelo processamento da imagem, fazendo os cálculos de
convolução da imagem com um determinado kernel.
Jtag Uart é um periférico cuja função é o download do software desenvolvido para a
memória do processador, permitindo assim a sua depuração.
38
NIOS II® Processor é um processador configurado na versão rápida, para melhor
eficiência no processamento e aquisição de dados.
SDRAM Controller possibilita que os sinais sejam gerados para a memória externa de
forma coerente, garantindo os requisitos de tempos, possui uma interface com endereços que
abrangem os 32MB de memória.
SysID é um periférico que identifica o processador e os demais componentes do
sistema, possui um registrador com um identificador único que pode ser gerado
automaticamente ou manualmente.
Performance Counter é um periférico que permite mensurar dois ou mais eventos em
termos de pulsos de clocks, através dele podemos descobrir o tempo de processamento dos
dados.
PLL_DE2115 (Phased Locked Loop) é um componente externo ao sistema
desenvolvido no QSYS, esse dispositivo é responsável por multiplicar o sinal de clock de
50MHz, gerando qualquer valor de sinal de clock necessário para o hardware funcionar.
On-Chip Memory é a memória localizada dentro do próprio FPGA, usada
normalmente para manter as instruções e dados usados pelo processador a cada instrução, ao
invés de um dispositivo de memória externa.
SDRAM Memory (Synchronous Dynamic Random Access Memory) é o módulo de
memória externa, é uma memória de acesso dinâmico randômico (DRAM) que é sincronizada
com o barramento do sistema.
USB-Blaster é driver responsável pela transferência de dados via USB entre o PC e os
dispositivos da Altera®, como o FPGA.
Os dados referentes a imagem ou vídeo são deslocados no registrador de deslocamento
Shift Register, essas informações simultaneamente serão armazenadas numa matriz de imagem
e deslocadas para a memória RAM, fazendo com que a imagem seja armazenada e processada
de forma paralela.
A matriz de imagem é convoluída com a matriz de kernel que tem a função de um
determinado filtro desejado de forma simultânea, ou seja, tem-se a entrada de dados da matriz
de imagem, deslocamento dessas informações e o processo de convolução tudo ao mesmo
tempo, isto é possível devido ao paralelismo do FPGA (MAX, 2004; MAYYA; ZARKA;
ALKAD, 2010), fazendo com que o seu processamento seja mais rápido, diferente do que
39
acontece se todo esse processo ocorresse apenas de forma serial, o processador realiza uma
leitura da saída do módulo, que já contém o resultado, baseado em multiplicações e adições
em hardware (PEDRONI, 2004; KILTS, 2007).
Através da integração entre o processador e o módulo de convolução ACD obtemos
um sistema ótimo para a realização da convolução (PAGANO, 2012).
3.4 Implementação em VHDL
3.4.1 Hardware ACD e Periféricos
Conforme a Figura 26, os dados são lidos das memórias internas pelo controlador
projetado responsável pelas conexões entre os elementos do módulo desenvolvido e o
barramento de dados do processador, conforme Apêndice A.
Figura 26. Diagrama em Blocos do Hardware ACD e Periféricos
O pipeline desenvolvido para o processamento do ACD foi realizado utilizando
estágios, representando a descrição genérica de um conjunto de elementos lógicos e
componentes genéricos, sendo colocadas em uma fila de memória dentro do processador onde
aguardam o momento de serem executadas.
40
Através do Data_in tem-se a entrada de dados que serão deslocados no registrador de
deslocamento Shift Register, essas informações simultaneamente serão armazenadas numa
matriz de imagem e deslocadas para a memória RAM, fazendo com que a imagem em tempo
real seja armazenada e processada de forma paralela.
A matriz de imagem será convoluída com o kernel de forma simultânea, ou seja, tem-
se a entrada de dados da imagem, deslocamento dessas informações e o processo de
convolução tudo ao mesmo tempo, isso é possível devido ao paralelismo do FPGA, fazendo
com que o seu processamento seja mais rápido, diferente do que acontece se todo esse
processo ocorresse apenas de forma serial.
Há memórias internas para escrita dos dados e um bloco de memórias que receberá o
resultado do processamento do ACD. Essas memórias serão lidas posteriormente pela
interface Avalon que funciona como uma espinha dorsal, fazendo a ligação entre todos os
componentes. Os sinais de clock e reset são repassados para todos os componentes do
periférico através do barramento.
O sinal write data recebe a informação que entrará na memória e o sinal address
recebe o endereço em que essa informação deverá entrar. O sinal read possibilita que o
processador realize a leitura de dados, dessa forma, o sinal de endereços é aplicado ao
conjunto de memórias que contêm o resultado dos cálculos. O sinal read data recebe a
informação da memória selecionada pelo endereçamento.
Após a inserção das informações na memória RAM, o pipeline tem início quando o bit
é levado para um, iniciando assim o processo e no final o bit é automaticamente desativado,
gerando um bit de fim de processamento, representado pelo sinal finished e escrito no
registrador de estado e controle no próximo bit menos significativo. Dessa forma é possível
detectar o fim do processamento através da leitura deste registrador, e assim realizar a leitura
da memória.
3.4.2 Módulo de Processamento de Imagens
A imagem é armazenada na memória MIF (Memory Initialization File), que é utilizada
na inicialização de memória no simulador ou compilador, conforme modelo apresentado na
Figura 27. Na MIF é carregada o valor inicial de um bloco de memória, ou seja, os valores
iniciais para cada endereço de memória. Este arquivo é usado durante a compilação e/ou
41
simulação do projeto e deve ser especificado a profundidade (DEPTH) de memória, valores de
largura (WIDTH) e o ADDRESS_RADIX como binário (BIN), octal (OCT), hexadecimal
(HEX), decimal com sinal (DEC) ou decimal sem sinal (UNS). Pares de dados representam os
dados inseridos dentro dos endereços de memória (CONTENT), contendo os pixels da imagem
que são delimitados por BEGIN e END.
Figura 27. Dados da Imagem na Memória MIF
A Figura 28 representa o módulo de Memória MIF do Hardware ACD, através desse
módulo de memória é feita a armazenagem da imagem de entrada que será processada.
42
Figura 28. Módulo de Memória MIF do Hardware ACD
Através da simulação com a ferramenta Waveform Editor e MODELSIM®
disponibilizado no QUARTUS II®
(Figura 29) é possivel observar a imagem sendo
armazenada no módulo de memória (Figura 30).
Figura 29. Modelsim: Waveform da Aquisição de Dados da Imagem
43
Figura 30. Imagem Processada pelo Hardware de Aquisição de Dados
A Figura 31 apresenta a implementação do módulo personalizado para o cálculo da
ACD, após a sua integração ao controlador, sendo realizado através da criação de interfaces
internas ao módulo.
Figura 31. Módulo de Processamento de Imagens em Hardware
44
Após o processamento da imagem através do módulo de processamento de imagens, o
dado processado é transmitido através do FPGA (Figura 32) pelo módulo de filtragem e
UART (Universal Asynchronous Receiver-Transmitter) do hardware ACD (Figura 33) para o
computador, onde a imagem é armazenada.
Figura 32. Processamento Hardware ACD no FPGA
45
Figura 33. Módulo de Filtragem e UART do Hardware ACD
46
4. RESULTADOS E DISCUSSÕES
4.1 Implementação no MATLAB®
Foram utilizados kernels para reduzir o ruído em sinais e melhorar a qualidade das
imagens, para detecção de bordas e para destacar relevo. A Figura 34 representa a imagem de
entrada colorida RGB. Ela é utilizada para a experiência prática passando por dois tipos de
kernel, um para detecção de bordas e outro Gaussiano para suavização da imagem e
eliminação de ruídos.
Figura 34. Imagem de Entrada Colorida RGB
A Figura 35 representa a imagem RGB que foi processada pelo MATLAB®, tendo
como saída a imagem GRAY representada na Figura 36 eliminando assim as camadas RGB.
Dessa forma ainda temos a informação da imagem original, no entanto é utilizada apenas uma
camada. Isso faz com que se tenha um aumento no desempenho, pois há processamento de
apenas uma camada da imagem e não de três camadas como ocorre na imagem RGB.
47
Figura 35. Obtenção da Imagem Gray a partir da Imagem RGB de Entrada no MATLAB®
Figura 36. Imagem Convertida para Gray
A Figura 37 apresenta a matriz de imagem colorida RGB, a matriz de imagem GRAY
com apenas uma camada e as matrizes de imagens convoluídas com os filtros K1 (Detecção de
Bordas) e K2 (Destacar Relevo).
48
Figura 37. Transformação da Imagem de Entrada RGB para Gray e Posterior Tratamento com os Kernels
K1 e K2
A Figura 38 representa a imagem filtrada com o kernel K1 de detecção de bordas
Sobel. Pode-se observar como resultado a extração de bordas da imagem. Essa imagem pode
ser utilizada na detecção de faces.
49
Figura 38. Imagem Filtrada com o Kernel para Detecção de Bordas K1
Já a Figura 39 representa a imagem filtrada com o kernel K2, pode-se observar como
resultado o destaque do relevo.
Figura 39. Imagem Filtrada com o Kernel para Destacar Relevo K2
50
Para efeito de comparação dos resultados, foi feita a mesma convolução realizada pelo
software MATLAB®, mas agora utilizando o hardware ACD desenvolvido com o processador
em FPGA utilizando NIOS II®
e também utilizando VHDL.
4.2 Implementação do NIOS II®
Utilizando o processador embarcado NIOS II® da Altera
® com implementação em
C/C++ têm-se os recursos utilizados conforme Figura 40.
Figura 40. Recursos Utilizados com o NIOS II® no FPGA
Pode-se observar a utilização de 4% do total de elementos lógicos disponíveis no
FPGA e 17% do total de bits de memória.
4.3 Implementação do VHDL
Utilizando o FPGA com implementação em VHDL têm-se os recursos utilizados
conforme Figura 41.
51
Figura 41. Recursos Utilizados com o VHDL no FPGA
Pode-se observar a utilização de menos de 1% do total de elementos lógicos
disponíveis no FPGA e 32% do total de bits de memória.
4.4 Análise de Recursos usando o FPGA
De acordo com a Figura 40 e Figura 41 pode-se montar a Tabela 2 abaixo. Verifica-se
que no desenvolvimento em VHDL é utilizada uma quantidade menor de elementos lógicos do
FPGA com relação a mesma codificação utilizando o NIOS II®
. No entanto a codificação em
VHDL utiliza 32% da memória, enquanto a codificação em NIOS II®
utiliza 17%. Essa
diferença é devido ao armazenamento da imagem na memória MIF durante o processamento
em VHDL.
52
Tabela 2. Performance e Recursos Utilizados
FPGA % Memória Utilizada Elementos Lógicos
NIOS II® 17 5384
VHDL 32 1031
4.5 Justificativa da Solução Proposta para Acelerar os Tempos de Resposta
O FPGA trabalha com processamento paralelo, diferente do MATLAB®, o que
aumenta consideravelmente a velocidade de execução do algoritmo, acelerando assim os
tempos de resposta.
4.6 Análise de Desempenho Usando a Implementação em Software e em Hardware
Uma pesquisa avaliando o desempenho entre FPGA, GPU e CPU foi realizada por
(COPE, 2006) na aplicação de cálculos de convolução 2D. Seus resultados demonstram a
superioridade do FPGA em aproximadamente 30 vezes mais rápido que a CPU Pentium-4 de
3.0 GHz para um kernel 7x7.
Os resultados apresentados na Figura 42 referem-se a comparação entre o
processamento de imagens para o cálculo de convolução 2D realizado pelo ACD, utilizando o
software MATLAB® e o FPGA.
53
Figura 42. Tempo de Processamento de Imagens em Software X Hardware
Para todas as imagens de entrada obteve-se um desempenho superior no hardware
desenvolvido com FPGA em VHDL, seguido pelo software MATLAB® que foi executado em
um computador Intel® Xeon E5335 Dual Core de 2 GHz de clock e 8 GB de memória RAM e
posteriormente para o hardware desenvolvido em FPGA com o NIOS II®
. É importante
salientar que dependendo da configuração da CPU onde o código de convolução do software
MATLAB® for executado, isso irá alterar o valor do tempo de processamento e o FPGA com
NIOS II®
passaria também a apresentar um desempenho superior com relação ao software.
O FPGA com VHDL foi em média 79 vezes mais rápido para uma imagem de entrada
de 200x266 pixels, 46 vezes mais rápido para uma imagem de entrada de 400x389 pixels e 38
vezes mais rápido para uma imagem de entrada de 512x512 pixels que a mesma
implementação realizada em software MATLAB®.
4.7 Comparação das Imagens de Saída Lena no MATLAB®, NIOS II
® e VHDL
Estes resultados ilustram a eficiência da utilização do FPGA no processamento de
imagens. Após uma sequência de testes com imagens diferentes, obteve-se como resultado as
54
imagens mostradas na Figura 43, em que é mostrada a imagem original Lena, seguida da
imagem filtrada suavizada por um filtro Gaussiano em MATLAB® e pela imagem filtrada
suavizada por um filtro Gaussiano em NIOS II®
.
Figura 43. Imagens de Saída no MATLAB®, NIOS II
® e VHDL
A imagem gerada pelo NIOS II®
apresenta um erro de aproximadamente 0.3831 % em
relação a imagem de saída obtida no MATLAB®. A imagem gerada pelo VHDL apresenta um
erro de aproximadamente 4.2796 % em relação a imagem de saída obtida no MATLAB®, isto
é devido ao circuito desenvolvido em VHDL fazer o cálculo de convolução de maneira
diferente da realizada pelo MATLAB® que utiliza o recurso de borda para efetuar a
convolução. É importante salientar que os erros apresentados são referentes a borda utilizada
no cálculo da convolução, o que não interfere na qualidade final da imagem processada.
55
5. CONCLUSÕES E SUGESTÕES PARA TRABALHOS FUTUROS
Através desta implementação de hardware em FPGA através de VHDL e de NIOS II®,
percebe-se, comparando-se os resultados obtidos com o software MATLAB®, a potencialidade
de um sistema embarcado baseado em FPGA.
Os circuitos desenvolvidos em FPGA com NIOS II®
e FPGA com VHDL permitem a
obtenção de imagens praticamente iguais as processadas pelo MATLAB®, ou seja, o resultado
da convolução foi praticamente o mesmo para todos os casos e a qualidade das imagens
processadas pelos hardwares não apresentam diferenças significativas com a imagem
processada no MATLAB®, pois os erros apresentados são referentes ao tratamento da borda da
imagem durante o cálculo da convolução.
Os hardwares desenvolvidos têm a vantagem de serem reprogramados para quaisquer
funções de filtragem como o Sobel na detecção de bordas, Gaussiano na suavização de
imagens, Laplaciano de comportamento de um filtro "passa-alta", Bartlett na reconstrução de
imagens entre outros e também permitem a criação de novas topologias de rede de convolução
de forma rápida e flexível, podendo ser utilizados futuramente em projetos de aquisição de
imagens em tempo real para utilização em veículos robóticos autônomos, na detecção de sinais
cardíacos empregado na engenharia biomédica entre outros.
O hardware desenvolvido totalmente em VHDL apresentou desempenho muito
superior no tempo de processamento se comparado com o software MATLAB®, sendo uma
ótima solução mesclando flexibilidade e velocidade.
Os requisitos de desempenho de aplicações de processamento de imagens têm
demandado um maior poder computacional, principalmente com relação ao processamento em
tempo real. Neste caso, o processamento por hardware especializado surge como um elemento
decisivo, possibilitando em redução do tempo de processamento em decorrência da execução
paralela das operações.
Os sistemas de hardware reconfigurável permitem acelerar a execução de algoritmos,
proporcionando uma alternativa de alto desempenho para soluções que antes eram executadas
exclusivamente em software.
As arquiteturas desenvolvidas podem ser utilizadas no processamento de imagens em
tempo real em várias áreas como:
56
Operação remota de dispositivos robóticos em ambiente hostil.
Projeto e aplicação de sistemas robóticos móveis para uso em educação.
Desenvolvimento de estratégias de controle automático e navegação para veículos
robóticos aéreos e terrestres.
Aplicação de métodos ópticos de Moiré no levantamento topográfico de objetos e
na determinação da distribuição de tensões e deformações em elementos de
estrutura.
Ao final deste trabalho de pesquisa sugere-se como trabalhos futuros uma análise da
técnica visando:
Implementar uma rede de convolução 1D usando o conjunto desenvolvido.
Unificar os dois desenvolvimentos colocando o módulo em VHDL como periférico
do NIOS II®.
Desenvolver aplicações em reconhecimento de imagens (2D e 3D).
57
REFERÊNCIAS
______. Altera® . NIOS II
® Processor reference Handbook, 2010a, 2010b.
______. Altera® . Altera
® Avalon Interface Specifications, 2011a.
______. Altera® . Embedded Peripherals IP User Guide, 2011b.
______. Altera® . Implementing an LCD Controller, 2011c.
______. Altera® . NIOS II
® embedded evaluation kit, cyclone III edition. 2011d.
______. Altera® . NIOS II
® embedded evaluation kit picture viewer example. 2011e.
______. Altera® . SOPC Builder User Guide, 2011f.
______. Altera® . Video Sync Generator and Pixel Converter Cores, 2011g.
______.COMPUTER VISION GROUP <http://decsai.ugr.es/cvg/CG/base.htm> Acesso
em 27/04/2014.
______.Embedded Peripherals IP User Guide. [S.l.], 2014. Disponível em:
<http://www.Altera.com/literature/ug/ug_embedded_ip.pdf>. Acesso em 27 de Junho de
2014.
______. MAC DEVELOPER LIBRARY. Performing Convolution Operations,
[Online], Disponível em: <https://developer.apple.com/library/mac/documentation/>
Acesso em 27 de Junho de 2014.
58
______.Quartus II University Interface Program. Disponível em:
<http://www.Altera.com/education/univ/research/quip/unv-quip.html>. Acesso em 13 de
Maio de 2014.
______.NIOS II® Processor Reference Handbook. [S.l.], 2014. Disponível em:
<http://www.Altera.com/literature/hb/nios2/n2cpu_nii5v1.pdf>. Acesso em 27 de Junho
de 2014.
______.SOPC Builder User Guide. [S.l.], 2014. Disponível em:
<http://www.Altera.com/literature/ug/ug_sopc_builder.pdf>. Acesso em 27 de Junho de
2014.
______.VHDL Basics. 2011. Altera® Corporation Website Online Course. Disponível
em:<http://www.Altera
.com/education/training/courses/OHDL1110?GSA_pos=2&WT.oss_r=1&WT.oss=vhdl>.
Acesso em 15 de Agosto de 2014.
ACHARYA, T.; RAY, A. "Image Processing: Principles and Applications". [S.l.]:
Wiley, 2005. ISBN 9780471745785 452p.
AIZAWA, K.; SAKAUE, K.; SUENAGA, Y. "Image Processing Technologies:
Algorithms, Sensors, and Applications". [S.l.]: Taylor & Francis, 2004. (Signal
Processing and Communications). ISBN 9780824750572 295p.
ANTONIOU, A. "Digital Signal Processing, Signals, System and Filters". New York,
United States of America: McGraw-Hill, 2006. 991p.
ASSUMPÇÃO, M. B; "Implementação em FPGA de Algoritmo de Detecção de Cantos
de Imagens para Aplicações em Tempo Real" 106p. Dissertação de Mestrado,
Universidade de Brasília, 2013.
59
BAILEY, D. G. "Design for Embedded Image Processing on FPGAs". Massey
University, New Zealand: John Wiley and Sons (Asia) Pte Ltd, 2011 482p.
BENKRID, K. "A high Level Software Environment for FPGA Based Image
Processing". Queen´s University of Belfast, UK. p. 112 – 116. 1999. (Conference
Publication No. 465).
BONATO, V. "Projeto de um Módulo de Aquisição e Pré-processamento de Imagem
Colorida baseado em Computação Reconfigurável e Aplicado a Robôs Móveis". 82 p.
Dissertação de Mestrado — USP, Universidade de São Paulo, São Paulo, Brasil, 2004.
BROWN, S.; VRANESIC, Z. "Fundamentals of Digital Logic with VHDL Design".
Toronto McGraw Hill, 2000.
CARRO, L. "Projeto e Prototipação de Sistemas Digitais". Porto Alegre, RS: Editora
Universidade/UFRGS, 2001.
CHAN, P.K.; MOURAD, S. "Digital Design using Field Programmable Gate Arrays".
Prentice Hall, 1994.
COPE, BEN. "Implementation of 2D Convolution on FPGA, GPU and CPU".
Technical report, Department of Electrical and Electronic Engineering, Imperial College,
London, UK, 2006.
CROOKES, D; ALOTAIBI, K; BOURIDANE, A; DONACHY P; BANKRID, A. "An
Environment for Generating FPGA Architectures for Image Algebra-based
Algorithms". Department of Computer Science, The Queen´s University of Belfast. p. 990
– 994, 2002.
FARABET, C.; MARTINI, B.; AKSELROD, P.; TALAY, S.; LECUN, Y.,
CULURCIELLO, E.; "Hardware Accelerated Convolutional Neural Networks for
60
Synthetic Vision Systems". Circuits and Systems (ISCAS), Proceedings of 2010 IEEE
International Symposium on. IEEE, 2010.
FARABET, C.; COUPRIE, C.; NAJMAN, L.; LECUN, Y.; "Learning Hierarchical
Features for Scene Labeling", IEEE TRANSACTIONS ON PATTERN ANALYSIS AND
MACHINE INTELLIGENCE, VOL. 35, NO. 8, AUGUST 2013.
FARABET, C.; COUPRIE, C.; NAJMAN, L.; LECUN. Y; "Scene Parsing with
Multiscale Feature Learning, Purity Trees, and Optimal Covers". In Proc. of the 2012
International Conference on Machine Learning, Edinburgh, Scotland, June 2012.
FARABET, C.; POULET, C.; HAN, J.Y.; LECUN, Y.; "CNP: An FPGA-Based
Processor for Convolutional Networks" in Proc. International Conference on Field
Programmable Logic and Applications (FPL’09), IEEE, Prague, 2009.
FARABET, C.; POULET, C.; LECUN, Y.; "An FPGA-Based Stream Processor for
Embedded Real-Time Vision with Convolutional Networks" IEEE Transactions on
Pattern Analysis and Machine Intelligence 2011.
FILHO, O. M.; NETO, H. V. "Processamento Digital de Imagens". 1nd. ed. Rio de
Janeiro, RJ, Brasil: Editora Brasport, 1999.
GARCIA, C.; DELAKIS, M. "Convolutional Face Finder: A Neural Architecture for
Fast and Robust Face Detection". IEEE TRANSACTIONS ON PATTERN ANALYSIS
AND MACHINE INTELLIGENCE, 26(11):1408–1423. (2004).
GONZALEZ, R. C.; WOODS, R. E. "Digital Image Processing". 2nd. ed. Boston, MA,
USA: Addison-Wesley Longman Publishing Co., Inc., 2001.
GONZALEZ, R. C.; WOODS, R. E.; EDDINS, S. L. "Digital Image Processing Using
MATLAB®". 2. ed. [S.l.]: Gatesmark Publishing, 2009.
61
HAYES, M.H. "Digital Signal Processing". New York: McGraw-Hill, 1999.
KILTS, S. (2007). "Advanced FPGA Design: Architecture, Implementation, and
Optimization". Wiley-IEEE Press.
KIM, S.; CASPER, R. "Applications of Convolution in Image Processing with
MATLAB®". University of Washington 2013.
LAWRENCE, S; GILES, C. L; TSOI, A. C; BACK, A. “Face Recognition: A
Convolutional Neural Network Approach”, IEEE Trans. Neural Netw., vol. 8, no. 1, pp.
98–113, Feb. 1997.
LECUN, Y.; BOTTOU, L.; BENGIO, Y.; HAFFNER, P. “Gradient-based Learning
Applied to Document Recognition,” Proc. IEEE, vol. 86, no. 11, pp. 2278–2324, Nov.
1998.
LECUN, Y.; KAVUKCUOGLU, K.; FARABET, C.; "Convolutional Networks and
Applications in Vision", Proceedings of 2010 IEEE International Symposium on Circuits
and Systems (ISCAS), 2010.
LIAO, YU-PING; ZHOU, HAO-GONG; FAN. GANG-REN; "Accelerating Recognition
System of Leaves on NIOS II®
Embedded Platform”, 2010 International Symposium on
Computer, Communication, Control and Automation.
LIPSETT, R.; SCHAEFER, C.; USSERY, C. E. "VHDL: Hardware Description and
Design". [S.l.]: Kluwer Academic Press, 1989.
MAX, C.M. "The Design Warrior’s Guide to FPGAs". Burlington: Newnes, 2004.
62
MAYYA, M.; ZARKA, N.; ALKAD, S. "Embedded System for Real-time Human
Motion Detection. Image Processing Theory Tools and Applications (IPTA)", 2010
2nd International Conference. on, v. 1, p. 523 –528, 2010.
MELLO, L.I.A; COSTA, L.C.A.C; "História Moderna e Contemporânea". Editora
Scipione 1993.
MEYER-BAESE, U. (2007). "Digital Signal Processing with Field Programmable Gate
Arrays". Springer Verlag.
NING, F.; DELHOMME, D. ; LECUN, Y.; PIANO, F.; BOTTOU, L.; BARBANO, P.
“Toward Automatic Phenotyping of Developing Embryos from Videos,” IEEE
Transactions on Image Processing, 2005, special issue on Molecular and Cellular
Bioimaging.
ORDONEZ, E.D.M.; PENTEADO, C.G.; DA SILVA, A.C.R.; "Microcontroladores e
FPGAs: Aplicações em Automação", volume I. Novatec, 2006.
PAGANO, D. M.; "Proposta de uma Arquitetura de Processamento de Sinais
Utilizando FPGA". 129 p. Dissertação de Mestrado - UNICAMP, Universidade Estadual
de Campinas, Campinas, Brasil, 2012.
PEDRONI, V.; (2004). "Circuit Design with VHDL". The MIT Press.
PELLERIN, D.; THIBAULT, S. "Practical FPGA Programming in C", Prentice Hall
PTR 2005.
PERRY, D. L. ;"VHDL Programing by Example". [S.l.]: McGraw-Hill, 2002.
RAIZER, K.; IDAGAWA, H. S.; NÓBREGA, E.G.O.; FERREIRA, L.O.S; "Training
and applying a feedforward multilayer neural network in GPU", 11/2009, Científico
63
Internacional, Iberian-Latin-American Congress on Computational Methods in
Engineering (CILAMCE), Vol. cd, pp.1-6, Buzios, RJ, BRASIL, 2009.
RAIZER, K.; "Análise de Sinais de ECG com o Uso de Wavelets e Redes Neurais em
FPGA". 109 p. Dissertação de Mestrado - UNICAMP, Universidade Estadual de
Campinas, Campinas, Brasil, 2010.
RIFKIN, JEREMY; "The Third Industrial Revolution" isbn: 9788576801818, editora
M. Books, 2012.
ROSTEN, E.; DRUMMOND, T. "Machine Learning for High-speed Corner
Detection". Department of Engineering, Cambridge University, UK, 2006.
RUSSO, L. M; PEDRINO, E. C; KATO, E; RODA, V. O. "Image Convolution
Processing: A GPU versus FPGA Comparison", in 2012 VIII Southern Conference on
Programmable Logic, no. 2010. IEEE, Mar. 2012, pp. 1–6. [Online]. Disponível em :<
http://ieeexplore.ieee.org/xpls/abs all.jsp?arnumber=6211783> Acesso em 13 de Maio de
2014
SAMSUNG ELETRÔNICA DA AMAZÔNIA LTDA. CARLOS CAETANO DE
ALMEIDA. "Sistema e Método para Modificar as Cores da Capa Plástica Semi-
translúcida de Notebooks ". Patente BR 10 2012 033825 4 A2, 28 Dezembro 2012.
SEBESTA, R.W.; "Concepts of Programming Languages". 10th Edition, Bookman,
2012.
SOCHER, RICHARD; CHIUNG-YU LIN, CLIFF; Y. NG,ANDREW;
MANNING,CHRISTOPHER D. "Parsing Natural Scenes and Natural Language with
Recursive Neural Networks". 28 th International Conference on Machine Learning,
Bellevue, WA, USA, 2011.
64
SRIRAM, V.; KEARNEY. D.; "A FPGA Implementation of Variable Kernel
Convolution", in Eighth International Conference on Parallel and Distributed Computing,
Applications and Technologies (PDCAT 2007). University of South Australia: IEEE, Dec.
2007, pp. 105–110.
TOMAZATI, A. O.; "Detecção do Complexo QRS em Sinais Cardíacos Utilizando
FPGA". 136 p. Dissertação de Mestrado - UNICAMP, Universidade Estadual de
Campinas, Campinas, Brasil, 2009.
WOODS, R.; MCALLISTER, J.; YI, Y.; LIGHTBODY, G.; "FPGA-based
Implementation of Signal Processing Systems". [S.l.]: Wiley, 2008. ISBN 978-0-470-
03009-7.
ZONGQING, L. "An Embedded System with uClinux based on FPGA". p. 691 – 694,
2008.
ZWOLINSKI, M. "Digital System Design with VHDL". Pearson education, 2004.
65
APÊNDICE A - QUARTUS E HARDWARE ACD
Figura A. 1. System Builder DE2i-150 Altera®
Figura A. 2. Pinagem DE2i-150 Altera®
66
Figura A. 3. Vista Topo Cyclone IV GX DE2i-150 Altera®
Figura A. 4. Kit de Desenvolvimento Altera® De2i-150 Terasic
67
Figura A. 5. Análise de Tempo de Hardware do NIOS II® FPGA
Figura A. 6. Console NIOS II® com a Análise de tempo de Hardware
68
Figura A. 7. Modelsim: Waveform do Processamento de Imagens, Cálculo da Convolução
Figura A. 8. Máquina de Estados do Hardware de Aquisição de Dados
69
Figura A. 9. Hardware ACD
70
Figura A. 10. Hardware de Aquisição de Dados
71
Figura A. 11.Módulos de Convolução, Filtragem e UART do Hardware ACD
72
APÊNDICE B - CÓDIGOS EM VHDL
Código VHDL do Hardware ACD
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
library std;
use std.textio.all;
use IEEE.NUMERIC_STD.ALL;
entity CONV_TOP is
Port ( CLOCK_50 : in STD_LOGIC;
key : in STD_LOGIC_vector(3 downto 0);
LEDR: out STD_LOGIC_VECTOR(17 downto 0);
LEDG: out STD_LOGIC_VECTOR(7 downto 0);
HEX0, HEX1,HEX2, HEX3,HEX4, HEX5,HEX6, HEX7 : out
std_logic_vector(6 downto 0);
UART_TXD: OUT STD_LOGIC;
UART_RXD: IN STD_LOGIC);
end CONV_TOP;
architecture Behavioral of CONV_TOP is
COMPONENT PrjReadWriteMemory
PORT(
clk : in std_logic; -- barramentos de dados e
endereço --
data_out : buffer std_logic_vector(7 downto 0); --
mostra os dados lidos da memoria
status : out std_logic_vector(4 downto 0)); -- para
debug mostra os estados
END COMPONENT;
COMPONENT FIFO_512
PORT(
reset : IN std_logic;
clk : IN std_logic;
r : IN std_logic_vector(0 to 0);
w : IN std_logic_vector(0 to 0);
d : IN std_logic_vector(7 downto 0);
empty : OUT std_logic;
full : OUT std_logic;
q : OUT std_logic_vector(7 downto 0)
);
END COMPONENT;
COMPONENT shift_reg
PORT(
clk : IN std_logic;
73
reset : IN std_logic;
data_in : IN std_logic_vector(7 downto 0);
r_1 : OUT std_logic_vector(7 downto 0);
r_2 : OUT std_logic_vector(7 downto 0);
r_3 : OUT std_logic_vector(7 downto 0);
data_out : OUT std_logic_vector(7 downto 0)
);
END COMPONENT;
COMPONENT FIFO_512_2
PORT(
reset : IN std_logic;
clk : IN std_logic;
r : IN std_logic_vector(0 to 0);
w : IN std_logic_vector(0 to 0);
d : IN std_logic_vector(7 downto 0);
empty : OUT std_logic;
full : OUT std_logic;
q : OUT std_logic_vector(7 downto 0)
);
END COMPONENT;
COMPONENT Filtro_gaussiano3x3
PORT(
clk : IN std_logic;
a11 : IN std_logic_vector(7 downto 0);
a12 : IN std_logic_vector(7 downto 0);
a13 : IN std_logic_vector(7 downto 0);
a21 : IN std_logic_vector(7 downto 0);
a22 : IN std_logic_vector(7 downto 0);
a23 : IN std_logic_vector(7 downto 0);
a31 : IN std_logic_vector(7 downto 0);
a32 : IN std_logic_vector(7 downto 0);
a33 : IN std_logic_vector(7 downto 0);
result : OUT std_logic_vector(7 downto 0)
);
END COMPONENT;
COMPONENT UART
PORT(
CLOCK: IN STD_LOGIC;
DADOS: IN STD_LOGIC_VECTOR(7 downto 0);
ENVIA: IN STD_LOGIC; -- COMO UM KEY DE PULSO
UART_TXD2:OUT STD_LOGIC;
UART_RXD2:IN STD_LOGIC
);
END COMPONENT UART;
COMPONENT hexssd
PORT (
input : IN std_logic_vector(3 downto 0);
output: OUT std_logic_vector(6 downto 0)
);
END COMPONENT;
74
signal reset: std_logic;
signal result: STD_LOGIC_VECTOR(7 downto 0);
SIGNAL q: std_logic_vector(7 downto 0); --,result
signal full_1,full_2,empty_1,empty_2 : std_logic;
signal r1,w1,r2,w2 : std_logic_vector(0 downto 0) := (others =>'0');
signal data_in1,data_in2,data_in3,data_in4,data_in5 :
std_logic_vector(7 downto 0):=(others =>'0');
signal data_out1,data_out2,data_out3,data_out4,data_out5:
std_logic_vector(7 downto 0):=(others =>'0');
--signal data_sai1,data_sai2,data_sai3,data_sai4,data_sai5:
std_logic_vector(7 downto 0):=(others =>'0');
signal data_out: std_logic_vector(7 downto 0):=(others =>'0');
SIGNAL status: std_logic_vector(4 downto 0);
signal a11,a12,a13,a21,a22,a23,a31,a32,a33 : std_logic_vector(7 downto
0):=(others =>'0');
-- bloco de declaracao de variaveis , funcoes e procedimentos
--
type estado is (busca,decodifica,executa,inicializa, parado,
temporario);
signal enderram : integer range 0 to 262143 :=0; -- endereco da ram
signal std : estado :=parado;
signal wren : std_logic := '0';
signal data : unsigned(7 downto 0) := (others => '0');
--file fsaida : text open write_mode is "saida.txt";
subtype word_t is std_logic_vector(7 downto 0);
type imagem_t is array(255 downto 0) of word_t;
signal img : imagem_t;
signal clkgeral : std_LOGIC:='0';
signal envia : std_LOGIC:='0';
signal permite_envia : std_LOGIC:='0';
--Mostra no display
signal counter_super_mega_power: std_logic_vector(31 downto 0);
component altsyncram
generic (
clock_enable_input_a : string;
clock_enable_output_a : string;
init_file : string;
intended_device_family : string;
lpm_hint : string;
lpm_type : string;
numwords_a : natural;
operation_mode : string;
outdata_aclr_a : string;
outdata_reg_a : string;
power_up_uninitialized : string;
ram_block_type : string;
read_during_write_mode_port_a : string;
widthad_a : natural;
75
width_a : natural;
width_byteena_a : natural);
port (
address_a : in std_logic_vector (17 downto 0);
clock0 : in std_logic ;
data_a : in std_logic_vector (7 downto 0);
wren_a : in std_logic ;
q_a : out std_logic_vector (7 downto 0));
end component;
begin
altsyncram_component : altsyncram
generic map (
clock_enable_input_a => "bypass",
clock_enable_output_a => "bypass",
init_file => "saidamif.mif",
intended_device_family => "cyclone iv e",
lpm_hint => "enable_runtime_mod=yes,instance_name=mem1",
lpm_type => "altsyncram",
numwords_a => 262144,
operation_mode => "single_port",
outdata_aclr_a => "none",
outdata_reg_a => "unregistered",
power_up_uninitialized => "false",
ram_block_type => "m9k",
read_during_write_mode_port_a => "new_data_no_nbe_read",
widthad_a => 18,
width_a => 8,
width_byteena_a => 1
)
port map (
address_a => std_LOGIC_VECTOR(to_unsigned(enderram,18)),
clock0 => clkgeral,
data_a => std_logic_vector(data),
wren_a => wren,
q_a => data_out
);
data_in2<= data_out1;
data_in3<= data_out2;
data_in4<= data_out3;
data_in5<= data_out4;
reset <= not key(0);
Shift_1: shift_reg PORT MAP(
clk => clkgeral,
reset => reset,
r_1 => a11,
r_2 => a12,
r_3 => a13,
data_in => data_in1,
data_out => data_out1
76
);
FIFO_1 : FIFO_512 PORT MAP(
reset => reset,
clk => clkgeral,
r => r1,
w => w1,
empty => empty_1,
full => full_1,
d => data_in2, -- data_in1
q => data_out2 -- data_in2
);
Shift_2: shift_reg PORT MAP(
clk => clkgeral,
reset => reset,
r_1 => a21,
r_2 => a22,
r_3 => a23,
data_in => data_in3,--data_in2,
data_out => data_out3--data_out2
);
FIFO_2 : FIFO_512_2 PORT MAP(
reset => reset,
clk => clkgeral,
r => r2,
w => w2,
empty => empty_2,
full => full_2,
d => data_in4,--data_in2,
q => data_out4--data_in3
);
Shift_3: shift_reg PORT MAP(
clk => clkgeral,
reset => reset,
r_1 => a31,
r_2 => a32,
r_3 => a33,
data_in => data_in5,--data_in3,
data_out => data_out5--data_out3
);
gaussiano3x3: Filtro_gaussiano3x3 PORT MAP(
clk => clkgeral,
a11 => a11,
a12 => a12,
a13 => a13,
a21 => a21,
a22 => a22,
a23 => a23,
a31 => a31,
a32 => a32,
a33 => a33,
result => result
);
77
LEDR(7 downto 0) <= result;
LEDR(17 downto 10) <= data_out;
LEDG(0) <= envia;
LEDG(1) <= clkgeral;
serial: UART PORT MAP(
CLOCK => CLOCK_50,
DADOS => result, --data_out, --result
ENVIA => clkgeral and permite_envia, --envia
UART_TXD2 => UART_TXD,
UART_RXD2 => UART_RXD
);
process(CLOCK_50)
variable contador: integer:=0;
begin
if(rising_edge(CLOCK_50)) then
contador :=contador+1;
if (contador>2500) then
clkgeral<=not clkgeral;
contador:=0;
end if;
end if;
end process;
process(clkgeral)
variable contador: integer range 0 to 4:=0;
begin
if(rising_edge(clkgeral)) then
case (contador) is
when 0 =>
envia <= '0';
when 1 =>
envia <= '0';
when 2 =>
envia <= '0';
when 3 =>
envia <= '0';
when 4 =>
envia <= '1';
contador:=1; --1
end case;
contador :=contador+1;
end if;
end process;
process(clkgeral)
variable i : integer ;
begin
78
if (clkgeral 'event and clkgeral ='1') then -- sempre na subida
do clock
case (std) is
when inicializa =>
wren <= '0';
std <= busca;
enderram <= 0;
status <= std_LOGIC_VECTOR(to_unsigned(0,5));
permite_envia<= '0';
when busca =>
std <= decodifica ;
status <= std_LOGIC_VECTOR(to_unsigned(1,5));
i:= enderram;
img(i) <= data_out;
permite_envia<= '0';
when decodifica =>
std <= executa ;
status <= std_LOGIC_VECTOR(to_unsigned(2,5));
permite_envia<= '0';
when executa =>
permite_envia <= '1';
if enderram = 262143 then
std <= parado ; -- muda estado para inicializa
permite_envia<= '0';
else
enderram <= enderram + 1; -- endereça o próximo
dado em ram
std <= busca ;
end if;
status <= std_LOGIC_VECTOR(to_unsigned(3,5));
when parado =>
if(key(3) = '0') then
std<=temporario;
end if;
when temporario =>
if(key(3) = '1') then
std<=inicializa;
end if;
end case;
end if;
end process;
process(CLOCK_50)
begin
if (rising_edge(CLOCK_50)) then
--data_in1<= std_logic_vector(unsigned(data_in1) +1);
data_in1<=data_out;
if full_1='0' then
r1<="0";
w1<="1";
79
else
r1<="1";
w1<="1";
end if;
if full_2='0' then
r2<="0";
w2<="1";
else
r2<="1";
w2<="1";
end if;
end if;
end process;
process(clkgeral)
begin
if (clkgeral 'event and clkgeral ='1') then
if (std /= parado) then
counter_super_mega_power <= counter_super_mega_power + 1;
end if;
end if;
end process;
u7: hexssd port map (counter_super_mega_power(31 downto 28), hex7) ;
u6: hexssd port map (counter_super_mega_power(27 downto 24), hex6) ;
u5: hexssd port map (counter_super_mega_power(23 downto 20), hex5) ;
u4: hexssd port map (counter_super_mega_power(19 downto 16), hex4) ;
u3: hexssd port map (counter_super_mega_power(15 downto 12), hex3) ;
u2: hexssd port map (counter_super_mega_power(11 downto 8), hex2) ;
u1: hexssd port map (counter_super_mega_power(7 downto 4), hex1) ;
u0: hexssd port map (counter_super_mega_power(3 downto 0), hex0) ;
end Behavioral;
Código VHDL do Registrador
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity shift_reg is
Port ( clk : in STD_LOGIC;
reset: in STD_LOGIC;
r_1 : out STD_LOGIC_VECTOR(7 downto 0);
r_2 : out STD_LOGIC_VECTOR(7 downto 0);
r_3 : out STD_LOGIC_VECTOR(7 downto 0);
data_in : in STD_LOGIC_VECTOR(7 downto 0);
80
data_out : out STD_LOGIC_VECTOR(7 downto 0));
end shift_reg;
architecture Behavioral of shift_reg is
-- m quantidade de valores de saida
-- arquitetura para criar um registrador
constant m : integer := 3;
subtype wrdtype is std_logic_vector(7 downto 0);
type regtype is array(0 to m-1) of wrdtype;
signal reg : regtype;
begin
shift : process(reset, clk)
begin
if reset = '1' then
-- zerando o registrador, inicializando com zero
for j in 0 to m - 1 loop
reg(j) <= (others => '0');
end loop;
elsif rising_edge(clk) then
reg(2) <= reg(1);
reg(1) <= reg(0);
reg(0) <= data_in;
end if;
end process;
data_out <= reg(2);
r_1 <= reg(0);
r_2 <= reg(1);
r_3 <= reg(2);
end Behavioral;
Código VHDL da DUAL RAM
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity FIFO_512 is
port (
reset, clk : in std_logic;
r,w : in std_logic_vector(0 downto 0);
empty, full : out std_logic;
d : in std_logic_vector(7 downto 0);
q : out std_logic_vector(7 downto 0));
81
end FIFO_512;
architecture Behavioral of FIFO_512 is
COMPONENT Fifo_8bits
PORT (
clka : IN STD_LOGIC;
wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
addra : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
dina : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
douta : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
clkb : IN STD_LOGIC;
web : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
addrb : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
dinb : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
doutb : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
constant m : integer := 512;
constant n : integer := 8;
signal rcntr, wcntr : std_logic_vector(8 downto 0); -- 2
subtype wrdtype is std_logic_vector(n - 1 downto 0);
type regtype is array(0 to m - 1) of wrdtype;
signal reg : regtype;
signal rw : std_logic_vector(1 downto 0);
signal full_buf, empty_buf : std_logic;
signal douta : std_logic_vector(7 downto 0);
signal rcntr_temp: std_logic_vector(8 downto 0);
begin
rw <= r & w;
F1 : Fifo_8bits
PORT MAP (
clka => clk,
wea => w,
addra => wcntr,
dina => d,
douta => douta,
clkb => clk,
web => (others =>'0'),--r,
addrb => rcntr_temp,
dinb => (others =>'0'),
doutb => q
);
rcntr_temp<= rcntr+1;
seq : process(reset, clk)
begin
-- execucao do algoritmo FIFO, primeiro que entra e o primeiro que
sai
82
if reset = '1' then
rcntr <= (others => '0');
wcntr <= (others => '0');
empty_buf <= '1';
full_buf <= '0';
for j in 0 to m - 1 loop
reg(j) <= (others => '0');
end loop;
elsif falling_edge(clk) then
case rw is
when "11" =>
-- read and write at the same time
rcntr <= rcntr + 1;
wcntr <= wcntr + 1;
reg(conv_integer(wcntr)) <= d;
when "10" =>
-- only read
if empty_buf = '0' then
-- not empty
if (rcntr + 1) = wcntr then
empty_buf <= '1';
end if;
rcntr <= rcntr + 1;
end if;
full_buf <= '0';
when "01" =>
-- only write
empty_buf <= '0';
if full_buf = '0' then
-- not full
reg(conv_integer(wcntr)) <= d;
if (wcntr + 1) = rcntr then
full_buf <= '1';
end if;
wcntr <= wcntr + 1;
end if;
when others =>
null;
end case;
end if;
end process;
full <= full_buf;
empty <= empty_buf;
end Behavioral;
Código VHDL da Convolução
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
83
entity Filtro_gaussiano3x3 is
Port ( clk : in STD_LOGIC;
a11,a12,a13,a21,a22,a23,a31,a32,a33 : in STD_LOGIC_VECTOR (7
downto 0);
result : out STD_LOGIC_VECTOR (7 downto 0));
end Filtro_gaussiano3x3;
architecture Behavioral of Filtro_gaussiano3x3 is
signal r_temp: std_logic_vector(18 downto 0):=(others =>'0');
signal u_a11: unsigned(18 downto 0):=(others =>'0');
signal u_a12: unsigned(18 downto 0):=(others =>'0');
signal u_a13: unsigned(18 downto 0):=(others =>'0');
signal u_a21: unsigned(18 downto 0):=(others =>'0');
signal u_a22: unsigned(18 downto 0):=(others =>'0');
signal u_a23: unsigned(18 downto 0):=(others =>'0');
signal u_a31: unsigned(18 downto 0):=(others =>'0');
signal u_a32: unsigned(18 downto 0):=(others =>'0');
signal u_a33: unsigned(18 downto 0):=(others =>'0');
begin
process(clk)
begin
if (rising_edge(clk)) then
-- u_a11<=unsigned("000000" & a11 & "00000")+unsigned("00000" &
a11 & "000000")+unsigned("0000" & a11 & "0000000"); -- 224
-- u_a12<=unsigned("00000000000" & a12)+unsigned("000000000" & a12
& "00")+unsigned("000000" & a12 & "00000")+unsigned("00000" & a12 &
"000000")+unsigned("0000" & a12 & "0000000"); -- 229
-- u_a13<=unsigned("000000" & a13 & "00000")+unsigned("00000" &
a13 & "000000")+unsigned("0000" & a13 & "0000000"); -- 224
--
-- u_a21<=unsigned("00000000000" & a21)+unsigned("000000000" & a21
& "00")+unsigned("000000" & a21 & "00000")+unsigned("00000" & a21 &
"000000")+unsigned("0000" & a21 & "0000000"); -- 229
-- u_a22<=unsigned("00000000000" & a22)+unsigned("00000000" & a22
& "000")+unsigned("000000" & a22 & "00000")+unsigned("00000" & a22 &
"000000")+unsigned("0000" & a22 & "0000000"); -- 233 --> 1 + 8 + 32 + 64 +
128 = 233
-- u_a23<=unsigned("00000000000" & a23)+unsigned("000000000" & a23
& "00")+unsigned("000000" & a23 & "00000")+unsigned("00000" & a23 &
"000000")+unsigned("0000" & a23 & "0000000"); -- 229
--
-- u_a31<=unsigned("000000" & a31 & "00000")+unsigned("00000" &
a31 & "000000")+unsigned("0000" & a31 & "0000000"); -- 224
-- u_a32<=unsigned("00000000000" & a32)+unsigned("000000000" & a32
& "00")+unsigned("000000" & a32 & "00000")+unsigned("00000" & a32 &
"000000")+unsigned("0000" & a32 & "0000000"); -- 229
-- u_a33<=unsigned("000000" & a33 & "00000")+unsigned("00000" &
a33 & "000000")+unsigned("0000" & a33 & "0000000"); -- 224
u_a11<=unsigned("0000000" & a11 & "0000")+unsigned("000000" &
a11 & "00000")+unsigned("00000" & a11 & "000000"); -- 112
84
u_a12<=unsigned("0000000000" & a12 & "0")+unsigned("0000000" &
a12 & "0000")+unsigned("000000" & a12 & "00000")+unsigned("00000" & a12 &
"000000"); -- 114
u_a13<=unsigned("0000000" & a13 & "0000")+unsigned("000000" &
a13 & "00000")+unsigned("00000" & a13 & "000000"); -- 112
u_a21<=unsigned("0000000000" & a21 & "0")+unsigned("0000000" &
a21 & "0000")+unsigned("000000" & a21 & "00000")+unsigned("00000" & a21 &
"000000"); -- 114
u_a22<=unsigned("000000000" & a22 & "00")+unsigned("0000000" &
a22 & "0000")+unsigned("000000" & a22 & "00000")+unsigned("00000" & a22 &
"000000"); -- 116
u_a23<=unsigned("0000000000" & a23 & "0")+unsigned("0000000" &
a23 & "0000")+unsigned("000000" & a23 & "00000")+unsigned("00000" & a23 &
"000000"); -- 114
u_a31<=unsigned("0000000" & a31 & "0000")+unsigned("000000" &
a31 & "00000")+unsigned("00000" & a31 & "000000"); -- 112
u_a32<=unsigned("0000000000" & a32 & "0")+unsigned("0000000" &
a32 & "0000")+unsigned("000000" & a32 & "00000")+unsigned("00000" & a32 &
"000000"); -- 114
u_a33<=unsigned("0000000" & a33 & "0000")+unsigned("000000" &
a33 & "00000")+unsigned("00000" & a33 & "000000"); -- 112
r_temp<= std_logic_vector(u_a11 + u_a12 + u_a13 + u_a21 + u_a22
+ u_a23 + u_a31 + u_a32 + u_a33);
end if;
end process;
--result<= r_temp(18 downto 11); -- divisao da matriz para gerar o kernel
antigo
result<= r_temp(17 downto 10); -- divisao da matriz para gerar o kernel
end Behavioral;
Código VHDL do Controlador da RAM
library altera;
use altera.altera_europa_support_lib.all;
library altera_mf;
use altera_mf.altera_mf_components.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity DDRSDRAM_controller_phy is
85
port (
-- inputs:
signal dqs_delay_ctrl_import : IN STD_LOGIC_VECTOR (5
DOWNTO 0);
signal dqs_offset_delay_ctrl : IN STD_LOGIC_VECTOR (5
DOWNTO 0);
signal global_reset_n : IN STD_LOGIC;
signal hc_scan_ck : IN STD_LOGIC;
signal hc_scan_din : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal hc_scan_enable_access : IN STD_LOGIC;
signal hc_scan_enable_dm : IN STD_LOGIC_VECTOR (0 DOWNTO
0);
signal hc_scan_enable_dq : IN STD_LOGIC_VECTOR (7 DOWNTO
0);
signal hc_scan_enable_dqs : IN STD_LOGIC_VECTOR (0 DOWNTO
0);
signal hc_scan_enable_dqs_config : IN STD_LOGIC_VECTOR (0
DOWNTO 0);
signal hc_scan_update : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal local_address : IN STD_LOGIC_VECTOR (24 DOWNTO 0);
signal local_autopch_req : IN STD_LOGIC;
signal local_be : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
signal local_burstbegin : IN STD_LOGIC;
signal local_multicast_req : IN STD_LOGIC;
signal local_read_req : IN STD_LOGIC;
signal local_refresh_chip : IN STD_LOGIC;
signal local_refresh_req : IN STD_LOGIC;
signal local_self_rfsh_chip : IN STD_LOGIC;
signal local_self_rfsh_req : IN STD_LOGIC;
signal local_size : IN STD_LOGIC_VECTOR (2 DOWNTO 0);
signal local_wdata : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
signal local_write_req : IN STD_LOGIC;
signal oct_ctl_rs_value : IN STD_LOGIC_VECTOR (13 DOWNTO
0);
signal oct_ctl_rt_value : IN STD_LOGIC_VECTOR (13 DOWNTO
0);
signal pll_phasecounterselect : IN STD_LOGIC_VECTOR (3
DOWNTO 0);
signal pll_phasestep : IN STD_LOGIC;
signal pll_phaseupdown : IN STD_LOGIC;
signal pll_reconfig : IN STD_LOGIC;
signal pll_reconfig_counter_param : IN STD_LOGIC_VECTOR (2
DOWNTO 0);
signal pll_reconfig_counter_type : IN STD_LOGIC_VECTOR (3
DOWNTO 0);
signal pll_reconfig_data_in : IN STD_LOGIC_VECTOR (8
DOWNTO 0);
signal pll_reconfig_enable : IN STD_LOGIC;
signal pll_reconfig_read_param : IN STD_LOGIC;
signal pll_reconfig_soft_reset_en_n : IN STD_LOGIC;
signal pll_reconfig_write_param : IN STD_LOGIC;
signal pll_ref_clk : IN STD_LOGIC;
signal soft_reset_n : IN STD_LOGIC;
-- outputs:
signal aux_full_rate_clk : OUT STD_LOGIC;
signal aux_half_rate_clk : OUT STD_LOGIC;
86
signal aux_scan_clk : OUT STD_LOGIC;
signal aux_scan_clk_reset_n : OUT STD_LOGIC;
signal dll_reference_clk : OUT STD_LOGIC;
signal dqs_delay_ctrl_export : OUT STD_LOGIC_VECTOR (5
DOWNTO 0);
signal ecc_interrupt : OUT STD_LOGIC;
signal hc_scan_dout : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
signal local_init_done : OUT STD_LOGIC;
signal local_power_down_ack : OUT STD_LOGIC;
signal local_rdata : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
signal local_rdata_valid : OUT STD_LOGIC;
signal local_ready : OUT STD_LOGIC;
signal local_refresh_ack : OUT STD_LOGIC;
signal local_self_rfsh_ack : OUT STD_LOGIC;
signal mem_addr : OUT STD_LOGIC_VECTOR (12 DOWNTO 0);
signal mem_ba : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
signal mem_cas_n : OUT STD_LOGIC;
signal mem_cke : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_clk : INOUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_clk_n : INOUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_cs_n : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_dm : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_dq : INOUT STD_LOGIC_VECTOR (7 DOWNTO 0);
signal mem_dqs : INOUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_dqsn : INOUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_odt : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_ras_n : OUT STD_LOGIC;
signal mem_reset_n : OUT STD_LOGIC;
signal mem_we_n : OUT STD_LOGIC;
signal phy_clk : OUT STD_LOGIC;
signal pll_phase_done : OUT STD_LOGIC;
signal pll_reconfig_busy : OUT STD_LOGIC;
signal pll_reconfig_clk : OUT STD_LOGIC;
signal pll_reconfig_data_out : OUT STD_LOGIC_VECTOR (8
DOWNTO 0);
signal pll_reconfig_reset : OUT STD_LOGIC;
signal reset_phy_clk_n : OUT STD_LOGIC;
signal reset_request_n : OUT STD_LOGIC
);
end entity DDRSDRAM_controller_phy;
architecture europa of DDRSDRAM_controller_phy is
component DDRSDRAM_alt_mem_ddrx_controller_top is
PORT (
signal afi_we_n : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal local_init_done : OUT STD_LOGIC;
signal afi_ctl_long_idle : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_ba : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
signal afi_cas_n : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ecc_interrupt : OUT STD_LOGIC;
signal afi_ctl_refresh_done : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal csr_waitrequest : OUT STD_LOGIC;
signal afi_rdata_en_full : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_cal_byte_lane_sel_n : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal csr_rdata : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
signal afi_ras_n : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
87
signal afi_cke : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_mem_clk_disable : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_dm : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
signal csr_rdata_valid : OUT STD_LOGIC;
signal afi_addr : OUT STD_LOGIC_VECTOR (12 DOWNTO 0);
signal afi_odt : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_rst_n : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_rdata_en : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal local_ready : OUT STD_LOGIC;
signal afi_dqs_burst : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal local_readdata : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
signal afi_wdata_valid : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_cal_req : OUT STD_LOGIC;
signal local_powerdn_ack : OUT STD_LOGIC;
signal local_self_rfsh_ack : OUT STD_LOGIC;
signal local_refresh_ack : OUT STD_LOGIC;
signal afi_wdata : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
signal afi_cs_n : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal local_readdatavalid : OUT STD_LOGIC;
signal local_write : IN STD_LOGIC;
signal local_autopch_req : IN STD_LOGIC;
signal afi_cal_fail : IN STD_LOGIC;
signal local_beginbursttransfer : IN STD_LOGIC;
signal local_refresh_req : IN STD_LOGIC;
signal reset_n : IN STD_LOGIC;
signal csr_be : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
signal local_multicast : IN STD_LOGIC;
signal half_clk : IN STD_LOGIC;
signal local_priority : IN STD_LOGIC;
signal local_self_rfsh_chip : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_rdata : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
signal afi_cal_success : IN STD_LOGIC;
signal csr_addr : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
signal local_read : IN STD_LOGIC;
signal local_address : IN STD_LOGIC_VECTOR (24 DOWNTO 0);
signal afi_seq_busy : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal local_byteenable : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
signal local_self_rfsh_req : IN STD_LOGIC;
signal local_refresh_chip : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal local_powerdn_req : IN STD_LOGIC;
signal csr_read_req : IN STD_LOGIC;
signal csr_beginbursttransfer : IN STD_LOGIC;
signal local_burstcount : IN STD_LOGIC_VECTOR (2 DOWNTO 0);
signal local_writedata : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
signal afi_wlat : IN STD_LOGIC_VECTOR (4 DOWNTO 0);
signal csr_wdata : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
signal afi_rdata_valid : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal clk : IN STD_LOGIC;
signal csr_write_req : IN STD_LOGIC;
signal csr_burst_count : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal afi_rlat : IN STD_LOGIC_VECTOR (4 DOWNTO 0)
);
end component DDRSDRAM_alt_mem_ddrx_controller_top;
component DDRSDRAM_phy is
PORT (
signal mem_cke : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_cal_fail : OUT STD_LOGIC;
88
signal mem_addr : OUT STD_LOGIC_VECTOR (12 DOWNTO 0);
signal mem_dm : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal aux_full_rate_clk : OUT STD_LOGIC;
signal mem_dq : INOUT STD_LOGIC_VECTOR (7 DOWNTO 0);
signal mem_ras_n : OUT STD_LOGIC;
signal dbg_rd_data : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
signal mem_cs_n : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_ba : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
signal mem_reset_n : OUT STD_LOGIC;
signal dbg_waitrequest : OUT STD_LOGIC;
signal ctl_rdata : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
signal ctl_wlat : OUT STD_LOGIC_VECTOR (4 DOWNTO 0);
signal ctl_rdata_valid : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_clk : OUT STD_LOGIC;
signal aux_half_rate_clk : OUT STD_LOGIC;
signal ctl_cal_success : OUT STD_LOGIC;
signal mem_dqs_n : INOUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_we_n : OUT STD_LOGIC;
signal mem_odt : OUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_cas_n : OUT STD_LOGIC;
signal ctl_rlat : OUT STD_LOGIC_VECTOR (4 DOWNTO 0);
signal mem_clk : INOUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_reset_n : OUT STD_LOGIC;
signal reset_request_n : OUT STD_LOGIC;
signal mem_dqs : INOUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal mem_clk_n : INOUT STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_doing_rd : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_dm : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
signal soft_reset_n : IN STD_LOGIC;
signal dbg_clk : IN STD_LOGIC;
signal ctl_cal_req : IN STD_LOGIC;
signal global_reset_n : IN STD_LOGIC;
signal dbg_cs : IN STD_LOGIC;
signal ctl_mem_clk_disable : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_rst_n : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_we_n : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_addr : IN STD_LOGIC_VECTOR (12 DOWNTO 0);
signal ctl_odt : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
signal dbg_addr : IN STD_LOGIC_VECTOR (12 DOWNTO 0);
signal ctl_wdata : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
signal dbg_wr : IN STD_LOGIC;
signal ctl_cke : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_dqs_burst : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal pll_ref_clk : IN STD_LOGIC;
signal ctl_cs_n : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_cas_n : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal ctl_cal_byte_lane_sel_n : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal dbg_rd : IN STD_LOGIC;
signal ctl_ras_n : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal dbg_wr_data : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
signal ctl_wdata_valid : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
signal dbg_reset_n : IN STD_LOGIC
);
end component DDRSDRAM_phy;
signal afi_addr : STD_LOGIC_VECTOR (12 DOWNTO 0);
signal afi_ba : STD_LOGIC_VECTOR (1 DOWNTO 0);
89
signal afi_cas_n : STD_LOGIC;
signal afi_cke : STD_LOGIC;
signal afi_cs_n : STD_LOGIC;
signal afi_ctl_long_idle : STD_LOGIC;
signal afi_ctl_refresh_done : STD_LOGIC;
signal afi_dm : STD_LOGIC_VECTOR (1 DOWNTO 0);
signal afi_dqs_burst : STD_LOGIC;
signal afi_odt : STD_LOGIC;
signal afi_ras_n : STD_LOGIC;
signal afi_rdata : STD_LOGIC_VECTOR (15 DOWNTO 0);
signal afi_rdata_en : STD_LOGIC;
signal afi_rdata_en_full : STD_LOGIC;
signal afi_rdata_valid : STD_LOGIC;
signal afi_rst_n : STD_LOGIC;
signal afi_wdata : STD_LOGIC_VECTOR (15 DOWNTO 0);
signal afi_wdata_valid : STD_LOGIC;
signal afi_we_n : STD_LOGIC;
signal afi_wlat : STD_LOGIC_VECTOR (4 DOWNTO 0);
signal csr_rdata_sig : STD_LOGIC_VECTOR (31 DOWNTO 0);
signal csr_rdata_valid_sig : STD_LOGIC;
signal csr_waitrequest_sig : STD_LOGIC;
signal ctl_cal_byte_lane_sel_n : STD_LOGIC;
signal ctl_cal_fail : STD_LOGIC;
signal ctl_cal_req : STD_LOGIC;
signal ctl_cal_success : STD_LOGIC;
signal ctl_clk : STD_LOGIC;
signal ctl_mem_clk_disable : STD_LOGIC;
signal ctl_rlat : STD_LOGIC_VECTOR (4 DOWNTO 0);
signal dbg_rd_data_sig : STD_LOGIC_VECTOR (31 DOWNTO 0);
signal dbg_waitrequest_sig : STD_LOGIC;
signal internal_aux_full_rate_clk : STD_LOGIC;
signal internal_aux_half_rate_clk : STD_LOGIC;
signal internal_ecc_interrupt : STD_LOGIC;
signal internal_local_init_done : STD_LOGIC;
signal internal_local_power_down_ack : STD_LOGIC;
signal internal_local_rdata : STD_LOGIC_VECTOR (15 DOWNTO
0);
signal internal_local_rdata_valid : STD_LOGIC;
signal internal_local_ready : STD_LOGIC;
signal internal_local_refresh_ack : STD_LOGIC;
signal internal_local_self_rfsh_ack : STD_LOGIC;
signal internal_mem_addr : STD_LOGIC_VECTOR (12 DOWNTO 0);
signal internal_mem_ba : STD_LOGIC_VECTOR (1 DOWNTO 0);
signal internal_mem_cas_n : STD_LOGIC;
signal internal_mem_cke : STD_LOGIC_VECTOR (0 DOWNTO 0);
signal internal_mem_cs_n : STD_LOGIC_VECTOR (0 DOWNTO 0);
signal internal_mem_dm : STD_LOGIC_VECTOR (0 DOWNTO 0);
signal internal_mem_odt : STD_LOGIC_VECTOR (0 DOWNTO 0);
signal internal_mem_ras_n : STD_LOGIC;
signal internal_mem_reset_n : STD_LOGIC;
signal internal_mem_we_n : STD_LOGIC;
signal internal_reset_request_n : STD_LOGIC;
signal reset_ctl_clk_n : STD_LOGIC;
begin
phy_clk <= ctl_clk;
90
reset_phy_clk_n <= reset_ctl_clk_n;
DDRSDRAM_alt_mem_ddrx_controller_top_inst :
DDRSDRAM_alt_mem_ddrx_controller_top
port map(
afi_addr => afi_addr,
afi_ba => afi_ba,
afi_cal_byte_lane_sel_n(0) => ctl_cal_byte_lane_sel_n,
afi_cal_fail => ctl_cal_fail,
afi_cal_req => ctl_cal_req,
afi_cal_success => ctl_cal_success,
afi_cas_n(0) => afi_cas_n,
afi_cke(0) => afi_cke,
afi_cs_n(0) => afi_cs_n,
afi_ctl_long_idle(0) => afi_ctl_long_idle,
afi_ctl_refresh_done(0) => afi_ctl_refresh_done,
afi_dm => afi_dm,
afi_dqs_burst(0) => afi_dqs_burst,
afi_mem_clk_disable(0) => ctl_mem_clk_disable,
afi_odt(0) => afi_odt,
afi_ras_n(0) => afi_ras_n,
afi_rdata => afi_rdata,
afi_rdata_en(0) => afi_rdata_en,
afi_rdata_en_full(0) => afi_rdata_en_full,
afi_rdata_valid => A_TOSTDLOGICVECTOR(afi_rdata_valid),
afi_rlat => ctl_rlat,
afi_rst_n(0) => afi_rst_n,
afi_seq_busy => A_TOSTDLOGICVECTOR(std_logic'('0')),
afi_wdata => afi_wdata,
afi_wdata_valid(0) => afi_wdata_valid,
afi_we_n(0) => afi_we_n,
afi_wlat => afi_wlat,
clk => ctl_clk,
csr_addr => std_logic_vector'("0000000000000000"),
csr_be => std_logic_vector'("0000"),
csr_beginbursttransfer => std_logic'('0'),
csr_burst_count => A_TOSTDLOGICVECTOR(std_logic'('0')),
csr_rdata => csr_rdata_sig,
csr_rdata_valid => csr_rdata_valid_sig,
csr_read_req => std_logic'('0'),
csr_waitrequest => csr_waitrequest_sig,
csr_wdata =>
std_logic_vector'("00000000000000000000000000000000"),
csr_write_req => std_logic'('0'),
ecc_interrupt => internal_ecc_interrupt,
half_clk => internal_aux_half_rate_clk,
local_address => local_address,
local_autopch_req => local_autopch_req,
local_beginbursttransfer => local_burstbegin,
local_burstcount => local_size,
local_byteenable => local_be,
local_init_done => internal_local_init_done,
local_multicast => local_multicast_req,
local_powerdn_ack => internal_local_power_down_ack,
local_powerdn_req => std_logic'('0'),
local_priority => std_logic'('1'),
local_read => local_read_req,
local_readdata => internal_local_rdata,
91
local_readdatavalid => internal_local_rdata_valid,
local_ready => internal_local_ready,
local_refresh_ack => internal_local_refresh_ack,
local_refresh_chip => A_TOSTDLOGICVECTOR(local_refresh_chip),
local_refresh_req => local_refresh_req,
local_self_rfsh_ack => internal_local_self_rfsh_ack,
local_self_rfsh_chip =>
A_TOSTDLOGICVECTOR(local_self_rfsh_chip),
local_self_rfsh_req => local_self_rfsh_req,
local_write => local_write_req,
local_writedata => local_wdata,
reset_n => reset_ctl_clk_n
);
DDRSDRAM_phy_inst : DDRSDRAM_phy
port map(
aux_full_rate_clk => internal_aux_full_rate_clk,
aux_half_rate_clk => internal_aux_half_rate_clk,
ctl_addr => afi_addr,
ctl_ba => afi_ba,
ctl_cal_byte_lane_sel_n =>
A_TOSTDLOGICVECTOR(ctl_cal_byte_lane_sel_n),
ctl_cal_fail => ctl_cal_fail,
ctl_cal_req => ctl_cal_req,
ctl_cal_success => ctl_cal_success,
ctl_cas_n => A_TOSTDLOGICVECTOR(afi_cas_n),
ctl_cke => A_TOSTDLOGICVECTOR(afi_cke),
ctl_clk => ctl_clk,
ctl_cs_n => A_TOSTDLOGICVECTOR(afi_cs_n),
ctl_dm => afi_dm,
ctl_doing_rd => A_TOSTDLOGICVECTOR(afi_rdata_en),
ctl_dqs_burst => A_TOSTDLOGICVECTOR(afi_dqs_burst),
ctl_mem_clk_disable => A_TOSTDLOGICVECTOR(ctl_mem_clk_disable),
ctl_odt => A_TOSTDLOGICVECTOR(afi_odt),
ctl_ras_n => A_TOSTDLOGICVECTOR(afi_ras_n),
ctl_rdata => afi_rdata,
ctl_rdata_valid(0) => afi_rdata_valid,
ctl_reset_n => reset_ctl_clk_n,
ctl_rlat => ctl_rlat,
ctl_rst_n => A_TOSTDLOGICVECTOR(afi_rst_n),
ctl_wdata => afi_wdata,
ctl_wdata_valid => A_TOSTDLOGICVECTOR(afi_wdata_valid),
ctl_we_n => A_TOSTDLOGICVECTOR(afi_we_n),
ctl_wlat => afi_wlat,
dbg_addr => std_logic_vector'("0000000000000"),
dbg_clk => ctl_clk,
dbg_cs => std_logic'('0'),
dbg_rd => std_logic'('0'),
dbg_rd_data => dbg_rd_data_sig,
dbg_reset_n => reset_ctl_clk_n,
dbg_waitrequest => dbg_waitrequest_sig,
dbg_wr => std_logic'('0'),
dbg_wr_data =>
std_logic_vector'("00000000000000000000000000000000"),
global_reset_n => global_reset_n,
mem_addr => internal_mem_addr,
mem_ba => internal_mem_ba,
92
mem_cas_n => internal_mem_cas_n,
mem_cke(0) => internal_mem_cke(0),
mem_clk(0) => mem_clk(0),
mem_clk_n(0) => mem_clk_n(0),
mem_cs_n(0) => internal_mem_cs_n(0),
mem_dm(0) => internal_mem_dm(0),
mem_dq => mem_dq,
mem_dqs(0) => mem_dqs(0),
mem_dqs_n(0) => mem_dqsn(0),
mem_odt(0) => internal_mem_odt(0),
mem_ras_n => internal_mem_ras_n,
mem_reset_n => internal_mem_reset_n,
mem_we_n => internal_mem_we_n,
pll_ref_clk => pll_ref_clk,
reset_request_n => internal_reset_request_n,
soft_reset_n => soft_reset_n
);
--<< start europa
--vhdl renameroo for output signals
aux_full_rate_clk <= internal_aux_full_rate_clk;
--vhdl renameroo for output signals
aux_half_rate_clk <= internal_aux_half_rate_clk;
--vhdl renameroo for output signals
ecc_interrupt <= internal_ecc_interrupt;
--vhdl renameroo for output signals
local_init_done <= internal_local_init_done;
--vhdl renameroo for output signals
local_power_down_ack <= internal_local_power_down_ack;
--vhdl renameroo for output signals
local_rdata <= internal_local_rdata;
--vhdl renameroo for output signals
local_rdata_valid <= internal_local_rdata_valid;
--vhdl renameroo for output signals
local_ready <= internal_local_ready;
--vhdl renameroo for output signals
local_refresh_ack <= internal_local_refresh_ack;
--vhdl renameroo for output signals
local_self_rfsh_ack <= internal_local_self_rfsh_ack;
--vhdl renameroo for output signals
mem_addr <= internal_mem_addr;
--vhdl renameroo for output signals
mem_ba <= internal_mem_ba;
--vhdl renameroo for output signals
mem_cas_n <= internal_mem_cas_n;
--vhdl renameroo for output signals
mem_cke <= internal_mem_cke;
--vhdl renameroo for output signals
mem_cs_n <= internal_mem_cs_n;
--vhdl renameroo for output signals
mem_dm <= internal_mem_dm;
--vhdl renameroo for output signals
mem_odt <= internal_mem_odt;
--vhdl renameroo for output signals
mem_ras_n <= internal_mem_ras_n;
--vhdl renameroo for output signals
mem_reset_n <= internal_mem_reset_n;
93
--vhdl renameroo for output signals
mem_we_n <= internal_mem_we_n;
--vhdl renameroo for output signals
reset_request_n <= internal_reset_request_n;
end europa;
Código VHDL do Módulo de Memória MIF
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity PrjReadWriteMemory is
port(
clk : in std_logic;
-- barramentos de dados e endereço --
data_out : buffer std_logic_vector(7 downto 0); -- mostra os
dados lidos da memoria
status : out std_logic_vector(4 downto 0)); -- para debug
mostra os estados
end PrjReadWriteMemory;
architecture readwrite of PrjReadWriteMemory is
-- bloco de declaracao de variaveis , funcoes e procedimentos
--
type estado is (busca,decodifica,executa,inicializa);
signal enderram : integer range 0 to 255 :=0; -- endereco da ram
signal std : estado :=inicializa;
signal wren : std_logic := '0';
signal data : unsigned(7 downto 0) := (others => '0');
--file fsaida : text open write_mode is "saida.txt";
subtype word_t is std_logic_vector(7 downto 0);
type imagem_t is array(255 downto 0) of word_t;
signal img : imagem_t;
component altsyncram
generic (
clock_enable_input_a : string;
clock_enable_output_a : string;
init_file : string;
intended_device_family : string;
lpm_hint : string;
lpm_type : string;
numwords_a : natural;
operation_mode : string;
outdata_aclr_a : string;
outdata_reg_a : string;
power_up_uninitialized : string;
ram_block_type : string;
94
read_during_write_mode_port_a : string;
widthad_a : natural;
width_a : natural;
width_byteena_a : natural);
port (
address_a : in std_logic_vector (7 downto 0);
clock0 : in std_logic ;
data_a : in std_logic_vector (7 downto 0);
wren_a : in std_logic ;
q_a : out std_logic_vector (7 downto 0));
end component;
begin
altsyncram_component : altsyncram
generic map (
clock_enable_input_a => "bypass",
clock_enable_output_a => "bypass",
init_file => "imagem.mif",
intended_device_family => "cyclone iv e",
lpm_hint => "enable_runtime_mod=yes,instance_name=mem1",
lpm_type => "altsyncram",
numwords_a => 256,
operation_mode => "single_port",
outdata_aclr_a => "none",
outdata_reg_a => "unregistered",
power_up_uninitialized => "false",
ram_block_type => "m9k",
read_during_write_mode_port_a => "new_data_no_nbe_read",
widthad_a => 8,
width_a => 8,
width_byteena_a => 1
)
port map (
address_a => conv_std_logic_vector(enderram,8),
clock0 => clk,
data_a => std_logic_vector(data),
wren_a => wren,
q_a => data_out
);
process(clk)
variable i : integer ;
begin
if (clk 'event and clk ='1') then -- sempre na subida do clock
case (std) is
when inicializa =>
wren <= '0';
std <= busca;
enderram <= 0;
status <= conv_std_logic_vector(0,5);
when busca =>
std <= decodifica ;
status <= conv_std_logic_vector(1,5);
95
i:= enderram;
img(i) <= data_out;
when decodifica =>
std <= executa ;
status <= conv_std_logic_vector(2,5);
when executa =>
if enderram = 255 then
std <= inicializa ; -- muda estado para
inicializa
else
enderram <= enderram + 1; -- endereça o próximo
dado em ram
std <= busca ;
end if;
status <= conv_std_logic_vector(3,5);
end case;
end if;
end process;
end readwrite;
Código VHDL do Módulo RX
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY RX IS
PORT(
CLK:IN STD_LOGIC;
RX_LINE:IN STD_LOGIC;
DATA:OUT STD_LOGIC_VECTOR(7 downto 0);
BUSY:OUT STD_LOGIC
);
END RX;
ARCHITECTURE MAIN OF RX IS
SIGNAL DATAFLL: STD_LOGIC_VECTOR(9 downto 0);
SIGNAL RX_FLG: STD_LOGIC:='0';
SIGNAL PRSCL: INTEGER RANGE 0 TO 5208:=0;
SIGNAL INDEX: INTEGER RANGE 0 TO 9:=0;
BEGIN
PROCESS(CLK)
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
IF(RX_FLG='0' AND RX_LINE='0')THEN
INDEX<=0;
96
PRSCL<=0;
BUSY<='1';
RX_FLG<='1';
END IF;
IF(RX_FLG='1')THEN
DATAFLL(INDEX)<=RX_LINE;
IF(PRSCL<434)THEN
PRSCL<=PRSCL+1;
ELSE
PRSCL<=0;
END IF;
IF(PRSCL=217)THEN
IF(INDEX<9)THEN
INDEX<=INDEX+1;
ELSE
IF(DATAFLL(0)='0'AND DATAFLL(9)='1')THEN
DATA<=DATAFLL(8 DOWNTO 1);
ELSE
DATA<=(OTHERS=>'0');
END IF;
RX_FLG<='0';
BUSY<='0';
END IF;
END IF;
END IF;
END IF;
END PROCESS;
END MAIN;
Código VHDL do Módulo TX
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY TX IS
PORT(
CLK:IN STD_LOGIC;
START:IN STD_LOGIC;
BUSY:OUT STD_LOGIC;
DATA: IN STD_LOGIC_VECTOR(7 downto 0);
TX_LINE:OUT STD_LOGIC
);
END TX;
ARCHITECTURE MAIN OF TX IS
SIGNAL PRSCL: INTEGER RANGE 0 TO 5208:=0;
SIGNAL INDEX: INTEGER RANGE 0 TO 9:=0;
SIGNAL DATAFLL: STD_LOGIC_VECTOR(9 DOWNTO 0);
SIGNAL TX_FLG: STD_LOGIC:='0';
BEGIN
97
PROCESS(CLK)
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
IF(TX_FLG='0' AND START='1')THEN
TX_FLG<='1';
BUSY<='1';
DATAFLL(0)<='0';
DATAFLL(9)<='1';
DATAFLL(8 DOWNTO 1)<=DATA;
END IF;
IF(TX_FLG='1')THEN
IF(PRSCL<434)THEN
PRSCL<=PRSCL+1;
ELSE
PRSCL<=0;
END IF;
IF(PRSCL=217)THEN
TX_LINE<=DATAFLL(INDEX);
IF(INDEX<9)THEN
INDEX<=INDEX+1;
ELSE
TX_FLG<='0';
BUSY<='0';
INDEX<=0;
END IF;
END IF;
END IF;
END IF;
END PROCESS;
END MAIN;
Código VHDL do Módulo Shift_Register
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity shift_reg is
Port ( clk : in STD_LOGIC;
reset: in STD_LOGIC;
r_1 : out STD_LOGIC_VECTOR(7 downto 0);
r_2 : out STD_LOGIC_VECTOR(7 downto 0);
r_3 : out STD_LOGIC_VECTOR(7 downto 0);
data_in : in STD_LOGIC_VECTOR(7 downto 0);
data_out : out STD_LOGIC_VECTOR(7 downto 0));
end shift_reg;
architecture Behavioral of shift_reg is
constant m : integer := 3;
subtype wrdtype is std_logic_vector(7 downto 0);
type regtype is array(0 to m-1) of wrdtype;
signal reg : regtype;
98
begin
shift : process(reset, clk)
begin
if reset = '1' then
for j in 0 to m - 1 loop
reg(j) <= (others => '0');
end loop;
elsif rising_edge(clk) then
reg(2) <= reg(1);
reg(1) <= reg(0);
reg(0) <= data_in;
end if;
end process;
data_out <= reg(2);
r_1 <= reg(0);
r_2 <= reg(1);
r_3 <= reg(2);
end Behavioral;
Código VHDL do Módulo UART
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY UART IS
PORT(
CLOCK: IN STD_LOGIC;
DADOS: IN STD_LOGIC_VECTOR(7 downto 0);
ENVIA: IN STD_LOGIC; -- COMO UM KEY DE PULSO
UART_TXD2:OUT STD_LOGIC;
UART_RXD2:IN STD_LOGIC
);
END UART;
ARCHITECTURE MAIN OF UART IS
SIGNAL TX_DATA: STD_LOGIC_VECTOR(7 downto 0);
SIGNAL TX_START: STD_LOGIC:='0';
SIGNAL TX_BUSY: STD_LOGIC;
SIGNAL RX_DATA: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL RX_BUSY: STD_LOGIC;
----------------------------------------
COMPONENT TX
PORT(
99
CLK:IN STD_LOGIC;
START:IN STD_LOGIC;
BUSY:OUT STD_LOGIC;
DATA: IN STD_LOGIC_VECTOR(7 downto 0);
TX_LINE:OUT STD_LOGIC
);
END COMPONENT TX;
----------------------------------------
COMPONENT RX
PORT(
CLK:IN STD_LOGIC;
RX_LINE:IN STD_LOGIC;
DATA:OUT STD_LOGIC_VECTOR(7 downto 0);
BUSY:OUT STD_LOGIC
);
END COMPONENT RX;
------------------------------------------------------
signal send: STD_LOGIC:='0';
signal trigger: std_LOGIC:='0';
BEGIN
C1: TX PORT MAP (CLOCK,TX_START,TX_BUSY,TX_DATA,UART_TXD2);
C2: RX PORT MAP (CLOCK,UART_RXD2,RX_DATA,RX_BUSY);
--
--PROCESS(RX_BUSY)
--BEGIN
--IF(RX_BUSY'EVENT AND RX_BUSY='0')THEN
--LEDR(7 DOWNTO 0)<=RX_DATA;
--END IF;
--END PROCESS;
PROCESS(CLOCK)
BEGIN
IF(CLOCK'EVENT AND CLOCK='1')THEN
if(send = '0' AND (ENVIA='1')) then
send <= '0';
trigger <= '0';
elsif(send = '0' AND (ENVIA='0') AND trigger= '0') then
send <= '1';
trigger <= '1';
elsif(send = '1' AND (ENVIA='0')) then
send <= '0';
end if;
end if;
end process;
PROCESS(CLOCK)
BEGIN
IF(CLOCK'EVENT AND CLOCK='1')THEN
IF(send = '1' and TX_BUSY='0')THEN
TX_DATA<=DADOS;
--LEDG<=TX_DATA;
TX_START<='1';
100
ELSE
TX_START<='0';
END IF;
END IF;
END PROCESS;
END MAIN;
Código em VHDL Microcontrolador com NIOS II®
library ieee;
use ieee.std_logic_1164.all;
entity hardware is
port (
clock_50 : in std_logic := 'X'; -- clk
ledg : out std_logic_vector(8 downto 0); -- export
DRAM_ADDR : out std_logic_vector(12 downto 0);
-- addr
DRAM_BA : out std_logic_vector(1 downto 0);
-- ba
DRAM_CAS_N : out std_logic;
-- cas_n
DRAM_CKE : out std_logic;
-- cke
DRAM_CS_N : out std_logic;
-- cs_n
DRAM_DQ : inout std_logic_vector(31 downto 0) := (others
=> 'X'); -- dq
DRAM_DQM : out std_logic_vector(3 downto 0);
-- dqm
DRAM_RAS_N : out std_logic;
-- ras_n
DRAM_WE_N : out std_logic;
-- we_n
DRAM_CLK : out std_logic;
-- clk
FAN_CTRL : inout std_logic
-- fan control
);
end hardware;
architecture behavioral of hardware is
component nios2 is
port (
clock_50_clk : in std_logic := 'X';
-- clk
reset_reset_n : in std_logic := 'X';
-- reset_n
ledg_export : out std_logic_vector(7 downto 0);
-- export
101
sdram_clk_clk : out std_logic;
-- clk
sdram_addr : out std_logic_vector(12 downto 0);
-- addr
sdram_ba : out std_logic_vector(1 downto 0);
-- ba
sdram_cas_n : out std_logic;
-- cas_n
sdram_cke : out std_logic;
-- cke
sdram_cs_n : out std_logic;
-- cs_n
sdram_dq : inout std_logic_vector(31 downto 0) := (others
=> 'X'); -- dq
sdram_dqm : out std_logic_vector(3 downto 0);
-- dqm
sdram_ras_n : out std_logic;
-- ras_n
sdram_we_n : out std_logic
-- we_n
);
end component nios2;
begin
u0 : component nios2
port map (
clock_50_clk => clock_50, -- clock_50.clk
reset_reset_n => '1', -- reset.reset_n
ledg_export => ledg(7 downto 0), -- ledg.export
sdram_clk_clk => DRAM_CLK, -- clk_sdram.clk
sdram_addr => DRAM_ADDR, -- sdram.addr
sdram_ba => dram_ba, -- .ba
sdram_cas_n => dram_cas_n, -- .cas_n
sdram_cke => dram_cke, -- .cke
sdram_cs_n => dram_cs_n, -- .cs_n
sdram_dq => dram_dq, -- .dq
sdram_dqm => dram_dqm, -- .dqm
sdram_ras_n => dram_ras_n, -- .ras_n
sdram_we_n => dram_we_n -- .we_n
);
ledg(8) <= '0';
FAN_CTRL <= 'Z';
end behavioral;
102
APÊNDICE C - CÓDIGOS EM C/C++
Código em C++ ACD
#include <altera_hostfs.h>
#include <io.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "altera_avalon_performance_counter.h"
#include "system.h"
//#include "matlab.hpp"
//#include 'C:\Program Files\MATLAB\R2013a\extern\include\*'
//#define s1 1 /* contar o tempo de performance de leitura do arquivo de
entrada */
//#define s2 2 /* conta o tempo de performance de calculo das variaveis de
preparacao do filtro */
#define ConvNet 1 /* conta o tempo de performance de calculo da aplicacao
do filtro */
#define ConvNetSDRAM 2 /* conta o tempo de performance de calculo da
aplicacao do filtro lendo direto na memoria SDRAM*/
/*format long -> MATLAB
H=[224.0/1024.0 229.0/1024.0 224.0/1024.0; 229.0/1024.0 233.0/1024.0
229.0/1024.0; 224.0/1024.0 229.0/1024.0 224.0/1024.0]
H =
0.218750000000000 0.223632812500000 0.218750000000000
0.223632812500000 0.227539062500000 0.223632812500000
0.218750000000000 0.223632812500000 0.218750000000000
*/
void funcConvNet(float *matDados,float *matDados2, unsigned int n ,
unsigned int m)
{
//Dessa maneira a matriz de dados sera percorrida a cada linha a partir
da 3
// kernel de borda
//float k[]={ -1.0/9.0, -1.0/9.0, -1.0/9.0,-1.0/9.0, 8.0/9.0, -
1.0/9.0,-1.0/9.0, -1.0/9.0, -1.0/9.0 };
//kernel gaussiano
float k[]={ 0.21875, 0.223632812, 0.21875, 0.223632812, 0.227539062,
0.223632812, 0.21875, 0.223632812, 0.21875 };
float filtro = 0.0;
int i=0,m2, m2Inicio, m2Final;
unsigned int tam = m*n;
m2=m+2;
103
m2Inicio = m2+1;
m2Final = tam-m2-1;
for (i=m2Inicio; i < m2Final; i++)
{
filtro = matDados[i-m2-1] * k[0]
+ matDados[i-m2] * k[1]
+ matDados[i-m2+1] * k[2]
+ matDados[i-1] * k[3]
+ matDados[i] * k[4]
+ matDados[i+1] * k[5]
+ matDados[i+m2-1] * k[6]
+ matDados[i+m2] * k[7]
+ matDados[i+m2+1] * k[8];
// matDados2[i] = filtro;
}
}
void funcConvNetSDRAM(float *matDadosSaida, unsigned int n , unsigned int
m)
{
//kernel gaussiano
float k[]={ 0.21875, 0.223632812, 0.21875, 0.223632812, 0.227539062,
0.223632812, 0.21875, 0.223632812, 0.21875 };
float filtro = 0.0;
int i=0,m2;
unsigned int tam = m*n;
m2=m+2;
for (i=m2+1; i< tam-m2-1; i++)
{
filtro = IORD(SDRAM_CONTROLLER_BASE, i-m2-1) * k[0]
+ IORD(SDRAM_CONTROLLER_BASE, i-m2) * k[1]
+ IORD(SDRAM_CONTROLLER_BASE, i-m2+1) * k[2]
+ IORD(SDRAM_CONTROLLER_BASE, i-1) * k[3]
+ IORD(SDRAM_CONTROLLER_BASE, i) * k[4]
+ IORD(SDRAM_CONTROLLER_BASE, i+1) * k[5]
+ IORD(SDRAM_CONTROLLER_BASE, i+m2-1) * k[6]
+ IORD(SDRAM_CONTROLLER_BASE, i+m2) * k[7]
+ IORD(SDRAM_CONTROLLER_BASE, i+m2+1) * k[8];
// matDadosSaida[i] = filtro;
}
}
int main()
{
FILE *arqDados;
FILE *arqSaida;
float dado = 0.0;
printf("Abrindo arquivo... ");
arqDados = fopen ("/mnt/host/arqDados.txt", "r");
104
//Apenas para esperarmos o tempo de resposta de leitura do arquivo
if (arqDados == NULL)
{
printf ("ERRO: Nao foi possl abrir o arquivo arqDados.txt. \n");
exit(1);
}
printf("OK!\n Salvando dados na SDRAM...\n");
//PERF_RESET (PERFORMANCE_COUNTER_0_BASE); //Reset Performance
Counters to 0
//PERF_START_MEASURING (PERFORMANCE_COUNTER_0_BASE); //Start the
Counter
//Inicio da performance do arquivo de entrada
// vetor de dados para armazenar pixels da imagem
// tam = numero de pixels
//unsigned int tam = 264196; /// numero de linhas do arquivo de dados
ou numero de pixel da imagem
unsigned int tam = 2704; /// numero de linhas do arquivo de dados ou
numero de pixel da imagem
// int widthImg= 512; //Largura da imagem
// int heightImg = 512; //Altura da image
int widthImg= 50; //Largura da imagem
int heightImg = 50; //Altura da image
float * arrDados = (float *) malloc(sizeof(float)*tam);
float * arrDados2 = (float *) malloc(sizeof(float)*tam);
int enderecoDram = 0;
while (fscanf(arqDados, "%f", &dado) != EOF)
{
arrDados[enderecoDram] = dado;
arrDados2[enderecoDram] = dado;
IOWR(SDRAM_CONTROLLER_BASE, enderecoDram, dado);
//printf("Colocando na memoria SDRAM[%d] = %f \n", enderecoDram,
arrDados[enderecoDram]);
enderecoDram ++;
}
fclose (arqDados);
printf("OK!\nPreparando o Filtro ConvNet:\n");
PERF_RESET (PERFORMANCE_COUNTER_0_BASE); //Reset Performance
Counters to 0
PERF_START_MEASURING (PERFORMANCE_COUNTER_0_BASE); //Start the Counter
PERF_BEGIN (PERFORMANCE_COUNTER_0_BASE, ConvNet); //Start the overhead
counter
funcConvNet(arrDados,arrDados2, widthImg, heightImg);
//funcConvNet(SDRAM_CONTROLLER_BASE,arrDados2, widthImg,heightImg);
PERF_END (PERFORMANCE_COUNTER_0_BASE, ConvNet);//fim da performance
//Stop the overhead counter
PERF_STOP_MEASURING (PERFORMANCE_COUNTER_0_BASE);
105
PERF_START_MEASURING (PERFORMANCE_COUNTER_0_BASE); //Start the Counter
PERF_BEGIN (PERFORMANCE_COUNTER_0_BASE, ConvNetSDRAM); //Start the
overhead counter
funcConvNetSDRAM(arrDados2, widthImg, heightImg);
PERF_END (PERFORMANCE_COUNTER_0_BASE, ConvNetSDRAM);//fim da
performance //Stop the overhead counter
PERF_STOP_MEASURING (PERFORMANCE_COUNTER_0_BASE);
perf_print_formatted_report ((void *)PERFORMANCE_COUNTER_0_BASE, /*
defined in "system.h" */
ALT_CPU_FREQ, /*
defined in "system.h" */
2, /*
How many sections to print */
"ConvNet", "ConvNetSDRAM");
//Imprimindo resultado no arquivo de saida
arqSaida = fopen("/mnt/host/ImagemSaida2.txt","w");
if (arqSaida == NULL)
{
printf ("Nao pode abrir/criar ImagemSaida512x683.txt.\n");
exit(1);
}
else
{
printf("Escrevendo no arquivo");
}
int i;
for (i = 0; i < tam; i++)
{
//printf("Escrevendo no arquivo[%d]: %f \n", i, arrDados[i]);
fprintf (arqSaida, "%f \n", arrDados2[i]);
}
free(arrDados);
//PERF_STOP_MEASURING (PERFORMANCE_COUNTER_0_BASE);
//perf_print_formatted_report ((void *)PERFORMANCE_COUNTER_0_BASE, /*
defined in "system.h" */
// ALT_CPU_FREQ, /*
defined in "system.h" */
// 1,
/* How many sections to print */
// "ConvNet");
fclose (arqSaida);
printf("Fim da execucao!\n");
return 0;
}
106
Código em C++ Pixels MIF
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
FILE *arqSaida, *arqEntrada;
char nomeArquivoSaida[255];
char extArquivoSaida[5] = ".mif";
char nomeArquivoEntrada[255];
int width, depth = 0;
char ADDRESS_RADIX[4]="UNS";
char DATA_RADIX[4]="BIN";
char CONTENT_BEGIN[14]="CONTENT BEGIN";
char END[5]="END;";
float linha;
printf("Entre com o Tamanho da Largura da Imagem em pixels : ");
scanf("%d",&width);
printf("Entre com o Tamanho da Altura da Imagem em pixels : ");
scanf("%d",&depth);
printf("Tamanho da Imagem : %d x %d\n", width, depth);
printf("Entre com o Nome do Arquivo de Saida (Nao precisa escrever a
extensao, sera .mif) : ");
scanf("%s",nomeArquivoSaida);
strcat(nomeArquivoSaida, extArquivoSaida);
printf("Nome do arquivo digitado : %s\n", nomeArquivoSaida);
if((arqSaida = fopen(nomeArquivoSaida, "w+t")) == NULL)
{
puts("Nao foi possivel criar o arquivo");
getchar();
return 0;
}
printf("Criado o Arquivo!\n");
fprintf(arqSaida,"WIDTH=%d;\n",width);
fprintf(arqSaida,"DEPTH=%d;\n",depth);
fprintf(arqSaida,"\n");
fprintf(arqSaida,"ADDRESS_RADIX=%s;\n",ADDRESS_RADIX);
fprintf(arqSaida,"DATA_RADIX=%s;\n",DATA_RADIX);
fprintf(arqSaida,"\n");
fprintf(arqSaida,"%s \n",CONTENT_BEGIN);
printf("Entre com o Nome do Arquivo de Entrada (Com a extensao) : ");
scanf("%s",nomeArquivoEntrada);
printf("Nome do Arquivo digitado : %s\n", nomeArquivoEntrada);
107
if ((arqEntrada = fopen(nomeArquivoEntrada, "rt")) == NULL) {
puts("Nao foi possivel encontrar o arquivo de Entrada! :(\n");
getchar();
return 0;
}
printf("Arquivo encontrado! Iniciando Leitura, isso pode demorar... Por
favor, aguarde! \n");
for(int i=0; !feof(arqEntrada); i++)
{
fscanf(arqEntrada,"%f ",&linha);
printf("Linha[%d] = %f\n", i, linha);
if (i < 10)
{
fprintf(arqSaida, " %d : ",i);
}
else if ((i > 9) && (i < 100))
{
fprintf(arqSaida, " %d : ",i);
}
else if ((i > 99) && (i < 1000))
{
fprintf(arqSaida, " %d : ",i);
}
else if ((i > 999) && (i < 10000))
{
fprintf(arqSaida, " %d : ",i);
}
else
{
fprintf(arqSaida, " %d: ",i);
}
fprintf(arqSaida, "%f;", linha);
fprintf(arqSaida, "\n");
}
fprintf(arqSaida,"\n%s\n",END);
fclose(arqSaida);
fclose(arqEntrada);
printf("Operacao Finalizada! \n");
return 0;
}
Código em C++ Cria ROM
#pragma hdrstop
108
#pragma argsused
#include <stdio.h>
#include<iostream.h>
void cria_rom_sinal(int W, int DEPTH,char *nomearq){
FILE *fp,*fpt;
char *vet = new char[W];
char ADDRESS_RADIX[4]="UNS";
char DATA_RADIX[4]="BIN";
char conteudo[14]="CONTENT BEGIN";
char end[4]="END;";
int i,j,k;
float num;
fp = fopen(nomearq,"wt");
fpt = fopen("ImagemEntrada.txt","rt");
fprintf(fp,"WIDTH=%d;\n",W);
fprintf(fp,"DEPTH=%d;\n",DEPTH);
fprintf(fp,"\n");
fprintf(fp,"ADDRESS_RADIX=%s;\n",ADDRESS_RADIX);
fprintf(fp,"DATA_RADIX=%s;\n",DATA_RADIX);
fprintf(fp,"\n");
fprintf(fp,"%s \n",conteudo);
int tam =0;
for(;!feof(fpt);tam++){
fscanf(fpt,"%f ",&num);
//printf("%5.3f \n",num);
if (num <= 0){
vet[0]=0;
num = num*(-10000);}
else{
vet[0]=1;
num = num*10000;}
int numero = (int)num;
int valor ;
valor = numero/10000;
numero %=10000;
//printf("%d %d \n",numero,valor);
for(i = 4 ; i > 0 ; i--){
vet[i]= valor%2;
valor /=2;
}
for(j = 19 ; j > 4 ; j--){
vet[j]= numero%2;
numero /=2;
}
fprintf(fp," %.4d : ",tam);
for(k = 0 ; k < 20 ; k++){
109
fprintf(fp,"%d",vet[k]);}
fprintf(fp,";\n");
}
fprintf(fp,"\n");
fprintf(fp,"END;\n");
fclose(fp);
fclose(fpt);
return ;
}
void cria_rom(int W, int DEPTH,char *nomearq){
FILE *fp,*fpt;
int i,j ;
char ADDRESS_RADIX[4]="UNS";
char DATA_RADIX[4]="BIN";
char conteudo[14]="CONTENT BEGIN";
char end[4]="END;";
char *p = new char[W];
if((fp =fopen(nomearq,"w+t"))==NULL)
{
puts("Nao foi possivel abrir o arquivo");
getchar();
exit(1);
}
fpt=fopen("angulo.txt","rt");
fprintf(fp,"WIDTH=%d;\n",W);
fprintf(fp,"DEPTH=%d;\n",DEPTH);
fprintf(fp,"\n");
fprintf(fp,"ADDRESS_RADIX=%s;\n",ADDRESS_RADIX);
fprintf(fp,"DATA_RADIX=%s;\n",DATA_RADIX);
fprintf(fp,"\n");
fprintf(fp,"%s \n",conteudo);
int inteira,decimal,tam = (W-1);
int num;
for(i=0;i<DEPTH;i++){
fscanf(fpt,"%d ",&num);
for(j=tam;j>=0;j--){
p[j]=(num%2);
num =num/2;
}
fprintf(fp," %.4d : ",i);
for(j=0;j<=tam;j++){
fprintf(fp,"%d",p[j]);
110
}
fprintf(fp,";\n");
//getchar();
}
fprintf(fp,"\n");
fprintf(fp,"END;\n");
fclose(fp);
fclose(fpt);
}
int main(){
FILE *fp;
int W;
int DEPTH;
char nomearq[80];
printf("entre com o tamanho da palavra : ");
scanf("%d",&W);
printf("\n");
printf("entre com o numero de palavras : ");
scanf("%d",&DEPTH);
printf("\n");
printf("entre com o nome do arquivo.mif : ");
scanf("%s",nomearq);
printf("\n");
cria_rom(W,DEPTH,nomearq);
getchar();
return 0;
}
111
APÊNDICE D - CÓDIGOS EM MATLAB®
Código em MATLAB® da Convolução
clear all;close all;clc
I= imread('lena512color.tiff');
I= imresize(I,[512,512]);
%figure(1)
%imshow(I)
f=rgb2gray(I);
figure
imshow(f)
[x,y]=size(f);
fpad=zeros(x+2,y+2);
fpad(1,1)=f(1,1);
fpad(end,end)= f(end,end);
fpad(1,end)= f(1,end);
fpad(end,1)= f(end,1);
fpad(1,2:end-1)=f(1,:);
fpad(2:end-1,1)=f(:,1);
fpad(end,2:end-1)=f(end,:);
fpad(2:end-1,end)=f(:,end);
fpad(2:end-1,2:end-1)=f;
%H = [-1 -1 -1; -1 8 -1; -1 -1 -1];
%H = [0 1 0; 1 -4 1; 0 1 0]; %--detectar borda
%H = [-2 -1 0; -1 1 1; 0 1 2]; %--kernel relevo
%H =[1 2 1; 2 4 2; 1 2 1];
%H=[224.0/1024.0 229.0/1024.0 224.0/1024.0; 229.0/1024.0 233.0/1024.0
229.0/1024.0; 224.0/1024.0 229.0/1024.0 224.0/1024.0]; %Kernel Gaussiano
mesmo desenvolvido em VHDL e NIOS
H = fspecial('gaussian',[3 3],5.5);
H=H/(sum(sum(H)));
G=zeros(x,y);
for i=2:x+1
for j=2:y+1
val= fpad(i-1,j-1)*H(1,1)+fpad(i,j-1)*H(2,1)+fpad(i+1,j-
1)*H(3,1)+fpad(i-1,j)*H(1,2)+fpad(i,j)*H(2,2)+fpad(i+1,j)*H(3,2)+fpad(i-
1,j+1)*H(1,3)+fpad(i,j+1)*H(2,3)+fpad(i+1,j+1)*H(3,3);
G(i-1,j-1)=val;
end
end
G=G/255;
figure
112
imshow(G);
f=fpad(:);
save ImagemGRAY.txt f /ascii
save ImagemCONV.txt G /ascii
% f=rgb2gray(I);
% Conv=imfilter(f,H);
% figure
% imshow(Conv,[])
% figure
% imshow(G,[])
% %para ler arquivo matlab usar fun磯 load
% %G = load('ImagemSaida2f.txt');
% G = load('vetor.mat', 'vetor');
% %G = load('ImagemSaidaNIOS512x683.txt');
%
%
% % for i=1:x
% %
% % for j=1:y
% % S(i,j)=G(x*(j-1)+i);
% % end
% % end
%
% x=x+2;
% y=y+2;
% for i=1:x
% for j=1:y
% S(i,j)=G(x*(j-1)+i);
% end
% end
%
% figure
% imshow(S,[])
%
%
% %fazer normalização com valores do matlab
% G_normFPGA=G-min(min(G));
% G_normFPGA=G_normFPGA/max(max(G_normFPGA));
%
% %figure
% %imshow(G_normFPGA>0.48)
% %imshow(G_normFPGA)
%
% f=fpad(:);
%
%
113
Código em MATLAB® da Convalida NIOS II
®
clear all;close all;clc
I= imread('lena512color.tiff');
I= imresize(I,[512,512]);
Y=rgb2gray(I);
figure(1)
imshow(Y)
%para ler arquivo matlab usar função load G = load('capture.txt');
%G = load('vetor.mat', 'vetor');
%G = load('ImagemSaidaNIOS512x683.txt');
% for i=1:x
%
% for j=1:y
% S(i,j)=G(x*(j-1)+i);
% end
% end
% x=512;
% y=512;
x=512;
y=512;
x=x+2;
y=y+2;
for i=1:x
for j=1:y
S(i,j)=G(x*(j-1)+i);
end
end
figure
imshow(S,[])
% %para ler arquivo matlab usar função load % G = load('captureInt.txt');
% %G = load('vetor.mat', 'vetor');
% %G = load('ImagemSaidaNIOS512x683.txt');
%
%
% % for i=1:x
% %
% % for j=1:y
% % S(i,j)=G(x*(j-1)+i);
114
% % end
% % end
% x=512;
% y=512;
% x=x+2;
% y=y+2;
% for i=1:x
%
% for j=1:y
% S(i,j)=G(x*(j-1)+i);
% end
% end
%
% figure
% imshow(S,[])
%fazer normalização com valores do matlab G_normFPGA=G-min(min(G));
G_normFPGA=G_normFPGA/max(max(G_normFPGA));
%figure
%imshow(G_normFPGA>0.48)
%imshow(G_normFPGA)
% f=fpad(:);
Código em MATLAB® da Convalida VHDL
clear all
close all
I= imread('lena512color.tiff');
%I= imread('Gabe1.jpg');
I= imresize(I,[512,512]);
Y=rgb2gray(I);
figure(1);
imshow(Y)
%file = fopen('capture.txt', 'r');
file = fopen('captureF.txt', 'r');
vetor = fread(file);
fclose(file);
%vetor com o tamanho mḩmo de linhas do arquivo capture2.txt
vetor(262144) = 0;
x = 512;
y = 512;
S = zeros(x,y);
for i=1:x
for j=1:y
S(j,i)=vetor(x*(j-1)+i);
end
115
end
figure
imshow(S,[])
Código em MATLAB® Imagem para Memória MIF
function IMG2mif(imgfile, outfile)
%IMG2mif('lena512color.tiff','saidamif.mif')
%IMG2mif('Gabe1.jpg','saidamif.mif')
img = imread(imgfile);
height = size(img, 1);
width = size(img, 2);
s = fopen(outfile,'wb'); %opens the output file
fprintf(s,'WIDTH = 8;\n');
fprintf(s,'DEPTH = %d;\n',height*width);
fprintf(s,'ADDRESS_RADIX = HEX;\n');
fprintf(s,'DATA_RADIX = HEX;\n');
fprintf(s,'CONTENT BEGIN\n\n');
cnt = 0;
img2 = img;
for r=1:height
for c=1:width
cnt = cnt + 1;
fprintf(s,'%x : ',cnt);
Y = img(r,c);
Yb = dec2bin(double(Y),8);
Outbyte = Yb;
if (Outbyte(1:4) == '0000')
fprintf(s,'0%X;\n',bin2dec(Outbyte));
else
fprintf(s,'%X;\n',bin2dec(Outbyte));
end
end
end
fprintf(s,'END;\n');
fclose(s);
116
Código em MATLAB® Filtro Gaussiano
clear all;close all;clc
%mcc -B sgl convo
I= imread('carloscaetano.jpg');
figure(1)
imshow(I)
f=rgb2gray(I);
figure
imshow(f)
f=double(f);
[x,y]= size(f);
h=fspecial('gaussian',[5 5], 2.5);
F=imfilter(f,h);
figure
imshow(F)
q = quantizer('ufixed', 'floor', 'saturate', [19 11])
Xh= quantize(q,h)
Fq=imfilter(f,Xh);
Fq= quantize(q,Fq);
figure
imshow(Fq,[])
DF=F-Fq; %Diferencial - quantizado
DF=DF.*DF; % Multiplicacao elemento por elemento
S=sum(sum(DF));
err= sqrt(S/(x*y))*100/255