Memória RAM com megafunção

Mega Memória

O projeto descrito a seguir é um exemplo de circuito sequencial descrito em VHDL através de uma função do Quartus II, a Megafunção. Ela gera um componente a partir de especificações passadas pelo usuário através de um assistente, parecido com o utilizado para criar um projeto. Uma vez especificado, o assistente gera o componente e um template para a declaração e outro pra instanciação, o que torna possível a realização de um bloco de lógica complexo de forma rápida até mesmo para um usuário pouco experiente.

A lógica descrita neste projeto pode ser utilizada para implementação de projetos maiores.

Componentes utilizados:

Lógica de Funcionamento

Figura 1 - Diagrama de Blocos do projeto.

A memória deve permitir tanto a escrtita quanto a leitura de dados.

Escrita

Para a escrita de dados, deve-se colocar o dado que se deseja escrever, o endereço no qual será escrito e manter o ESCRITA em nível lógico alto. Com um pulso de CLOCK IN, as entradas serão registradas então a escrita terá sido completa. Se quisermos ver o que foi escrito basta fornecer um pulso de CLOCK OUT.

Leitura

Para a leitura de dados, o ESCRITA deve estar em nível lógico baixo e deve-se colocar o endereço a ser lido. Um pulso de CLOCK IN fará com que o comando seja registrado. Um pulso de CLOCK OUT fará com que a saída seja atualizada e registrada.

Megafunção

Primeiramente, abrimos o MegaWizard. Abrimos a opção Tools e MegaWizard Plug-In Manager.

Figura 2 - Seleção da ferramenta.

Uma vez aberto, pode-se selecionar a opção de criar uma nova função. Observe que o Megawizard auxilia também na edição de megafunções já criadas e na criação de megafunções a partir de outras.

Figura 3 - Primeira etapa da criação da Mega Função.

Se selecionado para criar uma megafunção a partir do zero, deve-se selecionar o tipo Megafunção que se deseja. Esta etapa irá definir como o componente irá se comportar.

Figura 4 - Seleção do tipo de componente que se deseja.

Após a definição do modelo, podemos definir algumas características do comportamento. Neste caso, escolhemos a opção de registrar as entradas e as saídas da memória.

Figura 5 - Seleção de características.

Por ser uma memória, pode-se optar por dar um valor inicial para ela. Neste caso não será utilizado esta opção, porém em outros projetos cria-se um arquivo .mif ou .hex para gerar a memória com valores iniciais já estabelecidos, como no projeto VGA para FPGA.

Figura 6 - Seleção do valor inicial da memória.

O Megawizard adiciona bibliotecas para uma posterior simulação.

Figura 7 - Bibliotecas a serem adicionadas para a simulação.

Pode-se escolher os arquivos a serem criados pelo Megawizard. Ele possui a opção de gerar um arquivo em AHDL, um .bsf e um template da instanciação do componente criado.

Figura 8 - Arquivos que podem ser criados pelo Megawizard.

Após finalizar, o componente terá sido criado. Para utilizá-lo, basta adicionar ao projeto.

Mega Memória

Na entidade, definimos as estradas e saídas do projeto.

library lpm;
use lpm.lpm_components.all;
entity MegaMemoria is
   port(
         ClockIn     :  in    std_logic;
         ClockOut    :  in    std_logic;
         Saida       :  out   std_logic_vector(7 DOWNTO 0);
         Endereco    :  in    std_logic_vector(1 downto 0);
         Dado        :  in    std_logic_vector(7 DOWNTO 0);
         Escrita          :  in    std_logic
   );
end entity MegaMemoria;

Declaração do Componente

Depois, fazemos a declaração do componente. Podemos pegar o template gerado pelo Quartus II e colar diretamente na arquitetura.

Figura 9 - Template da declaração do componente.

 


architecture comportamento of MegaMemoria is
   component Memoria
      PORT
      (
         address      : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
         data            : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
         inclock        : IN STD_LOGIC ;
         outclock      : IN STD_LOGIC ;
         we               : IN STD_LOGIC  := '1';
         q                 : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
      );
   end component;

Instanciação do componente

Uma vez declarado o componente, vamos associar suas entradas e saídas com os sinais do projeto, de acordo com a lógica desejada. Mais uma vez o Quartus gera um template que pode facilitar bastante o trabalho.

Figura 10 - Template da instanciação do componente.

   begin
   Memoria_inst : Memoria PORT MAP (
      address => Endereco,
      data => Dado,
      inclock => ClockIn,
      outclock => ClockOut,
      we => not (Escrita),
      q => Saida
);      
   end architecture comportamento;

Simulação

Para a simulação,  foram inseridos e lidos dados da memória seguindo a ordem necessária para tais operações. Foram feitas as seguintes operações:

  1. Escreveu-se o dado "10101010" no endereço "00".

  2. Escreveu-se o dado "11001100" no endereço "01".

  3. Leu-se o dado no endereço "00".

  4. Leu-se o dado no endereço "01".

Escrita

O código abaixo apresenta a simulação da escrita de um dado.

         -- Escrevendo "10101010" no endereco "00"
         Endereco <= "00";
         Dado <= "10101010";
         wait for 20 us;
         Escrita <= '0';   -- Aperta o botão de escrita
         wait for 10 us;
         ClockIn <= '0';   -- Aperta o botão de clockIn
         wait for 10 us;
         ClockIn <= '1';   -- Solta o botão de ClockIn
         -- Com este pulso de ClockIn, o dado já foi gravado.
         wait for 5 us;
         Escrita <= '1';   -- Solta o botão de escrita
         wait for 5 us;

Leitura

O código abaixo apresenta a simulação da escrita de um dado.

         -- Lendo o dado escrito no endereco "00"
         Endereco <= "00";
         ClockIn <= '0';   -- Aperta o botão de ClockIn
         wait for 10 us;
         ClockIn <= '1';   -- Solta o botão de ClockIn
         wait for 5 us;
         ClockOut <= '0';  -- Aperta o botão de ClockOut
         wait for 10 us;
         ClockOut <= '1';  -- Solta o botão de ClockOut
         wait for 10 us;

Os nomes utilizados no testbench foram os mesmos utilizados no projeto, lembrando que isso não é necessário e a atribuição depende da ordem em que aparece no projeto e na declaração de UUT. O resultado da simulação pode ser visto abaixo na janela do ModelSim-Altera:

Figura 11 - Simulação da Mega Memória

Estrutura Física

Figura 12 - Montagem do projeto.

O projeto implementado utiliza um kit CPLD 7064, onde será gravado o projeto. A placa de LEDs irá com CON1,   as duas placas de chaves no CON2 e CON3 e a placa de botões no CON4. 

Montagem e Roteamento

A montagem pode ser feita como na ilustração abaixo, feita no Fritizing:

Figura 13 - Esquema proposto.

Com base na montagem feita e na pinagem da placa, podemos definir a pinagem do componente:

Figura 14 - Pinagem proposta para o projeto.

Arquivos do Projeto

Para o download do projeto completo, clique aqui.

O arquivo está no formato "zip", e inclui, entre outros:

   - O arquivo de projeto do Quartus ".qpf"

   - A descrição no formato VHDL ".vhd"

   - O Testbench no formato VHDL ".vhd"   

   - O arquivo para gravação do CPLD, no formato ".pof".