Este repositório contém o desenvolvimento do projeto final da disciplina de Computação Digital (PUC-Rio), ministrada pelo Prof. Wouter Caarls.
O objetivo é projetar, implementar em VHDL e testar um processador de 8 bits com arquitetura Harvard, baseado em acumulador, e seus periféricos essenciais.
O processador a ser construído segue estas especificações de alto nível:
-
Arquitetura: Harvard (memórias de dados e instruções separadas)
-
Modelo de Execução: Load/Store (apenas
lda/staacessam a memória) e baseado em acumulador (ACC) -
Tamanho da Palavra: 8 bits para dados e instruções
-
Memórias:
IMEM(Instruções): ROM assíncrona de 256 palavrasDMEM(Dados): RAM de 256 palavras (leitura assíncrona, escrita síncrona)
-
Banco de Registradores (RU): 16 registradores de 8 bits
-
Registradores Especiais:
- PC (Program Counter):
r15(rPC= "1111") - SP (Stack Pointer):
r14(rSP= "1110")
- PC (Program Counter):
-
Pilha (Stack): Implementada via software
-
Entrada/Saída (I/O): Mapeada na memória
-
Flags: Carry (C), Zero (Z), Negative (N) e Overflow (V) Apenas instruções lógicas e aritméticas atualizam as flags.
O processador acessa tanto a RAM quanto os periféricos usando endereços de 8 bits.
Os endereços de 0x00 a 0x08 da memória de dados são reservados para periféricos. O arquivo libcpu.vhd já fornece as constantes correspondentes.
| Endereço | Nome | Constante VHDL | Uso |
|---|---|---|---|
0x00 |
btn |
addr_BUTTON |
Estado dos botões |
0x01 |
enc |
addr_ENCODER |
Contagem do encoder |
0x02 |
kdr |
addr_PS2_DATA |
Caractere lido do teclado PS/2 |
0x03 |
udr |
addr_UART_DATA |
Dados da porta serial |
0x04 |
usr |
addr_UART_STATUS |
Estado da porta serial |
0x05 |
led |
addr_LED |
Valor mostrado nos LEDs |
0x06 |
ssd |
addr_SSD |
Valor mostrado no display de 7 segmentos |
0x07 |
ldr |
addr_LCD_DATA |
Caractere enviado ao LCD |
0x08 |
lcr |
addr_LCD_CMD |
Comando enviado ao LCD |
-
Início da Pilha (Stack): A pilha começa no topo da memória de dados (
0xFF) e cresce para baixo. O SP (r14) deve ser inicializado com este valor. Constante VHDL:addr_SP = x"ff" -
Vetor de Reset: O processador começa a executar a instrução no endereço
0x00da memória de instruções. Constante VHDL:addr_RESET = x"00"
O arquivo libcpu.vhd define constantes para todos os opcodes, facilitando o desenvolvimento da Unidade de Controle. O ISA é dividido em grupos:
lda [rs](Op:oLDA"0000"):acc <- MEM[rs]sta [rs](Op:oSTA"0001"):MEM[rs] <- acc
ldi c8(Op:oLDI"0100"):acc <- c8(valor imediato)b<cond> c8(Op:oB"0101"):pc <- c8se a condição for verdadeira Condições comobBZ,bBNZ,bBCCsão definidas emlibcpu.vhd.
get rs(Op:oGET"0110"):acc <- rsset rd(Op:oSET"0111"):rd <- acc
add rs(Op:oADD"1000"):acc <- acc + rssub rs(Op:oSUB"1001"):acc <- acc - rsinc rd(Op:oINC"1010"):rd <- rd + 1dec rd(Op:oDEC"1011"):rd <- rd - 1
and rs(Op:oAND"1100"):acc <- acc & rsor rs(Op:oOR"1101"):acc <- acc | rsxor rs(Op:oXOR"1110"):acc <- acc ^ rsshft rs(Op:oSHFT"1111"):acc <- acc << rsouacc >> -rs
Dica: Os códigos da ALU (ex: aADD, aSUB) têm os mesmos valores que os opcodes das instruções correspondentes, simplificando o design da Unidade de Controle.
O professor fornece um pacote Python para compilar os programas sem precisar escrever binário manualmente.
- Instalação:
pip install puc8a - Assembler (
as-puc8a): Converte código Assembly (.asm) em um array VHDL (ROMT) para inicializar aIMEM. - Compilador C (
cc-puc8a): Compila uma versão simplificada de C (inteiros de 8 bits) para Assembly ou VHDL. - Macros: O assembler suporta macros (
.macro), permitindo criar pseudoinstruções comopush,pop,calleret, que implementam a pilha e chamadas de sub-rotina em software.
- Crie um repositório Git.
- Adicione os arquivos fornecidos (
projeto.pdf,libcpu.vhd). - Crie o arquivo
README.md. - Instale o toolchain:
pip install puc8a.
- ALU: Módulo que recebe
A,Beopcodee produz resultado e flags. - Banco de Registradores (RU): 16 registradores de 8 bits com portas de leitura e escrita.
- Registradores: Crie módulos para
ACCUMeFLAGS. - Multiplexadores (MUXes): Adicione os MUXes do diagrama de blocos (ex: entrada B da ALU).
-
Estados:
FetcheExecute. -
Registradores:
state(estado atual) ecir(Instruction Register). -
Lógica:
- Próximo estado: define a transição entre
FetcheExecute. - Saída: gera sinais de controle (
reg_write_enable,alu_op, etc.). - Dica: defina valores padrão e sobrescreva apenas o necessário para cada instrução.
- Próximo estado: define a transição entre
Crie o módulo cpu.vhd, que instancia e conecta o datapath e a unidade de controle, ligando as flags de volta à CU.
imem.vhd: ROM de instruções inicializada com ounittest.asmcompilado.dmem.vhd: RAM síncrona na escrita e assíncrona na leitura, com decoder interno para periféricos.
- Crie o testbench
system_tb.vhdcomcpu,imemedmem. - Compile o teste com
as-puc8ae use o VHDL gerado. - Simule e depure até passar em todos os testes do
unittest.asm.
- Display de 7 Segmentos: Use
hex2ssdpara converter e exibir valores. - Teclado PS/2: Receptor que armazena o último scancode em
addr_PS2_DATA. - Controlador LCD: Responde aos endereços
addr_LCD_DATAeaddr_LCD_CMD.
- Escreva um programa (Assembly ou C) que leia dados do teclado e exiba no LCD.
- Compile com
as-puc8aoucc-puc8a. - Simule, sintetize e teste na placa.
- Tire fotos da placa funcionando.
- Reúna os resultados dos programas.
- Escreva o relatório.
- Gere o arquivo
.zipfinal.
A entrega final deve ser feita até 11/12/2025 às 23:59.
Itens a entregar:
-
Arquivo
.zip: Projeto completo em VHDL, pronto para simulação e síntese. -
Relatório
.pdf(aproximadamente 10 páginas), contendo:- Diagrama do caminho de dados
- Descrição das unidades (incluindo FSM da CU)
- Programas em Assembly e C desenvolvidos
- Resultados obtidos
- Fotos da placa em funcionamento
- Observações e conclusões