Alguns detalhes podem ser alterados no Internet Explorer. Se possível, empregue o Mozilla Firefox


CPU-1

 

Microprocessador didático descrito em VHDL

 

Tópicos

·                 Arquitetura e Modos de Endereçamento

·                 Conjunto de instruções

·                 Interligação e comunicação com periféricos

·                 Diagrama de blocos

·                 Operação da unidade de controle

·                 Exemplos de operação de algumas instruções

·                 Código VHDL do microprocessador

C_icon_2.gif  1.   Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4              Retorna





Objetivo

·   Propor um código VHDL para uma arquitetura de um microprocessador

·   Análise das unidades operativas frente ao código

C_icon_2.gif   2. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4               Retorna




Arquitetura do microprocessador

·   Procura explorar situações diversas

- Sinais de controle de periféricos

- Instruções com um acesso à memória

- Instruções com dois acessos à memória

·   Contém um conjunto básico de instruções com:

- Diferentes modos de endereçamento

- 8 bits: Acesso Direto e Acesso Indireto

- 8+8 bits: Aceso Imediato

- Operações com uma Unidade Lógica Aritmética

- Desvios condicionais

- Chamadas de sub-rotinas

·   Permite ampliar o conjunto de instruções

C_icon_2.gif   3. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4                Retorna



Arquitetura e Modos de Endereçamento

image002.gif

C_icon_2.gif   4. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4               Retorna



Conjunto de instruções: Load, Store e Aritméticas

Mnemônico e Operação

Descrição da operação

Pc

Pc+1

LDmP,n

Load Immediate Page

Pg <= n

0n

 

LDmA,mm

Load Immediate Acc

Acc <= [Pc+1]

F7

mm

LDmS,mm

Load Immediate Stack

St <= [Pc+1]

F6

mm

LDdA,n

Load Direct Acc

Acc <= [Pg & n]

1n

 

LDiA,n

Load Indirect Acc

Acc <= [[Pg & n]]

2n

 

STdA,n

Store Direct Acc

 [Pg & n] <=  Acc

3n

 

STiA,n

Store Indirect Acc

[[Pg & n]] <= Acc

4n

 

 

 

 

 

 

ADdA,n

Add Direct Acc

Acc <= Acc + [Pg & n]

An

 

SBdA,n

Subtract Direct Acc

Acc <= Acc - [Pg & n]

Bn

 

[Pc+1] = conteúdo do endereço de memória apontado pelo valor Pc+1

[Pg & n] = conteúdo do endereço de memória apontado pelo valor de Pg concatenado com n

[[Pg & n]]= conteúdo do endereço de memória apontado pelo endereço de memória apontado pelo valor de Pg & n

C_icon_2.gif   5. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4              Retorna



Conjunto de instruções: Desvio, Desvio condicional e Subrotina

Mnemônico e Operação

Descrição da operação

Pc

Pc+1

Jump,mm

Jump Unconditional

Pc <= [Pc+1]

F0

mm

JP_Z,mm

Jump Zero

Z=1       Pc <= [Pc+1]

Z=0       Pc <= [Pc+2]

F1

mm

JPNZ,mm

Jump Non Zero

Z=0       Pc <= [Pc+1]

Z=1       Pc <= [Pc+2]

F2

mm

JPNG,mm

Jump Negative

N=1       Pc <= [Pc+1]

N=0       Pc <= [Pc+2]

F3

mm

 

 

 

 

 

Call,mm

Call Subroutine

Pc <= [Pc+1]

[St] <= Pc+2

St <= St-1

F8

mm

Retn

Return Subroutine

Pc <= [St+1]

St <= St+1

F9

 

 

C_icon_2.gif   6. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4              Retorna



Conjunto de instruções: Pacote cpu_aux

·   Declaração de tipo:

       possíveis estados da máquina (busca de instrução ou execução de instrução)

·   Função de conversão:

    - valor numérico do código (dado em memória) => mnemônico correspondente

    - instruções com código 4 bits + n:  valores reservados => '0,n' a 'E,n'

    - instruções com código de 8 bits:   valores reservados =>  'F,0'  a 'F,F'

 

 

Package cpu_aux Is       -- declaracao do pacote
 
  -- Tipo contendo os possiveis estados da maquina
  Type Tipo_estado Is (busca,
                       LDmP, LDmS, LDmA, LDdA, LDiA,
                       STdA, STiA,
                       Jump, JP_Z, JPNZ, JPNG, ADdA, SBdA,
                       Call, RETN, Halt);
   
  Function para_estado(dado : Std_Logic_Vector(7 Downto 0)) Return Tipo_Estado;
 
End cpu_aux;
 
 
 
 
Package Body cpu_aux Is  -- corpo do pacote
 
  -- Funcao para converter um valor numerico no codigo do mnemonico correspondente.
  -- Entrada tipo Std_Logic_Vector. Retorna valor no tipo estado com o mnemonico decodificado
  Function para_estado(dado : Std_Logic_Vector(7 Downto 0)) Return Tipo_Estado Is
    Variable mnemonico : Tipo_Estado;  -- Mnemonico interpretado
  Begin
    If (dado(7 Downto 4) /= x"f") Then 
      -- Codigos entre "0" e "d". Mnemonico identificado pelos 4 bits mais significativos
      Case dado(7 Downto 4) Is
        When x"0" => mnemonico := LDmP; 
        When x"1" => mnemonico := LDdA;  When x"2" => mnemonico := LDiA; 
        When x"3" => mnemonico := STdA;  When x"4" => mnemonico := STiA;
        When x"a" => mnemonico := ADdA;  When x"b" => mnemonico := SBdA;
        When Others => mnemonico := Halt;
      End Case;
    Else
      -- Codigos entre "f0" e "ff". Mnemonico identificado pelos 8 bits
      Case dado Is                              
        When x"f0" => mnemonico := Jump; When x"f1" => mnemonico := JP_Z;
        When x"f2" => mnemonico := JPNZ; When x"f3" => mnemonico := JPNG;
        When x"f6" => mnemonico := LDmS; When x"f7" => mnemonico := LDmA;
        When x"f8" => mnemonico := Call; When x"f9" => mnemonico := RETN;    
        When Others => mnemonico := Halt;
      End Case;
    End If;
    Return mnemonico;
  End Function;
 
End cpu_aux;

 

C_icon_2.gif   7-8. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna



Interligação e comunicação com periféricos

image004.gif

C_icon_2.gif   9. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna



Diagrama de blocos
image006.gif

C_icon_2.gif   10. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna



Operação da unidade de controle: duas máquinas seqüenciais

image008.gif

C_icon_2.gif   11. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna



Exemplos de operação de algumas instruções (próximas imagens)

 

·   Carta de tempos

·   Unidades envolvidas 

C_icon_2.gif   12. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Busca de Instrução: carta de tempos

image010.gif

C_icon_2.gif   13. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Instrução LDiA,n  (Load Indirect Acc): carta de tempos

image012.gif

C_icon_2.gif   14. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna



Instrução LDiA,n  (Load Indirect Acc): Unidades envolvidas Passo_op_cod=0
image014.gif

C_icon_2.gif   15. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Instrução LDiA,n  (Load Indirect Acc): Unidades envolvidas Passo_op_cod=1

image016.gif

C_icon_2.gif   16. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Instrução STiA,n  (Store Indirect Acc): carta de tempos

image018.gif

C_icon_2.gif   17. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Instrução STiA,n  (Store Indirect Acc): Unidades envolvidas Passo_op_cod=0
image020.gif

C_icon_2.gif   18. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Instrução STiA,n  (Store Indirect Acc): Unidades envolvidas Passo_op_cod=1
image022.gif

C_icon_2.gif   19. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Instrução Call,mm  (Chamada de subrotina): carta de tempos

image024.gif

C_icon_2.gif   20. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Instrução Call,mm  (Chamada de subrotina): Unidades envolvidas Passo_op_cod=0

image026.gif

C_icon_2.gif   21. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna




Instrução Call,mm  (Chamada de subrotina): Unidades envolvidas Passo_op_cod=1

image028.gif

C_icon_2.gif   22. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna






Teste da descrição  (3 entidades: CPU, Memória e Conjunto)

·   Memória contem um pequeno programa para verificar a operação das instruções

·    Compile:    Declaração do pacote   cpu_aux,      Corpo do pacote cpu_aux,

                     Declaração da entidade cpu_8bits,    Arquitetura teste de cpu_8bits

                     Declaração da entidade ram_8x8,     Arquitetura teste de ram_8x8

                     Declaração da entidade conjunto_5   Arquitetura teste de conjunto_5

·   Para verificar a operação simule a entidade conjunto_5


image030.gif

C_icon_2.gif   22. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna


Código do microprocessador

----------------------------------------------------------------------------------------------------------
-- VHDL - Descricao e Sintese de Circuitos Digitais  http://www.ele.ita.br/~damore/vhdl/
-- Roberto d'Amore
-- Editora LTC - 2005   http://www.ltceditora.com.br
--
--

-- Teste do conjunto CPU + Memoria
-- Memoria contem um pequeno programa para verificar a operacao das instrucoes

--
-- Compile o conjunto: Declaracao do pacote   cpu_aux,     Corpo do pacote cpu_aux,
--                     Declaracao da entidade cpu_8bits,   Arquitetura teste de cpu_8bits
--                     Declaracao da entidade ram_8x8,     Arquitetura teste de ram_8x8
--                     Declaracao da entidade conjunto_5 e Arquitetura teste de conjunto_5
--
-- Para verificar a operacao simule a entidade conjunto_5

----------------------------------------------------------------------------------------------------------


----------------------------------------------------------------------------------------------------------
-- Pacote auxiliar
-- Definicao de tipo contendo mnemonicos e funcao de valor numerioco para mnemonico
----------------------------------------------------------------------------------------------------------
---->> Emprego do pacote 'textio': veja capitulo 13 <<----
---->> Definicao e uso de pacotes: veja capitulo 9 <<----

Library IEEE;
Use IEEE.Std_Logic_1164.All;
Use IEEE.Std_Logic_arith.All;   -- Biblioteca Synopsys necessaria conversoes com Std_Logic

Package cpu_aux Is       -- declaracao do pacote
  -- Tipo contendo os possiveis estados da maquina
  Type Tipo_estado Is (busca, LDmP, LDmS, LDmA, LDdA, LDiA, STdA, STiA, Jump, JP_Z , JPNZ, JPNG, ADdA, SBdA, Call, RETN, Halt);
   
  Function para_estado(dado : Std_Logic_Vector(7 Downto 0)) Return Tipo_Estado;
 
End cpu_aux;

Package Body cpu_aux Is  -- corpo do pacote
  -- Funcao para converter um valor numerico no codigo do mnemonico correspondente.
  -- Entrada tipo Std_Logic_Vector. Retorna valor no tipo estado com o mnemonico decodificado
  Function para_estado(dado : Std_Logic_Vector(7 Downto 0)) Return Tipo_Estado Is
    Variable mnemonico : Tipo_Estado;  -- Mnemonico interpretado
  Begin
    If (dado(7 Downto 4) /= x"f") Then 
      -- Codigos entre "0" e "d". Mnemonico identificado pelos 4 bits mais significativos
      Case dado(7 Downto 4) Is
        When x"0" => mnemonico := LDmP; 
        When x"1" => mnemonico := LDdA;  When x"2" => mnemonico := LDiA; 
        When x"3" => mnemonico := STdA;  When x"4" => mnemonico := STiA;
        When x"a" => mnemonico := ADdA;  When x"b" => mnemonico := SBdA;
        When Others => mnemonico := Halt;
      End Case;
    Else
      -- Codigos entre "f0" e "ff". Mnemonico identificado pelos 8 bits
      Case dado Is                              
        When x"f0" => mnemonico := Jump; When x"f1" => mnemonico := JP_Z; When x"f2" => mnemonico := JPNZ;  When x"f3" => mnemonico := JPNG;
        When x"f6" => mnemonico := LDmS; When x"f7" => mnemonico := LDmA;
        When x"f8" => mnemonico := Call; When x"f9" => mnemonico := RETN;    
        When Others => mnemonico := Halt;
      End Case;
    End If;
    Return mnemonico;
  End Function; 
End cpu_aux;






----------------------------------------------------------------------------------------------------------
-- Codigo da CPU
----------------------------------------------------------------------------------------------------------
---->> Bibliotecas e Pacotes: veja capitulo 9 <<----
---->> Padroes IEEE 1164 e IEEE 1076.e: veja capitulos 10 e 11 <<----

Library IEEE;
Use IEEE.Std_Logic_1164.All;
Use IEEE.Std_Logic_arith.All;    -- Biblioteca Synopsys necessaria para a operacoes aritmeticas com Std_Logic
Use IEEE.Std_Logic_unsigned.All; -- Biblioteca Synopsys necessaria para a operacoes aritmeticas com Std_Logic
Use Work.cpu_aux.All;            -- Pacote com definicao de tipos e funcoes

---->> Declaracao de Entidade: veja capitulo 2 <<----
Entity cpu_8bits Is
  ---->> Genericos: veja capitulos 2 e 10 <<----
  Generic (ne : Integer := 8;     -- ne = numero de linhas do barramento de endereco
           nd : Integer := 8);    -- nd = numero de linhas do barramento de dado
  ---->> Clausula 'port' e modo das portas: veja capitulo 2 <<----
  Port    (ck     : In     Std_Logic;                        -- Entrada. Sinal de relogio: operacoes nas bordas de subida e descida
           rst_b  : In     Std_Logic;                        -- Entrada. Sinal de inicializacao sincrona, ativo nivel baixo (reset)
           mrq_n  : Buffer Std_Logic;                        -- Saida. Sinal para requisicao de memoria, ativo nivel baixo
           wr_n   : Buffer Std_Logic;                        -- Saida. Sinal de escrita, ativo nivel baixo
           rd_n   : Buffer Std_Logic;                        -- Saida. Sinal de leitura, ativo nivel baixo
           Ed     : Out    Std_Logic_Vector(ne-1 Downto 0);  -- Saida. Barramento de enderecos
           Dt     : InOut  Std_Logic_Vector(nd-1 Downto 0)); -- Entrada Saida. Barramento de dados
End cpu_8bits;

---->> Corpo da Arquitetura: veja capitulo 2 <<----
Architecture teste Of cpu_8bits IS
 
---->> Classe de objetos: veja capitulo 2 <<----
  Signal Estado          : Tipo_estado;          -- Estado da maquina: busca de instrucao ou execucao da instrucao
  Signal Passo_rd_wr     : Integer Range 0 To 3; -- Passo da operacao de escrita ou leitura. Controlado por 'borda_descida'
  Signal Passo_op_cod    : Integer Range 0 to 3; -- Passo da operacao de acesso indireto a memoria.
  Signal Ler, Escrever   : Boolean;              -- Sinais empregados para inicio das operacoes de leiutura e escrita na memoria
  -- Codigo não permite ainda alteracao nos valores de 'ne' e 'nd'
  Signal Pc              : Std_Logic_Vector(ne-1 Downto 0);  -- Registrador contador de programa.
  Signal pc_inc          : Std_Logic_Vector(ne-1 Downto 0);  -- Saida da unidade que incrementa o valor de Pc
  Signal St              : Std_Logic_Vector(ne-1 Downto 0);  -- Registrador endereco da pilha - "Stack Pointer".
  Signal st_novo         : Std_Logic_Vector(ne-1 Downto 0);  -- Saida da unidade que incrementa/decrementa o valor de St
  Signal End_mem         : Std_Logic_Vector(ne-1 Downto 0);  -- Registrador que armazena o valor imposto ao barramento de endereco
  Signal Pg              : Std_Logic_Vector(3 Downto 0);     -- Registrador de pagina de memoria
  Signal Ir              : Std_Logic_Vector(nd-1 Downto 0);  -- Registrador de instrucao
  Signal Acc             : Std_Logic_Vector(nd-1 Downto 0);  -- Acumulador
  Signal Aux             : Std_Logic_Vector(nd-1 Downto 0);  -- Registrador auxiliar para armazenar o valor do barramento de dado
  Signal Dado_escr       : Std_Logic_Vector(nd-1 Downto 0);  -- Registrador que armazena o valor imposto ao barramento de dado
  Signal alu_s, alu_b    : Std_Logic_Vector(nd-1 Downto 0);  -- Saida e operando 'b' da ALU
  Signal Alu_flags       : Std_Logic_Vector(1 Downto 0);     -- Registrador que armazena 'alu_n' e 'alu_z'
  Signal alu_n, alu_z    : Std_Logic;                        -- Valor decodificado da saida da ALU


Begin
    
-- Maquina principal responsavel pela decodificacao das instrucoes e realizacao das operacoes
-- Trabalha em conjunto com a maquina que realiza o acesso a memoria denominada: 'borda_descida'
-- Informacoes enviadas para maquina 'borda_descida' via os sinas 'Ler' e 'Escrever'
-- Informacoes recebidas da maquina  'borda_descida' via o  sinal 'Passo_rd_wr'
---->> Comando 'process': veja capitulo 3 <<----
---->> Lista de sensibilidade em processos: veja capitulo 4 <<----

borda_subida: Process (ck, rst_b)
  Variable salta : Boolean;         -- Empregada para determinar a necessidade de desvio nas instrucoes Jump, JPNZ etc.
Begin
  -- Preparacao: inicializacao assincronas
  ---->> Maquinas sequenciais sincronas: veja capitulo 6 <<----
  ---->> Comando 'If': veja capitulo 4 <<----

  If rst_b ='0' Then
    Ler <= False;  Escrever <= False;                    -- Condicoes para maquina 'borda_descida'
    Estado <= busca;                                     -- Estado inicial: busca de instrucao
    Passo_op_cod <= 0;                                   -- Sinal empregado em operacoes de acesso indireto a memoria
    ---->> Agregado: veja capitulo 2 <<----
    Pc <= (Others => '0');  End_mem <= (Others => '0');  -- Valor inicial do contador de programa e registrador de endereco
   
  -- Operacao normal
  ---->> Deteccao de borda de subida em sinais: veja capitulo 6 <<----

  ElsIf ck'Event And ck='1' Then
    Case Estado Is
      -- Busca na memoria da proxima operacao
      When busca   =>
        If    Passo_rd_wr = 0 Then Ler <= True;  end_mem <= Pc;
        ElsIf Passo_rd_wr = 2 Then Ir <= Dt; 
        ElsIf Passo_rd_wr = 3 Then Estado <= para_estado(Ir); Ler <= False;
        End If;

      -- Load Immediate Page: Pg <= Ir(3..0)
      When LDmP   =>
        Pg <= Ir(3 Downto 0); Pc <= pc_inc; Estado <= busca;
                    
      -- Load Immediate Acc: Acc <= [Pc +1]
      When LDmA   =>     -- Atualiza valor de Acc. Dado armazenado na proxima posicao de memoria
        If    Passo_rd_wr =0 Then Ler <= True; End_mem <= pc_inc;              -- Leitura do conteudo da prox. posicao de memoria: Pc+1
        ElsIf Passo_rd_wr =2 Then Acc <= Dt;   Pc <= pc_inc;                   -- Acc recebe novo valor. Contador de programa recebe valor: Pc+1
        ElsIf Passo_rd_wr =3 Then Estado <= busca; Pc <= pc_inc; Ler <= False; -- Contador de programa recebe valor: Pc+2. Fim do ciclo de leitura.
        End If;

      -- Load Immediate Stack: St <= [Pc +1]
      When LDmS   =>     -- Atualiza valor de St. Dado armazenado na proxima posicao de memoria
        If    Passo_rd_wr =0 Then Ler <= True; End_mem <= pc_inc;              -- Leitura do conteudo da prox. posicao de memoria: Pc+1
        ElsIf Passo_rd_wr =2 Then St <= Dt;   Pc <= pc_inc;                    -- St recebe novo valor. Contador de programa recebe valor: Pc+1
        ElsIf Passo_rd_wr =3 Then Estado <= busca; Pc <= pc_inc; Ler <= False; -- Contador de programa recebe valor: Pc+2. Fim do ciclo de leitura.
        End If;
               
      -- Load Direct Acc: Acc <= [Pg & Ir(3..0)]
      When LDdA   =>      -- Leitura do dado armazenado em [Pg & Ir(3..0)]
        If    Passo_rd_wr = 0 Then Ler <= True;  End_mem <= Pg & Ir(3 Downto 0); -- Leitura da posicao de memoria M[Pg & Ir(3..0)]
        ElsIf Passo_rd_wr = 2 Then Acc <= Dt;    Pc <= pc_inc;                   -- Acc recebe novo valor. Contador de programa incrementado
        ElsIf Passo_rd_wr = 3 Then Estado <= busca; Ler <= False;                -- Fim do ciclo de leitura
        End If;

      -- Store Direct: [Pg & Ir(3..0)] <= Acc
      When STdA   =>       -- escrita do dado no endereco [Pg & Ir(3..0)]
        If    Passo_rd_wr = 0 Then Escrever <= True; Dado_escr <= Acc; End_mem <= Pg & Ir(3 Downto 0); -- Escrita na posicao de memoria M[Pg & Ir(3..0)]
        ElsIf Passo_rd_wr = 2 Then Pc <= pc_inc;                                                       -- Contador de programa incrementado
        ElsIf Passo_rd_wr = 3 Then Estado <= busca; Escrever <= False;                                 -- Fim do  ciclo de escrita
        End If;

      -- Load Indirect: Acc <=[[Pg & Ir(3..0)]]
      When LDiA   =>      -- Leitura do dado armazenado em [[Pg & Ir(3..0)]]
        If Passo_op_cod = 0 Then  -- leitura do endereco armazenado em [Pg & Ir(3..0)]
          If    Passo_rd_wr = 0 Then Ler <= True;  End_mem <= Pg & Ir(3 Downto 0); -- Leitura da posicao de memoria M[Pg & Ir(3..0)]
          ElsIf Passo_rd_wr = 2 Then Aux <= Dt;                                    -- Registrador Aux armazena endereco apontado
          ElsIf Passo_rd_wr = 3 Then Passo_op_cod <= 1; Ler <= False;              -- Fim do primeiro ciclo de leitura
          End If;
        Else                     -- leitura do dado armazenado M[[Pg & Ir(3..0)]]
          If    Passo_rd_wr = 0 Then Ler <= True; End_mem <= Aux;                      -- Leitura da posicao de memoria contida em Aux
          ElsIf Passo_rd_wr = 2 Then Acc <= Dt;   Pc <= pc_inc;                        -- Acc recebe novo valor. Contador de programa incrementado
          ElsIf Passo_rd_wr = 3 Then Estado <= busca; Ler <= False; Passo_op_cod <= 0; -- Fim do segundo ciclo de leitura
          End If;
        End If;          
     
      -- Store Indirect: [[Pg & Ir(3..0)]] <= Acc
      When STiA   =>      -- Armazenamento do dado em [[Pg & Ir(3..0)]]
        If Passo_op_cod = 0 Then  -- leitura do endereco armazenado em [Pg & Ir(3..0)]
          If    Passo_rd_wr = 0 Then Ler <= True;    End_mem <= Pg & Ir(3 Downto 0);  -- Leitura da posicao de memoria M[Pg & Ir(3..0)]
          ElsIf Passo_rd_wr = 2 Then aux <= Dt;                                       -- Registrador Aux armazena endereco apontado
          ElsIf Passo_rd_wr = 3 Then Passo_op_cod <= 1; Ler <= False;                 -- Fim do ciclo de leitura
          End If;
        Else                      -- escrita do dado no endereco M[[Pg & Ir(3..0)]]
          If    Passo_rd_wr = 0 Then Escrever <= True; Dado_escr <= Acc; End_mem <= aux;    -- Escrtia na posicao de memoria contida em Aux
          ElsIf Passo_rd_wr = 2 Then Pc <= pc_inc;                                          -- Contador de programa incrementado
          ElsIf Passo_rd_wr = 3 Then Estado <= busca; Escrever <= False; Passo_op_cod <= 0; -- Fim do  ciclo de escrita
          End If;
        End If;
     
      -- Instrucoes de salto. Salto, Salto se Zero, Salto se Nao Zero, Salto se Negativo
      ---->> Comando 'case' com delimitador '|': capitulo 4 <<----
      When Jump |JP_Z | JPNZ | JPNG =>
        -- Teste para determinar a necessidade de desvio para um novo endereco de memoria
        If    Estado = Jump                       Then salta := True; -- Instrucao Jump. Sempre Pc <= [Pc+1].
        ElsIf Estado = JP_Z And alu_flags(1) ='1' Then salta := True; -- Instrucao JP_Z. Se Z =1, Pc <= [Pc+1]. Se Z=0 Pc <= Pc+2;
        ElsIf Estado = JPNZ And alu_flags(1) ='0' Then salta := True; -- Instrucao JPNZ. Se Z =0, Pc <= [Pc+1]. Se Z=1 Pc <= Pc+2;
        ElsIf Estado = JPNG And alu_flags(0) ='1' Then salta := True; -- Instrucao JPNG. Se N =1, Pc <= [Pc+1]. Se N=0 Pc <= Pc+2;
        Else                                           salta := False;
        End If;
        -- Executa o desvio ou nao
        If salta Then  -- Desvio para novo endereco de memoria apontado pela proxima posicao de memoria
          If    Passo_rd_wr =0 Then Ler <= True; end_mem <= pc_inc;     -- Leitura do conteudo da prox. posicao de memoria
          ElsIf Passo_rd_wr =2 Then Pc <= Dt;                           -- Pc recebe novo valor
          ElsIf Passo_rd_wr =3 Then Estado <= busca; Ler <= False;      -- Fim do ciclo de leitura
          End If;
        Else           -- Incrementar o Pc duas vezes para busca da nova instucao em duas etapas
          If Passo_op_cod =0  Then Pc <= pc_inc; Passo_op_cod <= 1;                  -- Primeiro incremento
          Else                     Pc <= pc_inc; Estado <= busca; Passo_op_cod <= 0; -- Segundo incremento
          End If;
        End If;
     
      -- Operacoes com a ALU          
      -- Add Direct      'ADdA': Acc <= Acc + [Pg & Ir(3..0)]     bits de sinalizacao ativados (alu_flags <= zero, negativo)
      -- Subtract Direct 'SBdA': Acc <= Acc - [Pg & Ir(3..0)]     bits de sinalizacao ativados (alu_flags <= zero, negativo)
      When ADdA | SBdA =>         -- leitura do dado armazenado em M[Pg & Ir(3..0)]
        If    Passo_rd_wr = 0 Then  Ler <= True;  end_mem <= Pg & Ir(3 Downto 0);
        ElsIf Passo_rd_wr = 2 Then  alu_b <= Dt;  Pc <= pc_inc;
        ElsIf Passo_rd_wr = 3 Then  Acc <= alu_s; alu_flags <= alu_z & alu_n; Estado <= busca; Ler <= False;
        End If;
       
      -- Operacoes com a pilha. Chamada de subrotina e retorno da subrotina
      When Call   =>      -- Chama subrotina Pc <= [Pc+1]; [St] <= Pc +2; 
        If Passo_op_cod = 0 Then        -- leitura do endereco da subrotina
          If    Passo_rd_wr = 0 Then Ler <= True;  End_mem <= pc_inc;    -- Leitura da proxima posicao de memoria: contem endereco da subrotina
          ElsIf Passo_rd_wr = 2 Then Aux <= Dt;    Pc <= pc_inc;         -- Endereco da subrotina armaz. em Aux. Contador de programa incrementado
          ElsIf Passo_rd_wr = 3 Then Passo_op_cod <= 1; Ler <= False;    -- Fim do ciclo de leitura
          End If;
        Else             -- Escrita do endereco de retorno na pilha; Decremento do ponteiro da pilha: St <= St -1;
          If    Passo_rd_wr = 0 Then Escrever <= True; Dado_escr <= pc_inc; End_mem <= St; -- Escrita do endereco de retorno
          ElsIf Passo_rd_wr = 2 Then St <= st_novo;  Pc <= Aux;                             -- Ponteiro da pilha decrementado. Pc recebe end. da subrotina
          ElsIf Passo_rd_wr = 3 Then Estado <= busca; Escrever <= False; Passo_op_cod <= 0; -- Fim do  ciclo de escrita
          End If;
        End If;        
         
      When RETN   =>      -- Retorno da subrotina Pc <= [St+1]; [St] <= St +1
        If    Passo_rd_wr = 0 Then Ler <= True;  End_mem <= st_novo;     -- Leitura do endereco apontado por St
        ElsIf Passo_rd_wr = 2 Then Pc <= Dt;     St <= st_novo;          -- Endereco de retorno em Pc. Ponteiro da pilha incrementado
        ElsIf Passo_rd_wr = 3 Then Estado <= busca; Ler <= False;        -- Fim do ciclo de leitura
        End If;
       
      -- Halt: parada de operacao 
      When Halt   =>
         Estado <= Halt;
       
    End Case;
  End If;
End Process;
 
-- Maquina secundaria que realiza as operacoes de acesso a memoria.
-- Ciclo de leitura tem inicio com Ler=verdairo. Ciclo de escrita tem inicio com Escrever=verdadeiro
-- Opera em conjunto com a maquina 'borda_subida'
-- Para operacao correta: apenas Ler ou Escrever ativos; uma vez iniciada a operacao devem ser manditidos ate Passo_rd_wr=3
borda_descida: Process (ck, rst_b)
 Begin
   If rst_b ='0' Then
     mrq_n <= '1'; wr_n <= '1'; rd_n <='1'; Passo_rd_wr <= 0;   
  
   -- Acesso a memoria: passos para leitura e escrita
   -- Operacoes executadas caso Ler ou Escrever verdadeiros.
   ElsIf ck'Event And ck='0' Then
     Case Passo_rd_wr Is
       When 0 => If    Ler      Then Passo_rd_wr <= 1; mrq_n <= '0'; rd_n <= '0';
                 Elsif Escrever Then Passo_rd_wr <= 1; mrq_n <= '0';             
                 End If;               
       When 1 => If    Ler      Then Passo_rd_wr <= 2;
                 Elsif Escrever Then Passo_rd_wr <= 2;               wr_n <= '0';
                 End If;
       When 2 => If    Ler      Then Passo_rd_wr <= 3; mrq_n <= '1'; rd_n <= '1';
                 Elsif Escrever Then Passo_rd_wr <= 3; mrq_n <= '1'; wr_n <= '1';
                 End If;
       When 3 =>                     Passo_rd_wr <= 0;
      End Case;    
   End If;
 End Process;
 
 -- Comando da saida do barramento de enderecos
 Ed <= end_mem;
 
 -- Comando da saida do barramento de dados
 Dt <=  dado_escr When (Escrever And mrq_n ='0') Else (Others => 'Z');
 
---->> Comando 'Block': veja capitulo 3 <<----
-- Unidade Logica Aritmetica

 Unidade_Logica: Block
   Constant zero : Std_Logic_Vector(alu_s'Range) := (Others => '0');
 Begin
   alu_s  <= Acc + alu_b When (Estado = ADdA) Else         -- alu executa operacao de soma
             Acc - alu_b;                                 -- alu executa operacao de subtracao
   alu_z  <= '1' When (alu_s = zero) Else '0';            -- resultado da op. na alu igual a zero
   alu_n  <= '1' When (alu_s(alu_s'High) = '1') Else '0'; -- resultado da op. na alu negativo
 End Block;
 
 -- Incremento do endereco do contador de programa: Pc
 Contador_Programa: Block
 Begin
  pc_inc <= Pc +1;
 End Block;
 
  -- Incremento / Decremento do ponteiro da pilha
 pilha: Block
 Begin
   st_novo <= St -1 When (Estado = Call) Else      -- ponteiro decrementado: chamada de subrotina
              St +1;                              -- ponteiro incrementado: retorno de subrotina
 End Block;

 
 End teste;
 
 
----------------------------------------------------------------------------------------------------------
-- Celula de memoria com programa para teste
---->> Sintese e descricao de memorias: veja capitulo 12 <<----
----------------------------------------------------------------------------------------------------------
Library IEEE;
Use IEEE.Std_Logic_1164.All;
Use IEEE.Std_Logic_arith.All;
Use IEEE.Std_Logic_unsigned.All;  -- Biblioteca Synopsys necessaria para a funcao Conv_Integer
Use Work.cpu_aux.All;             -- Pacote com definicao de tipos e funcoes

Entity ram_8x8 Is
  Port (ce_n, oe_n, wr_n: In    Std_Logic;
        Ed     : In    Std_Logic_Vector(7 Downto 0);
        Dt     : InOut Std_Logic_Vector(7 Downto 0));
End ram_8x8;

Architecture teste Of ram_8x8 Is
  Type arranjo_memoria Is Array (Natural Range <>) Of Std_Logic_Vector(7 downto 0);
  Signal dados : arranjo_memoria(0 To 255) := 
  --  endereco  valor inicial da memoria
     (16#00# => x"0A",  -- Load Immediate Page  (LDmP) Pg <= A                (Pg recebe o valor A)  
    
      16#01# => x"f6",  -- Load Immediate Stack (LDmS) Sp <= FF               (Sp recebe valor)
      16#02# => x"FF",  -- dado de LDmS
     
      16#03# => x"10",  -- Load Direct Acc      (LDdA) Acc <=[Pg & 0]         (Acc =77) (77 e' o valor contido no endereco A0)
      16#04# => x"af",  -- Add Direct Acc       (ADdA) Acc <= Acc+[Pg & f]    (Acc =77 +02) (02 e' o valor contido no endereco AF)
      16#05# => x"31",  -- Store Direct Acc     (STdA) [Pg & 1] <= Acc        (Endereco A1 recebe o valor 79)     
     
      16#06# => x"2E",  -- Load Indirect Acc    (LDiA) Acc <=[[Pg & E]]       (Acc =25) (Acc recebe o valor contido no endereco apontado pelo endereco AE)
      16#07# => x"BF",  -- Subtract Direct Acc  (SBdA) Acc <= Acc-[Pg & f]    (Acc =25 -02)
      16#08# => x"4C",  -- Store Indirect Acc   (STiA) [[Pg & C]] <= Acc      (Endereco A3, apontado pelo endereco AC, recebe o valor 23)

      16#09# => x"f0",  -- Jump                 (Jump) Pc <= [Pc+1]           (Salto para no endereco apontado no proximo endereco de memoria, no caso "3A")
      16#0A# => x"3A",  -- endereco de Jump
     
      16#3A# => x"f7",  -- Load Immediate Acc   (LDmA) Acc <= fb              (Acc recebe valor -5)
      16#3B# => x"fb",  -- dado de LDmA                      
      16#3C# => x"a7",  -- Add Direct Acc       (ADdA) Acc <= Acc+[Pg & 7]    (Acc recebe o valor -5+4=-1. Valor 4 armazenado em A7)
      16#3D# => x"f3",  -- Jump Negative        (JPNG) Pc <=[Pc+1] (se N=1)   (Salto para o endereco 25, resultado neg. na op. da Alu)
      16#3E# => x"40",  -- endereco de JPNG

      16#40# => x"f8",  -- Call Subrotine       (Call) Pc <= [Pc+1]
      16#41# => x"70",  -- dado de Call
      16#42# => x"ff",  -- Halt     
     
      16#70# => x"f7",  -- Load Immediate Acc   (LDmA) Acc <=03               (Acc recebe o valor 3)
      16#71# => x"03",  -- dado de LDmA
      16#72# => x"BB",  -- Subtract Direct Acc  (SBdA) Acc <= Acc-[Pg & B]    (Acc recebe os valores 3-1, 2-1,1-1. Valor 1 armazenado em 3f
      16#73# => x"f2",  -- Jump Not Zero        (JPNZ) Pc <= [Pc+1] (se Z=0)  (Termina a iteracao se resultado da op. na alu igual a zero)
      16#74# => x"72",  -- endereco de JPNZ 
      16#75# => x"f9",  -- Return               (RETN)
     
 
      16#A0# => x"77",  -- dado para instrucao LDdA no endereco 03 (valor +77)
      16#A1# => x"FF",  -- local onde e' armazenado o resultado da operacao na linha 05
      16#A2# => x"25",  -- dado apontado pelo endereco AE na instrucao da linha 06 (valor +25)
      16#A3# => x"FF",  -- local onde e' armazenado o resultado da operacao na linha 08
     
      16#A7# => x"04",  -- dado para instrucao ADdA no endereco 3C (valor +4)
     
      16#AB# => x"01",  -- dado para instrucao SBdA no endereco 72 (valor +1)
      16#AC# => x"A3",  -- ponteiro instrucao  STiA no endereco 08
      16#AD# => x"03",  -- dado para instrucao SBdA no endereco 07 (valor +3)
      16#AE# => x"A2",  -- ponteiro instrucao  LDiA no endereco 06
      16#AF# => x"02",  -- dado para instrucao ADdA no endereco 04 (valor +2)
     
     Others => x"ff");  -- halt
 
  Begin
    Process(ce_n, oe_n, wr_n, dados, Dt, Ed)
    Begin
      -- operacao de escrita da memoria
      If rising_edge(wr_n) Then 
        If ce_n = '0' Then        
          dados(Conv_Integer(Ed)) <= Dt;
        End If;     
      End If;
      -- tratamento da saida
      If ce_n = '0' And oe_n = '0' And wr_n = '1' Then
        Dt <= dados(Conv_Integer(Ed)) After 10 ns; -- leitura de dados
      Else
        Dt <= (Others => 'Z') After 10 ns;           -- saida em alta impedancia
      End If;
    End Process;    
  End teste;
 




--------------------------------------------------------------------------------------------------------- 
-- Teste do conjunto: interligacao de cpu_8bits com ram_8x8
-- Geracao de estimulos contida no codigo
-- Simule conjunto_5
---------------------------------------------------------------------------------------------------------
Library IEEE;
Use IEEE.Std_Logic_1164.All;
Use IEEE.Std_Logic_arith.All;
Use IEEE.Std_Logic_unsigned.all;


Entity conjunto_5 Is
End conjunto_5;

Architecture teste Of conjunto_5 IS
  ---->> Declaracao de componentes: veja capitulo 7 <<----
  Component cpu_8bits
  Port (ck, rst_b     : In     Std_Logic;
        mrq_n, wr_n, rd_n : Buffer Std_Logic;
        Ed       : Out    Std_Logic_Vector(7 downto 0);
        Dt       : InOut  Std_Logic_Vector(7 Downto 0));       
  End Component;
 
  Component ram_8x8
  Port (ce_n, oe_n, wr_n: In Std_Logic;
        Ed     : In Std_Logic_Vector(7 Downto 0);
        Dt     : InOut Std_Logic_Vector(7 Downto 0));
  End Component;

  Signal ck, rst_b      :  Std_Logic := '0';
  Signal mrq_n, wr_n, rd_n  :  Std_Logic;
  Signal ce_n, oe_n       :  Std_Logic;
  Signal Ed        :  Std_Logic_Vector(7 downto 0);
  Signal Dt        :  Std_Logic_Vector(7 Downto 0);

Begin
  ce_n <= mrq_n;
  oe_n <= rd_n;

 
---->> Solicitacao de componentes: veja capitulo 7 <<----
  x0: cpu_8bits Port Map(ck, rst_b, mrq_n, wr_n, rd_n, Ed, Dt);
  x1: ram_8x8 Port Map(ce_n, oe_n, wr_n, Ed, Dt);
 
  ck <= Not ck After 50 ns;
  rst_b <= '1' After 150 ns;
 
End teste;

C_icon_2.gif   23. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4             Retorna





Resultados da simulação: Cartas de tempo

Instruções LDmP (0ns - 550ns), LDmS (550ns -1350ns) e LDmA (1350ns - 2150ns)

Instruções LDdA (1350ns - 2150ns), ADdA (2150ns -2950ns) e STdA (2950ns - 4950ns)

Instruções SBdA (4950ns - 5750ns), STiA (5750ns -6950ns) e Jump (6950ns - 7750ns)

Instruções ADdA (8550ns - 9350ns), JPNG (9350ns -10150ns), Call (10150ns - 11350ns) e LDmA (11350 - 12150)

Chamada da sub-rotina (11350ns), Execução da subrotina (11350ns -16750ns), Retn (16750ns - 17550ns) e Halt (17550 - 18350)


C_icon_2.gif   24. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-1 - revisão 1.4            Retorna