Este documento descreve como cada instrução do processador é codificada em binário. Todas as instruções possuem 19 bits e seguem diferentes formatos, conforme seu tipo (acumulador, imediato, salto, etc).
| Bits | Significado |
|---|---|
| [18:15] | Opcode (4 bits) |
| [14:0] | Campos variáveis, dependendo da instrução |
Essas instruções operam entre o acumulador (AC) e um registrador do banco.
Formato:
[18:15] Opcode
[14:11] Registrador fonte (a ser operado com o AC)
[10:0] Não utilizado (zeros)
Exemplo:
ADD R4→0001 0100 00000000000
(AC ← AC + R4)
Essas instruções operam entre o acumulador (AC) e um valor imediato.
Formato:
[18:15] Opcode
[14:11] Ignorados (podem ser 0)
[10:0] Imediato (unsigned)
Exemplo:
SUBI 1→1011 0000 00000000001
(AC ← AC - 1)
Formato:
[18:15] Opcode = 0110
[14:11] Registrador destino
[10:0] Imediato a ser carregado
Exemplo:
LOADREG R3, 5→0110 0011 00000000101
[18:15] Opcode = 1100
[14:11] Registrador destino
[10:0] Não utilizado (zeros)
[18:15] Opcode = 1000
[14:11] Registrador origem
[10:0] Não utilizado (zeros)
Formato:
[18:15] Opcode = 0100
[10:0] Imediato (unsigned)
[14:11] Ignorados (podem ser 0)
[18:15] Opcode
[14:8] Endereço de destino (7 bits)
[7:0] Zeros (ou ignorados)
[18:15] Opcode
[14:7] Offset
[6:0] Zeros (ou ignorados)
Exemplo:
JUMP 20→0010 0010100 00000000
[18:15] Opcode = 0000
[14:11] Registrador com o ponteiro do endereço de memória desejado
[10:2] Não utilizados (zeros)
[1] = 1 (diferencia de NOP)
[0] = 0
[18:15] Opcode = 0000
[14:11] Registrador com o ponteiro do endereço de memória desejado
[10:2] Não utilizados (zeros)
[1] = 0
[0] = 1 (diferencia de NOP)
Formato:
[18:0] = 0000000000000000000
| Instrução | Opcode |
|---|---|
NOP |
0000 |
JUMP |
0010 |
ADD |
0001 |
SUB |
0011 |
AND |
0101 |
CMP |
0111 |
ADDI |
1001 |
SUBI |
1011 |
CLEAR |
1101 |
CMPI |
1111 |
LOADAC |
0100 |
LOADREG |
0110 |
MVAC |
1000 |
MVREG |
1100 |
BHI |
1010 |
BCC |
1110 |
MOVRAM |
0000¹ |
LOADRAM |
0000² |
¹ instr(1) = 1 e instr(0) = 0
² instr(1) = 0 e instr(0) = 1
Esta atividade corresponde à última entrega da disciplina, cujo objetivo é validar o funcionamento completo do processador implementado.
De acordo com o enunciado proposto pelo professor, a tarefa consiste em:
- Implementar o Crivo de Eratóstenes via assembly personalizado, populando a RAM com números de 1 a 32 e eliminando múltiplos de 2, 3 e 5.
- Realizar a leitura dos dados restantes da RAM e enviá-los por um pino de saída para visualização.
- Além disso, implementar um programa que verifique se o número 751 é primo, utilizando apenas os recursos do processador construído.
Para a verificação da primalidade de 751:
- Inicializamos registradores com o número 751, um divisor começando de 2, uma flag de primalidade (inicialmente 1), e o limite 28 (( \sqrt{751} \approx 27{,}4 )).
- Utilizamos subtrações sucessivas para simular uma operação de módulo (resto da divisão).
- Caso algum divisor seja exato, a flag é zerada (indicando que 751 não é primo).
- Ao final, o valor da flag é movido para o registrador
R8, utilizado como registrador de debug, permitindo a visualização do resultado.
- Se o registrador
R8contiver1, significa que 751 é primo (o esperado). - Se contiver
0, significa que foi encontrado um divisor entre 2 e 27.
- R0 ← 751
- R1 ← 2 (divisor)
- R4 ← 1 (flag: assume que é primo)
- R5 ← 28 (limite do loop, pois \sqrt{751} ≈ 27.4)
- Loop para testar se algum divisor de 2 a 27 divide 751:
- Simula divisão por subtrações sucessivas
- Se resto for 0, define R4 ← 0 (não é primo)
- Copia o resultado final para R8
; Inicializa RAM de 1 a 32
0: LOADAC 1
1: MVREG R1
2: MOVRAM R1
3: ADDI 1
4: CMPI 33
5: BHI 2
6: JUMP 1
; Zera posições 4,6,...,32 da RAM (teste de escrita)
7: LOADAC 4
8: CMPI 33
9: BHI 7
10: MVREG R1
11: LOADAC 0
12: MOVRAM R1
13: MOVAC R1
14: ADDI 2
15: JUMP 8
16: LOADAC 6
17: CMPI 33
18: BHI 7
19: MVREG R1
20: LOADAC 0
21: MOVRAM R1
22: MOVAC R1
23: ADDI 3
24: JUMP 17
25: LOADAC 10
26: CMPI 33
27: BHI 7
28: MVREG R1
29: LOADAC 0
30: MOVRAM R1
31: MOVAC R1
32: ADDI 5
33: JUMP 26
; Percorre e lê da RAM
34: LOADAC 1
35: CMPI 33
36: BHI 7
37: MVREG R1
38: LOADRAM R1
39: LOADREG R2
40: MOVAC R1
41: ADDI 1
42: JUMP 35
43: NOP
; --- Início da verificação de primalidade de 751 ---
44: LOADREG R0, 751
45: LOADREG R1, 2
46: LOADREG R4, 1 ; assume que é primo
47: LOADREG R5, 28
; loop_divisor:
48: MOVAC R0
49: MVREG R3
; loop_sub:
50: SUB R1
51: BCC 54
52: MVREG R3
53: JUMP 49
; fim_sub:
54: MOVAC R3
55: CMPI 0
56: BHI 60
57: LOADAC 0
58: MVREG R4
59: JUMP 66
; continua:
60: MOVAC R1
61: ADDI 1
62: MVREG R1
63: CMP R5
64: BHI 66
65: JUMP 48
; fim:
66: MOVAC R4
67: MVREG R8 ; resultado (debug)- O valor final em
R8indica se 751 é primo:1= é primo (nenhum divisor foi encontrado)0= não é primo
Esse registrador pode ser lido via sinal de debug ou LED de visualização na FPGA.
- O algoritmo pode ser adaptado para verificar outros números bastando alterar a instrução
LOADREG R0, número. - Tempo de execução cresce linearmente com o valor testado.
- O acumulador é o registrador principal para operações aritméticas.
- Os registradores são codificados em 4 bits (de
0000a1000, ou R0 a R8). - Os imediatos são valores de 11 bits (de
0a2047). - Instruções que não usam todos os bits devem preencher os restantes com zeros.
- Instruções
MOVRAMeLOADRAMutilizam dois bits extras (instr(1)einstr(0)) para diferenciação, já que compartilham o mesmo opcode0000.