GERADOR DE PULSOS DIGITAIS E INTERFACE SERIAL …rivello.me/proj.pdf · aceleradores de partículas...

72
CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA CELSO SUCKOW DA FONSECA – CEFET/RJ GERADOR DE PULSOS DIGITAIS E INTERFACE SERIAL PARA CONTROLE IMPLEMENTADOS EM FPGA Maurício Féo Pereira Rivello de Carvalho Rio de Janeiro Julho 2013

Transcript of GERADOR DE PULSOS DIGITAIS E INTERFACE SERIAL …rivello.me/proj.pdf · aceleradores de partículas...

CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA CELSO

SUCKOW DA FONSECA – CEFET/RJ

GERADOR DE PULSOS DIGITAIS E

INTERFACE SERIAL PARA CONTROLE

IMPLEMENTADOS EM FPGA

Maurício Féo Pereira Rivello de Carvalho

Rio de Janeiro

Julho 2013

I

CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA CELSO

SUCKOW DA FONSECA – CEFET/RJ

GERADOR DE PULSOS DIGITAIS E

INTERFACE SERIAL PARA CONTROLE

IMPLEMENTADOS EM FPGA

Maurício Féo Pereira Rivello de Carvalho

Projeto Final apresentado em comprimento às normas do Departamento de Educação Superior do CEFET-RJ, como parte dos requisitos como obtenção do título de Engenharia Eletrônica.

Prof. Orientador: Jesse Costa

Prof. Co-Orientador: André Massafferri

Rio de Janeiro

Julho 2013

II

III

DEDICATÓRIA

À Deus: “Porque dEle e por Ele, e para Ele, são todas as coisas; glória, pois, a Ele eternamente. Amém.” Romanos 11:36 À minha esposa Raquel, por ser minha motivação, minha inspiração, minha alegria, minha vida.

IV

AGRADECIMENTOS

Agradeço primeiramente aos meus pais Osvaldo e Laís, pelo apoio incondicional e por terem tornado esta conquista possível. Em especial aos meus orientadores Jesse Costa e André Massafferri, pois sem eles esse trabalho não teria sido realizado. Aos amigos e colegas de faculdade, por tantas horas de aprendizado compartilhadas e os desafios que enfrentamos juntos.

V

RESUMO

No estudo de física de partículas de alta energia se faz necessário o uso de pesada

instrumentação com um número elevado de sensores e equipamentos de medição para que

todo fenômeno físico de interesse possa ser apropriadamente registrado e medido. A

eletrônica de front-end é responsável pela amplificação e digitalização dos sinais analógicos

provenientes dos sensores, e os módulos de aquisição são responsável pela aquisição e

processamento inicial destes sinais após serem digitalizados.

Quando há a necessidade de validação ou teste dos módulos de aquisição de dados, é

necessário ter a noção ou preferencialmente conhecer por completo o sinal de entrada para

inferirmos se este está sendo captado e processado corretamente pelos módulos de aquisição.

Desta necessidade surgiu a idéia do projeto de um gerador de sinais digitais com o objetivo de

simular os sinais de entrada que os módulos de aquisição receberiam em sua condição normal

de operação.

Neste contexto, foi desenvolvido e implementado em FPGA um gerador de pulsos

digitais, com parâmetros controlados por software em computador sendo estes a largura de

pulso, o período, a defasagem entre cada canal e o número de pulsos a serem enviados cada

vez que o gerador for engatilhado. Por ter sido usado estrutura FPGA, o bloco do gerador

pode ser replicado por quantos canais forem necessários dentro das limitações do FPGA. O

gerador foi implementado com sucesso e seu desempenho foi satisfatório para a aplicação em

questão, que é o teste e diagnóstico de módulos de aquisição de dados, usados em montagens

de medição de partículas de altas energias.

VI

ABSTRACT

In the study of high energy particle physics is required the use of heavy

instrumentation with a large number of sensors and measuring equipment so that all physical

phenomena of interest can be properly recorded and measured. The front-end electronics is

responsible for amplification and digitization of analog signals from the sensors and the

acquisition modules are responsible for the acquisition and initial processing of these signals

after they are digitalized.

When there is a need for validation or testing of the data acquisition modules, it is

necessary to know the input signal in order to infer whether it is being properly captured and

processed by the acquisition modules or not. From this need arose the idea of the design of a

digital signal generator in order to simulate the input signals that the acquisition modules

receive in its normal operating condition.

In this context, we developed and implemented in FPGA, a digital pulse generator

with parameters controlled by computer software, which are pulse width, period, the gap

between each channel and the number of pulses to be sent each time the generator is

triggered. Because a FPGA structure was used, the generator block can be replicated by how

many channels are needed within the limitations of the FPGA. The generator has been

successfully implemented and its performance was satisfactory for the currently application,

which is test and diagnostic of data acquisition modules used in measurement of high energy

particles.

VII

SUMÁRIO

DEDICATÓRIA .................................................................................................................................... III

AGRADECIMENTOS ........................................................................................................................... IV

RESUMO ................................................................................................................................................ V

ABSTRACT ........................................................................................................................................... VI

SUMÁRIO ............................................................................................................................................ VII

LISTA DE FIGURAS ............................................................................................................................ IX

Capítulo 1 ................................................................................................................................................ 1

1.Introdução ............................................................................................................................................ 1

1.1 Contextualização .................................................................................................................... 1

1.1.1 O CERN ................................................................................................................................ 1

1.1.2 O CBPF ................................................................................................................................. 2

1.2 Motivação e justificativa do trabalho .................................................................................... 2

1.3 Objetivo .................................................................................................................................. 4

1.4 Metodologia e Trabalho Realizado ........................................................................................ 4

Capítulo 2 ................................................................................................................................................ 6

2. Primeira Versão do Gerador........................................................................................................... 6

2.1 Especificações do Projeto ....................................................................................................... 7

2.2 Plataforma V1495 ................................................................................................................... 7

2.3 Interface de Acesso aos módulos VME ................................................................................ 10

2.3.1 Interface de Hardware ................................................................................................. 10

2.3.2 Interface de Software ................................................................................................... 12

2.4 Desenvolvimento e Funcionamento do Gerador ................................................................ 13

2.5 Software de Controle ........................................................................................................... 16

2.6 Limitações ............................................................................................................................. 16

Capítulo 3 .............................................................................................................................................. 18

3. Segunda Versão do Gerador ........................................................................................................ 18

3.1. Especificações do Projeto ..................................................................................................... 18

3.2 Placa de Desenvolvimento LX9 MicroBoard ........................................................................ 19

3.3 FPGA ...................................................................................................................................... 20

3.4 Projeto Síncrono vs Assíncrono ............................................................................................ 23

3.5 Visão Geral da Top Level Entity ............................................................................................ 24

3.6 Gerador Controlável ............................................................................................................. 26

3.6.1 Delayer .............................................................................................................................. 28

VIII

3.6.2 Pulses Counter .................................................................................................................. 29

3.6.3 Generator Unit .................................................................................................................. 31

3.7 Interface Serial UART ............................................................................................................ 32

3.7.1 Protocolo Serial................................................................................................................. 33

3.7.2 Unidade Rx ........................................................................................................................ 34

3.7.3 Unidade Tx ........................................................................................................................ 36

3.8 Entidade Top Level ............................................................................................................... 38

3.9 Software para Controle ........................................................................................................ 39

Capítulo 4 .............................................................................................................................................. 42

4. Conclusão ...................................................................................................................................... 42

Referências bibliográficas .................................................................................................................... 45

APÊNDICE ........................................................................................................................................... 46

Apêndice I: Código fonte da entidade de nível superior ................................................................... 46

Apêndice II: Código fonte do Gerador de Pulsos.............................................................................. 51

Apêndice III: Código fonte da unidade Delayer ............................................................................... 54

Apêndice IV: Código fonte da Generator Unit ................................................................................. 55

Apêndice V: Código fonte da N_Unit ............................................................................................... 56

Apêndice VI: Código fonte do Receptor UART ............................................................................... 58

Apêndice VII: Código fonte do Transmissor UART ........................................................................ 60

Apêndice VIII: Código fonte da unidade Single Pulser .................................................................... 62

IX

LISTA DE FIGURAS

Figura 1: Cadeia de aceleração do LHC ..................................................................................... 1

Figura 2: Módulo VME V1495 .................................................................................................. 8

Figura 3: Diagrama de blocos do módulo V1495....................................................................... 9

Figura 4: Parte frontal do módulo V1495. ................................................................................ 11

Figura 5: Representação em bloco simplificado do primeiro gerador...................................... 14

Figura 6: Esboço do diagrama de blocos do primeiro gerador. ................................................ 15

Figura 7: Vista superior da placa de desenvolvimento LX9 MicroBoard. ............................... 20

Figura 8: Arquitetura padrão de um FPGA moderno. .............................................................. 21

Figura 9: Diagrama de blocos da entidade de nível superior do gerador. ................................ 25

Figura 10: Representação do bloco da segunda versão do gerador. ......................................... 26

Figura 11: Diagrama de blocos da segunda versão do gerador. ............................................... 28

Figura 12: Ilustração do funcionamento do bloco delayer. ...................................................... 29

Figura 13: Ilustração do funcionamento da unidade pulses conter. ......................................... 30

Figura 14: Ilustração do funcionamento da unidade geradora. ................................................ 32

Figura 15: Placa Avnet LX9 conectada à USB pela porta UART............................................ 33

Figura 16: Configuração do protocolo UART usada no projeto. ............................................. 34

Figura 17: Diagrama de estados da máquina de estado da unidade UART receptora. ............. 35

Figura 18: Interface gráfica do aplicativo de controle do gerador. .......................................... 40

Figura 19: Verificação da saída de 4 canais utilizando um osciloscópio digital. ..................... 43

Figura 20: Software de controle do gerador. ............................................................................ 44

1

1

Capítulo 1

1.Introdução

O presente projeto descreve a idealização, projeto e implementação, e características

de funcionamento de um gerador de pulsos implementado em FPGA e controlável através de

interface serial universal assíncrona implementando o protocolo RS-232 e uma versão anterior

projetada especificamente para utilização em um módulo VME modelo V1495 de fabricação

CAEN ou similar.

1.1 Contextualização

1.1.1 O CERN

Atualmente o CERN (Centro Europeu de Pesquisa Nuclear) é um dos centros de

pesquisa de maior relevância no mundo. Nele é encontrado o LHC (Grande Colisor de

Hádrons), que é o maior acelerador de partículas já construído até o presente momento.

Figura 1: Cadeia de aceleração do LHC

2

Ao longo de um túnel de 27km de circunferência há 2 canais por onde passa, em

direções opostas, feixes de partículas. Em 4 pontos diferentes há o cruzamento destes feixes,

onde ocorrem as colisões. Nestes pontos há grande estrutural e aparato para controle das

colisões e medição dos eventos e partículas consequentes das colisões.

Nestes quatro pontos é onde ocorrem as experiências do LHC, cada uma com estrutura

e objetivos diferentes, as quais são: ALICE (Grande Colisor de Íons), ATLAS (Aparato

Toroidal do LHC), CMS (Solenoide Compacto de Múons) e LHCb (LHC-beauty).

Em cada uma dessas experiências há um grande número de sensores que geram sinais

elétricos de diversas formas representando sua medição. São milhares de sensores,

organizados em camadas, com diferentes aplicações, desde medir o nível energético de uma

partícula passante até rastrear a trajetória percorrida por dada partícula. Por trás destes

sensores há uma eletrônica muito complexa envolvida, cujo objetivo é fazer a leitura dos

sinais destes sensores, processar, filtrar os sinais de interesse e enviar os dados para serem

armazenados em computadores para mais tarde poderem ser analisados por softwares e

pessoas competentes.

A eletrônica que faz a aquisição dos dados varia de acordo com o tipo de sensor,

experiência e volume de dados. Um dos tipos existentes é o padrão VME, que são

organizados em caixas chamadas “Crate” onde são conectados módulos que desempenham

diversas funções e todos podem se comunicar entre si por um barramento que interliga todos

os módulos de um mesmo crate. Para a primeira versão do gerador foi utilizado um desses

módulo com um chip de lógica programável, para podermos configurá-lo conforme a

aplicação desejada.

1.1.2 O CBPF

O Centro Brasileiro de Pesquisas Físicas (CBPF) é um instituto de pesquisa do

Ministério da Ciência e Tecnologia (MCT) do Brasil. Atualmente é um centro de referência

em Física. Nele há vários trabalhos sendo realizados em cooperação com projetos

desenvolvidos no CERN.

1.2 Motivação e justificativa do trabalho

O Laboratório Multiusuário de Física de Altas Energias da Coordenação de Física

Experimental de Altas Energias (LAFEX), no Centro Brasileiro de Pesquisas Físicas (CBPF),

contém atualmente duas montagens experimentais vinculadas às experiências LHCb e CMS,

3

do LHC. Na montagem da experiência do LHCb está sendo montado um sistema de detecção

de múons cósmicos (partículas atômicas vindas do espaço que atingem a Terra a todo o

momento) que utilizará câmaras proporcionais e cintiladores plásticos como sensores de

detecção de partículas. Tanto para detecção de raios cósmicos como para colisão em

aceleradores de partículas como o LHC, o sinal de saída dos sensores são pulsos elétricos

analógicos que são amplificados e digitalizados por um conjunto de componentes eletrônicos

a qual chamamos de eletrônica de front-end. A estrutura usada para experimentos como os

realizados no LHCb dispõe de um grande número de sensores, de vários tipos e funções, os

quais geram milhares de sinais a cada evento, que no LHC, por exemplo, ocorre a cada 25ns

(ou a 40MHz) resultando em milhares de canais gerando pulsos na ordem dos milhões a cada

segundo. Circunstâncias como essa exigem processamento paralelo e por isso são utilizados

módulos de aquisição específicos, com alta resolução temporal e comumente baseados em

FPGA (Field Programmable Gate Arrays ou Arranjo de Portas Programável em Campo).

A montagem da experiência LHCb para detecção de raios cósmicos no CBPF conta

com sensores do tipo câmara de gás. Estes sensores são câmaras com gases que são ionizados

com a passagem de uma partícula cósmica e que ocasionam o surgimento de uma corrente

elétrica, ou seja, um sinal elétrico analógico. Este sinal analogico proveniente destes sensores

são amplificados e digitalizados pela a eletrônica de front-end do experimento. Para a

aquisição e processamento destes sinais é utilizado um crate VME de fabricação Caen em

conjunto com alguns módulos, entre eles: o módulo Bridge V1718 responsáveis pela interface

entre os módulos do crate e o computador, o módulo Scaler V830 responsável pela contagem

de pulsos emitidos em cada evento, um módulo TDC (Conversor de Tempo para Digital)

V1290 e módulos de propósito genérico V1495, que são baseados em FPGA que podem ser

programados conforme conveniência do usuário. Estes módulos podem ser configurados e ter

seus dados extraídos através da interface provida pelo módulo V1718, na qual há uma porta

USB para conexão física, drivers para acesso ao dispositivo USB pelo sistema operacional do

computador e uma biblioteca contendo diversas funções de acesso aos módulos do crate para

que o usuário possa fazer seus próprios aplicativos de controle com a finalidade de configurar

o módulo e receber e tratar os dados adquiridos pelos módulos VME.

Os módulos usados na montagem dependem de um software que os configure

apropriadamente e faça a leitura dos dados dos módulos em sincronia com a aquisição dos

dados dos eventos, e este software usualmente precisa ser desenvolvido pelo usuário para se

conformar com a aplicação para a qual o sistema está sendo usado. Devido ao fato da tarefa

de desenvolvimento deste software não se tratar de uma tarefa simples ou trivial, se faz

4

necessário realizar numerosos testes para garantir o funcionamento do software. Porém, como

no sistema há varias camadas passíveis de erro (software, interface USB, interface VME,

módulo de aquisição, eletrônica de front-end e sensores), torna-se demasiadamente difícil

atestar o bom funcionamento do sistema e saber em qual camada ocorre um erro ou, atestar se

os dados recebidos pelo software condizem com o que se deveria de fato receber. Na

aplicação da medição de raios cósmicos, por exemplo, por se tratar de eventos aleatórios e

imprevisíveis, não há como prever qual deveria ser o resultado obtido pelo módulo sem

conhecer previamente o sinal gerado pelos sensores.

Desta problemática surgiu a idéia do presente projeto, que consiste em criar um

gerador de pulsos digitais de modo a simular os pulsos digitais provenientes da eletrônica de

front-end dos sensores utilizados e dessa forma poder inferir o resultado esperado pelos

módulos de aquisição, uma vez que agora saberemos os sinais de entrada dado que estes

partirão do gerador. Com isso é possível verificar se a aquisição, processamento e leitura dos

dados do sistema estão sendo realizados de forma correta.

1.3 Objetivo

Este projeto tem como principal objetivo fornecer uma solução para o problema

proposto no item 1.1. A solução proposta é desenvolver, implementar e caracterizar um

gerador de pulsos digitais que tenha parâmetros configuráveis através do computador e

desenvolver um software com interface de usuário para controle através do computador.

Os parâmetros controlados do gerador devem conter os seguintes:

• Largura de pulso, em ciclos de clock.

• Período, em ciclos de clock.

• Defasagem em relação ao gatilho, em ciclos de clock.

• Número de pulsos a ser enviado por gatilho.

O presente trabalho não se limita somente ao problema em questão mas tem por

objetivo também tornar a solução genérica implementando-a em FPGA de forma que o

gerador de pulsos desenvolvido possa ser utilizado em qualquer plataforma FPGA para

qualquer outra aplicação que possa se tornar necessária no futuro, também documentando e

garantindo que a implementação do gerador seja uma tarefa simples para um futuro usuário.

1.4 Metodologia e Trabalho Realizado

5

O projeto da primeira versão do gerador foi realizado através do software Quartus II

da Altera, utilizando linguagem VHDL e a gravação do firmware no FPGA sendo realizado

através da interface fornecida pelo fabricante do módulo de propósito geral V1495 usado no

projeto. O software foi desenvolvido utilizando a linguagem C e usando as bibliotecas

também fornecidas pelo fabricante, para Linux.

As atualizações do firmware foram realizadas através do computador e seus resultados

testados através da leitura de um osciloscópio do laboratório do LAFEX. Após a fase de

desenvolvimento do firmware, se iniciou o desenvolvimento do aplicativo para interface com

usuário, que foi feito através do computador e testado através da leitura do osciloscópio.

Após a fase de desenvolvimento, o gerador foi ligado a um módulo tipo Scaler modelo

V830, que executa uma contagem dos pulsos recebidos em um intervalo de tempo

configurável, e foram criadas extensas rotinas de testes que consistiam em gerar várias

sequências com milhares de pulsos em cada uma, alternando os parâmetros do gerador entre

cada sequência de pulsos e fazendo a leitura através do módulo V830 para verificar se há

erros no gerador para alguma faixa de operação.

O projeto da segunda versão do gerador foi implementada numa placa de

desenvolvimento de FPGA Avnet LX9 Microboard. Os métodos de grvação do firmware são

fornecidos pela interface USB do fabricante.

Reduzindo a frequência de operação do gerador através de um divisor de frequência

implementado no próprio FPGA era possível atestar o funcionamento do gerador pelos

próprios LEDs da placa. Dessa forma foi possível testar as funções implementadas tanto no

firmware quanto no software durante o próprio desenvolvimento.

Após a fase de desenvolvimento, testamos o gerador implementado na placa LX9 em

sua frequência máxima de operação com um osciloscópio no laboratório do LAFEX variando

os parâmetros durante a leitura com o osciloscópio.

6

Capítulo 2

2. Primeira Versão do Gerador

A primeira versão do gerador foi desenvolvida no Laboratório Multiusuário de Física

de Altas Energias do LAFEX no CBPF, com o objetivo de ser uma ferramenta de teste e

diagnóstico da eletrônica de aquisição de dados das montagens experimentais presentes neste

laboratório.

Na ocasião, estava sendo implementado um método de aquisição de dados através de

alguns módulos VME da CAEN, especificamente os já mencionados V830 Scaler, V1290A

TDC e V1495 de propósito genérico. Esses módulos são responsáveis pela leitura e pré-

processamento de pulsos digitais provenientes da eletrônica de front-end dos sensores a

montagem. A implementação em questão consistia na ligação física dos módulos de aquisição

à eletrônica de front-end, na interface de comunicação entre o crate VME e o computador, e

no software para controle e leitura dos dados provenientes dos módulos de aquisição contidos

no crate VME.

O sistema completo para realizar a aquisição de dados dos sensores compreende várias

etapas e até ser corretamente configurado ou ter um software desenvolvido corretamente, fica

muito suscetível a erros de implementação. Caso isto ocorra, o diagnóstico e depuração do

erro se torna muito complexo e difícil por não sabermos em qual camada o erro ocorreu, ou

seja, dependendo da situação, não há como saber se uma leitura incoerente feita no software

em execução no computador é proveniente de falha no código ou desenvolvimento do

software, se é falha da interface USB com o crate VME, se é falha em algum dos módulos

VME ou se é ainda falha na ligação física dos módulos VME com a eletrônica de front-end.

Devido às dificuldades apresentadas e após certa análise do problema, chegamos à

conclusão que sabendo o sinal de entrada no sistema de aquisição poderíamos inferir a saída

em cada uma das etapas e, portanto, depurar com maior facilidade a causa e proveniência de

uma falha no sistema. Por consequência destas coisas foi decidido fazer um gerador de pulsos

digitais implementado em FPGA, que pudesse funcionar em um dos módulos V1495 de

propósito geral e fazer uso de toda interface já adequada para os demais módulos VME, com

o objetivo de emular os sinais que viriam da eletrônica de front-end, mas desta forma sabendo

o formato deste sinal.

7

2.1 Especificações do Projeto

Após a concepção da idéia inicial do projeto, foi feito o levantamento das exigências e

especificações que o projeto deveria ter. Estas são:

• O módulo ou placa com o FPGA a ser implementado o projeto deve ser

compatível com a interface elétrica dos módulos de aquisição usados, que neste

caso recebiam sinais com níveis de tensão especificados pelos padrões LVDS e

NIM.

• O gerador deve ser desenvolvido como um bloco a parte da entidade de nível

superior do projeto, de modo que possa ser duplicado nesta entidade para se

obter qualquer número de canais desejados.

• O gerador deve ter um sinal correspondente à saída de pulsos, um sinal de

clock, um sinal de reset e quatro vetores de 16 bits correspondentes aos

parâmetros controlados pelo usuário, que são expostos a seguir:

o Period: Tempo (em unidades de clock) entre o início de cada pulso.

o Width: Tempo (em unidades de clock) em que cada pulso permanecerá

em valor lógico alto.

o N: Número de pulsos a ser dados após cada reset.

o Delay: Tempo de atraso (em unidades de clock) em relação ao disparo

do gerado.

• O projeto deve ter um conjunto de registradores em sua entidade de nível

superior onde são guardados os parâmetros controláveis de cada gerador e deve

fornecer uma interface e método de escrita a partir de um computador.

• Deve ser possível disparar os geradores através de um sinal de entrada externo

ou através de comando pela interface de escrita nos registradores.

2.2 Plataforma V1495

O Módulo VME V1495 foi a plataforma escolhida para desenvolvimento e

implementação do projeto.

8

Figura 2: Módulo VME V1495

O V1495 é um módulo VME de uso geral aplicável para vários fins como gerador de

sinal de “gate”, gerador de sinal de “trigger”, conversor de sinais, buffers e aplicações de

9

teste, as quais podem ser diretamente customizáveis pelo usuário. A placa é gerenciada por

dois FPGAs, o Bridge e o User. O FPGA Bridge, é responsável pela interface VME e conexão

do FPGA User ao VME através do barramento local proprierário. Este também gerencia o

upload da programação para o FPGA User. O FPGA User é um FPGA modelo Altera

Cyclone EP1C20 que gerencia os canais de I/O do painel frontal e é substancialmente um

FPGA vazio que pode ser programado pelo usuário da forma como desejar.

O V1495 possui um painel frontal com 64 canais de entrada digital podendo ser

configuráveis como tipos de entrada LVDS, ECL e PECL, e podendo ser expandidos para até

162 canais. O V1495 também possui 32 canais de saída digital do tipo LVDS, podendo ser

expandido até 130 canais.

O módulo suporta a frequência máxima de 405MHz de clock para a lógica

implementada no FPGA User, possui tempos de atraso menores que 15 ns para as saídas e

entradas digitais e também LEDs programáveis.

Os canais de entrada e saída LVDS são divididos em portas de 32 canais, nomeadas A,

B e C podendo ser expandidas como D, E e F com módulos expansores. Adicionalmente

também há 2 canais NIM que podem ser configurados como entrada ou saída, compondo a

porta G.

O diagrama de blocos do módulo V1495 pode ser visto na Figura 1.

Figura 3: Diagrama de blocos do módulo V1495.

10

O módulo V1495 foi escolhido para a implementação da primeira versão do gerador

por já dispor de toda a interface necessária para cumprir com os requisitos do sistema.

2.3 Interface de Acesso aos módulos VME

2.3.1 Interface de Hardware

O módulo V1495 em sua configuração sem os módulos expansores, contém 2 portas

de entrada A e B, cada uma com 32 canais de sinal LVDS, ECL ou PECL, tendo impedância

de 100 ohm, banda passante de 200 MHz e dispostas na frente do módulo por 2 conectores

tipo Robinson Nugent P50E-068-P1-SR1-TG type, (34+34) pinos. O módulo dispõe de uma

porta de saída C, com 32 canais de sinal somente LVDS e o mesmo tipo de conector que as

portas A e B, diferindo destas somente pela banda passante de 250 MHz. O módulo também

dispõe de uma porta G de 2 canais de sinal NIM ou TTL, configuráveis entre entrada e saída,

com impedância de 50 ohm e banda passante de 250 MHz.

Podemos ver na Figura 3 o posicionamento das portas A, B, C e G.

11

Figura 4: Parte frontal do módulo V1495.

A interface de comunicação entre o módulo V1495 e o software de controle executado

em um computador é dada através do módulo tipo “bridge” V1718. O V1495 é ligado ao

barramento VME, o FPGA Bridge gerencia a comunicação entre o FPGA User e o

barramento VME. O barramento VME é gerenciado pelo módulo V1718, que deve ser único

12

para cada crate VME. O módulo V1718 possui toda interface necessária para se comunicar

com um aplicativo através da porta USB. Não devemos confundir o módulo bridge V1718

com o FPGA bridge do módulo V1495.

Explicando de maneira sucinta, a interface de hardware se resume ao computador

conectado ao V1718 usando um cabo USB como meio físico, o módulo V1718 se

comunicando com o módulo V1495 através do barramento VME e, no módulo V1495, o

FPGA Bridge gerenciando o acesso ao FPGA User através do barramento VME.

2.3.2 Interface de Software

O fabricante dos módulos fornecem os drivers necessários para comunicação do

computador com o módulo bridge V1718 e um conjunto de bibliotecas com funções de acesso

ao barramento VME.

O fabricante também fornece um firmware base de exemplo para o FPGA User onde

há uma camada de abstração de hardware. Nele as portas de I/O, os componentes mais

importantes e a pinagem associada a estes já estão declarados de modo que o usuário pode se

concentrar no desenvolvimento sem precisar ter que pesquisar quais os pinos I/O do FPGA

correspondem a cada saída ou porta do barramento da placa. Neste firmware há um código de

exemplo com uma lógica básica e um conjunto de registradores, de leitura, escrita e

leitura/escrita também com a lógica necessária para acessar esses registradores através do

barramento VME.

A interface de acesso aos registradores do firmware de exemplo do V1495 é composta

por um sinal que diz quando houve acesso do usuário e outro que dita se é de leitura ou

escrita. A cada clock ocorre a checagem do sinal de acesso do usuário, se este estiver ativo, o

registrador correspondendo ao barramento de endereço recebe o valor do barramento de dados

caso o comando seja de escrita, ou o referido registrador expõe seu conteúdo no barramento

de dados caso o comando seja de leitura. Como mencionado anteriormente há um sinal que

dita se o acesso é de escrita ou leitura. O o barramento é ligado ao barramento de dados

através de um multiplexador que é implementado pela estrutura de código “when”. Abaixo

exibimos em pseudo-código a implementação do acesso aos registradores:

13

process (clock) if (usuário_acessou) then if (tipo_acesso = escrita) then case (barramento_endereço) is when endereço_1 => registrador_1 <= barramento_dados; when endereço_N => registrador_N <= barramento_dados; end case; elsif (tipo_acesso = leitura) then case (barramento_endereço) is when endereço_1 => barramento_dados <= registrador_1; when endereço_N => barramento_dados <= registrador_N; end case; end if; end if; end process;

O envio dos sinais de controle, do valor de endereço e de dados para serem recebidos

pela dita interface ocorre através do barramento VME pelo módulo bridge V1718, este por

sua vez recebe os comandos e dados do software em execução no computador através da

interface USB.

O fabricante fornece uma biblioteca com as funções de envio dos comandos em

questão e cabe ao usuário desenvolver um software que gerencie o uso dessas funções e

forneça uma interface de usuário para que este possa controlar os registradores do módulo

V1495 através do computador.

2.4 Desenvolvimento e Funcionamento do Gerador

A primeira versão do gerador foi desenvolvida no laboratório multiusuário do

LAFEX/CBPF. Até que chegasse à versão funcional, houveram algumas tentativas e uma

série de aprimoramentos que culminaram no circuito que veio a ser a primeira versão do

gerador.

Desde o início, a idéia básica do gerador era ser um bloco que recebia os quartos

parâmetros controláveis pelo usuário (largura de pulso “width, período “period”, número de

pulsos “N” e defasagem “delay”), um sinal de reset e o clock, e gerasse os pulsos através de

um sinal de saída.

14

Figura 5: Representação em bloco simplificado do primeiro gerador.

O primeiro gerador foi implementado com todos os componentes em um único bloco,

sem sub-divisões (como foi feito na segunda versão) e por isso o desenvolvimento foi de certa

forma dificultado. Inicialmente foi usado VHDL mas por a primeira versão ser assíncrona e

envolver tantas variáveis dependentes umas das outras o desenvolvimento chegou em um

nível de complexidade impraticável. Por isso a parte principal da primeira versão do gerador

foi desenvolvido em diagrama de circuito e depois transcrito para VHDL. O esbolço pode ser

visto na Figura 5.

O gerador compreende um contador, que é um registrador de 16 bits representado no

esboço como “cont”, que conta de 0 até o valor do período gravado no registrador “period”. O

contador é zerado quando seu valor se iguala ao valor do período. Caso haja um reset, o

contador vai para seu valor inicial que é o período menos o delay mais um. Isto é feito para

que ao iniciar a contagem, o contador se atrase o valor escrito em “delay”, que é a defasagem

para dado canal.

Na saída do contador cont há um comparador que compara seu valor com a largura de

pulso width. Enquanto cont é menor que width, a saída é alta, quando cont ultrapassa width o

valor da saída do comparador é baixo. Dessa forma a largura de pulsos é dada por o número

gravado em width, em ciclos de clock. Na saída do referido comparador há um multiplexador

que permite habilitar ou desabilitar a saída do gerador. Quando ativo, a saída do gerador

recebe o valor do comparador, caso contrário recebe zero. Este multiplexador foi mais tarde

simplificado para uma simples porta AND.

15

Figura 6: Esboço do diagrama de blocos do primeiro gerador.

Usando a saída do comparador da largura de pulso como clock, temos um contador

representado no diagrama por “pulses” que conta o número de pulsos dados. Para cada pulso

gerado pelo comparador na saída de cont é incrementado 1 no valor de pulses. Quando o valor

de pulses ultrapassa o valor do registrador “N”, que guarda o número de pulsos a ser gerado

após cada reset, a saída do comparador de N desabilita a saída do gerador, tornando esta zero.

Caso o valor de N seja zero, o gerador não é cortado após atingir certo número de pulsos,

desta forma gerando pulsos indefinidamente até que seja resetado.

A entidade de nível superior do gerador foi desenvolvida a partir do firmware base de

exemplo provido pelo fabricante do módulo. Esta compreendia um número de blocos

16

geradores declarados como entidade correspondendo ao número de canais em que se queria

gerar pulsos, um grupo de 4 registradores de 16 bits para guardar os parâmetros controláveis

de cada canal e uma interface de acesso para que todos os registradores de controle fossem

acessíveis pelo usuário via software.

2.5 Software de Controle

Para que o usuário pudesse ter controle do gerador a partir do computador, assim

como programar rotinas de teste automatizadas, foi desenvolvido os softwares de controle. A

plataforma usada no desenvolvimento foi Linux (Ubuntu) e os softwares foram desenvolvidos

em linguagem C utilizando as bibliotecas com funções de acesso ao barramento VME

fornecidas pelo fabricante dos módulos.

Foi desenvolvido dois aplicativos. Um com uma interface de usuário amigável e o

outro acessado apenas por linha de comando, sendo este último para ser utilizado por scripts

no Linux.

2.6 Limitações

A maneira que executamos o projeto da primeira versão do gerador logo deixou claro

que haveriam algumas limitações.

A primeira limitação é que por a entidade de nível superior ser baseada em um

firmware de exemplo especificamente desenvolvido para o módulo V1495, a qualquer

momento que precisássemos migrar de plataforma teríamos que refazer a entidade de nível

superior.

A segunda limitação é a interface de acesso, que por depender totalmente da interface

de hardware dos módulos da CAEN e do VME, para qualquer outra aplicação o sistema

ficaria limitado, se fazendo necessário a criação de uma nova interface de acesso assim como

drivers e novos aplicativos com interface de usuário a ser executado pelo computador. Ou

seja, o sistema do gerador em sua primeira versão ficou dependente por completo da

plataforma em que foi implementado.

A terceira limitação foi o fato de ter sido desenvolvido de forma assíncrona. Apesar de

não ter ficado evidente durante as etapas de projeto do primeiro gerador, após este ter sido

concluído um estudo mais aprofundado da arquitetura do FPGA demonstrou que os sinais

usados para disparar os flip-flops do projeto assíncrono são considerados pelo FPGA como

17

sinais de clock e precisam de vias internas especiais para que seja distribuído entre todas as

células lógicas que fazem uso de tal sinal de forma otimizada, visando minimizar o atraso de

propagação. Por exemplo, imaginando que o contador principal de todos os blocos de gerador

do sistema sejam disparador por um mesmo sinal de trigger, é necessário que este sinal seja

propagado por uma via dedicada ao clock, caso contrário terá atraso de propagação e um

contador pode ser iniciado atrasado em relação aos demais.

Todas estas limitações aqui citadas a respeito da primeira versão do gerador foram

superadas com a segunda versão do gerador, cuja intensão era justamente suprimir todos esses

problemas.

18

Capítulo 3

3. Segunda Versão do Gerador

A segunda versão do gerador foi desenvolvida com o objetivo de solucionar alguns

problemas encontrados durante o desenvolvimento da primeira versão e adicionar algumas

funcionalidades e características que foram idealizadas a medida que a primeira versão do

gerador ia sendo implementado.

Essa nova versão foi desenvolvida do zero, com o objetivo de dividir o processo de

desenvolvimento em etapas simples e modulares, visando uma organização melhor para

futuras alterações, desenvolvimento, e facilitar o entendimento de quem vier a usar. O projeto

foi também todo reescrito de maneira síncrona, visando otimizar o uso em FPGAs e permitir

ao desenvolvedor ter uma percepção melhor do comportamento esperado do circuito.

A idéia de refazer toda a primeira versão do gerador partiu de uma sugestão do Prof.

Jesse Costa para adaptar o gerador de forma que ele funcionasse de forma genérica e

adaptável ao maior número possível de plataformas baseadas em FPGA a fim de poder ser

usado para outras aplicações, se não a tão específica que era o objetivo inicial. Observou-se

que seria um processo trabalhoso a adaptação do código uma vez que este não estava dividido

em partes organizadas. Por isto surgiu a idéia de refazer todo o projeto, simplificando,

otimizando e adaptando-o às novas especificações do sistema.

Para o desenvolvimento da segunda versão do projeto foi usada uma plataforma de

desenvolvimento de FPGA da Avnet, baseada em um FPGA da família Spartan-6 da Xilinx.

O principal desafio era criar o circuito de forma que seu uso fosse prático e de fácil adaptação

para qualquer plataforma, e também de forma que sua interface com o computador fosse

independente do hardware da placa em que o FPGA estivesse instalado.

3.1. Especificações do Projeto

Dada a experiência e os resultados obtidos com a primeira versão do gerador, foi

criado novas especificações para o projeto, as quais são:

• O projeto deveria ser simples e executado da forma mais trivial possível de

modo a facilitar sua implementação nas mais diversas plataformas em que

pudesse ser usado, visando tornar o projeto o mais genérico possível.

19

• O gerador deve ser desenvolvido como um bloco a parte da entidade de nível

superior do projeto, de modo que possa ser duplicado nesta entidade para se

obter qualquer número de canais desejados.

• O gerador deve ter um sinal correspondente à saída de pulsos, um sinal de

clock, um sinal de trigger, um sinal de veto e quatro vetores de 16 bits

correspondentes aos parâmetros controlados pelo usuário, que são expostos a

seguir:

o Period: Tempo (em unidades de clock) entre o início de cada pulso.

o Width: Tempo (em unidades de clock) em que cada pulso permanecerá

em valor lógico alto.

o N: Número de pulsos a ser dados após cada reset.

o Delay: Tempo de atraso (em unidades de clock) em relação ao disparo

do gerador.

• O gerador deve ser engatilhado sempre que o sinal de trigger alternar de nível

lógico baixo para alto.

• O gerador deve ter seu funcionamento cessado sempre que o sinal de veto

alternar seu nível lógico de baixo para alto.

• O projeto deve ter uma caixa de registradores em sua entidade de nível

superior onde são guardados os parâmetros controláveis de cada gerador e deve

fornecer uma interface e método de escrita a partir de um computador.

• Deve ser possível disparar e vetar os geradores através de um sinal de entrada

externo ou através de comando pela interface de escrita nos registradores.

3.2 Placa de Desenvolvimento LX9 MicroBoard

Para o desenvolvimento da segunda versão do gerador foi utilizado a placa de

desenvolvimento Avnet LX9 MicroBoard.

Esta é uma placa que possui um FPGA XC6SLX9 da família Spartan-6 do fabricante

Xilinx, 64 MB de memória SDRAM, 128 MB de memória Flash acessada por SPI, interface

ethernet de 10/100, conversor integrado USB-UART, circuito JTAG integrado acessado por

USB, 16 pinos de I/O genéricos, circuito integrado gerador de clock programável, além de ter

4 LEDs, um DIP switch de 4 bits, um botão de reset e um push-button programável como

interface de usuário.

20

Uma imagem da placa pode ser vista na Figura 6:

Figura 7: Vista superior da placa de desenvolvimento LX9 MicroBoard.

A escolha desta placa de desenvolvimento foi especialmente conveniente por conter o

circuito integrado CP2102 que é um conversor USB-UART e deste modo já é fornecido a

interface de hardware necessária para realizar a comunicação entre o aplicativo no

computador e o FPGA.

3.3 FPGA

Os FPGAs (Field Programable Logic Array) são dispositivos semicondutores que

dispõem de um circuito digital reprogramável, que pode assumir várias funções lógicas

diferentes.

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

entrada e saída (IOB), blocos lógicos configuráveis (CLB) e matriz de interconexão (Switch

Matrix).

Os CLB (Configuration Logical Blocks) são circuitos idênticos, espalhados como

células por uma grande área do FPGA formando uma matriz bidimensional, construídos pela

reunião de flip-flops e a utilização de lógica combinacional para que este bloco possa

desempenhar a função de qualquer unidade lógica básicas, de maneira que a conexão de

vários destes executandos várias funções diferentes possa formar circuitos lógicos complexos

e permitir ao usuário uma grande flexibilidade.

Os IOB (Input/Output Blocks) são circuitos responsáveis pelo interfaceamento das

saídas provenientes das saídas das combinações de CLBs. São basicamente buffers que

funcionarão como um pino bidirecional entrada e saída do FPGA.

21

A Matriz de Interconexão (Programmable Interconnect) são trilhas utilizadas para

conectas CLBs e IOBs entre si. Este terceiro grupo é composto pelas interconexões. Os

recursos de interconexões possuem trilhas para conectar as entradas e saídas dos CLBs e IOBs

para as redes apropriadas através de canais de roteamento horizontais e verticais entre as

linhas e colunas dos blocos lógicos. É através da capacidade da matriz de interconexão de

conectar vários blocos CLB entre si e à IOBs que o FPGA provê ao usuária tamanha

flexibilidade na implementação de circuitos digitais. Geralmente, a configuração é

estabelecida por programação interna de células de memória, estáticas ou dinâmicas, que

determinam funções lógicas e conexões internas implementadas no FPGA entre os CLBs e os

IOBs. O processo de escolha das interconexões é chamado de roteamento.

Figura 8: Arquitetura padrão de um FPGA moderno.

No interior dos blocos lógicos configuráveis de um FPGA existem vários modos

possíveis para implementação de funções lógicas. O mais utilizados pelos grandes fabricantes

de FPGA, como, por exemplo, a Altera, são os blocos de memória LUT (Look-Up Table).

Esse tipo de bloco lógico contém células de armazenamento que são utilizadas para

22

implementar pequenas funções lógicas. Cada célula é capaz de armazenar um único valor

lógico: zero ou um.

Nos FPGAs disponíveis comercialmente como, por exemplo, da empresa Altera Corp.,

os blocos lógicos LUTs possuem geralmente quatro ou cinco entradas, o que permite

endereçar 16 ou 32 células de armazenamento. Quando um circuito lógico é implementado

em um FPGA, os blocos lógicos são programados para realizar as funções necessárias, e os

canais de roteamento são estruturados de forma a realizar a interconexão necessária entre os

blocos lógicos.

As células de armazenamento dos LUTs de um FPGA são voláteis, o que implica

perda do conteúdo armazenado, no caso de falta de suprimento de energia elétrica. Dessa

forma, o FPGA deve ser programado toda vez que for energizado. Geralmente utiliza-se uma

pequena memória FLASH EEPROM (Electrically Erasable Programmable Read Only

Memory) cuja função é carregar automaticamente as células de armazenamento, toda vez que

o FPGA for energizado.

O FPGA contido na placa LX9 MicroBoard é um Spartan-6 XC6SLX9 produzido pela

Xilinx. Este utiliza a lógica de LUTs (look-up table) com 6 entradas e 2 flip-flops e contém

9152 células lógicas, 2 PLLs para multiplicação do clock e um total de 200 I/Os.

Cada CLB ou Bloco Lógico Configurável da série Spartan-6 consiste em duas fatias,

arranjadas lado a lado como parte de duas colunas verticais. Há três tipos de fatias na

arquitetura Spartan-6: SLICEM, SLICEL e SLICEX. Cada fatia contém quatro LUTs, oito

flip-flops e lógica variada. Os tipos de fatia serão vistos a seguir:

SLICEM constituem 25% do total do FPGA e cada uma pode ser configurada como

uma LUT de 6 entradas e uma saída ou como duas LUTs de 5 entradas com endereços de 5

bits idênticos e duas saídas independentes. Estas LUTs podem ser usadas também como

memórias RAMs distribuídas de 64 bits, como um registrador de deslocamento de 32 bits ou

como 2 registradores de deslocamento de 16 bits com comprimento endereçável. Cada saída

da LUT pode ser registrada em um flip-flop interno à CLB.

SLICEL constituem 25% do total do FPGA e contém todos os recursos da fatia

SLICEM exceto a função de memória RAM e registradores de deslocamento.

SLICEX constituem 50% do total do FPGA e contém os mesmos recursos que a fatia

SLICEL exceto a opção de carry aritmético e os multiplexadores amplos.

23

3.4 Projeto Síncrono vs Assíncrono

Como veremos em uma descrição mais detalhada a seguir, o gerador utiliza um sinal

de clock como base de tempo e vários outros sinais como trigger de diversos contadores nos

blocos do gerador. O gerador possui um bloco para controle dos pulsos e ele todo funciona a

base de contadores que contam quantos clocks se passaram para então iniciar ou encerrar um

pulso. Tem a unidade de delay que cria uma defasagem programada em cada canal que

funciona tendo o clock do gerador como referência e há uma unidade que conta o número de

pulsos dados até o momento para controlar a quantidade de pulsos por trem. Este contadores

utilizam sinais que não são o clock principal como gatilho. O contador é engatilhado e vetado

por dois sinais externos.

A maneira mais fácil de ter sinais engatilhando sistemas ou contadores é utilizar estes

sinais como o clock de flip-flops. No entanto, o FPGA em sua arquitetura interna separa vias

dedicadas a sinais de clock, e interpreta qualquer sinal que dispare um flip-flop como sinal de

clock. Isto é porque ele julga que estes sinais que disparam os flip-flops tem requisitos de

timing muito exigentes para que todos os flip-flops sejam disparados em tempos bem

próximos.

Os sinais no FPGA podem ser propagados através das vias normais da matriz de

interconexão ou através das células lógicas, porém, estas geram atrasos nos sinais. Por este

motivo que há vias dedicadas aos sinais de clock ao longo do FPGA. O grande problema é

que não há vias suficientes para cada sinal de gatilhos dos flip-flops do gerador se este usar

vários sinais diferentes como gatilho, como discutido anteriormente.

Deste problema, surgiu a necessidade de adaptar todo o projeto para funcionar em

função somente de um único sinal de clock, de maneira síncrona. O projeto havia sido

totalmente escrito de forma assíncrona e já estava sendo implementado na placa, mas quando

se negligenciava o uso das vias especiais de clock para os sinais internos de gatilho o gerador

funcionava de maneira estável como previsto.

Por estas causas o projeto foi reescrito de forma a se tornar completamente síncrono de

forma a só precisar propagar um sinal de clock ao longo de todo o circuito.

24

3.5 Visão Geral da Top Level Entity

A Entidade de Nível Superior ou “Top Level Entity” é o bloco de maior hierarquia em

um dispositivo reprogramável.

No desenvolvimento de circuito digitais, para simplificação e otimização do trabalho

separamos as diferentes partes do circuito que desempenham uma certa função em blocos.

Todos esses blocos são interconectador na Entidade de Nível Superior. É nela onde se tem a

visão geral do que está a ser implementado no FPGA.

A segunda versão do gerador compreende os seguintes componentes:

• Divisor de Frequência

• Arquivo de Registradores (proporcional ao número de canais do gerador)

• Unidades Geradoras (uma por canal)

• Buffer de dados de entrada

• Comparador

• Receptor UART

• Transmissor UART

O diagrama de blocos do gerador pode ser visto na Figura 8.

25

Figura 9: Diagrama de blocos da entidade de nível superior do gerador.

Nos capítulos seguintes abordaremos detalhadamente cada um dos blocos que a entidade de nível superior compreende e explicaremos a relação entre eles.

26

3.6 Gerador Controlável

O coração do projeto é o bloco gerador de pulsos. Este foi projetado de modo

independente do restante do circuito para que tivesse a versatilidade de poder ser

implementado em qualquer plataforma e também poder ser duplicado dentro de um projeto

para que seja possível obter quantos canais de saída foram necessários.

O gerador é controlado por quatro parâmetros de 16 bits e 2 sinais de controle

conforme a Figura 9.

Figura 10: Representação do bloco da segunda versão do gerador.

O que o diferencia da versão anterior apresentada na Figura 4, em termos de entrada, é

a substituição do sinal “reset” pelos sinais “trigger” e “veto” que são responsáveis por

disparar e interromper o funcionamento do gerador respectivamente e um sinal de clock

adicional que é somente para a geração de pulsos. Isto permitiu um maior controle do gerador

e uma implementação mais simplificada da interface de controle. Outra grande diferença é

que este gerador é síncrono enquanto a versão antiga era assíncrono.

Esta versão possui dois clocks. Um é proveniente de um divisor de frequência externo

ao gerador e através dele pode-se criar pulsos mais longos, não ficando limitado aos pulsos

com período de 16 bits de ciclos do clock principal. Este é usado na unidade geradora de

pulsos e no atrasador. O outro é o clock principal do circuito e é usado para os circuitos que

detectam quando há mudança nos sinais. Uma vez que o circuito agora é síncrono, os

contadores não são mais disparados por sinais ligados direto na entrada de clock, mas sim de

comparadores formados por flip-flops que comparam o sinal anterior com o atual. Flip-flops

27

esses que são disparados com o clock do sistema, que deve ser o mais rápido possível e com

frequência igual ou maior ao clock do gerador.

O gerador é disparado na subida o sinal de trigger e começa a gerar após “delay”

ciclos de clock. Passado o tempo de delay, o gerador emitirá “N” pulsos de largura “width”

com distância “period” entre eles. O gerador cessará os pulsos automaticamente quando o

número de pulsos dados alcançar N ou quando o sinal de “veto” ir de zero para um. Caso “N”

seja igual a zero, o gerador emitirá pulsos indefinidamente até que ocorra a subida do sinal de

veto.

A segunda versão do gerador compreende os seguintes blocos:

• Unidade geradora (Generator Unit): Responsável pera geração dos pulsos.

• Atrasador (delayer): Responsável pelo atraso do delay.

• Contador de pulsos (Pulses Counter): Responsável por cessar a geração de

pulsos após alcançado o número de pulsos pretendido.

• Degrau: Bloco responsável por transformar a subida do VETO em um sinal

interno de degrau com o objetivo de vetar o gerador até que haja um novo

gatilho.

• Pulso: Bloco responsável por transformar a subida do TRIGGER em um pulso

interno que iniciará a operação do gerador.

O diagrama de blocos da segunda versão do gerador pode ser visto na Figura 10 (as

entradas correspondentes aos parâmetros de controle de 16 bits foram omitidas para melhor

visualização):

28

Figura 11: Diagrama de blocos da segunda versão do gerador.

3.6.1 Delayer

A unidade Delayer é responsável por atrasar o início da operação da unidade geradora.

Dessa forma é possível configurar defasagem entre diferentes canais.

O bloco de delayer recebe o parâmetro “delay” de 16 bits, um sinal de reset, o sinal de

clock do gerador e o sinal de clock do sistema. Quando é dado o trigger do gerador, um

contador começa a contar os ciclos do clock do gerador e mantém a unidade geradora

desabilitada até que o contador alcançe o número de clocks correspondente ao parâmetro

delay. Ao alcançar este, ele habilita a unidade geradora para que esta começe a emitir pulsos.

Desta forma é obtido o atraso em ciclos de clock, antes do início da operação do gerador após

um sinal de trigger.

Para que a unidade delayer haja de forma síncrona ele utiliza dois clocks. O clock do

sistema e o clock do gerador. O clock do sistema é o que engatilha cada comparação entre o

29

estado atual e o último estado do clock do gerador. Cada vez que o estado atual do clock do

gerador for 1 e o estado anterior for 0 significa que houve uma subida do clock e então o

contador é incrementado em um.

Inicialmente o próprio sinal do clock do gerador engatilhava o contador, tornando o

circuito bem mais simples. No entanto, devido a limitação do FPGA usar os sinais de gatilho

de flip-flops através das vias especiais de clock, se fez necessário a mudança.

Sempre que há um evento de subida no sinal de trigger do gerador, o contador é

zerado e volta a contar do zero. Quando o contador alcança o valor de delay, este também

cessa sua operação até que haja um novo sinal de trigger.

Abaixo na Figura 11 vemos uma ilustração da operação do bloco delayer, onde a

primeira forma de onda é o sinal de trigger do gerador, a segunda é o contador do delayer e a

terceira é a saída do gerador.

Figura 12: Ilustração do funcionamento do bloco delayer.

3.6.2 Pulses Counter

Este bloco é responsável por vetar o sinal de saída do gerador quando o número de

pulsos emitidos atingir o numero de pulsos desejado.

O bloco consiste em um contador que conta o número de pulsos emitidos. Consiste em

um registrador de 16 bits que incrementa de um sempre engatilhado quando há borda de

descida do sinal de saída do gerador. Os flip-flops do contador não são engatilhados

diretamente pelo sinal de saída do gerador devido ao problema de clock assíncrono já

mencionado anteriormente. No lugar disto, usamos um flip-flop que a cada pulso do clock

registra o sinal de saída do gerador e um comparador, que compara o valor desse flip-flop ao

valor da saída do gerador. O valor do flip-flop sempre corresponderá ao valor anterior ao

30

presente do sinal de saída do gerador. Comparando este sinal com o sinal atual podemos

atestar que houve uma mudança no sinal do gerador. Como mencionado, sempre que essa

mudança é uma borda de descida, ou seja, quando o sinal anterior é ‘1’ e o atual é ‘0’, o

contador é incrementado de uma unidade.

O bloco recebe um parâmetro de entrada de 16 bits correspondente ao número de

pulsos que deve ser emitido por cada trem de pulsos. Este valos fica guardado num

resgistrador e um comparador avalia se o numero de pulsos dados registrado no contador já

alcançou o número de pulsos a serem dados. O sinal desse comparador vai para ‘1’ quando o

contador alcança o número de pulsos a ser dado. A saída deste comparador é ligada à entrada

de veto do gerador e por isto os pulsos cessam quando a saída do comparador é setado.

Na Figura 12 podemos observar o comportamento do bloco contador de pulsos.

Figura 13: Ilustração do funcionamento da unidade pulses conter.

31

3.6.3 Generator Unit

A unidade geradora de pulsos é a responsável pela geração propriamente dita dos

pulsos, é o coração do gerador.

Esta recebe dois parâmetros de 16 bits, que são a largura de pulso ‘width’ e a distância

entre o início de cada pulso ou período ‘period’. Ambos os parâmetros são dados em ciclos de

clock e guardados em registradores externos ao gerador.

O gerador compreende um contador que conta os ciclos do clock do gerador, um

circuito comparador para indicar quando o contador alcança o valor de ‘width’ e outro para

indicar quando o contador alcança o valor de ‘period’.

Partindo do zero, o contador inicia a contagem quando ocorre a transição de subida do

sinal de trigger. Neste momento o sinal de saída do gerador vai para ‘1’ e permanece até que

o valor do contador atinja o valor especificado pelo parâmetro ‘width’. Quando isto ocorre o

sinal de saída do gerador retorna a ‘0’ e permanece até o reset do contador. O contador segue

incrementando 1 a cada ciclo de clock do gerador até que este atinja o valor do período, que é

dado pelo parâmetro ‘period’ decrescido de uma unidade. Neste momento o contador é

zerado, o sinal de saída do gerador volta a ‘1’ e o contador inicia a contagem do zero.

Desta forma a unidade geradora gera pulsos que permanecem em nível lógico alto

durante ‘width’ ciclos de clock e retorna a nível lógico baixo até que atinja ‘period’ ciclos de

clock.

O contador só permanece ativo enquanto seu sinal de reset está em nível lógico baixo.

A qualquer momento em que este sinal está em nível alto, o contador é zerado e a saída do

gerador resetada.

Na Figura 13 podemos ver um gráfico que ilustra o funcionamento da unidade

geradora.

32

Figura 14: Ilustração do funcionamento da unidade geradora.

3.7 Interface Serial UART

O programa do projeto contemplava a criação de uma interface de acesso para que o

usuário pudesse facilmente configurar o gerador a partir de um computador. A interface

escolhida para comunicação entre o circuito e um aplicativo no computador foi a UART

(Universal Assynchronous Receiver Transmitter).

Essa escolha se deu ao fato de a comunicação assíncrona só utilizar 2 pinos de IO, no

caso da unidirecional, e 3 pinos no caso da bidirecional e ser um padrão bem popular, com um

número bem grande de conversores USB-UART a baixo preço no mercado, e de fácil

desenvolvimento de softwares de acesso. Os pinos usados são um para envio de dados, um

para recebimento e um para tensão de referência. Outro fator que motivou a escolha da

interface UART foi o fato de que a placa de desenvolvimento utilizada no projeto já

compreendia um conversor USB-UART integrado, o que permitia ligar a placa diretamente na

porta USB do computador para controlar o circuito, nos poupando da necessidade de adquirir

hardware adicional para executar o projeto. A grande maioria das placas de desenvolvimento

para FPGA atuais já compreende algum tipo de circuito conversor USB-UART.

Na Figura 14 podemos ver a porta USB utilizada no projeto.

33

Figura 15: Placa Avnet LX9 conectada à USB pela porta UART.

A interface UART é dividida em 2 blocos, um responsável pela recepção dos dados e

outro responsável pelo envio.

3.7.1 Protocolo Serial

O protocolo de comunicação utilizado no projeto é o RS-232 com níveis de tensão de

0V a 3.3V.

Os dados no protocolo RS-232, na forma configurada no projeto, são enviados byte a

byte, através de um frame que compreende 10 bits. Enquanto ociosa, a linha fica com sinal

lógico 1. Para indicar o início da transmissão de um byte é enviado o chamado Start Bit que é

sempre igual a ‘0’. Em seguida são enviados os 8 bits do byte e ao final é enviado o chamado

Stop Bit, sendo este sempre ‘1’, para indicar que o byte já foi transmitido. A linha pode ou

continuar em ‘1’ indicando ociosa, ou emendar em um bit ‘0’ indicando que outro byte está

sendo recebido.

O protocolo é apresentado a seguir na Figura 15:

34

Figura 16: Configuração do protocolo UART usada no projeto.

3.7.2 Unidade Rx

A Unidade Rx é a unidade receptora UART. Ela é responsável por receber o frame de

10 bits através da porta serial, filtrar os 8 bits de dados e expô-los em uma saída paralela.

A Unidade Rx recebe dois sinais de entrada e dois de saída. Como entrada temos o

clock interno da placa e o sinal de dados proveniente do pino receptor da porta serial. Como

saída temos um sinal tipo flag que indica quando um byte foi recebido e está pronto para ser

lido, e o outro é um barramento de 8 bits por onde o byte recebido pode ser lido.

A unidade Rx compreende uma máquina de estado, um registrador de deslocamento

de 8 bits que guarda em sequência os bits recebidos, um contador para marcar o tempo de

cada bit, um contador para controlar o número de bits já recebidos, um registrador que guarda

os 8 bits recebidos ao final de cada leitura e um flip-flop que representa o flag indicador de

byte recebido.

O receptor UART foi implementado através de uma máquina de estado, contendo

quatro estados que podemos observar na imagem abaixo (Figura 16), seguido de uma

explicação sobre cada estado.

35

Figura 17: Diagrama de estados da máquina de estado da unidade UART receptora.

• Wait_Start_bit (Espera Start bit): É o estado inicial do receptor. Neste estado o

receptor fica aguardando uma transição de nível alto para nível baixo no sinal

de entrada da porta serial. No padrão RS232, uma porta em estado ocioso fica

36

em nível lógico alto constante e o que caracteriza o início da transmissão é a

transição de ‘1’ para ‘0’ no sinal durante o tempo de um bit. Isto é o que

caracteriza o “start bit”.

• Start_bit (Recebe Start bit): Logo que o start bit é identificado, o receptor entra

neste estado. Um contador é iniciado do zero e ele esperar o tempo equivalente

a um bit e meio. Isto porque no próximo estado o receptor efetuará a leitura dos

bit e é mais seguro que a leitura seja efetuada no centro da janela de tempo

entre o início e final de cada bit. Esperando um bit e meio, o start bit passará

por completo e o primeiro bit de dados estará aproximadamente na metade.

• Lendo_bits (Lê 1 bit): É o estado em que o receptor guarda o valor recebido na

porta serial. Ligado à entrada da porta serial há um registrador de

deslocamento de 8 bits que é deslocado de 1 e isto que caracteriza a leitura de

um bit. Neste estado o receptor efetua a leitura de 1 bit, incrementa um

contador de bits recebidos e espera mais o tempo equivalente a 1 bit para

efetuar a leitura do próximo, até que o número de bits contados seja 8. Ao

chegar neste ponto, o receptor seta a flag Rx_Flag, que indica que o byte

recebido está pronto para ser lido na saída do bloco receptor da UART, e

avança para o próximo estado, Stop_bit. A Rx_Flag fica em nível alto até o fim

da transmissão do stop bit.

• Stop_bit (Recebe Stop bit): Neste estado, como os 8 bits de dados já estão

guardados no registrador de deslocamento, o receptor apenas esperar a

passagem do stop bit para então voltar ao estado inicial onde fica aguardando

um novo start bit para iniciar uma nova transmissão. Ao terminar o stop bit e

voltar para o estado inicial, o receptor zera o contador e reseta a flag Rx_Flag.

3.7.3 Unidade Tx

A Unidade Tx é a unidade transmissora UART. Ela é responsável por montar e enviar

um frame de 10 bits através do pino de saída da porta serial, a partir dos 8 bits de dados de um

barramento interno.

O bloco que compõe a Unidade Tx recebe três sinais de entrada e dois de saída. Os

sinais de entrada são um sinal de clock, uma entrada paralela de 8 bits e um sinal para iniciar a

transmissão chamado de “go” . Na saída temos um sinal responsável pela transmissão dos

37

frames do protocolo serial com os bits serializados e um sinal tipo flag “Busy” para indicar se

que a porta serial está ocupada, ou seja, está em processo de envio de bits.

A unidade Tx, assim como a unidade Rx, também compreende uma máquina de

estado, no entanto, esta só tem dois estado: o em espera (Idle) e o enviando (Sending). A

unidade Tx adicionalmente compreende um registrador de 10 bits usado para montar o frame

do protocolo serial, um registrador de deslocamento e um contador de tempo que define a

velocidade de transmissão e outro que conta o número de bits enviados.

O primeiro estado, o estado “Idle”, corresponde ao período ocioso da porta serial.

Neste período o nível lógico da saída fica continuamente em ‘1’. Quando há transição do sinal

“go” de nível lógico baixo para alto, ou seja, borda de subida, a unidade Tx inicia a

transmissão. Neste momento, o byte na entrada paralela de dados da unidade Tx é guardado

no buffer interno de 10 bits “outBuff” juntos com o Start bit e o Stop bit, ambos os contadores

são zerados e a operação de envio se inicia. O flag “Busy” é setado e a máquina avança para o

próximo estado, o “Sending”.

O próximo estado é o “Sending”, responsável pelo envio do frame serial armazenado

no buffer interno “outBuff” no estado anterior. A unidade Tx desloca um bit do buffer

“outBuff” para a saída e inicia um contador que indicará quando passou o tempo equivalente a

um bit. Passado este tempo, o contador de bits enviados é incrementado de um, o contador de

tempo é reiniciado e o buffer interno é deslocado novamente, caracterizando assim a

transmissão do próximo bit. O processo é repetido até que 10 bits sejam enviados. Quando

isto ocorre, o estado da máquina retorna a “Idle” ou em espera e o flag “Busy” é resetado.

Enquanto um byte está sendo transmitido e por isto a flag “Busy” está setada, é

possível deixar agendado a transmissão do próximo byte. Se a unidade Tx estiver em estado

Idle, um pulso na entrada “go” iniciará a transmissão do byte na entrada. Se a unidade Tx

estiver em estado Sending, a transmissão do próximo byte ficará agendada e será realizada

assim que a transmissão atual for concluída. Se a unidade Tx estiver em estado Sending e já

houver um byte a ser transmitido em espera, qualquer pulso na entrada Go será ignorado.

Deste modo evitamos que haja um delay entre cada byte enviado pois o circuito utilizando a

porta serial não precisa esperar o término de cada envio para ordenar o próximo, no entando,

ainda é preciso agendar o envio de cada byte à medida que os anteriores forem sendo

enviados.

38

3.8 Entidade Top Level

Esta seção detalha a entidade de nível superior e seus componentes. Como já vimos na

seção 3.5, a segunda versão do gerador compreende os seguintes componentes:

• Divisor de Frequência

• Arquivo de Registradores (proporcional ao número de canais do gerador)

• Unidades Geradoras (uma por canal)

• Buffer de dados de entrada

• Comparador

• Receptor UART

• Transmissor UART

E seu diagrama de blocos pode ser visto na Figura 8.

A entidade de nível superior trabalha utilizando uma fonte de clock externa que é

distribuído para todos os componentes do sistema. Internamente é criado um segundo sinal de

clock, gerado a partir da divisão do clock principal, que é usado para os geradores de pulsos.

O sistema é todo síncrono, desta forma, para melhor funcionamento e precisão, é favorável

que o clock externo seja o maior possível. No entanto, não é interessante que o clock utilizado

nos geradores seja sempre o mais rápido possível, pois os geradores utilizam contadores de 16

bits, limitando a frequência mínima de operação para o clock externo dividido por 216. Por isto

foi criado um divisor de frequência para gerar um segundo clock usado somente para os

geradores. Este divisor de frequência divide em até 231 vezes o clock e é controlado por 2

registradores de 8 bits que podem ser escritos pela interface serial.

O gerador em si são blocos individuais que recebem os parâmetros do trêm de pulsos a

ser gerado e tem uma única saída, podendo ser atribuída a um pino de I/O. Desta forma

podem ser replicados para o número de canais que for necessário, respeitando os limites de

espaço e número de I/O do FPGA sendo usado. Neste projeto, os sinais de veto, trigger e

clock são compartilhados entre todos os blocos geradores.

Os blocos geradores recebem os quatro parâmetros individuais de uma caixa de

registradores, que no código VHDL é declarado como um vetor de sinais de 16 bits. Isto

significa que a caixa de registradores tem pelo menos 4 registradores para cada gerador. Nesta

mesma caixa está armazenada os registradores que controlam o divisor de frequência.

Na entidade de nível superior é também onde está a interface de escrita nos

registradores da caixa de registradores, que armazena os parâmetros dos blocos

39

geradores.Todos os bytes recebidos são armazenados em um buffer de 5 bytes e exite um

comparador para interpretar o comando que está contido neste buffer.

As seguintes operações podem ser interpretadas pela interface de escrita nos

registradores:

• Disparo dos geradores: Este comando é executado através de um pulso dado

nas entradas de trigger dos geradores e ocorre quando o comparador identifica

os bytes correspondentes pela tabela ASCII aos 5 caracteres “start” no buffer,

ou seja, para iniciar a operação dos blocos geradores, basta enviar a palavra

“start” pela porta serial.

• Veto dos geradores: Este comando é executado através de um pulso dado nas

entradas de veto dos blocos geradores e ocorre quando o comparador identifica

os bytes correspondentes pela tabela ASCII aos 4 characteres “stop” nos 4

primeiros bytes do buffer da porta serial. Para cessar a operação de todos os

blocos geradores, basta enviar a palavra “stop” pela porta serial.

• Escrita em um registrador: Este comando escreve um valor de 16 bits em um

dos registradores da caixa de registradores. Ele é executado quando o

comparador identifica os bytes correspondente pela tabela ASCII aos

caracteres ‘#’ e ‘*’ nos primeiro e último registrador do buffer da porta serial

respectivamente. Quando isto ocorre, o quarto byte do buffer será o endereço

do registrador a ser escrito e o segundo e terceiro bytes serão o dado a ser

escrito.

Desta forma é possível iniciar e cessar a operação do gerador assim como alterar

qualquer de seus parâmetros em tempo de execução pela porta serial.

3.9 Software para Controle

Para facilitar e automatizar o controle do gerador através da porta serial foi criado uma

aplicação gráfica para ambiente Windows.

O conceito da aplicação é criar uma interface fácil para automatizar o envio de

comandos para o gerador através de uma porta serial. Através desta se poderia editar os

parâmetros de cada canal e enviá-los para o gerador de forma simples.

A linguagem de programação escolhida para desenvolvimento da aplicação foi Object

Pascal e o desenvolvimento foi feito no ambiente de desenvolvimento integrado Lazarus para

Windows. Esta escolha se deu devido ao fato do desenvolvedor já ter experiência com a

40

plataforma Delphi que usa a mesma linguagem, e a escolha da plataforma Lazarus se deu por

ser uma plataforma livre e de código aberto.

Abaixo podemos ver na Figura 17 a interface gráfica de usuário do aplicativo de

controle do gerador:

Figura 18: Interface gráfica do aplicativo de controle do gerador.

Esta aplicação foi desenvolvida especificamente para testes e portanto foi

implementado somente para 4 canais.

Para iniciar o uso do aplicativo, a primeira coisa necessária a se fazer é conectar o

gerador à porta serial e selecioná-la através do combobox onde se vê escrito “Porta” na

imagem. Ao fazer isto o aplicativo abre uma conexão serial com a porta selecionada e aguarda

algum comando.

Para dar partida nos geradores, que é equivalente a escrever a palavra “start” na porta

serial, basta apertar o botão “Trigger”.

Para vetar a operação dos geradores, basta apertar o botão “Veto” e este enviará a

palavra “stop” pela porta serial, que é o comando para tal.

Para alterar qualquer dos parâmetros dos geradores, basta alterar os valores nas caixas

de texto. O valor escrito acima das colunas ditam o número do canal em que se está alterando

os parâmetros e o texto à esquerda das caixas de texto indicam quais dos quatro parâmetros

corresponde a linha de caixas de texto. Ao concluir a seleção dos valores, basta clicar em

41

“Enviar” e o aplicativo enviará o comando para a interface de escrita nos registradores do

circuito executar as alterações nos registradores correspondentes e então ter o gerador

funcionando com os parâmetros passados.

É importante notar que os parâmetros são passados em série pela porta serial, portanto

quando é feito alteração em vários valores diferentes, os comandos serão enviados um a um e

os registradores serão também alterados um a um em diferentes instantes de tempo. Se o

gerador estiver em funcionamento durante a passagens destes comandos pode ocorrer a perda

de sincronia entre os diferentes canais. Por isso recomenda-se para o gerador clicando em

“Veto”, efetuar a mudanças nos parâmetros alterando as caixas de texto e clicando em

“Enviar” e por último clicar em “Trigger” para retornar a operação do gerador com os novos

parâmetros.

A caixa de texto na parte inferior da janela é responsável pelo valor do divisor de

frequência. Ao alterá-la e clicar em “Enviar” os registradores que controlam o divisor de

frequência serão atualizados e o gerador passará a operar sob nova frequência de clock.

O aplicativo também não atualiza os valores do geradores desnecessariamente, isto é,

caso você clique no botão “Enviar” sem ter efetuado nenhuma alteração nos valores das

caixas de texto, este não realizará ação alguma. Caso uma ou mais caixas de texto tenham

sido alteradas, somente os comandos referentes aos registradores correspondentes aos

parâmetros alterados serão enviados, de forma a tornar o processo mais rápido e minimizar o

uso desnecessário da porta serial.

42

Capítulo 4

4. Conclusão

Muitos dos testes foram sendo realizados junto com as etapas de desenvolvimento do

projeto. A placa Microboard LX9 tem botões e LEDs os quais tornavam possível um

diagnóstico se tais funções implementadas estavam funcionais.

Logo na fase inicial do desenvolvimento foi feito o divisor de frequência para que

dividisse o clock para um período de um segundo, com o objetivo de tornar visível através dos

LEDs da placa o formato de onda que o circuito estava gerando.

Quando a etapa de desenvolvimento foi concluída, era possível visualizar que os

diferentes segmentos do gerador estavam funcionando. Os seguintes itens foram testados,

dividindo a frequência para que o período do clock fosse um segundo e observando os

resultados através dos LEDs:

• Diferentes valores de período.

• Diferentes valores de largura de pulso.

• Diferentes valores do número de pulsos por trem de pulsos.

• Diferentes valores de defasagem entre canais.

• Taxa de perda de bytes da porta serial.

• Diferentes valores para o divisor de frequência.

Nenhum dos testes apresentaram qualquer inconsistência no funcionamento do

gerador.

A seguir todos os itens foram retestados sem uso do divisor de clock, sendo este o

maior possível, no caso, 100MHz, e a saída do circuito foi visualizada em osciloscópio.

Novamente nenhum dos testes apresentou qualquer inconsistência no circuito, sendo o

resultado de todos conforme o esperado.

43

Figura 19: Verificação da saída de 4 canais utilizando um osciloscópio digital.

Na Figura 18 podemos verificar um dos testes realizados com osciloscópio e na Figura

19 a configuração usada no software de controle.

44

Figura 20: Software de controle do gerador.

Podemos observar que a largura de pulso está configurada como 1 ciclo de clock em

todos os canais e o período total como 4 ciclos de clock. O número de pulsos está configurado

para zero, que significa infinitos pulsos, e em Delay observamos que cada canal está defasado

um do outro de 1 ciclo de clock. Vemos na imagem do osciloscópio que está coerente com o

esperado.

É importante notar que não houve a intenção de caracterizar a qualidade do sinal, o

nível de ruído, jitter e tempos de subida e descida, uma vez que o projeto é caracterizado

somente pelo circuito digital a ser implementado no FPGA e não a placa ou interface

eletrônica utilizada. Portanto, os itens citados são características somente do FPGA utilizado,

da placa de desenvolvimento e da forma com que foi medida utilizando o osciloscópio. Estes

não refletem a qualidade do projeto em si, mas só da plataforma em que foi implementado.

45

Referências bibliográficas

[1] CAEN Electronic Instrumentation. Mod. V1495 General Purpose VME Board. Itália:

2012, 41 p.

[2] CAEN Electronic Instrumentation. Mod. V820/V830, 32 ch. Latching/Multievent

Latching scaler. Itália: 2007, 48 p.

[3] CAEN Electronic Instrumentation. Mod. V1718 VME USB Bridge. Itália: 2007, 62 p.

[4] Avnet Microboard LX9 Getting Started. Disponível em: <http://www.em.avnet.com/en-

us/design/drc/Pages/Xilinx-Spartan-6-FPGA-LX9-MicroBoard.aspx> Acessao em 12 de

Fevereiro de 2013.

[5] XILINX. Spartan-6 FPGA Data Sheet. 2011, 89 p.

46

APÊNDICE

Apêndice I: Código fonte da entidade de nível superior

---------------------------------------------------------------------------------- -- Maurício Féo Rivello - [email protected] -- Projeto Final de engenharia. -- Interface para o Gerador de Pulsos Digitais ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Placa_LX9 is Port ( --clk_40 : in STD_LOGIC; -- clock 40 MHz --clk_67 : in STD_LOGIC; -- clock 66.7 MHz clk_100 : in STD_LOGIC; -- clock 100 MHz --J4 : out STD_LOGIC_VECTOR (7 downto 0); -- I/Os (7 downto 0) J5 : out STD_LOGIC_VECTOR (3 downto 0); -- I/Os (7 downto 0) Led : out STD_LOGIC_VECTOR (3 downto 0); DIP : in STD_LOGIC_VECTOR (1 downto 0); -- In (3 downto 0) --BTN : in STD_LOGIC; -- Botão Serial_Rx : in STD_LOGIC; Serial_Tx : out STD_LOGIC ); end Placa_LX9; ------------------------------------------------------------------------------ architecture Behavioral of Placa_LX9 is COMPONENT pulse_gen2 PORT( width : IN std_logic_vector(15 downto 0); period : IN std_logic_vector(15 downto 0); N : IN std_logic_vector(15 downto 0); delay : IN std_logic_vector(15 downto 0); clock : IN std_logic; clk_gen : in std_logic; trigger : IN std_logic; veto : IN std_logic; pulse_out : OUT std_logic ); END COMPONENT;

47

COMPONENT UART_Rx PORT( clock : IN std_logic; Serial_Rx : IN std_logic; inByte : OUT std_logic_vector(7 downto 0); Rx_Flag : OUT std_logic ); END COMPONENT; COMPONENT UART_Tx PORT( ByteIn : IN std_logic_vector(7 downto 0); clock : IN std_logic; Go : IN std_logic; Busy : OUT std_logic; Rx_Out : OUT std_logic ); END COMPONENT; signal gen_out : std_logic_vector(3 downto 0); signal cont : integer range 0 to 2147483647 := 0; ----------------------------- Sinais do gerador -- signal clk_div, clk_gen : std_logic; signal trigger : std_logic := '0'; signal veto : std_logic := '1'; signal SW_trigger, SW_veto: std_logic; ----------------------------- Sinais da interface -- type reg_array16 is array (255 downto 0) of std_logic_vector (15 downto 0); signal reg : reg_array16 := ( 0 => X"0001", 1 => X"0004", 2 => X"0000", 3 => X"0000", 4 => X"0001", 5 => X"0004", 6 => X"0000", 7 => X"0001", 8 => X"0001", 9 => X"0004",10 => X"0000",11 => X"0002", 12 => X"0001",13 => X"0004",14 => X"0000",15 => X"0003", 200 => X"05F5", 201 => X"E100", OTHERS => X"0000" ); signal Rx_Flag : std_logic_vector(2 downto 0); signal Rx_Byte : std_logic_vector(7 downto 0); signal Tx_Busy : std_logic; signal Tx_Byte : std_logic_vector(7 downto 0);

48

signal Tx_Send : std_logic; type reg_array8 is array (4 downto 0) of std_logic_vector (7 downto 0); signal Rx_Buff : reg_array8 := ( OTHERS => X"00" ); constant Num_Canais : integer := 3; -- Numero de canais do gerador signal clk_divider : std_logic_vector(30 downto 0); --signal clk_divider : integer range 1 to 2147483647 := 1; ------------------------------------------------------------------------------ begin ---------------------------------------------------- Frequency divider clk_gen <= clk_100 when (reg(201)&reg(200)=X"00000001") else clk_div; clk_divider <= reg(201) & reg(200)(15 downto 1); frequency_divider: process (clk_100) begin if rising_edge(clk_100) then if (cont < to_integer(unsigned(clk_divider))-1) then cont <= cont+1; --clk_div<= clk_div; else cont <= 0; clk_div <= not clk_div; end if; end if; end process; ---------------------------------------------------- Gerador trigger <= DIP(0) or SW_trigger; veto <= DIP(1) or SW_veto; Gerando_canais: for k in 0 to Num_Canais generate begin Inst_pulse_gen2: pulse_gen2 PORT MAP( width => reg(4*k+0), period => reg(4*k+1), N => reg(4*k+2), delay => reg(4*k+3), clock => clk_100, clk_gen => clk_gen,

49

trigger => trigger, veto => veto, pulse_out => gen_out(k) ); end generate; J5 <= gen_out; Led <= gen_out; ---------------------------- Interface Registradores On_Serial_Rx : process(clk_100) begin if rising_edge(clk_100) then Rx_Flag(2 downto 1) <= Rx_Flag(1 downto 0); if std_match(Rx_Flag,"-01") then Rx_Buff <= Rx_Buff (3 downto 0) & Rx_Byte; Tx_byte <= Rx_Byte; Tx_Send <= '1'; elsif std_match(Rx_Flag,"01-") then if (Rx_Buff(4)&Rx_Buff(3)&Rx_Buff(2)&Rx_Buff(1)&Rx_Buff(0)=X"7374617274") then -- "start" SW_trigger <= '1'; SW_veto <= '0'; elsif (Rx_Buff(3)&Rx_Buff(2)&Rx_Buff(1)&Rx_Buff(0)=X"73746F70") then -- "stop" SW_trigger <= '0'; SW_veto <= '1'; elsif (Rx_Buff(4)=X"23")and(Rx_Buff(0)=X"2A") then -- "#---*" reg(to_integer(unsigned(Rx_Buff(1)))) <= Rx_Buff(3)&Rx_Buff(2); else SW_trigger <= '0'; SW_veto <= '0'; end if; else

50

Tx_Send <= '0'; end if; end if; end process; Inst_UART_Rx: UART_Rx PORT MAP( clock => clk_100, Serial_Rx => Serial_Rx, inByte => Rx_Byte, Rx_Flag => Rx_Flag(0) ); Inst_UART_Tx: UART_Tx PORT MAP( ByteIn => Tx_Byte, clock => clk_100, Go => Tx_Send, Busy => Tx_Busy, Rx_Out => Serial_Tx ); end Behavioral;

51

Apêndice II: Código fonte do Gerador de Pulsos

---------------------------------------------------------------------------------- -- Maurício Féo Rivello - [email protected] -- Projeto Final de engenharia. -- Gerador de Pulsos Digitais ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity pulse_gen2 is Port ( width : in STD_LOGIC_VECTOR (15 downto 0); period : in STD_LOGIC_VECTOR (15 downto 0); N : in STD_LOGIC_VECTOR (15 downto 0); delay : in STD_LOGIC_VECTOR (15 downto 0); clock : in STD_LOGIC; clk_gen : in STD_LOGIC; trigger : in STD_LOGIC; veto : in STD_LOGIC; pulse_out : out STD_LOGIC); end pulse_gen2; architecture Behavioral of pulse_gen2 is signal trig: std_logic_vector (1 downto 0):="00"; signal vet : std_logic_vector (1 downto 0):="00"; signal vetado : std_logic; signal delaying : std_logic; COMPONENT Delay_unit PORT( clock : IN std_logic; clk_gen : IN std_logic; reset : IN std_logic; delay : IN std_logic_vector(15 downto 0); delaying : OUT std_logic ); END COMPONENT; signal gen_out : std_logic; signal reset : std_logic;

52

signal gen_reset : std_logic; COMPONENT Gen_unit PORT( width : IN std_logic_vector(15 downto 0); period : IN std_logic_vector(15 downto 0); clk_gen : IN std_logic; reset : IN std_logic; gen_out : OUT std_logic ); END COMPONENT; signal N_vet : std_logic; COMPONENT N_unit PORT( N : IN std_logic_vector(15 downto 0); gen_out : IN std_logic; clock: IN std_logic; reset : IN std_logic; N_vet : OUT std_logic ); END COMPONENT; begin vet(0) <= veto; trig(0) <= trigger; pulse_out <= gen_out; gen_reset <= delaying or vetado or N_vet or reset; reset_process : process (clock) begin if rising_edge(clock) then trig(1) <= trig(0); vet(1) <= vet(0); if trig="01" then reset<='1'; vetado<='0'; elsif vet="01" then vetado<='1'; else reset<='0'; end if;

53

end if; end process; delayer: Delay_unit PORT MAP( clock => clock, clk_gen => clk_gen, reset => reset, delay => delay, delaying => delaying ); Generator_unit: Gen_unit PORT MAP( width => width, period => period, clk_gen => clk_gen, reset => gen_reset, gen_out => gen_out ); N_unit_inst: N_unit PORT MAP( N => N, gen_out => gen_out, clock => clock, reset => reset, N_vet => N_vet ); end Behavioral;

54

Apêndice III : Código fonte da unidade Delayer

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Delay_unit is Port ( clock : in STD_LOGIC; clk_gen : in STD_LOGIC; reset : in STD_LOGIC; delay : in STD_LOGIC_VECTOR (15 downto 0); delaying : out STD_LOGIC); end Delay_unit; architecture Behavioral of Delay_unit is signal clkIn : STD_LOGIC_VECTOR (1 downto 0):= "00"; signal cont : STD_LOGIC_VECTOR (15 downto 0):= X"0000"; begin clkIn(0) <= clk_gen; process (clock) begin if (falling_edge(clock)) then clkIn(1) <= clkIn(0); if (reset = '1') then cont <= X"0000"; delaying <= '1'; else if (clkIn(1)='0') and (clkIn(0)='1') then if (cont<delay) then cont <= std_logic_vector(unsigned(cont)+1); delaying <= '1'; else cont <= cont; delaying <= '0'; end if; end if; end if; end if; end process; end Behavioral;

55

Apêndice IV: Código fonte da Generator Unit

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Gen_unit is Port ( width : in STD_LOGIC_VECTOR (15 downto 0); period : in STD_LOGIC_VECTOR (15 downto 0); clk_gen : in STD_LOGIC; reset : in STD_LOGIC; gen_out : out STD_LOGIC); end Gen_unit; architecture Behavioral of Gen_unit is signal cont : STD_LOGIC_VECTOR (15 downto 0); begin process (clk_gen) begin if (clk_gen='1' and clk_gen'event) then if (reset='0') then if (cont<width) then gen_out <= '1'; else gen_out <= '0'; end if; if (unsigned(cont)<unsigned(period)-1) then cont <= std_logic_vector(unsigned(cont) + 1); else cont <= X"0000"; end if; else cont <= X"0000"; gen_out <= '0'; end if; end if; end process; end Behavioral;

56

Apêndice V: Código fonte da N_Unit

---------------------------------------------------------------------------------- -- Maurício Féo Rivello - [email protected] -- Projeto Final de engenharia. -- Gerador de Pulsos Digitais ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity N_unit is Port ( N : in STD_LOGIC_VECTOR (15 downto 0); gen_out : in STD_LOGIC; clock: in STD_LOGIC; reset : in STD_LOGIC; N_vet : out STD_LOGIC); end N_unit; architecture Behavioral of N_unit is signal gen : std_logic_vector (1 downto 0); signal cont : std_logic_vector (15 downto 0); signal output : std_logic; begin N_vet <= output; gen(0) <= gen_out; process (clock) begin if (falling_edge(clock)) then gen(1) <= gen(0); if (reset = '1') then output<='0'; cont <= X"0000"; else if (gen(1)='0') and (gen(0)='1') then cont <= std_logic_vector(unsigned(cont) + 1); end if; if (cont = N) and (N /= X"0000") then output<='1'; end if; end if; end if; end process;

57

end Behavioral;

58

Apêndice VI: Código fonte do Receptor UART

---------------------------------------------------------------------------------- -- Maurício Féo Rivello - [email protected] -- -- www.engenheirando.com -- -- Porta serial p/ Baud rate de 9600 bps com clock de 100MHz -- P/ usar clock/BR diferente, observar comentários abaixo ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity UART_Rx is Port ( clock : in STD_LOGIC; Serial_Rx : in STD_LOGIC; inByte : out STD_LOGIC_VECTOR (7 downto 0); Rx_Flag : out STD_LOGIC); end UART_Rx; architecture Behavioral of UART_Rx is signal cont : integer range 0 to 16000:= 0; -- observar o limite ao mudar o clock / baud rate signal bitsRecebidos : integer range 0 to 8:=0; signal inBits : std_logic_vector (7 downto 0); signal Rx_Antes : std_logic; type Estados is (Wait_Start_bit, Start_bit, Lendo_bits, Stop_bit); signal Estado : Estados; begin UART_Rx : process (clock) begin if rising_edge(clock) then Rx_Antes <= Serial_Rx; case Estado is ---------------------------------------------------------- when Wait_Start_bit => if (Rx_Antes = '1') and (Serial_Rx = '0') then Estado <= Start_bit; cont<=0; end if; ---------------------------------------------------------- when Start_bit => if (cont<15417) then -- 15417 = Clock / BaudRate * 1.5 cont<=cont+1; else

59

bitsRecebidos<=0; Estado <= Lendo_bits; end if; ---------------------------------------------------------- when Lendo_bits => if (bitsRecebidos<8) then if (cont<10417) then -- 10417 = Clock / BaudRate cont <= cont+1; else cont <=0; bitsRecebidos <= bitsRecebidos+1; inBits <= Serial_Rx & inBits(7 downto 1); end if; else inByte <= inBits; Rx_Flag <= '1'; Estado <= Stop_bit; end if; ---------------------------------------------------------- when Stop_bit => if (cont<5208) then -- Metade de 10417! cont<=cont+1; else cont<=0; Rx_Flag <= '0'; Estado <= Wait_Start_Bit; end if; ---------------------------------------------------------- when others => Estado <= Estado; end case; end if; end process; end Behavioral;

60

Apêndice VII: Código fonte do Transmissor UART

---------------------------------------------------------------------------------- -- Maurício Féo Rivello - [email protected] -- -- www.engenheirando.com -- -- Porta serial p/ Baud rate de 9600 bps com clock de 100MHz -- P/ usar clock/BR diferente, observar comentários abaixo ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity UART_Tx is Port ( ByteIn : in STD_LOGIC_VECTOR (7 downto 0); clock : in STD_LOGIC; Go : in STD_LOGIC; Busy : out STD_LOGIC; Rx_Out : out STD_LOGIC); end UART_Tx; architecture Behavioral of UART_Tx is signal outBuff : std_logic_vector (9 downto 0); -- envia do zero ao 7 do byte signal Go_Antes : std_logic:='0'; signal cont : integer range 0 to 11000:=0; -- observar o limite ao mudar o clock / baud rate signal bits_Sent : integer range 0 to 10:=0; type Estados is (Idle, Sending); signal Estado : Estados; signal Byte_em_Espera : boolean := false; begin UART_Tx : process (clock) begin if rising_edge(clock) then Go_Antes <= Go; case Estado is ---------------------------------------------------------- when Idle => Rx_Out <= '1'; if ((Go = '1')and(Go_Antes = '0')) or Byte_em_Espera then Byte_em_Espera <= false; outBuff <= '1' & ByteIn (7 downto 0) & '0'; -- stop + byte + start

61

cont <= 0; bits_Sent <= 0; Estado <= Sending; Busy <= '1'; end if; ---------------------------------------------------------- when Sending => Rx_Out <= outBuff(0); if ((Go = '1')and(Go_Antes = '0')) then Byte_em_Espera <= true; end if; if (bits_Sent<10) then if (cont<10417) then --10417 cont<=cont+1; else cont <= 0; bits_Sent <= bits_Sent+1; outBuff <= '0' & outBuff(9 downto 1); end if; else Estado <= Idle; Busy <= '0'; end if; ---------------------------------------------------------- when others => Estado <= Estado; end case; end if; end process; end Behavioral;

62

Apêndice VIII : Código fonte da unidade Single Pulser

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity Single_Pulser is

Port ( trigger : in STD_LOGIC;

clock : in STD_LOGIC;

pulse : out STD_LOGIC);

end Single_Pulser;

architecture Behavioral of Single_Pulser is

signal QA: std_logic := '0';

signal QB: std_logic := '0';

begin

pulse <= QB;

process (trigger, QB)

begin

if QB='1' then

QA <= '0';

elsif (trigger'event and trigger='1') then

QA <= '1';

end if;

end process;

process (clock)

begin

if (clock'event and clock ='1') then

QB <= QA;

end if;

end process;

end Behavioral;