Aula 1: O Fluxo de Dados

Questão: Como era a programação na Era do ENIAC?

Objetivos

  1. Introduzir o conceito de Fluxo de Dados (FD).

Pré-requisitos

Ter o Quartus Prime Lite instalado e funcional. Ele está disponível no site da Intel:

Download Center for FPGAs

Ter feito o Tutorial para início das Aulas: Uso do Quartus e VHDL, que está no blackboard em:


Contextualização 1

O ENIAC, criado por John Presper Eckert e John Mauchly entre 1943 e 1945 na Universidade da Pensilvania, foi considerado por muito tempo o primeiro computador de uso geral já construído. Porém, ele não possuía uma caracteristica muito importante, a capacidade de armazenar o programa sendo executado para uso posterior. O conceito de programa armazenado, foi implementado no sucessor do ENIAC (Electronic Numerical Integrator and Computer), o EDVAC (Electronic Discrete Variable Automatic Computer).

Características do ENIAC:

Visão Geral do ENIAC
Visão Geral do ENIAC
Visão Geral do ENIAC
Visão Geral do ENIAC

Na verdade, o ENIAC era uma coleção de unidades funcionais que eram interconectadas e configuradas para resolver um determinado problema matemático. Ou seja, a programação do ENIAC era feita através da conexão de cabos e configuração de chaves nos painéis dessas unidades funcionais.

O ENIAC sendo programado
O ENIAC sendo programado
O ENIAC sendo programado
O ENIAC sendo programado
O ENIAC sendo programado
O ENIAC sendo programado
O Resultado da Programação do ENIAC

Com o objetivo do programa definido, era feita a sua programação através de esquemas de conexão.

Um Programa para o ENIAC
Um Programa para o ENIAC

A programação do ENIAC era a criação de um caminho para os dados, ou fluxo de dados, que resolvesse o problema em questão. Uma atividade similar ainda é utilizada na criação de projetos digitais, mais especificamente, no projeto de processadores.

Curiosidade

O primeiro bug verdadeiro foi encontrado, em 09 de setembro de 1947, no computador Mark II, em Harvard. Fazia parte da equipe a criadora do primeiro compilador: Grace Murray Hopper.

Primeiro Bug não foi no ENIAC
Primeiro Bug não foi no ENIAC

Por exemplo, para criar, de forma semelhante ao que era feito no ENIAC, um caminho de dados que resolva a seguinte equação:

S = 2x - 3y + 7

Utilizaríamos unidades funcionais para executar as somas e outra para executar a subtração.

As unidades funcionais utilizam os operandos, indicados pelas letras A e B, da seguinte forma: A operação B.
Ou seja, no caso de se usar um subtrator, a saída dele será dada por: A - B.


Um grande inconveniente, similar ao que ocorria com o ENIAC, é a necessidade de reconectar (reprogramar) as unidades funcionais para resolver outra equação diferente.

Por exemplo, para a equação S = 3x + 3y - 5, teríamos o FD mostrado abaixo.

Além disso, para cada operação temos que usar uma unidade funcional nova, não há como reutilizar a mesma unidade várias vezes.


Responder o quiz de participação, no blackboard, em:

Conteúdos > Participação > Aula_1_Quiz-P1


Para otimizar a utilização dos componentes do fluxo de dados, podemos fazer com que ele seja configurável dinamicamente. Uma forma de fazer isso é utilizando elementos que memorizem os resultados intermediários e adicionar circuitos multiplex para reconfigurar o caminho de dados.

Fluxo de Dados para Equação de Primeiro Grau
Fluxo de Dados para Equação de Primeiro Grau

A configuração do FD é feita pela alteração dos sinais de controle de acordo com o cálculo que desejamos fazer. Por exemplo, para calcular o valor de 3x - 4, podemos utilizar a seguinte sequência passos de ativação dos pontos de controle.

Primeiro Passo para a Equação 3x - 4

Condição Após Configuração e Antes do Clock
Condição Após Configuração e Antes do Clock

Como o clock ainda não ocorreu, após o tempo de propagação dos sinais pelo FD, teremos a entrada do Acumulador com o valor de “x” e a sua saída com o valor anterior (após o reset) 0.

No momento do pulso de clock, a saída do Acumulador é atualizada para o valor “x”.

De agora em diante, a cada pulso de clock adicionaremos “x” ao Acumulador. Ou seja, teremos o resultado acumulado das somas.

Condição Entre o Primeiro e o Segundo Pulso de Clock
Condição Entre o Primeiro e o Segundo Pulso de Clock

Segundo Passo para a Equação 3x - 4

Este passo, como visto anteriormente, é o envio de um pulso de clock.

Após esse clock teremos o valor de “x+x+x” na entrada do Acumulador, como pode ser visto abaixo.

Condição Entre o Segundo e o Terceiro Pulso de Clock
Condição Entre o Segundo e o Terceiro Pulso de Clock

Terceiro Passo para a Equação 3x - 4

Este passo é o envio de um pulso de clock, para obter o resultado final das somas com “x” no Acumulador.

Condição Entre o Terceiro e o Quarto Pulso de Clock
Condição Entre o Terceiro e o Quarto Pulso de Clock

Quarto Passo para a Equação 3x - 4

Neste passo, precisamos:

Condição Após o Alteração da Entrada e da Operação
Condição Após o Alteração da Entrada e da Operação

Ao enviar o último pulso de clock, armazenamos no acumulador o valor 3X-4.

Condição Após o Último Pulso de Clock
Condição Após o Último Pulso de Clock

Responder o quiz de participação, no blackboard, em:

Conteúdos > Participação > Aula_1_Quiz-P2



Atividade 1

Para tanto, utilizaremos uma ULA que possui somente a soma e a subtração, que está na ABA Modelos VHDL.

Os outros componentes utilizados também estão na ABA Modelos VHDL.

As características do circuito estão listadas abaixo:

Para cada projeto, deve existir a definição da funcionalidade dos pinos da FPGA em um arquivo do tipo .qsf.

Durante a criação do projeto, o Quartus cria, na pasta principal do seu projeto, um arquivo chamado Nome_do_Projeto.qsf.

Ele contém as definições básicas do projeto e deve ser acrescentada a definição dos pinos. Essa definição está na ABA: Modelos VHDL > Kit DE0-CV > Arquivo de Configuração dos Pinos (.qsf) do Kit FPGA DE0CV para o Quartus.

Para confirmar o funcionamento do seu projeto, veja o circuito RTL resultante e faça a simulação.

Após o circuito funcionar adequadamente, grave-o na FPGA e faça alguns testes para confirmar o seu funcionamento.

Verifique o funcionamento do sinal Habilita A. O que ocorre se o sinal Habilita A estiver em nível 0 e ocorrer um pulso de clock?

Devido ao uso de 4 bits, é necessário restringir os números utilizados para evitar ultrapassar o limite representável pelos 4 bits (valor decimal = 15).

Esquema Completo (com entradas e saídas).

As conexões dos I/Os da placa DE0-CV são mostrado abaixo:

Fluxo de Dados para Equação de Primeiro Grau
Fluxo de Dados para Equação de Primeiro Grau

Procedimento

O seu projeto será formado por cinco arquivos, todos eles baseados na estrura do esqueleto (disponível na ABA Modelos VHDL), que são:

O estado em repouso do Botão é o nível ALTO, portanto, para o RESET devemos usar not KEY(1).

Abaixo, temos um exemplo do top_level desta atividade, completo e funcional.

Note que, para interligar os compontentes, utilizamos a declaração signal, como mostrado no exemplo abaixo.


library ieee;
use ieee.std_logic_1164.all;

entity Aula1 is
  -- Total de bits das entradas e saidas
  generic ( larguraDados : natural := 4;
              simulacao : boolean := TRUE -- para gravar na placa, altere de TRUE para FALSE
  );
  port   (
    CLOCK_50 : in std_logic;
    KEY: in std_logic_vector(3 downto 0);
    SW: in std_logic_vector(9 downto 0);
    LEDR  : out std_logic_vector(9 downto 0)
  );
end entity;

architecture arquitetura of Aula1 is
-- Obs.:
-- SW(9 downto 6) : entrada da variavel X.
-- SW(3 downto 0) : entrada da variavel Y.
-- SW(4) : o ponto de controle da Operacao da ULA.
-- SW(5) : o ponto de controle de SelMUX.
-- KEY(0) : o botão do clock.
-- KEY(1) : o ponto de controle para Reset A (o Botao em repouso fica no nível alto, portanto, devemos usar not KEY(1) no Reset).
-- KEY(2) : o ponto de controle de Habilita A.
-- KEY(3) : sem uso.

  signal chavesX_ULA_B : std_logic_vector (larguraDados-1 downto 0);
  signal chavesY_MUX_A : std_logic_vector (larguraDados-1 downto 0);
  signal REG1_ULA_A : std_logic_vector (larguraDados-1 downto 0);
  signal Saida_ULA : std_logic_vector (larguraDados-1 downto 0);
  signal MUX_REG_A : std_logic_vector (larguraDados-1 downto 0);
  signal Chave_Operacao_ULA : std_logic;
  signal CLK : std_logic;
  signal SelMUX : std_logic;
  signal Habilita_A : std_logic;
  signal Reset_A : std_logic;
  signal Operacao_ULA : std_logic;
begin

-- Instanciando os componentes:

-- Para simular, fica mais simples tirar o edgeDetector
gravar:  if simulacao generate
CLK <= KEY(0);
else generate
detectorSub0: work.edgeDetector(bordaSubida)
        port map (clk => CLOCK_50, entrada => (not KEY(0)), saida => CLK);
end generate;

-- Instancia do MUX.
MUX1 :  entity work.muxGenerico2x1  generic map (larguraDados => larguraDados)
        port map( entradaA_MUX => chavesY_MUX_A,
                 entradaB_MUX =>  Saida_ULA,
                 seletor_MUX => SelMUX,
                 saida_MUX => MUX_REG_A);

-- Instancia do Acumulador.
REG1 : entity work.registradorGenerico   generic map (larguraDados => larguraDados)
          port map (DIN => MUX_REG_A, DOUT => REG1_ULA_A, ENABLE => Habilita_A, CLK => CLK, RST => Reset_A);

-- Instancia da ULA:
ULA1 : entity work.ULASomaSub  generic map(larguraDados => larguraDados)
          port map (entradaA => REG1_ULA_A, entradaB =>  chavesX_ULA_B, saida => Saida_ULA, seletor => SW(4));

-- Chaves e Botoes.
chavesX_ULA_B <= SW(9 downto 6);
chavesY_MUX_A <= SW(3 downto 0);
SelMUX <= SW(5);
Operacao_ULA <= SW(4);
Reset_A <= not KEY(1);
Habilita_A <= KEY(2);


-- A ligacao dos LEDs:
LEDR (9) <= SelMUX;
LEDR (8) <= Habilita_A;
LEDR (7) <= Reset_A;
LEDR (6) <= Operacao_ULA;
LEDR (5) <= '0';    -- Apagado.
LEDR (4) <= '0';    -- Apagado.
LEDR (3 downto 0) <= REG1_ULA_A;

end architecture;

Verificação através do RTL

Para verificar se o projeto está conforme o desejado, podemos utilizar o visualizador RTL. No Quartus, ele está em:

Caso tenha mantido a linha de configuração para fazer simulação, como mostrado abaixo:

  generic (  larguraDados : natural := 4;
                simulacao : boolean := TRUE -- para gravar na placa, altere de TRUE para FALSE
  );

O diagrama obtido deverá ser similar ao abaixo.

RTL do Fluxo de Dados Configurável
RTL do Fluxo de Dados Configurável

Caso tenha mantido a linha de configuração para executar na placa, como mostrado abaixo:

  generic (  larguraDados : natural := 4;
                simulacao : boolean := FALSE -- para gravar na placa, altere de TRUE para FALSE
  );

O diagrama obtido deverá ser similar ao abaixo.

RTL do Fluxo de Dados Configurável
RTL do Fluxo de Dados Configurável

Teste com a Equação 3x - 4

Com o circuito pronto, faça o teste utilizando a equação 3x - 4. A sequência dos pontos de controle são as mesmas mostradas no exemplo anterior.

Para facilitar, faça uma tabela com essa sequência, que reutilizaremos na próxima aula.


Esta Atividade deverá ser entregue através do Blackboard!


Ferramenta Auxiliar: Conversor Binário para Decimal (com ou sem sinal)

    Binário com Sinal


Outras Ferramentas