• Nenhum resultado encontrado

2007.1TCC 03111166 0 Eder Santana Freire

N/A
N/A
Protected

Academic year: 2021

Share "2007.1TCC 03111166 0 Eder Santana Freire"

Copied!
75
0
0

Texto

(1)

Eder Santana Freire

Implementação do Atari 2600

Utilizando FPGAs.

Feira de Santana – BA, Março / 2008

(2)

Eder Santana Freire

Implementação do Atari 2600

Utilizando FPGAs.

Trabalho de Conclusão de Curso apresentado à Banca de Graduação em Engenharia de Computação da Universidade Estadual de Feira de Santana para a obtenção do título de Bacharel em Engenharia de Computação.

Orientador:

Prof. Dr. Wagner Luiz Alves de Oliveira

D

EPARTAMENTODE

T

ECNOLOGIA

U

NIVERSIDADE

E

STADUALDE

F

EIRADE

S

ANTANA

Feira de Santana – BA, Março / 2008

(3)

Trabalho de Conclusão de Curso de Graduação, sob o título “Implementação do Atari 2600 Utilizando FPGAs.”, da autoria de Eder Santana Freire, apresentado e aprovado em 09 de Abril de 2008, na cidade de Feira de Santana, Estado da Bahia, pela banca examinadora constituída pelos professores:

Prof. Marco Túlio Chella Departamento de Tecnologia – UEFS

Examinador

Prof. Marcos de Araujo Paz Departamento de Tecnologia – UEFS

Examinador

Prof. Wagner Luiz Alves de Oliveira Departamento de Tecnologia – UEFS

(4)

Dedico este trabalho aos meus pais, por todo esforço despendido, por todo incentivo dado e pelo apoio irrestrito em todos os momentos da minha vida.

(5)

Agradecimentos

Agradeço em princípio a Deus, criador de todas as coisas, pois sem Ele nada seria. A minha família, Levi, Eurides e Jéssica, pelo amor e carinho incondicionais.

A Rafinha, meu amor, pelos momentos inesquecíveis que tem me proporcionado ao seu lado.

Aos companheiros de turma, cuja amizade cultivada ao longo destes cinco anos preservarei para o resto da vida.

Ao meu orientador, professor Wagner, pelo apoio e encorajamento contínuos, pelo conhecimento compartilhado e pela sua inestimável amizade.

Aos demais mestres da casa, por todos os conhecimentos e valores sabiamente transmitidos.

(6)

Resumo

Este trabalho visou reconstruir o sistema computacional Atari 2600, usando metodologias de projeto modernas, juntamente com componentes de hardware atuais. Para tal propósito, foram utilizadas descrições de hardware do projeto original, baseadas em esquemáticos de circuito e datasheets dos seus componentes. O sistema foi implementado em linguagens de descrição de hardware, e testado num dispositivo FPGA da família ACEX 1K da Altera. Também foi abordado o padrão VGA para geração de imagens, e realizada a construção de uma interface para este padrão, a fim de que os resultados pudessem ser exibidos em um monitor de vídeo.

(7)

Abstract

This project aimed to redesign the Atari 2600 computer system, by using modern design methodologies, along with current hardware components. For such purpose, hardware descriptions of the original design were used, based on the circuit schematics and its component’s datasheets. The system was designed in hardware description languages, and tested on an ACEX 1K FPGA device from the Altera family. In addition, the VGA standard was also discussed, and an interface for this standard was assembled, in order to display the results on a video monitor screen.

(8)

Sumário

Lista de Figuras ... 10 1 Introdução e Motivação ... p. 5 2 Definição do Trabalho ... p. 6 3 Revisão de Literatura ... p. 7 3.1 Linguagens de Especificação ... p. 7 3.2 VHDL ... p. 9 3.3 Verilog ... p. 12 3.4 VHDL Versus Verilog ... p. 13 3.4.1 Modelagem ... p. 13 3.4.2 Compilação ... p. 14 3.4.3 Tipos de dados ... p. 15 3.4.4 Reusabilidade de Projeto ... p. 15 3.4.5 Facilidade de Aprendizado ... p. 15 3.4.6 Bibliotecas ... p. 15 3.5 SystemC ... p. 16 3.6 FPGAs ... p. 16 4 Tecnologias e Ferramentas Utilizadas ... p. 19 4.1 A Placa FPGA PI1K100A... p. 19 4.2 Linguagens de Descrição de Hardware ... p. 21 4.3 Outras ferramentas ... p. 22 5 A Arquitetura do Atari ... p. 23 5.1 Primeiras Impressões ... p. 23 5.2 O processador MOS 6507 ... p. 26 5.3 O chip RIOT ... p. 28 5.4 O chip TIA ... p. 31 6 Desenvolvimento ... p. 38 6.1 Considerações Gerais ... p. 38 6.2 CPU 6507 ... p. 39 6.3 Módulo RIOT ... p. 40 6.4 Módulo TIA ... p. 45 6.5 Controlador de barramento ... p. 49 6.6 Gerador de clock ... p. 51 6.7 Módulo cartucho ... p. 52 6.8 Conversor NTSC - VGA ... p. 53 6.9 Controlador VGA ... p. 55 6.10 Interface VGA ... p. 56

(9)

6.11 Integração do Sistema ... p. 58 Conclusões e Trabalhos Futuros ... p. 62 Referências ... p. 64 Glossário ... p. 65

(10)

Lista de Figuras

Figura 1: O sistema Atari 2600 Video Computer System ... p. 5 Figura 2: Ciclo de vida de um projeto VHDL ... p. 10 Figura 3: Comparativo de capacidade de modelagem das HDLs ... p. 14 Figura 4: Arquitetura de um FPGA ... p. 18 Figura 5: Placa FPGA PI1K100A ... p. 20 Figura 6: Diagrama de blocos da placa PI1K100A ... p. 21 Figura 7: Placa-mãe do Atari 2600 ... p. 23 Figura 8: Esquemático do Atari 2600 ... p. 25 Figura 9: Encapsulamento DIP do chip MOS 6507, e pinagem do 6502... p. 26 Figura 10: Pinagem do MOS 6532 RIOT ... p. 28 Figura 12: Temporizador de intervalo ... p. 30 Figura 11: Diagrama de blocos do RIOT ... p. 30 Figura 13: Pinagem do chip TIA ... p. 31 Figura 14: Registrador de playfield ... p. 33 Figura 15: Circuito de movimentação horizontal ... p. 34 Figura 16: Detecção de colisão no chip TIA ... p. 35 Figura 17: Frame de TV no Atari ... p. 36 Figura 18: Diagrama do sistema em alto nível ... p. 38 Figura 19: Bloco MOS 6507 no Quartus II ... p. 39 Figura 20: Esboço do subsistema RIOT ... p. 40 Figura 21: Bloco do chip RIOT ... p. 41 Figura 22: Esboço do subsistema TIA ... p. 45 Figura 23: Bloco do módulo TIA ... p. 46 Figura 24: Bloco do controlador de barramento ... p. 50 Figura 25: Diagrama do divisor de clock... p. 51 Figura 26: Divisor de clock descrito no Quartus II ... p. 52 Figura 27: Simulação das formas de onda do circuito divisor ... p. 52 Figura 28: Bloco ROM no Quartus II ... p. 53 Figura 29: Bloco do módulo cartucho no Quartus II ... p. 53

(11)

Figura 30: Bloco conversor NTSC - VGA ... p. 54 Figura 31: Esquema da interface VGA ... p. 56 Figura 32: Circuito da interface VGA na protoboard, e o seu funcionamento ... p. 57 Figura 33: Rede de resistores R-2R, que atua como um DAC ... p. 57 Figura 34: Interface VGA com 24 bits de profundidade de cor, sem amplificação ... p. 58 Figura 35: Integração dos módulos 6507, RIOT e TIA ... p. 59 Figura 36: Bloco que representa o núcleo do Atari 2600... p. 59 Figura 37: Integração do módulo Atari 2600 com o restante do sistema... p. 61

(12)

1 Introdução e Motivação

O Atari 2600 foi um sistema computacional lançado em 1977 nos Estados Unidos e em 1983 no Brasil, tendo sido um fenômeno de vendas em todo o mundo, e sendo referência em termos de entretenimento até os dias atuais. Por isso, o mesmo é considerado um símbolo cultural dos anos 80.

Um dos primeiros consoles de videogame fabricados, o sistema do Atari 2600 (figura 1) fornece uma visão interessante das primeiras arquiteturas de hardware, assim como da forma de programação para um sistema com recursos limitados.

Entretanto, existem hoje poucas unidades funcionais do hardware original, impedindo o fácil acesso ao sistema. Além do mais, detalhes do projeto deste sistema (geralmente esquemáticos de circuitos) utilizam metodologias de projeto ultrapassadas, referenciando componentes de hardware na sua maioria obsoletos, fazendo com que a tarefa de reconstruir um sistema funcional (com o seu projeto e hardware 100% originais) seja muito dispendiosa (BEER, 2007).

Surge, portanto a questão de como reconstruir o projeto de uma arquitetura desenvolvida há cerca de três décadas, utilizando apenas tecnologias presentes nos dias atuais.

(13)

2 Definição do Trabalho

Este trabalho visou o projeto de um circuito com o comportamento do Atari 2600, a partir de descrições funcionais dos seus componentes, juntamente com o esquemático original do sistema. Para que isto fosse possível, foram utilizadas tecnologias tais como linguagens de descrição de hardware (Verilog/VHDL), Field Programmable Gate Arrays (FPGAs), soft-cores e o padrão Video Graphics Array (VGA) para a geração de vídeo.

Ademais, este projeto propôs a recriação de uma arquitetura computacional de forma limpa e bem organizada, de modo que seja facilmente compreensível, e possa ser utilizada em diferentes contextos com poucas mudanças. Assim, com este trabalho, buscou-se adquirir proficiência no que diz respeito à arquitetura e organização de sistemas computacionais, bem como à tecnologia de FPGAs e a suas linguagens de descrição de hardware.

(14)

3 Revisão de Literatura

Esta seção visa fornecer uma breve revisão da área na qual este projeto está inserido, apresentando as soluções disponíveis na literatura para as principais questões que o envolvem.

3.1

Linguagens de Especificação

Na área de Sistemas Digitais, uma linguagem de descrição de hardware, ou Hardware Description Language - HDL, é qualquer linguagem que objetiva a descrição formal de circuitos eletrônicos. Tal linguagem pode descrever os passos de operação de um circuito, o seu projeto e organização, além de suporte a testes, a fim de verificar a sua operação por meio de simulação, e, finalmente, dar suporte à síntese do circuito.

Uma HDL é uma expressão textual padrão do comportamento temporal e/ou estrutural (espacial) do circuito de um sistema eletrônico. Em contraste com as linguagens de programação de software, a sintaxe de uma HDL e sua semântica incluem notações explícitas para expressar tempo e concorrência, que são os atributos primários do hardware. Além de simulação, muitas HDLs possuem a capacidade de expressar a conectividade de circuitos através de uma hierarquia de blocos, sendo classificadas como linguagens geradoras de netlists (PEDRONI, 2004).

HDLS também são utilizadas na descrição de especificações executáveis de certas partes de hardware. Um programa de simulação, projetado para implementar a semântica subjacente das declarações da linguagem, juntamente com a simulação do progresso no tempo, provê ao projetista de hardware a habilidade de modelar uma porção de hardware antes mesmo dela ser criada fisicamente. É essa capacidade de criar especificações executáveis que faz com que as HDLs pareçam linguagens de programação comuns. Há simuladores capazes de suportar a modelagem de eventos discretos (digitais) e de tempo contínuo (analógico), e existem HDLs disponíveis para cada um deles.

(15)

É possível representar a semântica de hardware utilizando linguagens de programação tradicionais, tais como C++. Entretanto, a linguagem C++ não inclui nenhuma capacidade de expressar tempo explicitamente e, conseqüentemente, não é uma linguagem de descrição de hardware adequada. Para contornar tais restrições, um consórcio de empresas de ponta desenvolveu a linguagem SystemC, a qual consiste na linguagem C++ aumentada com bibliotecas de classes voltadas para hardware, amparadas em um núcleo de simulação.

Ao se utilizar o subconjunto adequado de virtualmente qualquer linguagem (descrição de hardware ou de programação de software), um software chamado sintetizador de hardware pode inferir as suas operações lógicas a partir das declarações da linguagem e, assim, produzir uma netlist equivalente de primitivas genéricas de hardware, objetivando a implementação do comportamento especificado no código. Em muitos casos, isto requer que o sintetizador ignore expressões de temporização presentes no código. A capacidade de se ter um subconjunto da linguagem “sintetizável” não é o fator determinante para classificar uma linguagem como HDL.

As linguagens de descrição de hardware, portanto, permitem que projetistas de hardware implementem circuitos digitais utilizando uma linguagem de programação estruturada de alto nível. Ao contrário da maioria das linguagens de programação, que especificam apenas funcionalidade, as HDLs também permitem que o programador descreva a temporização do projeto. Isto deixa o projetista livre para focar na criação do sistema em um alto nível de abstração, deixando para ferramentas de síntese automática o tratamento de camadas mais baixas do hardware (BEER, 2007).

Embora as primeiras HDLs datem do final da década de 1970, a primeira linguagem de destaque, Verilog, surgiu em 1985, introduzida pela Gateway Design Automation. A Cadence Design Systems posteriormente adquiriu os direitos do Verilog-XL, o simulador HDL que se tornaria padrão de facto para simuladores Verilog da década seguinte. Em 1987, uma demanda do Departamento de Defesa dos Estados Unidos conduziu ao desenvolvimento da linguagem VHDL. Inicialmente, Verilog e VHDL eram utilizadas para documentar e simular projetos de circuito já capturados e descritos em outra forma (como por exemplo, um arquivo esquemático). A simulação por HDLs capacitou os engenheiros a trabalharem em um nível de abstração mais alto do que a simulação no

(16)

nível esquemático, elevando, assim, a capacidade de projeto de centenas para milhares de transistores.

3.2

VHDL

VHDL é a sigla para VHSIC Hardware Description Language ou Linguagem de Descrição de Hardware VHSIC. Por sua vez, VHSIC é uma abreviação para Very High Speed Integrated Circuit (Circuito Integrado de Velocidade Muito Alta). Esta linguagem pode descrever o comportamento e a estrutura de sistemas eletrônicos, mas é particularmente apropriada como linguagem para descrição da estrutura e do comportamento de projetos de hardware eletrônicos digitais, tais como ASICs e FPGAs, assim como circuitos digitais convencionais (OLIVEIRA, 2004).

VHDL é uma notação, a qual é precisamente e inteiramente definida pelo Manual de Referência da Linguagem (Language Reference Manual - LRM). Isto coloca VHDL além de outras linguagens de descrição de hardware, uma vez que estas são, de certa forma, moldadas pelo comportamento das ferramentas que as utilizam. VHDL é um padrão internacional, regulado pelo IEEE, e a sua definição é não-proprietária.

Simulação e síntese são os dois principais tipos de ferramentas que utilizam o potencial de VHDL. O Manual de Referência da Linguagem não define um simulador, mas define, sem ambigüidades, o que cada simulador deve fazer com cada parte da linguagem.

VHDL não restringe o usuário a um estilo específico de descrição, permitindo que projetos sejam descritos usando qualquer metodologia - top down, bottom up ou middle out. VHDL pode ser utilizada para descrever o hardware no nível de portas ou de uma forma mais abstrata.

A unidade básica de abstração de hardware em VHDL é a entidade (entity), a qual é utilizada para identificar e representar uma porção unitária de um projeto maior, realizando uma função específica e possuindo entradas e saídas bem definidas. A funcionalidade de cada entidade é descrita através de sua arquitetura (architecture) (OLIVEIRA, 2004). VHDL permite que o projetista represente a arquitetura associada a uma entidade de três formas, ou de uma combinação destas. Estas formas são:

(17)

a) Comportamental: Arquitetura utiliza-se de sentenças seqüenciais de programação, acondicionadas em processos, os quais são paralelos entre si;

b) A fluxo de dados (dataflow): Arquitetura utiliza-se de sentenças de programação concorrentes que trabalham somente sobre sinais, os quais representam armazenadores de valores com conteúdo escalonado;

c) Estrutural: Arquitetura descrita como uma interconexão de componentes, os quais correspondem a instâncias de pares entidade-arquitetura.

Assim como outras linguagens, VHDL segue um fluxo de projeto bem definido, composto por sete etapas, conforme pode ser visto na figura 2: Especificação de Requisitos, Modelagem, Síntese de Alto Nível, Mapeamento Tecnológico, Implementação e/ou Fabricação, Testes e Simulação. O tempo e o custo de cada etapa dentro de um projeto é bastante variável, dependendo da tecnologia utilizada para implementar o sistema (PEDRONI, 2004).

Na Especificação de Requisitos, o projetista realiza um estudo e levanta todos os requisitos e características do sistema que definem o seu funcionamento. Entre tais características, podem ser citadas: atraso máximo permitido para as saídas, freqüência máxima de operação, consumo de potência, custo, temperatura de operação e tensão de alimentação. Estas características visam satisfazer os requisitos, que podem ser desejáveis ou necessários. Esta fase é de extrema importância porque, uma vez compreendido corretamente o funcionamento do sistema, evita-se a ocorrência de erros

(18)

futuros. A cada unidade de tempo avançada no ciclo de projeto, maior o custo de correção de um erro e maior a dificuldade em encontrá-lo. Ou seja, além do prejuízo ser maior, maior também a probabilidade de que o erro passe despercebido e seja incluído na produção do sistema.

É na etapa de modelagem que o projeto propriamente dito é iniciado. Baseado nas especificações da etapa anterior, o projetista irá escrever os modelos que representam o circuito. É de fundamental importância que o projetista tenha já um prévio conhecimento das ferramentas de software que utilizará no projeto e da tecnologia que irá utilizar, a fim de obter os melhores resultados futuramente.

A Síntese de Alto Nível, no contexto de hardware, é equivalente à compilação, no contexto de software. Nesta fase, o modelo descrito será convertido para estruturas de dados representando as conexões, blocos, componentes e portas lógicas. Esta etapa é automática e dependente da ferramenta de software utilizada. Após a síntese, ainda não está definido o circuito a ser implementado - a especificação intermediária resultante é ainda bastante genérica e pode ser direcionada para diferentes tecnologias de implementação.

É na etapa de Mapeamento Tecnológico que o circuito é definido dentro da tecnologia em que será implementado. No contexto de software, seria equivalente à geração do código executável que ocorre ao final da compilação de um código fonte. Nesta etapa, os componentes de hardware serão gerados de acordo com a tecnologia empregada – dentre as tecnologias disponíveis no mercado, destacam-se a Full Custom, Gate Array e FPGAs, dentre outras. Esta etapa tem pouca intervenção do projetista, muitas vezes limitada à especificação de parâmetros de otimização desejados. Na etapa de implementação/fabricação, são criados protótipos e são avaliadas as condições finais, assim como detalhes de produção da implementação final. Posteriormente à fabricação, os circuitos são testados para que possam ser entregues ao usuário com maior garantia de isenção de falhas.

A Simulação é uma etapa de suporte, embora seja de grande relevância no ciclo de vida do projeto. Simular consiste em avaliar o comportamento do circuito e validar o modelo produzido até aquele momento. Durante a simulação, são apresentadas amostras de entradas possíveis ao modelo do circuito, e os valores das saídas, memórias e nós internos do circuito são analisados a fim de comparar com o esperado na

(19)

especificação. A Simulação gera uma realimentação para os processos de modelagem, síntese e mapeamento, evitando a propagação de erros para etapas posteriores. Muitos dos problemas encontrados na simulação não estão necessariamente ligados a erros no projeto, mas ao não preenchimento dos requisitos necessários, principalmente no que se refere aos tempos do circuito (atraso, setup/hold time, freqüência de operação).

Um recurso muito interessante presente na simulação são os testbenches – estes modelos não geram circuitos, servindo apenas para a simulação. O testbench nada mais é que um algoritmo responsável por gerar automaticamente os sinais que estimularão as entradas do modelo que será simulado. Dentro do testbench podem também estar presentes rotinas que capturem os valores de saída do circuito simulado e gerem apenas resultados de comparação, dizendo se o circuito está funcionando corretamente ou não, e sob quais aspectos estão ocorrendo os problemas.

3.3

Verilog

A linguagem Verilog, algumas vezes chamada de Verilog HDL, suporta o projeto, verificação, e implementação de circuitos de sinais analógicos, digitais e híbridos, em vários níveis de abstração.

A proposta de Verilog é a de uma linguagem com sintaxe similar à linguagem de programação C, de forma que fosse familiar a engenheiros e facilmente aceita. A linguagem é case-sensitive (isto é, diferencia caracteres maiúsculos e minúsculos) e, assim como C, possui um pré-processador. A maioria das palavras-chave de controle, como "if" e "while", são similares; o mecanismo de formatação das rotinas de impressão e operadores de linguagem e sua precedência são igualmente similares.

As duas linguagens também diferem em alguns pontos fundamentais. Verilog usa as cláusulas Begin/End ao invés de chaves para definir blocos de código. A definição de constantes em Verilog requer uma largura de bits, juntamente com sua base. Verilog 95 e 2001 não possuem estruturas, ponteiros, ou subrotinas recursivas, embora SystemVerilog (uma extensão de Verilog-2005) inclua estas características. Finalmente, o conceito de tempo – tão importante para uma HDL – não é encontrado em C.

A linguagem Verilog difere das linguagens de programação convencionais, no aspecto em que a execução das declarações não é necessariamente linear. Um projeto

(20)

em Verilog consiste numa hierarquia de módulos. Estes são definidos com um conjunto de portas de entrada, de saída e bidirecionais. Internamente, um módulo contém uma lista de fios e registradores. Declarações concorrentes e seqüenciais definem o comportamento do módulo, a partir de relações entre portas, fios e registradores. Declarações seqüenciais são inseridas dentro de um bloco Begin/End e executadas em ordem seqüencial interiormente ao bloco. Mas todas as declarações concorrentes e todos os blocos begin/ end no projeto são executados de forma paralela. Um módulo também pode conter uma ou mais instâncias de outro módulo, para definir um sub-comportamento.

Um subconjunto de declarações de Verilog é sintetizável se os módulos em um projeto contiverem apenas declarações sintetizáveis. Isto permite ao software sintetizador transformar (sintetizar) o projeto em uma netlist que descreve os componentes e conexões básicos a serem implementados no hardware. A netlist pode ser transformada em, por exemplo, uma forma de descrever as células padrão de um circuito integrado (por exemplo, um ASIC) ou um bitstream para um dispositivo lógico-programável (por exemplo, um FPGA) (OLIVEIRA, 2004)

3.4

VHDL Versus Verilog

Na seqüência, alguns aspectos individuais de ambas as linguagens citadas anteriormente são objeto de comparação.

3.4.1 Modelagem

A estrutura do hardware pode ser modelada de forma igualmente efetiva em ambas as linguagens. Ao se modelar hardware abstrato, a capacidade de VHDL algumas vezes pode ser obtida por Verilog com a utilização de PLI. A escolha sobre qual usar não é, entretanto, baseada somente na capacidade técnica, mas em:

• Preferências pessoais;

• Disponibilidade de ferramentas; • Questões comerciais e de marketing.

(21)

As construções de modelagem de VHDL e Verilog cobrem um espectro levemente diferente através dos níveis de abstração comportamental, conforme mostra a figura 3.

Percebe-se, portanto, que VHDL possui um nível de abstração maior do que Verilog tendo, esta última, maior acesso às camadas mais baixas do hardware (SMITH, 2003).

3.4.2 Compilação

VHDL: Múltiplas unidades de projeto (pares entidade/arquitetura), que residem no mesmo arquivo de sistema, podem ser separadamente compilados, se desejado. Entretanto, uma boa prática de projeto é manter cada unidade de projeto no seu próprio arquivo de sistema, em cujo caso a compilação separada não deveria ser uma conseqüência.

Verilog: Ainda está enraizada no seu modo interpretativo nativo. A compilação é um meio de acelerar a simulação, mas não modificou a natureza original da linguagem. Como resultado, deve-se tomar cuidado tanto com a ordem de compilação de código escrito num único arquivo, quanto com a ordem de compilação de múltiplos arquivos. Os resultados da simulação podem ser modificados simplesmente mudando-se a ordem da compilação.

(22)

3.4.3 Tipos de dados

VHDL: Permite o uso de uma grande quantidade de tipos de dados, tanto os da linguagem, quanto os definidos pelo usuário. Isto pode significar que funções dedicadas de conversão sejam necessárias para converter objetos de um tipo para outro – o que pode tornar o código consideravelmente mais complexo, porém, mais versátil.

Verilog: Seus tipos de dados são bastante simples, fáceis de usar e muito mais direcionados à modelagem de estrutura de hardware, em oposição à modelagem abstrata. Ao contrário de VHDL, todos os tipos de dados são definidos pela linguagem, e não pelo usuário. Verilog pode ser atrativa pela sua simplicidade.

3.4.4 Reusabilidade de Projeto

VHDL: Procedimentos e funções podem ser colocados em pacotes de forma que eles fiquem disponíveis para qualquer unidade de projeto que deseje utilizá-las.

Verilog: Não existe conceito de pacotes em Verilog. Funções e procedimentos usados em um módulo devem ser definidos no próprio módulo. Para torná-los acessíveis de diferentes módulos, as funções e procedimentos devem ser colocados em um arquivo de sistema diferente e incluídos através da diretiva de compilador include.

3.4.5 Facilidade de Aprendizado

Iniciando com conhecimento zero de linguagem alguma, Verilog provavelmente é a mais fácil de captar e entender. VHDL pode primeiramente parecer menos intuitiva por duas razões primárias: primeiro, ela é fortemente tipada (uma característica que a faz robusta e poderosa para o usuário avançado, demandando uma fase de aprendizado maior); segundo, existem muitas formas de se modelar o mesmo circuito, especialmente àqueles com grandes estruturas hierárquicas.

3.4.6 Bibliotecas

VHDL: Uma biblioteca armazena entidades compiladas, arquiteturas, pacotes e configurações. Útil para o gerenciamento de múltiplos projetos.

(23)

Verilog: Não existe o conceito de biblioteca em Verilog. Isto se deve às suas origens como uma linguagem interpretada.

As diferenças entre as duas linguagens, citadas anteriormente, são apenas um subconjunto de várias existentes. Outras comparações podem ser encontradas em Smith (2003). De antemão, percebe-se que cada linguagem tem seus pontos fortes e fracos, cada uma favorecendo diferentes abordagens no processo de descrição de hardware.

3.5

SystemC

Embora VHDL e Verilog sejam as linguagens de descrição de hardware atualmente predominantes, existe uma forte tendência de as mesmas perderem espaço para outra HDL num futuro não muito distante: SystemC.

SystemC é uma iniciativa da Sinopsys, começada em 1999, que ainda está em desenvolvimento, e consiste em um conjunto de rotinas de biblioteca e de macros implementado em linguagem C++, o que torna possível a simulação de processos concorrentes, cada um descrito pela sintaxe da C++ comum. Instanciados no framework do SystemC, os objetos descritos desta forma podem se comunicar em um ambiente simulado em tempo-real, usando sinais de todos os tipos de dados oferecidos por C++, alguns adicionais oferecidos pela biblioteca SystemC, assim como os definidos pelo usuário.

Esta linguagem, embora demonstre grande potencial futuro, ainda está em fase de desenvolvimento, necessitando ser amadurecida. Por tais razões, a mesma não será utilizada neste trabalho, que apenas faz uma breve citação à sua importância.

Após a aquisição dos conceitos elementares referentes às HDLs, se faz necessária a introdução de uma última tecnologia, necessária à aplicação prática de toda a teoria descrita anteriormente.

3.6

FPGAs

Um Field-Programmable Gate Array, ou arranjo de portas programável no local, é um dispositivo semicondutor que contém componentes de lógica programável (denominados “blocos lógicos”) e interconexões programáveis. Blocos lógicos podem ser programados para executar a função de portas lógicas básicas (como AND e XOR) ou funções combinacionais mais complexas (como decodificadores ou funções

(24)

matemáticas). Na maioria dos FPGAs, os blocos lógicos incluem elementos de memória, que podem ser desde flip-flops simples, até blocos de memória mais complexos. Os principais fabricantes de FPGAs são, atualmente, Altera e Xilinx.

Uma hierarquia de interconexões programáveis permite que os blocos lógicos sejam interconectados, à medida que o projetista do sistema precisar. Blocos lógicos e interconexões podem ser programados pelo cliente/projetista, após o FPGA ter sido fabricado, para implementar qualquer função lógica. Isso explica o termo "programável no local".

De acordo com Barr (1999), os FPGAs são normalmente mais lentos do que os ASICs (Application-Specific Integrated Circuits – Circuitos Integrados de Aplicação Específica), uma vez que não são otimizados para uma funcionalidade específica. Mas suas vantagens incluem um time-to-market (isto é, o prazo compreendido entre o momento em que se deu a idéia e a efetiva chegada do produto ao mercado) mais curto, a capacidade de serem reprogramados em campo (a fim de corrigir bugs / alterar a funcionalidade pretendida) e menores custos não recorrentes de engenharia. Fornecedores podem vender versões menos flexíveis de seus FPGAs a um custo menor, com porções do circuito que não possam ser modificadas após o projeto estar pronto: nesta abordagem, os projetos são originalmente desenvolvidos em FPGAs comuns, para então ser migrados para uma versão fixa (semelhante a um ASIC em sua especificidade). A arquitetura de um FPGA varia de acordo com o fabricante/família. Em geral, com algumas variações de nomenclatura, abrange os seguintes componentes (figura 4):

• CLBs - Configuration Logical Blocks, ou Blocos Lógicos de Configuração: Circuitos idênticos, construídos pela reunião de 2 a 4 flip-flops com a utilização de lógica combinacional. Utilizando os CLBs, o usuário pode construir elementos funcionais lógicos.

• IOBs - Input/Output Blocks, ou Blocos de Entrada/Saída: São basicamente buffers, que atuam no controle bidirecional de entrada e saída do FPGA.

• Switch Matrix, ou Rede de Interconexão: Trilhas utilizadas para realizar a conexão entre os CLBs e os IOBs. Geralmente, a sua configuração é estabelecida por programação interna das células de memória estática, que determinam funções

(25)

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 (BARR, 1999).

Como possíveis aplicações de FPGAs, podem ser citadas:

• Implementação de lógica aleatória: em substituição a chips totalmente customizados;

• Hardware reconfigurável: na definição de blocos de hardware que podem/necessitam ter seu comportamento alterado durante a execução de uma aplicação, num processo de readequação da arquitetura (visando-se aceleração de processamento / flexibilidade);

• Resolução de problemas específicos: ao permitir que um componente de hardware possa se tornar temporariamente dedicado à solução de um determinado problema;

• Prototipagem: ao permitir que uma combinação de matrizes e portas emule um circuito que ainda não foi fabricado (ou, da mesma forma, que foi descontinuado), obtendo uma análise maior, melhor e mais detalhada, se comparada à simulação – esta é a abordagem que será seguida neste trabalho.

(26)

4 Tecnologias e Ferramentas

Utilizadas

4.1

A Placa FPGA PI1K100A

A placa FPGA disponível para a execução deste projeto é a PI1K100A (figura 5), cujo propósito é prover uma plataforma de desenvolvimento e prototipagem de projetos funcional e de baixo custo, inclusive com possibilidade de uso no produto final.

Esta placa tem como componente principal um dispositivo de lógica programável FPGA da família Altera ACEX 1K, o EP1K100QC208-3, dispositivo em encapsulamento QFP de 208 pinos, com 100K portas utilizáveis, implementadas em 4992 elementos lógicos, contando ainda com 49152 bits de memória interna disponíveis, organizados em 12 blocos de memória de 4096 bits por bloco. Os blocos de memória podem ser organizados nas formas de memória tipo ROM, memória RAM ou memória RAM dual-port. O componente pode ser configurado via interface JTAG ou através de uma EPROM ou ROM paralela externa, usando para tal uma interface do tipo Passivo Serial implementada em um componente EPM3064ATC44-10 que lê os dados da EPROM ou ROM externa e emula uma PROM serial a partir dos dados lidos, configurando a EP1K100. A interface JTAG está implementada na própria placa, disponibilizando um conector JTAG padrão de 10 pinos tipo BERG, organizado em fila dupla (5x2 pinos), que é compatível com os sistemas de configuração ByteBlasterMV, ByteBlaster II e MasterBlaster da Altera.

(27)

O componente EP1K100 necessita, para sua operação, de duas tensões de alimentação diferentes, sendo estas de 3.3 e 2.5 volts. O componente usa 2.5 volts para alimentar a lógica interna e 3.3 volts para a interface com outros componentes, no padrão LVTTL. Estas duas tensões são geradas na própria placa a partir da uma tensão de alimentação única de entrada de 5.0 volts, que deve ser fornecida pelo usuário para que a mesma possa funcionar. Os sinais de I/O da placa aceitam e geram sinais compatíveis com o padrão TTL (nível lógico ‘0’ < 0.4 volts e nível lógico ‘1’ > 2.4 volts de saída e nível lógico ‘0’ < 0.8 volts e nível lógico ‘1’ > 2.0 volts de entrada).

Para possibilitar o carregamento da EP1K100 através da EPM3064, e para prover um sinal de clock de entrada para o EP1K100, a placa inclui um oscilador de 32.768 MHz, que está disponível para a mesma através do sinal CLOCK1.

Finalmente, todos os sinais de entrada e saída do EP1K100 estão disponíveis para serem usados em uma placa desenvolvida pelo usuário através de conectores BERG de duas filas de pinos. Por estes conectores são disponibilizados os pinos de I/O do componente e é enviada a alimentação de 5.0 volts para a placa. Para facilitar a conexão com placas padrão de montagem de protótipo, os conectores são alinhados em grade de 100 milésimos de polegada (aproximadamente 2,5 mm), grade esta usada na maioria das placas para desenvolvimento de protótipos disponíveis no mercado.

(28)

O diagrama de blocos da placa é apresentado na figura 6. Os principais blocos da placa são: componente lógico programável FPGA EP1K100, sistema de carga através da interface Passivo Serial, usando o CPLD EPM3064, as fontes de tensão, o oscilador, a interface JTAG e a conexão com a placa do usuário.

Na figura 6 estão mostrados os blocos que compõem a placa, com os conectores fazendo a interface entre a mesma e o circuito do usuário, sendo também os responsáveis pela alimentação da placa com 5.0 volts (conectada usando os conectores CN1, CN2 ou CN5), e mostrando os componentes que compõe a placa e a forma como estes componentes se interligam.

4.2

Linguagens de Descrição de Hardware

Visando obter as melhores características de implementação de cada linguagem, além de se buscar o aprofundamento nestas por meio da prática de programação, foram utilizadas neste projeto tanto a linguagem VHDL quanto Verilog (procurando-se

(29)

explorar os pontos fortes de cada uma). Foi utilizada para síntese dos circuitos a ferramenta Quartus II, versão 7.1 Web Edition, da Altera.

4.3

Outras ferramentas

Além das tecnologias e ferramentas já citadas, também foi utilizado material de apoio ao projeto, como componentes de hardware (resistores, diodos, amplificadores operacionais, fios, conectores, etc.), para montagem de circuitos auxiliares; equipamentos de suporte (fonte DC, protoboard, multímetro, ferro de solda) para teste dos circuitos montados; e cabos de programação para o dispositivo FPGA.

(30)

5 A Arquitetura do Atari

5.1 Primeiras Impressões

Inicialmente, foi realizado um estudo preliminar da arquitetura do Atari 2600, dando-se ênfase aos seus principais componentes. A figura 7 mostra a placa mãe do Atari 2600, juntamente com todo o seu sistema original. Cada um dos seus componentes é explicado em seguida.

1. Entrada para cartucho: constitui um conector fêmea de 24 pinos para cartões, sendo 12 pinos de cada lado. Esta entrada está ligada à alimentação, ao terra, e aos barramentos de endereços e de dados dos três chips principais.

2. Entradas para joystick e componentes relacionados. Estas portas são conectores D-sub de 9 pinos, e os resistores e capacitores associados às mesmas auxiliam no fornecimento adequado de tensão, assim como a proteger as linhas contra ruídos e realimentação. A partir deste ponto, as linhas de sinal se dirigem para os chips RIOT e TIA, que serão descritos na seqüência.

1

2

3

4 5 6 7 8 9 10

(31)

3. Este é o circuito de alimentação. Ele normalmente toma como entrada 9 volts DC de uma fonte externa, e tem como saída 5 volts, que é tensão utilizada pelo console. Tecnicamente, o circuito de alimentação pode receber qualquer entrada entre 6 e 35 volts (o regulador de tensão pode agüentar esta tensão) embora não seja recomendado.

4. O circuito de referência de cor toma ambas as tensões de 5 e 9 volts e, usando um potenciômetro (isto é, um resistor variável), envia um nível de tensão de referência ao pino 10 do chip TIA. Este chip usa esta tensão como referência para os sinais luma, que então afetam a coloração da imagem resultante. O potenciômetro permite ajustar a saída de cores para um equilíbrio “ideal”.

5. Circuito gerador de clock. Assim como nos computadores modernos, os três chips do sistema necessitam de um sinal de clock para funcionar. O cristal gerador de pulsos usado no Atari tem uma freqüência de 3.579545 MHz (aproximada para 3.58 MHz), que é a mesma utilizada pelo padrão NTSC. Este circuito de clock está presente na maioria dos aparelhos de TV e DVD players (assim como em outros aparelhos que façam interface com uma TV).

6. Chip RIOT – É primariamente responsável por ler informações do cartucho, controles e switches – embora o chip TIA trate as alavancas e botões de tiro. O RIOT está encapsulado em um DIP de 40 pinos.

7. CPU 6507. Uma versão mais simples do largamente utilizado processador MOS 6502, que foi utilizado em sistemas como Commodore 64, Apple II series, e Furbys. A CPU está encapsulada num chip DIP de 28 pinos.

8. Chip TIA – também chamado de Stella, este chip é responsável pela geração de imagens e sons dos jogos. Conforme mencionado, alguns sinais provenientes dos joysticks também estão ligados ao TIA. Este chip está encapsulado num DIP de 40 pinos.

9. Subsistema de Áudio/Vídeo (A/V). Sinais provenientes do TIA são manipulados e mixados, e então enviados para o modulador RF, de modo que possam ser “sintonizados” nos canais 3 ou 4 de qualquer aparelho de TV.

10. Modulador RF. Responsável por modular o sinal de A/V, de modo que este se torne acessível através dos canais 3 ou 4 do aparelho de TV.

(32)

Percebe-se, portanto que o sistema do Atari 2600 é construído ao redor dos seus três principais chips. Isto pode ser mais bem observado a partir de um dos esquemáticos do seu projeto original, na figura 8 a seguir.

Os componentes enumerados na figura acima serão descritos na seqüência. 1. Processador MOS 6507

2. Chip RIOT 3. Chip TIA

(33)

5.2 O processador MOS 6507

Este é uma versão mais simples (e barata) da CPU MOS 6502, fabricada pela MOS Technology Corporation, a qual foi largamente utilizada entre as décadas de 70 e 80.

O 6502 é um processador cujo comportamento é similar a uma arquitetura RISC, projetado em 1975 por Chuck Peddle. Quando foi lançado, o 6502 era o processador de uso geral mais barato disponível no mercado. Quando comparado aos seus concorrentes, o seu custo era menor que 1/6 dos demais e, apesar disto, era mais rápido do que dispositivos similares, fabricados por companhias de maior porte, como a Motorola e a Intel. Juntamente com o Zilog Z80, esta CPU originou uma série de projetos de computadores que viria, eventualmente, a resultar na revolução dos computadores pessoais, em 1980.

Sendo uma CPU de 8 bits, com barramento de endereços de 16 bits, o 6502 pode endereçar até 64 kilobytes de memória. A sua lógica interna trabalha na mesma freqüência que a sua taxa de clock externa, mas apesar das suas baixas velocidades de clock (tipicamente entre 1 e 2 MHz), a performance deste processador era, na prática, competitiva com outras CPUs que usavam clocks significantemente mais rápidos (NABERENZY, 2008).

Os registradores deste processador incluem um registrador acumulador de 8 bits (A), dois registradores de indexação de 8 bits (X e Y), um registrador de estado do processador (P), um apontador de pilha de 8 bits (S), e um contador de programa de 16 bits (PC).

(34)

De acordo com Jacobs (2003), os primeiros 256 bytes de memória ($0000-$00FF) se referem à "página zero", e concentram um número de modos especiais de endereçamento, que resultam em instruções mais curtas (e mais rápidas), ou permitem o acesso indireto à memória. A segunda página de memória ($0100-$01FF) é reservada para a pilha do sistema, a qual não pode ser realocada. O acesso à pilha é feito através de quatro modos de endereçamento, cujas funções são colocar (push) ou retirar (pop) dados a partir do acumulador ou do registrador de estado. A mesma pilha também é utilizada para chamadas de sub-rotina através das instruções JSR (Jump to Subroutine) e RTS (Return from Subroutine), e para tratamento de interrupções, que podem ser tanto mascaráveis quanto não mascaráveis.

Visando a redução de custos, os projetistas da versão 6507 retiraram três bits do barramento de endereços do 6502 original, reduzindo a sua capacidade de endereçamento para apenas 8 kilobytes de memória. Além disso, o 6507 não pode atender a interrupções, mascaráveis ou não mascaráveis (JACOBS, 2003).

Quando a CPU recebe um sinal de reset, esta imediatamente efetua um jump para a rotina de reset e inicia a execução do código. Uma instrução pode levar de 1 a 5 ciclos para ser executada, uma vez que o processador é capaz de iniciar a busca por uma instrução ao mesmo tempo em que ainda executa a instrução precedente. As instruções têm comprimento variável (de 1 ou 2 bytes), consistindo de um opcode e um valor imediato (opcional). Uma característica interessante deste processador é que o mesmo possui mais de 100 opcodes não documentados, muitos dos quais variam dependendo das especificações de fabricação do chip. Estes opcodes foram usados pelos programadores da Atari para empacotar múltiplas operações em uma única instrução. Vale ressaltar que a freqüência de operação deste processador no sistema Atari 2600 é de 1.19MHz.

(35)

5.3 O chip RIOT

Abreviação para RAM I/O Timer, é o circuito integrado 6532 projetado pela MOS Technology, tendo fornecedores secundários, como a Rockwell. Este chip incorpora 128 bytes de RAM estática, duas portas bidirecionais de E/S de 8 bits, e um temporizador programável. O seu alto grau de integração para a época o fez bastante popular no final dos anos 70 e começo dos anos 80, enquanto ocupou o lugar de diversos CIs diferentes. A sua mais conhecida utilização foi no próprio Atari 2600, embora também tenha sido utilizado em famosas máquinas pinball da produtora Gottlieb, como Haunted House e Black Hole. A figura 10 reproduz o encapsulamento do RIOT, com os seus principais pinos.

A comunicação com a CPU é realizada através de dois barramentos: um para endereços e outro para dados. Além disso, há 16 pinos de E/S para comunicação com periféricos, podendo cada um deles ser configurado individualmente como entrada ou saída (utiliza-se um registrador de direção de E/S). Dados que entram e saem da memória são armazenados em um registrador de E/S. Uma das linhas de E/S pode ser usada para detectar margens de nível de entrada e sinalizar uma interrupção. Finalmente, o chip contém um contador e um registrador de estado.

Os 16 pinos de E/S estão divididos em duas portas de 8 bits, PA0-PA7 e PB0-PB7. Um ‘0’ lógico em um bit do registrador de direção de dados da porta A (Data Direction Register A - DDRA) implica que o pino correspondente da porta A irá atuar como entrada. Conseqüentemente, ‘1’ lógico implica que o pino correspondente da porta A

(36)

atuará como saída. O nível lógico em qualquer linha programada como saída é determinado pelo bit correspondente no registrador de dados da porta A (Data Register A - DRA).

Os dados são lidos diretamente dos pinos de dados durante qualquer operação de leitura. Para qualquer pino de saída, os dados transferidos para o processador serão os mesmos contidos no registrador de dados se o ‘1’ lógico no pino de saída corresponder à tensão mínima de 2.4v, isto é, obedecer aos padrões TTL. É importante notar que, para linhas de entrada, o processador pode escrever no bit correspondente do registrador de dados. Isto não afetará a polaridade do pino até que o bit correspondente no DDRA for ‘1’, a fim de permitir que o pino de E/S atue como saída.

A operação na porta B é exatamente a mesma da porta A. Cada uma das oito linhas pode ser programada para atuar tanto como entrada quanto como saída, configurando-se ‘0’ ou ‘1’ no registrador de direção de dados da porta B (DDRB). No modo de saída, a tensão em um pino periférico é controlada pelo registrador de dados da porta B (DRB).

A diferença primária entre as portas A e B é a operação dos buffers de saída que guiam estes pinos. Os buffers de saída da porta B são dispositivos push-pull (isto é, podem fornecer tanto corrente positiva quanto negativa), que são capazes de fornecer 3.0 ma a 1.5v. Isto permite que estes pinos possam alimentar diretamente circuitos chaveadores de transistores. Para assegurar que o processador irá ler os dados corretamente em uma operação de "leitura da porta B", a lógica no chip 6532 permite que o processador leia o registrador de saída em vez de ler o pino periférico, como na porta A. A figura 11, na seqüência, exibe o diagrama de blocos do RIOT.

(37)

A seção de temporização do RIOT contém três partes básicas: registrador de divisão, registrador de 8 bits programável e lógica de interrupção.

O temporizador pode ser programado para contar até 255 intervalos de tempo. Cada intervalo de tempo pode ser um incremento de 1T, 8T, 64T ou 1024T, onde T é o clock do sistema. Quando uma contagem completa é atingida, um flag de interrupção é preenchido com ‘1’ lógico. Depois que o flag de interrupção é aceso, o clock interno começa uma contagem regressiva na freqüência de clock do sistema, a um máximo de -255T. Desta forma, após o flag de interrupção ascender, uma leitura do temporizador irá informar quanto tempo se passou desde que o flag foi aceso, a um período máximo de 255T. A figura 12 mostra o esquema básico do temporizador de intervalo.

Figura 12: Temporizador de intervalo Figura 11: Diagrama de blocos do RIOT

(38)

5.4 O chip TIA

Fabricado pela própria Atari, o TIA - Television Interface Adapter (figura 13) fornece a geração de sprites e de vídeo, tratamento de som e algumas funções extra de E/S. Devido ao alto custo de memória na época em que foi projetado, o chip TIA não possui RAM específica para vídeo, e por causa disto gera apenas uma linha de vídeo por vez – esta linha é chamada de scanline, ou linha de varredura.

O TIA foi projetado para servir de interface entre o processador de 8 bits e o modulador de vídeo de TV, e converter os dados paralelos de 8 bits em saídas seriais de cores, luminosidade e sincronização composta, necessários ao modulador de vídeo.

Conforme já mencionado, este circuito tem a sua operação feita "linha por linha", sempre emitindo a mesma informação a cada linha da imagem, a menos que novos dados sejam enviados pelo processador.

Conforme Wright (1979), os objetos na tela podem incluir dois jogadores de 8 pixels de largura (jogador 1 e jogador 2), uma bola, dois mísseis, e uma imagem de fundo para o cenário ou um playfield (isto é, uma área delimitada de jogo). Para cada scanline, o programador do Atari precisa carregar no TIA os pedaços de uma única linha: os gráficos da bola e dos mísseis, e uma fatia do cenário (todos referentes à mesma linha). Os gráficos de bola e mísseis são retirados de uma lista pré-existente de gráficos. A posição de cada objeto na scanline pode ser modificada, assim como suas cores e disposição. Os gráficos podem ser esticados e duplicados, enquanto o cenário pode ser

(39)

refletido. Além disso, um bit de atraso permite que gráficos sejam carregados e retidos, aguardando o processamento da próxima scanline.

O TIA também desempenha detecção de colisão entre todos os objetos da tela. Se dois objetos são desenhados no mesmo pixel, um bit específico no latch de colisão é elevado para ‘1’, dependendo das camadas em que os objetos se encontram. O latch de colisão pode ser lido pelo programador para verificar colisões.

Outra característica deste chip é o controle de sincronização. Sincronizar o processador com a saída e vídeo é muito importante para a correta execução do software. O principal método que o TIA fornece para tal é paralisar o processador até o início da próxima scanline. O programador do Atari utiliza esta função por meio do endereço WSYNC, de modo que se possa garantir que a próxima instrução executada corresponda à próxima scanline.

Um contador de sincronização produz a temporização de sincronização horizontal, independente do processador. Já a temporização de sincronização vertical é fornecida a este circuito pelo processador, e combinada com a sincronização composta.

Paredes, nuvens e outros objetos cuja posição na tela raramente se altera, são produzidos por um registrador de dados de baixa resolução, chamado registrador de playfield (figura 14). Este registrador de 20 bits é carregado a partir do barramento de dados por três endereços de gravação distintos (PF0, PF1 e PF2). O playfield pode ser carregado a qualquer momento, e é zerado quando os três endereços são preenchidos com ‘0’. O registrador de playfield é automaticamente escaneado (e convertido para uma saída serial) por um registrador de deslocamento bi-direcional, trabalhando a uma freqüência de clock que distribui os 20 bits sobre a metade esquerda da linha horizontal. Este processo de varredura é iniciado no final do período de vazio horizontal (margem esquerda da tela). Normalmente, o mesmo processo é então repetido, duplicando a mesma seqüência de 20 bits sobre a metade direita da linha horizontal.

(40)

Um playfield refletido (isto é, espelhado) pode ser obtido ao se escrever '1' no bit zero do registrador de controle do playfield (CTRLPF). Quando este bit possui valor lógico verdadeiro, o registrador de deslocamento irá varrer na direção oposta durante a segunda metade da linha horizontal, revertendo a seqüência de 20 bits.

Contadores de posição horizontal são usados para acionar a saída serial dos cinco objetos móveis: os dois jogadores, os dois mísseis e a bola. O processador pode adicionar ou subtrair dados destes contadores de posição, a fim de mover estes objetos para a esquerda ou para a direita. Da mesma forma, todo posicionamento e movimentação vertical são feitos pelo processador, que escreve ‘0s’ e ‘1s' nos registradores de objetos, antes do processamento de cada linha horizontal apropriada. Diferentemente do registrador de playfield, que é sempre varrido a partir da extremidade esquerda de cada linha horizontal, os registradores de objetos gráficos móveis são varridos somente quando acionados por um decodificador de início, proveniente dos seus contadores de posição horizontal. Um circuito típico de movimentação horizontal é mostrado na figura 15, na seqüência.

(41)

Um registrador de colisão de 15 bits detecta todas as 15 possíveis colisões entre os seis objetos (os cinco móveis e o playfield). Este registrador de colisão pode ser lido e zerado pelo processador. Seis portas de entrada são também alimentadas neste chip, que pode ser lido pelo processador. Estas portas de entrada e o registrador de colisão são os únicos endereços do chip que podem ser lidos pelo processador. Todos os outros endereços são utilizados somente para escrita. O sistema de detecção de colisão do TIA é ilustrado na figura 16. Nota-se que, nesta figura, BL corresponde ao objeto bola, P0 e P1 correspondem aos jogadores, M0 e M1 correspondem aos mísseis e PF corresponde ao playfield.

(42)

Registradores de luminosidade de cor estão presentes, de modo que possam ser preenchidos pelo processador com oito valores para luminosidade e quinze valores para cor. Também está incluso um deslocador digital de fase, a fim de fornecer uma única saída de cor com quinze fases angulares.

Dois circuitos independentes de geração de áudio estão inclusos, cada qual com uma freqüência programável, conteúdo de ruídos e registradores de controle de volume. Objetivando-se diminuir a complexidade do projeto, os circuitos de áudio não serão abordados neste trabalho.

O acesso ao chip TIA é feito através dos barramentos de dados e de endereços (compartilhado com os chips 6507 e 6532). Assim como o chip RIOT, a função do TIA é selecionada pelo seu endereço (BEER, 2007).

Para propósitos de programação do TIA, um único frame (ou quadro) da imagem sendo gerada consiste em 262 linhas horizontais, e cada linha é dividida por 228 contagens de clock, resultando numa freqüência de 3.58 MHz. Esta imagem é desenhada na TV linha por linha, do topo até a base da tela, cerca de 60 vezes por segundo, e na prática consiste em apenas uma porção do frame completo. Um frame típico irá consistir em 3 linhas de sincronização vertical (vertical sync - VSYNC), 37 linhas de vazio vertical (vertical blank - VBLANK), 192 linhas de imagem e 30 linhas de overscan (isto é, uma área em volta da imagem visível, necessária para a sua correta alocação na tela em

(43)

diferentes tipos de TV). Pesquisas da Atari mostraram que este padrão funcionaria satisfatoriamente em qualquer tipo de TV. Cada scanline é iniciada com 68 contagens de clock de vazio horizontal (horizontal blank - HBLANK) - não vistas na tela - seguidas de 160 contagens de clock, a fim de preencher completamente a linha da imagem na TV. Quando o canhão de elétrons atinge o fim da scanline, este retorna ao lado esquerdo da tela, espera por 68 contagens de clock de vazio horizontal, e prossegue para desenhar a próxima linha.

O frame atual da imagem (figura 17) é desenhado uma linha por vez; tendo o processador enviado os dados daquela linha ao chip TIA, este então converte tais informações em sinais de vídeo. O chip TIA somente pode trabalhar com os dados que pertençam à linha sendo desenhada naquele instante, logo o processador precisa estar "um passo à frente" do canhão de elétrons a cada linha. Uma vez que um ciclo de máquina do processador ocorre a cada 3 contagens de clock, o programador do Atari tem apenas 76 ciclos de máquina por linha (228/3 = 76) para construir a imagem atual (na prática menos, pois o processador precisa estar à frente do processo de rasterização).

(44)

Em geral, as 70 scanlines remanescentes (3 para VSYNC, 37 para VBLANK e 30 para overscan) irão fornecer 5320 ciclos de máquina (70 linhas x 76 ciclos de máquina) para realização da lógica do jogo, como cálculo da nova posição do jogador, atualização do escore, e verificação de novas entradas - são atividades normalmente feitas durante este intervalo de tempo.

(45)

6 Desenvolvimento

6.1 Considerações Gerais

A implementação deste sistema se baseou na arquitetura proposta por Beer (2007), que descreve um projeto de síntese do Atari 2600 para uma outra família de dispositivos lógico-programáveis, e se mostrou bastante útil para o correto encaminhamento deste trabalho.

O diagrama de blocos em alto nível é mostrado na figura acima. Este sistema é baseado em três módulos principais: o processador 6507, o módulo RIOT, e o módulo TIA. Os três módulos compartilham um barramento comum de dados e de endereços, que ainda é conectado a uma memória ROM externa do cartucho. A CPU controla o barramento de endereços, usando este para endereçar a ROM, a RAM e várias outras funções nos módulos, tais como E/S mapeada de memória. Todos os módulos possuem uma linha de dados de entrada e saída conectada ao controlador de barramento, que faz as conexões corretas entre os mesmos, de acordo com alguns bits do barramento de endereços.

(46)

O sistema é controlado por dois clocks distintos: um clock de pixel de 3.58 MHz e um clock de barramento de 1.19 MHz. O clock de pixel funciona na freqüência do padrão NTSC, executando o gerador de vídeo e o contador de pixel. O clock de barramento controla a CPU, as comunicações de barramento, e todas as operações entre os módulos. Ambos os clocks são provenientes de um gerador de clock, que tem como entrada o circuito de clock da placa FPGA. Os módulos RIOT e TIA tratam as linhas de entrada dos joysticks, permitindo que a CPU leia os seus estados. Os sinais de vídeo são gerados no módulo TIA, passados para o conversor NTSC - VGA, e finalmente para o controlador VGA, para ser exibido na tela. Na seqüência será detalhada a construção e/ou adaptação de cada módulo ao sistema.

6.2 CPU 6507

Uma vez que a recriação do processador principal do Atari está fora do escopo deste trabalho, uma versão open source do chip 6502, chamada T65, implementada em VHDL, foi utilizada. Adicionalmente, foi criado um módulo para integração deste com o restante do sistema (que usa originalmente a versão 6507). O módulo de integração renomeia as linhas de E/S para torná-lo compatível com a nomenclatura do Atari, deixa alguns pinos de endereços flutuando, e aterra os pinos de interrupção. A figura 19 exibe o bloco MOS 6507 sendo utilizado na ferramenta Quartus II. Do seu lado esquerdo estão todos os seus pinos de entrada e, do lado direito, os pinos de saída – e serão abordados na seqüência.

Entre as entradas deste bloco, Din, representa a entrada de dados de 8 bits, proveniente do controlador de barramento. O pino CLK_n, representa a entrada para o clock de barramento, que trabalha com o nível lógico invertido (isto é, está ativa quando

(47)

em nível ‘0’). Da mesma forma, todos os pinos com o sufixo “_n” que serão citados em seguida se encaixam nesta condição. RDY é o pino que habilita e desabilita o funcionamento do processador, e RES_n, responsável por receber os sinais externos de reset. Entre as saídas do bloco MOS 6507, estão A, correspondente ao barramento de endereços, de 13 bits; Dout, saída de dados de 8 bits; e R_W_n, que controla a leitura ou escrita nos outros módulos, como o RIOT e o TIA.

6.3 Módulo RIOT

O módulo RIOT foi construído através das especificações funcionais existentes na datasheet original do MOS 6532. A mesma contém atribuições de endereços, descrições de alto nível das diferentes funções que o chip pode desempenhar, e diagramas de temporização para tratamento de operações de entrada e de saída. O esboço deste módulo é mostrado na figura 20.

Este subsistema contém um módulo de memória síncrona, uma unidade de temporização e registradores de E/S, cada qual com linhas de habilitação controladas pela entrada de endereços. Um multiplexador também controlado pela entrada de

(48)

endereços seleciona o valor a ser colocado na linha de saída. O temporizador é mantido em um registrador, e uma máquina de estados e contadores de prescale (ou seja, valores de escalas de freqüência pré-determinados) são utilizados para atualizar o temporizador. Os registradores de E/S são atualizados a cada ciclo de clock, e o registrador de estado é atualizado baseado nas linhas de E/S e no contador.

A figura 21 mostra o bloco do 6532 RIOT implementado no Quartus II. Do seu lado esquerdo estão todos os seus pinos de entrada e, do lado direito, os pinos de saída.

O pino A representa uma entrada de 7 bits, provenientes do barramento de endereços do processador. O Pino Din representa uma entrada de dados de 8 bits, igualmente provenientes do MOS 6507. Em seguida estão presentes os pinos CS e CS_n, correspondentes à entrada para o seletor de chip (chip selector). Na seqüência estão

R_W_n, entrada para leitura/escrita no chip, proveniente da CPU; RS_n, entrada para o

seletor de ROM (ROM selector); e RES_n, entrada para sinais de reset. Em seguida vem o pino CLK, que recebe como entrada o pulso de clock de barramento. Por fim, estão as entradas de 8 bits PAin, correspondente à porta A, e PBin, correspondente à porta B.

Entre os pinos de saída do módulo RIOT, estão presentes Dout, representando os 8 bits do barramento de dados; IRQ_n, correspondente ao sinal de interrupção; e os pinos

PAout e PBout, referentes às saídas das portas A e B, respectivamente.

A criação do bloco com as 128 células de RAM (que possuem 8 bits cada) se dá pela declaração de uma matriz de RAM, cujos elementos variam de 0 a 127. Assim, é declarado um registrador de 8 bits para cada um dos elementos da matriz, formando

(49)

assim um arranjo de 128 células, cada qual podendo armazenar 8 bits (isto é, 1 byte) de informação. De forma semelhante são criados os registradores de E/S. os registradores de direção de dados e o registrador de saída de dados, embora estes sejam unidimensionais, isto é, retêm toda a informação em apenas uma dimensão matricial.

As saídas das portas A e B são configuradas como resultado de uma operação lógica “E” bit a bit entre os seus respectivos registradores de dados e registradores de direção de dados, conforme mostrado em pseudocódigo:

PAout = DRA E DDRA PBout = DRB E DDRB

A tabela prescaler possui as constantes de escala do temporizador, que são definidas através de uma matriz de valores de escala, que contém os incrementos de 1T, 8T, 64T e 1024T, respectivamente.

Uma vez definida a escala do temporizador, a cada passo de contagem, esta escala é decrementada de 1, até que atinja o valor 0. Quando isto ocorre, o valor do contador é também decrementado de 1, e o processo reinicia até que o contador seja zerado. O seguinte trecho de pseudocódigo ilustra este comportamento:

se (contador > 0) então se (escala > 0) então escala = escala - 1; senão se (contador = 0) modo_contagem = 0; senão escala = tabela_prescaler[modo_contagem]; contador = contador - 1; fim-se fim-se fim-se

O bloco de lógica de controle é responsável pela operação do chip a cada pulso de clock. Ele verifica a cada ciclo se o chip recebeu um sinal de reset e, em caso positivo, inicia as rotinas de tratamento de reset, que zeram os registradores, flags e a memória RAM do chip, além de configurar a operação atual como “NOP” (no operation). Caso o reset não tenha sido requisitado, é verificado se o chip está habilitado, por meio do bit do seletor de chip e, caso esteja, os bits de entrada são armazenados em registradores, o contador é atualizado e a operação atual é processada. Por fim, caso o chip não esteja

(50)

habilitado, são realizadas apenas rotinas secundárias, atualizando o contador e configurando a operação atual com “NOP”. O comportamento do bloco de lógica de controle é ilustrado por meio do seguinte algoritmo:

para cada pulso de clock faça se (reset) então zera_registradores(); zera_flags(); zera_ram(); operação = “NOP”; senão se (chip_select) então registra_entradas(); atualiza_contador(); processa_operação(); senão atualiza_contador(); operação = “NOP”; fim-se fim-se fim-para

O bloco de lógica de mascaramento é responsável pela decodificação de operações do RIOT, no qual um registrador de operações as armazena a partir dos pinos de entrada

RS_n, R_W_n e A[4:0], isto é, as operações que o chip irá executar dependerão dos valores nestes pinos de entrada, a cada ciclo.

Uma vez decodificada a operação atual, a lógica de controle irá acessar o seu valor a partir do registrador de operação, e efetuar as rotinas de operação de acordo com este valor, conforme o seguinte trecho de pseudocódigo:

caso (operação) início

ler_ram: Dout = RAM[A]; escrever_ram: RAM[A] = Din;

ler_DRA: Dout = (PAin E ~DDRA) OU (DRA E DDRA); escrever_DRA: DRA = Din;

ler_DDRA: Dout = DDRA; escrever_DDRA: DDRA = Din; ...

ler_contador: Dout = contador;

ler_flag_interrupcao: Dout = flag_interrupcao; ...

(51)

Caso a operação corrente seja de acesso à memória RAM, Dout recebe os dados no endereço de memória RAM apontado por A, ou neste endereço é gravado o valor de Din, dependendo de qual operação está sendo realizada (leitura ou escrita, respectivamente). Caso a operação seja de acesso aos dados da porta A, na operação de leitura, Dout recebe os dados provenientes de PAin ou DRA, dependendo dos valores no registrador de direção de dados, DDRA. Na operação de escrita, o registrador de dados da porta A recebe os dados provenientes de Din.

Na operação de acesso ao registrador de direção de dados da porta A, caso esta seja de leitura do registrador, Dout recebe o conjunto de bits a ser lido de DRA; caso seja uma operação de escrita, ocorre o inverso, com DRA recebendo os dados provenientes de Din. O acesso aos dados da porta B, assim como do seu registrador de direção é realizado de forma análoga à descrita acima.

Ao efetuar a operação de leitura do temporizador, Dout recebe os dados de contagem do registrador contador; caso seja requisitada a leitura do registrador de estado, Dout irá receber os valores dos flags de interrupção, como o do temporizador, por exemplo.

É importante notar que apenas algumas operações deste módulo foram aqui abordadas, de forma que fosse possível ilustrar o seu funcionamento de forma didática, sem a preocupação com maiores detalhes de implementação.

Referências

Documentos relacionados

Formação técnica: Técnicas de Operador de Câmera; Captação e Edição Áudio; Edição Adobe Premiere e Edição DaVinci Resolve Formação Visual: Direcção de Fotografia; Cultura

exemplo 2 Aplicação Hospitalar : salas de exame em uma clínica ou hospital-dia Zona CFD Condições de contorno impostas pelo multizona ao CFD Definição geometria, geração

Tubos de condução nos graus A e B, com composição química e propriedades mecânicas definidas.Sendo o de grau A apto a ser dobrado ou flangeado.São nor- malmente fornecidos no SHC

Após os ensaios de tração, foram obtidos gráficos de tensão por deformação de engenharia.. 34 Figura 4.8 Gráficos tensão-deformação das amostras sem processamento. Figura 4.9

A inspeção judicial é um importantíssimo meio de prova que visa prover o julgador de informações além das constantes nos autos para formação do seu

Diante da extrema importância agronômica, econômica e ambiental da difusão e ampliação do uso de inoculantes agrícolas no Brasil, este trabalho teve como objetivo o estudo

Tem-se como objetivo deste trabalho de pesquisa a proposta de arquitetura para a integração de diversas tecnologias em Automação em uma plataforma automatizada

Em síntese, no que tange à categoria integração, contribuição e desafios, pode- se concluir, a princípio, que, mesmo sendo reconhecido o potencial e desejo de ampliação dos