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


CPU-2

 

Microprocessador didático descrito em VHDL

e

Assembler descrito em VHDL

 

Tópicos

·                 Objetivos

·                 Arquitetura e Modos de Endereçamento

·                 Conjunto de instruções

·                 Diagrama de blocos

·                 Teste da descrição


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





Objetivos

·   Expansão do código do microprocessador CPU-1

·   Teste da arquitetura de um microprocessador com auxílio um assembler

·   Assembler integrado a um ambiente de simulação VHDL

·   Código VHDL realiza as operações de um assembler limitado:

- leitura programa fonte do microprocessador escrito em linguagem assembly

- detecção de erros (alguns erros podem ser não detectados)

- geração dos códigos hexadecimais necessários para operação da cpu

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



Arquitetura e Modos de Endereçamento  (idêntico ao exemplo CPU-1)

fig002.gif

C_icon_2.gif   3. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais    -  Exemplo de um microprocessador  CPU-2 - revisão 1.0              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   4. Roberto d’Amore - VHDL: Descrição e Síntese de Circuitos Digitais   -  Exemplo de um microprocessador  CPU-2 - revisão 1.0             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

JP_C,mm

* Jump Carry

C=1       Pc <= [Pc+1]

C=0       Pc <= [Pc+2]

F4

mm

JP_O,mm

* Jump Overflow

O=1       Pc <= [Pc+1]

O=0       Pc <= [Pc+2]

F5

mm

 
* Novas instruções

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



Conjunto de instruções: Aritméticas, Deslocamento, Chamada sub-rotina

Mnemônico e Operação

Descrição da operação

Pc

Pc+1

ADdA,n

Add Direct Acc

Acc <= Acc + [Pg & n]

An

 

SBdA,n

Subtract Direct Acc

Acc <= Acc - [Pg & n]

Bn

 

SLdA,n

* Shift Left Direct Acc

Acc <= shift_left[Pg & n]

Cn

 

SRdA,n

* Shift Right Direct Acc

Acc <= shift_right[Pg & n]

Dn

 

 

 

 

 

 

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

 

 

* Novas instruções

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



Diagrama de blocos   (CPU-1: alterações na ALU)

fig004.gif

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



Teste da descrição

·   O processo principal: - executa a leitura de um arquivo em disco

- interpreta os mnemônicos e grava os dados na memória dual

- após a programação, libera a operação da CPU ('rst_b'=1)

·   Facilidades: - alteração do programa da CPU não exige compilar código,

(basta alterar o arquivo de dados e reiniciar a simulação)

- programa da CPU escrito diretamente no formato de mnemônicos

fig006.gif

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




Teste da descrição  (Exemplo de um arquivo de entrada de dados)

·   Comentário: inicio com  '--'   ou após a coluna 25

·   Primeira coluna: endereço de um dado           Segunda coluna: instrução

·   Instruções com duas posições de memória: ('LDmS,mm', 'Jump,mm')

reserve uma posição de memória para que o dado 'mm' seja armazenado

·   Dados num endereço:

identificados na forma: endereço H#valor  (somente base hexadecimal)


 --------------------------------------------------------------------------------
 -- Subrotina para a troca caso dado(j+1)< dado(j)
 --------------------------------------------------------------------------------   
 30  LDmP,A
 31  LDiA,7     -- Acc <= [[A7]]    (endereco A7 aponta para dado(j))
 32  STdA,2     -- [A2] <= Acc
 33  LDiA,8     -- Acc <= [[A8]]    (endereco A8 aponta para dado(j+1))
 34  SBdA,2     -- Acc <= Acc-[A2]  (Acc <= dado(j+1)- dado(j)
 35  JP_O,40    --                  (Se ocorreu transbordo dado(j+1)< dado(j))
 36
 37  JPNG,40    --                  (Se negativo: dado(j+1)< dado(j))
 38
 39  Retn       --           (Nao negativo: dado(j+1) > dado(j) posicao mantida)

 -- Dados para a subrotina de ordenacao     
 A0   H#90       -- endereco inicial
 A1   H#A0       -- endereco final +1


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




Teste da descrição  (como simular)

·   Compile o conjunto:

        - Declaração do pacote   Pack_cpu_aux     Corpo do pacote Pack_cpu_aux  
    - Declaração do pacote   Pack_cpu_txt      Corpo do pacote Pack_cpu_txt    
    - Declaração do pacote   Pack_cpu_ram    Corpo do pacote Pack_cpu_ram    
    - Declaração da entidade cpu_8bits_2       Arquitetura teste de cpu_8bits_2
    - Declaração da entidade ram_dual1         Arquitetura teste de ram_dual1 
    - Declaração da entidade conj_arq2          Arquitetura teste de conj_arq2

·   Pack_cpu_aux: pacote com funções e definições de tipo da cpu

·   Pack_cpu_txt: Pacote com funções para interpretação dos dados contidos em arquivo

·   Pack_cpu_ram: Pacote de auxilio ao uso da Ram Dual

 

·   Para verificar a operação:      
   - crie um arquivo contendo o programa com mnemônicos (fonte_exe1.dat)

   - simule a entidade conj_arq2

·   Para alterar o programa:

     - modifique o programa com mnemônicos (fonte_exe1.dat)
   - reinicie a simulação da entidade conj_arq2

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




Código conjunto


----------------------------------------------------------------------------------------------------------
-- 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
--
--
-- Exemplo extra
--
-- Teste do conjunto CPU + Memoria
--
-- Dados da memoria carregados de um arquivo.
-- Nome do arquivo definido pelo generico: 'nome_do_arquivo' na entidade 'conj_arq2'
--
--
-- Compile o conjunto: Declaracao do pacote   Pack_cpu_aux,  Corpo do pacote Pack_cpu_aux,    -- Nao presente neste quadro. Pacote com funcoes e definicoes de tipo da cpu
--                     Declaracao do pacote   Pack_cpu_txt   Corpo do pacote Pack_cpu_txt     -- Nao presente neste quadro. Pacote com funcoes para interpretacao dos dados contidos em arquivo
--                     Declaracao do pacote   Pack_cpu_ram   Corpo do pacote Pack_cpu_ram     -- Nao presente neste quadro.Pacote de auxilio ao uso da Ram Dual
--                     Declaracao da entidade cpu_8bits_2    Arquitetura teste de cpu_8bits_2
--                     Declaracao da entidade ram_dual1      Arquitetura teste de ram_dual1   -- Nao presente neste quadro.
--                     Declaracao da entidade conj_arq2 e    Arquitetura teste de conj_arq2
--
-- Para verificar a operacao simule a entidade conj_arq2
----------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------
-- Para alterar o conjunto de instrucoes
-- No pacote Pack_cpu_aux
--   1- No 'Tipo_estado', defina o mnemonico da nova instrucao
--   2- Na funcao 'mnemonico', defina o tamanho da instrucao: 4 ou 8 bits
--   3- Na funcao 'mnemonico', defina o codigo numerico correspondente da instrucao
-- No pacote pack_cpu_txt
--   1- Na funcao 'Mnem_Para_Std_Logic_Vector', defina a correspondencia entre o mnemonico e o codigo numerico
----------------------------------------------------------------------------------------------------------


----------------------------------------------------------------------------------------------------------
-- 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.Pack_cpu_aux.All;            -- Pacote com definicao de tipos e funcoes

---->> Declaracao de Entidade: veja capitulo 2 <<----
Entity cpu_8bits_2 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_2;

---->> Corpo da Arquitetura: veja capitulo 2 <<----
Architecture teste Of cpu_8bits_2 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_b                   : Std_Logic_Vector(nd-1 Downto 0);  -- Registrador operando 'b' da ALU
  Signal alu_s                   : Std_Logic_Vector(nd-1 Downto 0);  -- Saida da ALU
  Signal Alu_flags               : Std_Logic_Vector(3 Downto 0);     -- Registrador que armazena 'alu_o','alu_c', 'alu_n' e 'alu_z'
  Signal alu_o,alu_c,alu_n,alu_z : Std_Logic;                        -- Valor decodificado da saida da ALU: Carry, Negativo, Zero


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)
  ---->> Variaveis: veja capitulo 5 <<----
  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
    ---->> Comando 'Case': veja capitulo 4 <<----
    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)]
        ---->> Concatenacao de sinais '&': veja capitulo 2 <<----
        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 Overflow, Salto se Carry, Salto se Zero, Salto se Nao Zero, Salto se Negativo
      ---->> Comando 'case' com delimitador '|': capitulo 4 <<----
      When Jump | JP_O | JP_C |JP_Z | JPNZ | JPNG  =>
        -- Teste para determinar a necessidade de desvio para um novo endereco de memoria
        ---->> Diferencas entre atribuicao de valores para variaveis e atribuicao de valores para sinais: veja capitulo 5
        If    Estado = Jump                       Then salta := True; -- Instrucao Jump. Sempre Pc <= [Pc+1].
        ElsIf Estado = JP_O And alu_flags(3) ='1' Then salta := True; -- Instrucao JP_O. Se O =1, Pc <= [Pc+1]. Se C=0 Pc <= Pc+2;
        ElsIf Estado = JP_C And alu_flags(2) ='1' Then salta := True; -- Instrucao JP_C. Se C =1, Pc <= [Pc+1]. Se C=0 Pc <= Pc+2;
        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 
      -- Alteram bits de sinalizacao (flags): (alu_flags <= overflow,carry,zero, negativo)    
      -- Add Direct      'ADdA': Acc <= Acc + [Pg & Ir(3..0)]    
      -- Subtract Direct 'SBdA': Acc <= Acc - [Pg & Ir(3..0)]
      -- Shift Left      'SLdA': Acc <= Alu_b(6..0) & '0'    carry <= Acc(7)
      -- Shift Right     'SRdA': Acc <= '0' & Alu_b(7..1)    carry <= Acc(0)
      When ADdA | SBdA | SLdA | SRdA  =>        -- 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_o & alu_c & 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');
 
 -- Unidade Logica Aritmetica
 --
 ---->> Ocorrencia de Carry e Overflow: veja capitulo 11 <<----
 --
 -- Ocorrencia de Vai-Um ou Carry
 --   Sinal interno 'alu_s_c' com 1 bit a mais e' definido no bloco
 --   ALU gerada deste modo possui nd+1 bits. Bit mais significativo de 'alu_s_c' permite detectar a ocorrencia do vai-um
 --
 -- Ocorrencia de Transbordo ou Overflow
 --            Operacao de soma                                                       Operacao de subtracao
 --  possivel problema no caso de operandos com sinais iguais    possivel problema no caso de operandos com sinais diferentes
 --   Acc       (0______) pos.       (1______) neg.               Acc      (0______) pos.       (1______) neg.
 --   Alu_b    +(0______) pos.      +(1______) neg.               Alu_b   -(1______) neg.      -(0______) pos.
 --            ------------          ------------                         ------------          ------------
 --   alu_s     (1______) neg.       (0______) pos.               alu_s    (1______) neg.       (0______) pos.
 --          resultado incorreto  resultado incorreto                 resultado incorreto   resultado incorreto 
 --
 ---->> Exemplos de deslocadores 'shift-register': veja capitulo 6 <<----
 --
 --  Deslocamentos:     para esquerda                                para direita  
 --            Alu_b:  |7|6|5|4|3|2|1|0|__'0'         Alu_b: '0'___  |7|6|5|4|3|2|1|0|    
 --                    / / / / / / / / /                            \ \ \ \ \ \ \ \ \____
 --         alu_s_c  |8|7|6|5|4|3|2|1|0|                   alu_s_ |8|7|6|5|4|3|2|1|0|    |
 --                                                                \_____________________|
 --
 ---->> Comando 'Block': veja capitulo 3 <<----
 Unidade_Logica: Block
   ---->> Atributo 'Range': veja capitulo 5 <<----
   Constant zero   : Std_Logic_Vector(alu_s'Range) := (Others => '0');          -- constante com valor zero
   Signal decide_o : Std_Logic_Vector(3 Downto 0);                              -- sinal para a decisao se ocorreu transbordo
   Signal alu_s_c  : Std_Logic_Vector(alu_s'High+1 Downto 0);                   -- sinal com um bit extra para deteccao de vai-um
 Begin
   alu_s_c  <= ('0'& Acc) + ('0'& Alu_b) When (Estado = ADdA) Else              -- alu executa operacao de soma
               ('0'& Acc) - ('0'& Alu_b) When (Estado = SBdA) Else              -- alu executa operacao de subtracao
               Alu_b & '0'               When (Estado = SLdA) Else              -- alu executa deslocamento para esquerda
               Alu_b(0) & '0'& Alu_b(Alu_b'High Downto 1);                      -- alu executa deslocamento para direita
  
   ---->> Atributo 'High': veja capitulo 5 <<----
   alu_s  <= alu_s_c(alu_s'High Downto 0);                                      -- bit do carry descartado
  
   alu_c  <= alu_s_c(alu_s_c'High);                                             -- resultado do carry
   ---->> Atribuicao condicional de sinal 'When': veja capitulo 3 <<----
   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
  
   decide_o <= ('0' & alu_s(alu_s'High) & Acc(Acc'High) & Alu_b(Alu_b'High)) When Estado = ADdA Else  -- sinal para a decisao caso operacao de soma
               ('1' & alu_s(alu_s'High) & Acc(Acc'High) & Alu_b(Alu_b'High));                         -- sinal para a decisao caso operacao de subtracao
   ---->> Atribuicao condicional de sinal 'With': veja capitulo 3 <<----
   ---->> Atribuicao condicional de sinal 'With' com delimitador '|': capitulo 3 <<----
   ---->> Atribuicao condicional de sinal 'With' com a palavra reservada 'Others': capitulo 3 <<----            
   With decide_o Select
     alu_o <= '1' When "0100" | "0011" | "1101" | "1010",
              '0' When Others;     --               \\\\_____________sinal Alu_b
                                   --                \\\_____________sinal Acc
                                   --                 \\_____________sinal alu_s
 End Block;                        --                  \_____________soma =0 / subtracao =1
 
 -- 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;
 
 
 
--------------------------------------------------------------------------------------------------------- 
-- Teste do conjunto: interligacao de cpu_8bits_2 com ram_dual1
-- Geracao de estimulos contida no codigo
-- Simule conj_arq2
-----------------------------------------------------------------------------------------------------------------------------------
---->> Emprego do pacote 'textio': veja capitulo 13 <<----
---->> Definicao e uso de pacotes: veja capitulo 9 <<----
Use STD.TEXTIO.All;
Use Work.Pack_cpu_txt.All;         -- Pacote com funcoes para interpretacao dos dados contidos em arquivo
Use Work.Pack_cpu_ram.All;         -- Pacote de auxilio ao uso da Ram Dual
Library IEEE;
Use IEEE.Std_Logic_1164.All;
Use IEEE.Std_Logic_unsigned.All;   -- Biblioteca Synopsys necessaria para operacoes aritimericas entre Std_Logic_Vector e Integer

Entity conj_arq2 IS
 Generic (nome_do_arquivo : String := "fonte_ex1.dat";        -- Nome do arquivo contendo os dados
          ne              : Integer  := 8;                  -- Numero de bits do barramento de endereco
          nd              : Integer  := 8;                  -- Numero de bits do barramento de dados
          td              : Time := 10 ns);                 -- Tempo para apresentacao dos dados
End conj_arq2;

Architecture teste Of conj_arq2 Is
  ---->> Declaracao de componentes e mapa de portas: veja capitulo 7 <<----
  Component cpu_8bits_2
  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;    
   
  ---->> Operacoes com arquivos: veja capitulo 13 <<----
  File arq_rd : TEXT;
  -- Sinais do microprocessador
  Signal ck, rst_b      :  Std_Logic := '0';
  Signal mrq_n, wr_n, rd_n  :  Std_Logic;
  -- Sinais de controle da Ram Dual
  Signal ce1_n, wr1_n, oe1_n : Std_Logic := '1';                 -- sinais controle 1
  Signal ce2_n, wr2_n, oe2_n : Std_Logic := '1';                 -- sinais controle 2
  Signal ed1, ed2            : Std_Logic_Vector(ne-1 Downto 0);  -- enderecos 1 e 2
  Signal dt1, dt2            : Std_Logic_Vector(nd-1 Downto 0);  -- dados 1 e 2
 
  Signal Fim_carga_de_dados  : Boolean := False;                 -- Indica o fim da programacao da memoria Ram com os dados
 
Begin
  Principal: Process  
    Variable linha        : Line;                   -- Objeto tipo LINE para armazenar texto
    Variable leitura_ok   : Boolean := TRUE;        -- verificacao do procedimento READ
    Variable caractere    : Character;              -- Armazena o caractere lido na linha
    Variable i            : Integer;                -- Conta o numero de caracteres
    Variable linha_lida   : String(1 To 25);        -- Armazena todos os caracters lidos numa linha

    Variable ed           : Std_Logic_Vector(ne-1 Downto 0);
    Variable dt           : Std_Logic_Vector(nd-1 Downto 0);  
    Variable dados        : Integer;                        -- Codigo que representa o numero de dados encontrados na leitura de uma linha
    Variable ender        : Std_Logic_Vector(7 Downto 0);
    Variable ext1, ext2   : Std_Logic_Vector(3 Downto 0);
    Variable mnem         : String (1 To 4);
    Variable prox_ed      : Std_Logic_Vector(ne-1 Downto 0);
    Variable prox_dt      : Std_Logic_Vector(nd-1 Downto 0);
   
 Begin
 ---->> Abertura de arquivos: veja capitulo 13 <<----
 File_Open(arq_rd, nome_do_arquivo,Read_Mode);
 ---->> Comando 'Loop' e esquema de iteracao 'While': veja capitulo 7 <<----
 While Not EndFile(arq_rd) Loop                              -- Operacao de leitura do arquivo
   ReadLine (arq_rd, linha);                                 -- Leitura de uma linha do aquivo
   leitura_ok := True;                                       -- Habilita leitura de caracteres contidos numa linha (proximo laco While)
   i := 1;                                                   -- Inicia contador de caracteres contidos numa linha (proximo laco While)
   linha_lida := (Others => ' ');                            -- Limpa a variavel 'linha_lida'para a leitura de uma proxima linha
   While (i < linha_lida'Length) Loop                        -- Teste: numero maximo de caracteres previsto excedido
     ---->> Funcao 'Read' em arquivos texto: veja capitulo 13 <<----
     Read(linha,caractere,leitura_ok);                       -- Leitura de um caractere na linha
     ---->> Comandos 'Exit' e 'Next': veja capitulo 7 <<----
     Exit When Not leitura_ok;                               -- Termina a leitura da linha: fim da linha contendo caracteres    
     Next When (caractere < ' ') Or (caractere > '~');       -- Caractere não é texto: descartado
     linha_lida(i) := caractere;                             -- Preenche com mais um caractere
     i := i +1;                                              -- Incrementa o contador de caracteres
   End Loop;
  
   ---->> Subprogramas: procedimento (procedure): veja capitulo 8 <<----
   Extrai_dados(linha_lida, dados, ender, mnem, ext1, ext2);   -- Extracao dos dados recuperados numa linha lida no arquivo
   Case dados IS
     When 2 => Null;                                                       -- Linha contendo somente endereco. Exemplo: [02]
     When 6 =>                                                             -- Linha contendo:[(endereco)(instrucao tipo Retn)] ou [(endereco) (dado tipo H#23)]
       If mnem(2) = '#' Then
               ---->> Subprogramas: funcao (function): veja capitulo 8 <<----
               ed := ender; dt := Para_Std_Logic_Vector(mnem(3 To 4));     -- Linha cont. endereco e dado. Exemplo: [A0 H#77]. Caractere '#' identifica.
        Else
               ed := ender; dt := Mnem_Para_Std_Logic_Vector(mnem);        -- Linha cont. endereco e instrucao. Exemplos: [75 Retn], [42 Halt]
        End If;
     When 7 => ed := ender; dt := Mnem_Para_Std_Logic_Vector(mnem) & ext1; -- Linha cont. endereco, instrucao e dado associado a instrucao. Exemplo: [06 LDiA,E]
     When 8 => ed := ender; dt := Mnem_Para_Std_Logic_Vector(mnem);        -- Linha cont. endereco, instrucao e dado do prox. endereco. Exemplo: [40 Call,70]
               prox_ed := ender +1;  prox_dt := ext1 & ext2;               -- Dado para o endereco seguinte preparado. Exemplo: [41 70]       
     When Others => Null;
   End Case;
  
   If (dados = 6) Or (dados = 7) Or (dados = 8) Then          -- Linha contendo dados para serem escritos na memoria     
     If dados =8 Then                                         -- Linha contendo endereco, instrucao e do proximo endereco. Exemplo: [40 Call,70]
       Escreve_porta_2 (ed, dt, ce2_n, wr2_n, ed2, dt2);      -- Dado 'dt' armazenado no endereco 'ed'
       ---->> Comando 'Wait': veja capitulo 4 <<----
       Wait For 1 ns;                                         -- Endereco e dado atualizados.       Exemplo para a instrucao Call,70 no endereco 40: [ed=40 dt=F8]
       ed := prox_ed; dt := prox_dt;                          -- Preparara para o proximo endereco. Exemplo para a instrucao Call,70 no endereco 40: [ed=41 dt=70]
     End If;
  
     Escreve_porta_2 (ed, dt, ce2_n, wr2_n, ed2, dt2);        -- Dado 'dt' armazenado no endereco 'ed'
     Wait For 1 ns;  
   End If;                                     
 End Loop;   
 ---->> Funcao 'File_Close' em arquivos: veja capitulo 13 <<----                                   
 File_Close(arq_rd);                                          -- Fecha o arquivo
 Fim_carga_de_dados <= True;                                  -- Indica que a memoria Ram contem todos os dados
 ---->> Comando 'Report': veja capitulo 14 <<----
 Report "Operacao de carga dos dados na memoria terminada"
   Severity Note;                     
 Wait;
 End Process;
 
 ---->> Clausula 'After': veja capitulo 5 <<----
 ---->> Geracao de sinais periodicos: veja capiutlo 15 <<----
 rst_b <= '1' After 150 ns When Fim_carga_de_dados Else
          '0';
 ck <= Not ck After 50 ns;         
 
 ce1_n <= mrq_n;
 oe1_n <= rd_n;
 wr1_n <= wr_n;
 
 ---->> Solicitacao de componentes, mapa de portas e mapa de genericos: veja capitulo 7 <<----
 X0: cpu_8bits_2 Port Map(ck, rst_b, mrq_n, wr_n, rd_n, ed1, dt1);
 X2: ram_dual1   Generic Map (ne, nd, td)
                Port Map(ce1_n, wr1_n, oe1_n, ed1, dt1, ce2_n, wr2_n, oe2_n, ed2, dt2);

 End teste;


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




Código do pacote Pack_cpu_aux

----------------------------------------------------------------------------------------------------------
-- 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
--
-- Exemplo extra
-- Pacote auxiliar
-- Definicao de tipo contendo mnemonicos e funcao de valor numerico para mnemonico
----------------------------------------------------------------------------------------------------------
---->> 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 conversoes com Std_Logic

---->> Declaracao de pacote: veja capitulo 9 <<----
Package Pack_cpu_aux Is       -- declaracao do pacote
  ---->> Declaracao de tipo: veja capitulo 12 <<----
  -- Tipo contendo os possiveis estados da maquina
  Type Tipo_estado Is (busca, LDmP, LDmS, LDmA, LDdA, LDiA,
                              STdA, STiA,
                              Jump, JP_O, JP_C, JP_Z, JPNZ, JPNG,
                              ADdA, SBdA, SLdA, SRdA,
                              Call, RETN, Halt);
   
  ----> Declaracao de funcao: veja capitulo 8 <<----
  ----> Lista de interface de um subprograma (parametros formal e real): veja capitulo 8 <<----
  Function para_estado(dado : Std_Logic_Vector(7 Downto 0)) Return Tipo_Estado;
 
End Pack_cpu_aux;


---->> Declaracao do corpo pacote: veja capitulo 9 <<----
Package Body Pack_cpu_aux Is  -- corpo do pacote
   
  ---->> Declaracao do corpo da funcao: veja capitulo 8 <<----
  -- 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 x"c" => mnemonico := SLdA;  When x"d" => mnemonico := SRdA;
        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"f4" => mnemonico := JP_C; When x"f5" => mnemonico := JP_O;
        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 Pack_cpu_aux;
      

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



Código do pacote Pack_cpu_txt

------------------------------------------------------------------------------------------------------------------------------------
-- 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
--
-- Pacote com operacoes para auxilio a leitura de arquivos - Necessita opcao VHDL-1993
--
------------------------------------------------------------------------------------------------------------------------------------
---->> 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 conversoes com Std_Logic

---->> Declaracao de pacote: veja capitulo 9 <<----
Package pack_cpu_txt Is       -- declaracao do pacote
 
  ----> Lista de interface de um subprograma (parametros formal e real): veja capitulo 8 <<----
  ----> Declaracao de funcao: veja capitulo 8 <<----
  Function Para_minusculo(c: character) Return Character;
  Function Para_minusculo(s: string)    Return String;
 
  Function Para_Std_Logic_Vector(c: Character) Return Std_Logic_Vector;
  Function Para_Std_Logic_Vector(s: String)    Return Std_Logic_Vector;
 
  Function Mnem_Para_Std_Logic_Vector(dado : String(1 To 4)) Return Std_Logic_Vector;
 
  ----> Declaracao de procedimento: veja capitulo 8 <<----
  Procedure Extrai_dados(s: In String;   dados : Out Integer;
                         endereco: Out Std_Logic_Vector(7 Downto 0); mnemonico: Out String(1 To 4);
                         extra_1:  Out Std_Logic_Vector(3 Downto 0); extra_2:  Out Std_Logic_Vector(3 Downto 0));

  
End pack_cpu_txt;


---->> Declaracao do corpo pacote: veja capitulo 9 <<----
Package Body pack_cpu_txt Is  -- corpo do pacote

  -----------------------------------------------------------------------------------------------------------------------------------
  -- Converte caractere maiuculo para minusculo
  -- Caracteres como '[', '1' e '#' nao sao alterados. Para caracteres fora da faixa prevista retorna o valor ' '.
  -----------------------------------------------------------------------------------------------------------------------------------
  Function Para_minusculo(c: Character) Return Character Is
    SubType caractere Is Character Range ' ' To '~';      -- Subtipo contendo os possiveis caracteres
    Type minusculo Is Array(caractere) Of Character;      -- O indice do vetor do tipo minusculo e' definido por elementos do Subtipo 'caractere'
    Constant equivalencia : minusculo :=                  -- Constante: vetor de elementos de 'A' ate' '~'
     (' '=>' ', '!'=>'!', '"'=>'"', '#'=>'#', '$'=>'$', '%'=>'%', '&'=>'&', '''=>''',
      '('=>'(', ')'=>')', '*'=>'*', '+'=>'+', ','=>',', '-'=>'-', '.'=>'.', '/'=>'/',
      '0'=>'0', '1'=>'1', '2'=>'2', '3'=>'3', '4'=>'4', '5'=>'5', '6'=>'6', '7'=>'7',
      '8'=>'8', '9'=>'9', ':'=>':', ';'=>';', '<'=>'<', '='=>'=', '>'=>'>', '?'=>'?', '@'=>'@',
      'A'=>'a', 'B'=>'b', 'C'=>'c', 'D'=>'d', 'E'=>'e', 'F'=>'f', 'G'=>'g', 'H'=>'h', 'I'=>'i',
      'J'=>'j', 'K'=>'k', 'L'=>'l', 'M'=>'m', 'N'=>'n', 'O'=>'o', 'P'=>'p', 'Q'=>'q', 'R'=>'r',
      'S'=>'s', 'T'=>'t', 'U'=>'u', 'V'=>'v', 'W'=>'w', 'X'=>'x', 'Y'=>'y', 'Z'=>'z',
      '['=>'[', '\'=>'\', ']'=>']', '^'=>'^', '_'=>'_', '`'=>'`',
      'a'=>'a', 'b'=>'b', 'c'=>'c', 'd'=>'d', 'e'=>'e', 'f'=>'f', 'g'=>'g', 'h'=>'h', 'i'=>'i',
      'j'=>'j', 'k'=>'k', 'l'=>'l', 'm'=>'m', 'n'=>'n', 'o'=>'o', 'p'=>'p', 'q'=>'q', 'r'=>'r',
      's'=>'s', 't'=>'t', 'u'=>'u', 'v'=>'v', 'w'=>'w', 'x'=>'x', 'y'=>'y', 'z'=>'z',
      '{'=>'{', '|'=>'|', '}'=>'}', '~'=>'~');
  Begin
    If (c >= ' ') And (c <= '~') Then Return equivalencia(c); -- Faixa de caracteres validos
    Else                              Return ' ';             -- Caso contrario retorna o valor ' '
    End If;     
  End Para_minusculo;
   
  -----------------------------------------------------------------------------------------------------------------------------------
  -- Converte caracteres de um vetor para minusculo
  -- Sobrecarrega e emprega a funcao para_minusculo(c : Character)
  -----------------------------------------------------------------------------------------------------------------------------------
   Function Para_minusculo(s: String) Return String Is
     Variable s_min : String(s'Range);
   Begin
     For i In s'Range Loop s_min(i) := Para_minusculo(s(i));
     End Loop;
     Return s_min;
   End Para_minusculo;
 
  -----------------------------------------------------------------------------------------------------------------------------------
  -- Converte valor representado por um caractere em um tipo Std_Logic_Vector
  -- Emprega a funcao Para_minuculo
  -----------------------------------------------------------------------------------------------------------------------------------
  Function Para_Std_Logic_Vector(c: Character) Return Std_Logic_Vector Is
    Variable sl: Std_Logic_Vector(3 Downto 0);
    Variable c_minusculo : Character;
  Begin
    c_minusculo := Para_minusculo(c);
    Case c_minusculo Is
      When '0' => sl := x"0"; When '1' => sl := x"1"; When '2' => sl := x"2"; When '3' => sl := x"3";
      When '4' => sl := x"4"; When '5' => sl := x"5"; When '6' => sl := x"6"; When '7' => sl := x"7";
      When '8' => sl := x"8"; When '9' => sl := x"9"; When 'a' => sl := x"A"; When 'b' => sl := x"B";
      When 'c' => sl := x"C"; When 'd' => sl := x"D"; When 'e' => sl := x"E";  
      When others => sl := x"F";
    End case;
    Return sl;
  End Para_Std_Logic_Vector;
 
  -----------------------------------------------------------------------------------------------------------------------------------
  -- Converte um conjunto de caracteres (que representam um valor Hexadecimal) em Std_Logic_Vector
  -- Sobrecarrega e emprega a funcao Para_Std_Logic_Vector(c: Character)
  -- Entrada: String ascendente (1 To n). Saida: Std_Logic_Vector decrescente
  -- Cada caracter acresce 4 bits no vetor de saida
  -- Exemplo de operacoes no laco para um string com 3 caracteres:
  --    h(11 Downto  8) := Para_Std_Logic_Vector(s(1));
  --    h( 7 Downto  4) := Para_Std_Logic_Vector(s(2));
  --    h( 3 Downto  0) := Para_Std_Logic_Vector(s(3));
  -----------------------------------------------------------------------------------------------------------------------------------
  Function Para_Std_Logic_Vector(s: String) Return Std_Logic_Vector Is
    Constant h_lgt : Integer := s'Length*4;       -- cada caracter resulta em 4 bits no vetor
    Variable h     : Std_Logic_Vector(h_lgt-1 Downto 0);
  Begin
    For i In 0 To s'Length-1 Loop
      h(h_lgt-(4*i+1) Downto h_lgt-(4*(i+1))) := Para_Std_Logic_Vector(s(s'Left+i));
    End Loop;
    Return h;
  End Para_Std_Logic_Vector;
 
   
  -----------------------------------------------------------------------------------------------------------------------------------
  -- Converte o codigo da instrucao em valor numerico no tipo Std_Logic_Vector
  -- Valor convertido pode ser um vetor de 4 ou 8 bits
  -----------------------------------------------------------------------------------------------------------------------------------
  Function Mnem_Para_Std_Logic_Vector(dado : String(1 To 4)) Return Std_Logic_Vector Is
    Variable dado_minusculo : String(dado'Range);
  Begin
    dado_minusculo := para_minusculo(dado);
    Case dado_minusculo Is
      -- Mnemonicos que resultam num codigo de 4 bits
      When "ldmp" => Return x"0";
      When "ldda" => Return x"1";  When "ldia" => Return x"2";
      When "stda" => Return x"3";  When "stia" => Return x"4";
      When "adda" => Return x"a";  When "sbda" => Return x"b";
      When "slda" => Return x"c";  When "srda" => Return x"d";
      -- Mnemonicos que resultam num codigo de 8 bits 
      When "jump" => Return x"f0";
      When "jp_z" => Return x"f1";
      When "jpnz" => Return x"f2";
      When "jpng" => Return x"f3";
      When "jp_c" => Return x"f4";
      When "jp_o" => Return x"f5";
      When "ldms" => Return x"f6";
      When "ldma" => Return x"f7";
      When "call" => Return x"f8";
      When "retn" => Return x"f9";         
      When "halt" => Return x"ff";
      When Others => Report CR & LF & "ERRO NA LEITURA DO ARQUIVO! Mnemonico '" & dado & "' nao encontrado" & LF Severity Failure;
                     Return x"ff";
   End Case;
End Mnem_Para_Std_Logic_Vector; 


  -----------------------------------------------------------------------------------------------------------------------------------
  -- Extrai dados de um conjunto de caracteres
  -- Entrada: String (1 To ...) Saida: dados endereco mnemonico extra_1 extra_2
  -- Emprega as funcoes: Para_Std_Logic_Vector e Para_minuculo
  -- Exemplos de retorno:
  --  03                      dados=(2) endereco=(03) mnemonico=(nao altera) extra_1,2=(nao altera)
  --  04 Retn                 dados=(6) endereco=(04) mnemonico=(retn)       extra_1,2=(nao altera)
  --  05 LDmP,7               dados=(7) endereco=(05) mnemonico=(ldmp)       extra_1=(7) extra_2=(nao altera)
  --  06 JPNZ,78              dados=(8) endereco=(06) mnemonico=(jpnz)       extra_1=(7) extra_2=(8)
  --  27 Hexa A7              dados=(8) endereco=(27) mnemonico=(hexa)       extra_1=(A) extra_2=(7)
  -----------------------------------------------------------------------------------------------------------------------------------
  Procedure Extrai_dados(s: In String;   dados : Out Integer;
                         endereco: Out Std_Logic_Vector(7 Downto 0); mnemonico: Out String(1 To 4);
                         extra_1:  Out Std_Logic_Vector(3 Downto 0); extra_2:  Out Std_Logic_Vector(3 Downto 0)) Is
    Variable dado : Integer Range 1 To 9 :=1;
  Begin
    For i In 1 To s'Length Loop
      Exit When (s(i) = '-') And (s(i+1) = '-');  -- Detectado o indentificador de comentario: o restante e' descartado
      Next When (s(i) = ' ') Or  (s(i) = ',');    -- Espacos em branco e virgulas eliminados do conjunto de dados
      Case dado Is                                           
        When 1 => dado := dado +1; endereco(7 Downto 4) := Para_Std_logic_Vector(s(i)); -- primeiro dado do endereco
        When 2 => dado := dado +1; endereco(3 Downto 0) := Para_Std_logic_Vector(s(i)); -- segundo  dado do endereco
        When 3 => dado := dado +1; mnemonico(1) := Para_minusculo(s(i));                -- primeiro dado do mnemonico
        When 4 => dado := dado +1; mnemonico(2) := Para_minusculo(s(i));                -- segundo  dado do mnemonico     
        When 5 => dado := dado +1; mnemonico(3) := Para_minusculo(s(i));                -- terceiro dado do mnemonico
        When 6 => dado := dado +1; mnemonico(4) := Para_minusculo(s(i));                -- quarto   dado do mnemonico
        When 7 => dado := dado +1; extra_1 := Para_Std_logic_Vector(s(i));              -- primeiro dado extra
        When 8 => dado := dado +1; extra_2 := Para_Std_logic_Vector(s(i));              -- segundo  dado extra                     
        When 9 => Null;           
      End Case;
    End Loop;
    dados := dado -1;
  End Extrai_dados;
   
End pack_cpu_txt;
     

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



Código do pacote Pack_cpu_ram

-----------------------------------------------------------------------------------------------------------------------------------
-- 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
--
-- Pacote de auxilio da memoria ram dual
-- Declaracao do componente 'ram_dual1' e procedimento de auxilio a escrita na porta 2 da Ram
-----------------------------------------------------------------------------------------------------------------------------------

---->> 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 conversoes com Std_Logic

---->> Declaracao de pacote: veja capitulo 9 <<----
Package pack_cpu_ram Is         -- Declaracao do pacote
  -----------------------------------------------------------------------------------------------------------------------------------
  -- Declaracao do componente 'Ram Dual Port'' para o armazenamento de dados
  ----------------------------------------------------------------------------------------------------------------------------------
  ---->> Declaracao componentes em pacote: veja capitulo 9 <<----
  Component ram_dual1
  Generic(ne  : Integer  := 8;                                       -- Numero de bits do barramento de endereco
          nd  : Integer  := 8;                                       -- Numero de bits do barramento de dados
          td  : Time := 10 ns);                                      -- Tempo para apresentacao dos dados
   Port (ce1_n, wr1_n, oe1_n : In Std_Logic;                           -- sinais controle 1
         Ei1                 : In    Std_Logic_Vector(ne-1 Downto 0);  -- endereco 1
         Dt1                 : InOut Std_Logic_Vector(nd-1 Downto 0);  -- dados: entrada e saida 1
         ce2_n, wr2_n, oe2_n : In Std_Logic;                           -- sinais controle 2
         Ei2                 : In    Std_Logic_Vector(ne-1 Downto 0);  -- endereco 2
         Dt2                 : InOut Std_Logic_Vector(nd-1 Downto 0)); -- dados: entrada e saida 2     
  End Component;

  ----> Lista de interface de um subprograma (parametros formal e real): veja capitulo 8 <<----
  ----> Declaracao de procedimento: veja capitulo 8 <<----
  Procedure Escreve_porta_2 (ed_in  : In  Std_Logic_Vector;         dt_in : In  Std_Logic_Vector;
                             Signal ce2_n  : Out Std_Logic;         Signal wr2_n : Out Std_Logic;
                             Signal ed2    : Out Std_Logic_Vector;  Signal dt2   : InOut Std_Logic_Vector);
End pack_cpu_ram;


Package Body pack_cpu_ram Is  -- corpo do pacote
  -----------------------------------------------------------------------------------------------------------------------------------
  -- Procedimento para executar uma operacao de escrita na memoria 'Dual Port'
  -- Dados presentes em 'ed_in' e 'dt_in' sao transferidos para 'ed2' e 'dt2'
  -- Pulsos de 1ns e 2ns sao gerados para a escrita dos dados
  -----------------------------------------------------------------------------------------------------------------------------------
  Procedure Escreve_porta_2 (       ed_in  : In  Std_Logic_Vector;         dt_in : In  Std_Logic_Vector;
                             Signal ce2_n  : Out Std_Logic;         Signal wr2_n : Out Std_Logic;
                             Signal ed2    : Out Std_Logic_Vector;  Signal dt2   : InOut Std_Logic_Vector) Is
    Variable dado : Integer Range 1 To 9 :=1;
  Begin
     ed2 <= ed_in;    dt2 <= dt_in;    -- Endereco e dado
     ce2_n <= '0';    wr2_n <= '0';    -- Prepara linhas de controle
   Wait For 1 ns;                      -- Ocorre uma iteracao dos sinais concorrentes
     wr2_n <= '1';                     -- Operacao de escrita de escrita executada
   Wait For 1 ns;                      -- Ocorre uma iteracao dos sinais concorrentes
     ce2_n <= '1';                     -- Fim da operacao de escrita
   Wait For 1 ns;                      -- Ocorre uma iteracao dos sinais concorrentes
  End Escreve_porta_2;
   
End pack_cpu_ram;
  

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





Código da entidade ram_dual1

-------------------------------------------------------------------------------------------------------------------------------------
-- 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
--
--
-- Exemplo extra
--
-- Memoria Ram Dual - Sintese ok
-- Composta de um componente: uma memoria Ram normal e um circuito externo de controle e selecao
-- Operacao de escrita simultanea nao e' controlada
-- Ce1_n =0 define selecao da informacao para os barramentos Ei e Di da memoria
-- Generico ne = numero de linhas de endereco. Generico nd = numero de linhas de dados
-------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------
-- Nucleo da memoria Ram - entrada e saida de dados independentes
---->> Sintese e descricao de memorias: veja capitulo 12 <<----
-------------------------------------------------------------------------------------------------------------------------------------
Library IEEE;
Use IEEE.Std_Logic_1164.All;
Use IEEE.Std_Logic_unsigned.All; -- Biblioteca Synopsys necessaria para a operacao de conversao do tipo Std_Logic

Entity ram_comp Is
  Generic (ne, nd : Integer);                                    -- Numero de bits do barramento de endereco e dados                                      -- Tempo para apresentacao dos dados
  Port    (ce_n, wr_n: In    Std_Logic;                         -- Sinais controle: habilitacao e escrita
           Ei        : In    Std_Logic_Vector(ne-1 Downto 0);   -- Barramento de endereco
           Di        : In    Std_Logic_Vector(nd-1 Downto 0);   -- Barranto de dados: entrada
           Do        : Out   Std_Logic_Vector(nd-1 Downto 0));  -- Barranto de dados: saida
End ram_comp;

Architecture teste Of ram_comp Is
  Type arranjo_memoria Is Array (Natural Range <>) Of Std_Logic_Vector(nd-1 downto 0);
  Signal dados : arranjo_memoria(0 To 2**ne-1);      -- Numero posicoes de memoria
  Signal ced_n  : Std_Logic;                         -- Sinal de habilitacao atrasado

Begin
   ---->> Atraso delta: veja capitulos 3 e 5 <<----
   -- Nota: ced_n atrasado 1 delta com relacao a wr_n: permite a escrita com transicao simultanea de wr e ce de 0 para 1
   -- Este atraso tem efeito para simulacao somente. Para efeito de sintese, ced_n e' igual a ce_n
   -- Exemplo:
   --            wr_n: -------_______-----
   --            ce_n: ----__________-------
   --
   ced_n <= ce_n; 
  
  Process(ced_n, wr_n, dados, Ei, Di)                                
  Begin
    -- operacao de escrita da memoria
    If rising_edge(wr_n) Then 
      If    ced_n  = '0' Then dados(Conv_Integer(Ei))  <= Di;  -- Devido ao atraso de 1 delta o valor de ced_n = 0 mesmo com ce_n =1
      End If;     
    End If;
    Do <= dados(Conv_Integer(Ei));
  End Process;    
End teste;

-------------------------------------------------------------------------------------------------------------------------------------
-- Memoria Ram Dual Port
-- Entidade que solicita ram_comp. Entrada e saida de dados no mesmo barramento
-------------------------------------------------------------------------------------------------------------------------------------
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

Entity ram_dual1 Is
 Generic (ne  : Integer  := 8;                                       -- Numero de bits do barramento de endereco
          nd  : Integer  := 8;                                       -- Numero de bits do barramento de dados
          td  : Time     := 10 ns);                                  -- Tempo para apresentacao dos dados
 Port (ce1_n, wr1_n, oe1_n : In    Std_Logic;                        -- Sinais controle 1
       Ei1                 : In    Std_Logic_Vector(ne-1 Downto 0);  -- Endereco 1
       Dt1                 : InOut Std_Logic_Vector(nd-1 Downto 0);  -- Dados: entrada e saida 1
       ce2_n, wr2_n, oe2_n : In    Std_Logic;                        -- Sinais controle 2
       Ei2                 : In    Std_Logic_Vector(ne-1 Downto 0);  -- Endereco 2
       Dt2                 : InOut Std_Logic_Vector(nd-1 Downto 0)); -- Dados: entrada e saida 2     
End ram_dual1;

Architecture teste Of ram_dual1 IS
  Component ram_comp
  Generic (ne, nd : Integer);                                   -- Numero de bits do barramento de endereco e dados
  Port    (ce_n, wr_n: In    Std_Logic;                         -- Sinais controle: habilitacao e escrita
           Ei        : In    Std_Logic_Vector(ne-1 Downto 0);   -- Barramento de endereco
           Di        : In    Std_Logic_Vector(nd-1 Downto 0);   -- Barranto de dados: entrada
           Do        : Out   Std_Logic_Vector(nd-1 Downto 0));  -- Barranto de dados: saida    
  End Component;
 
  Signal wrx, cex : Std_Logic;
  Signal Eix,Eixx      : Std_Logic_Vector(Ei1'Range);
  Signal Dix,Dixx     : Std_Logic_Vector(Dt1'Range);
  Signal Dox      : Std_Logic_Vector(Dt1'Range);
 
Begin
  -- Sinais aplicados a memoria
  wrx  <= wr1_n And wr2_n;                -- Controle de escrita do nucleo
  cex  <= ce1_n And ce2_n;                -- Controle de habilitacao do nucleo
  Eixx  <= Ei1 When ce1_n = '0' Else Ei2;  -- Seletor do barramento de enderecos do nucleo
  Dixx  <= Dt1 When ce1_n = '0' Else Dt2;  -- Seletor do barramento de dados do nucleo
  Eix <= Eixx;
  Dix <= Dixx;
 
 
  -- Controle da saida de dados da porta 1
  Dt1 <=  Dox After td   When (ce1_n = '0' And oe1_n = '0' And wr1_n = '1') Else -- Saida 1: leitura de dados
          (Others => 'Z');                                                       -- Saida 1: em alta impedancia

  -- Controle da saida de dados da porta 2
  Dt2 <=  Dox After td   When (ce2_n = '0' And oe2_n = '0' And wr2_n = '1') Else -- Saida 2: leitura de dados
          (Others => 'Z');                                                       -- Saida 2: em alta impedancia
 
 X1: ram_comp Generic Map (ne, nd) Port Map(cex, wrx, Eix, Dix, Dox);
 
 End teste;

      

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





Exemplos de simulação: Códigos e Cartas de tempo

  • Soma de valores com 16 bits:
         Código.dat  =  Código.txt          Carta 1 - endereços A0..AF      Carta 2 - sinais CPU

  • Multiplicação de valores com 8 bits:
         Código.dat  = Código.txt           Carta 1 - endereços A0..AF      Carta 2 - sinais CPU

  • Ordenação de dados com 8 bits:
         Código.dat  =  Código.txt           Carta 1 - endereços 90..9F (valores base 10)  e  A0..AF     


Lembre: para simulação, altere o nome do arquivo ".dat" ou ".txt"  para  "fonte_ex1.dat"

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