
FIFO (Primeiro a Entrar, Primeiro a Sair) é um método de armazenamento de dados no qual os primeiros dados escritos em um buffer são também os primeiros dados lidos. O princípio de funcionamento é semelhante a uma fila. Os dados entram no buffer em uma ordem específica e permanecem armazenados até serem lidos. Os dados mais antigos saem primeiro do buffer, enquanto os dados mais novos aguardam atrás deles.
Em sistemas FPGA e ASIC, o FIFO é comumente utilizado como uma área de armazenamento temporário entre circuitos que produzem dados e circuitos que consomem dados. Em vez de enviar dados diretamente de um bloco para outro, os dados de entrada são primeiro armazenados no FIFO. O circuito receptor então lê os dados armazenados quando está pronto. Essa abordagem ajuda a manter um fluxo de dados contínuo e confiável.
Ao contrário da memória ordinária, o FIFO não requer linhas de endereço externas para selecionar locais de armazenamento. Durante uma operação de escrita, os dados de entrada são automaticamente colocados no próximo local disponível no buffer. Durante uma operação de leitura, os dados armazenados mais antigos são automaticamente recuperados e enviados para a saída.
Esse processo é gerido por ponteiros de escrita e leitura internos. Quando novos dados são escritos, o ponteiro de escrita se move para o próximo local de armazenamento. Quando os dados são lidos, o ponteiro de leitura avança para o próximo item disponível. Como esses ponteiros operam automaticamente, o FIFO requer menos lógica de controle do que a memória convencional.
A desvantagem é que os dados só podem ser acessados sequencialmente. Ao contrário da RAM, o FIFO não pode acessar diretamente um local de armazenamento específico. Cada operação de leitura segue a ordem exata em que os dados foram originalmente escritos.
O FIFO é amplamente utilizado quando diferentes partes de um sistema operam em velocidades diferentes. Em muitas aplicações, um dispositivo gera dados continuamente enquanto outro dispositivo processa ou transmite esses dados em uma taxa mais lenta. Sem armazenamento temporário, os dados de entrada podem chegar mais rápido do que podem ser manipulados, causando perda de dados.
Por exemplo, um conversor analógico-digital (ADC) pode gerar continuamente amostras digitais enquanto um processador, barramento PCI ou interface de comunicação processa essas amostras em uma velocidade diferente. Um FIFO age como um buffer intermediário que armazena os dados de entrada e libera-os quando o circuito receptor está pronto. Isso permite que ambos os lados do sistema operem de forma independente sem perder informações.
O FIFO também pode resolver desajustes de largura de dados entre dispositivos. Em alguns sistemas, um dispositivo pode emitir dados de 8 bits enquanto outro espera dados de 16 bits. A comunicação direta pode exigir lógica de conversão adicional para reorganizar os dados.
Um FIFO pode simplificar esse processo armazenando temporariamente os dados de entrada e apresentando-os em um formato que corresponda ao dispositivo receptor. Essa capacidade ajuda diferentes blocos de hardware a trocar dados de forma eficiente, reduzindo a complexidade da interface.
As estruturas FIFO são geralmente divididas em FIFO síncromo e FIFO assíncrono.
Um FIFO síncromo utiliza um único sinal de clock para operações de leitura e escrita. Como todas as atividades ocorrem sob a mesma fonte de clock, as relações de tempo são mais fáceis de gerenciar e verificar. Os FIFOs síncronos são comumente utilizados quando os dados permanecem dentro de um único domínio de clock.
Um FIFO assíncrono utiliza clocks separados para escrita e leitura. Os dados podem entrar no FIFO usando uma frequência de clock e sair usando outra. Como os dois clocks operam de forma independente, os FIFOs assíncronos são amplamente utilizados para transferir dados entre diferentes domínios de clock.
Essa capacidade é especialmente importante em sistemas FPGA onde processadores, interfaces de comunicação, controladores de memória e dispositivos periféricos frequentemente operam em diferentes frequências.
A operação confiável do FIFO depende de saber quanto dado está atualmente armazenado no buffer. Se novos dados continuarem chegando após o FIFO atingir a capacidade, informações válidas podem ser sobrescritas. Da mesma forma, tentar ler dados de um FIFO vazio produz resultados inválidos.
Para prevenir essas condições, os projetos de FIFO utilizam vários sinais de status.
A bandeira cheia indica que todos os locais de armazenamento disponíveis estão ocupados e que nenhum dado adicional pode ser escrito. A bandeira vazia indica que não há dados válidos disponíveis para leitura.
Muitas implementações de FIFO também fornecem indicadores quase cheios e quase vazios. Esses sinais atuam como alertas precoces antes que o FIFO atinja uma condição completamente cheia ou completamente vazia. A lógica de controle pode usar esses sinais para desacelerar, parar ou ajustar transferências de dados antes que ocorra um transbordamento ou subfluxo.
Como esses indicadores de status afetam diretamente a integridade dos dados e a confiabilidade do sistema, eles são uma parte essencial do design do FIFO.
As estruturas FIFO são geralmente divididas em FIFO de Clock Único (SCFIFO) e FIFO de Clock Duplo (DCFIFO). Essas estruturas foram projetadas para suportar diferentes relações de clock e requisitos de transferência de dados.
As estruturas FIFO mais comuns incluem:
• SCFIFO (FIFO de Clock Único)
• DCFIFO (FIFO de Clock Duplo)
• DCFIFO Larguras Mistas (FIFO de Clock Duplo com diferentes larguras de dados para leitura e escrita)
Na maioria da documentação FPGA, os FIFOs de clock duplo padrão e os FIFOs de clock duplo de largura mista são ambos categorizados como FIFOs de clock duplo, a menos que uma distinção seja necessária.

A seleção de uma estrutura FIFO depende principalmente de como os dados entram e saem do buffer. A relação entre o clock de escrita e o clock de leitura é geralmente o fator mais importante ao escolher a arquitetura FIFO apropriada.
Um FIFO de Clock Único utiliza um sinal de clock para controlar tanto as operações de escrita quanto as de leitura. Como ambos os processos operam dentro do mesmo domínio de clock, o controle de tempo é relativamente simples e os problemas de sincronização são minimizados.
Quando dados válidos chegam à entrada do FIFO e um pedido de escrita é afirmado, os dados são armazenados na próxima localização de memória disponível na borda de clock ativa. À medida que mais dados chegam, o ponteiro de escrita continua avançando pela área de armazenamento do FIFO.
Quando um pedido de leitura é afirmado, o FIFO recupera os dados armazenados mais antigos e os coloca na saída. O ponteiro de leitura então avança para a próxima localização armazenada. Esse movimento contínuo dos ponteiros de leitura e escrita permite que os dados fluam pelo FIFO na ordem correta.
Os FIFOs de clock único também fornecem vários sinais de status que ajudam a monitorar as condições do buffer. A bandeira cheia indica que todos os locais de armazenamento estão ocupados e novas gravações devem ser interrompidas. A bandeira quase cheia avisa que o FIFO está se aproximando da capacidade.
A bandeira vazia indica que não há dados válidos restantes no buffer, enquanto a bandeira quase vazia alerta que apenas uma pequena quantidade de dados permanece. Muitas implementações também incluem um contador de palavras usadas, que relata quanto dado está atualmente armazenado no FIFO.
Esses indicadores permitem que a lógica circundante tome decisões seguras de leitura e escrita enquanto mantém uma operação confiável do FIFO.
Um FIFO de Clock Duplo utiliza clocks separados para operações de escrita e leitura. O lado de escrita opera dentro de um domínio de clock, enquanto o lado de leitura opera dentro de outro.
Os dados que chegam são escritos no FIFO usando o clock de escrita. Uma vez armazenados, os dados permanecem dentro do buffer até que o lado de leitura os recupere usando o clock de leitura. Como os dois clocks são independentes, o FIFO pode transferir dados com segurança entre diferentes domínios de clock.
Essa capacidade faz dos FIFOs de clock duplo uma das soluções mais comuns para cruzamento de domínios de clock em sistemas FPGA.
Para suportar uma operação fiável, FIFOs de relógio duplo fornecem sinais de estado para ambos os lados da interface. O lado de escrita utiliza comumente sinais como wrfull e wrempty para indicar as condições do buffer do lado de escrita. O lado de leitura utiliza comumente rdfull e rdempty para indicar a disponibilidade de dados para leitura.
Contadores separados também são frequentemente fornecidos para que cada domínio de relógio possa monitorizar a quantidade de dados armazenados de forma independente. Estes indicadores permitem que ambos os lados do FIFO tomem decisões sem interferir uns com os outros.
Algumas aplicações requerem diferentes larguras de dados no lado de escrita e no lado de leitura do FIFO. Nessas situações, pode-se usar um FIFO de Relógio Duplo de Largura Mista.
Por exemplo, dados podem ser escritos no FIFO como palavras de 16 bits, mas lidos como palavras de 8 bits. O FIFO reorganiza automaticamente a informação armazenada e realiza a conversão de largura necessária enquanto preserva a sequência original dos dados.
Esta funcionalidade é útil ao conectar dispositivos que utilizam diferentes larguras de barramento. Em vez de adicionar circuitos de conversão separados, o FIFO lida com a adaptação de largura internamente.
Um FIFO de Relógio Único é geralmente usado quando a leitura e a escrita ocorrem dentro do mesmo domínio de relógio. A sua arquitetura mais simples torna a análise de temporização e a implementação mais fáceis.
Um FIFO de Relógio Duplo é preferido quando os dados devem ser transferidos entre domínios de relógio independentes. Ele fornece uma transição fiável entre domínios de relógio e ajuda a eliminar problemas de sincronização.
Quando tanto a transição entre domínios de relógio quanto a conversão de largura de dados são necessárias, um FIFO de Relógio Duplo de Largura Mista oferece uma solução eficiente ao combinar ambas as funções dentro de uma única estrutura FIFO.
O FIFO atua como uma área de armazenamento temporário entre diferentes partes de um sistema digital. Em muitas aplicações, os dados não chegam e saem exatamente na mesma velocidade. Um dispositivo pode gerar dados continuamente, enquanto outro dispositivo pode processar ou transmitir esses dados a uma taxa mais lenta. Sem um buffer entre eles, os dados que entram podem acumular-se mais rapidamente do que podem ser manipulados, levando à perda de dados.
Um FIFO resolve este problema armazenando dados à medida que chegam e liberando-os quando o circuito receptor está pronto. Isso cria um fluxo de informação mais suave e permite que diferentes partes do sistema funcionem de forma mais eficiente, sem exigir uma coordenação perfeita de temporização.
Além de simples armazenamento em buffer, o FIFO também ajuda a melhorar o desempenho geral do sistema. Ao coletar dados temporariamente antes da transferência, o FIFO reduz o número de operações de acesso ao barramento e minimiza a sobrecarga de comunicação desnecessária. Isso permite que os recursos do sistema sejam utilizados de forma mais eficiente.
O FIFO também pode reduzir a carga de trabalho do processador. Em vez de forçar a CPU a lidar com cada transferência de dados individual, os dados podem ser acumulados no FIFO e processados em blocos maiores. Esta abordagem melhora a eficiência e libera recursos do processador para outras tarefas.
Outro benefício importante é o suporte para operações de Acesso Direto à Memória (DMA). Em sistemas de alta velocidade, o DMA permite que os dados se movimentem diretamente entre periféricos e memória sem constante envolvimento da CPU. O FIFO fornece o armazenamento temporário necessário para suportar essas transferências e manter um fluxo contínuo de dados.
Sem o armazenamento em buffer FIFO e suporte a DMA, o processador pode gastar uma quantidade significativa de tempo gerenciando a movimentação de dados, o que pode reduzir o desempenho geral do sistema e aumentar o risco de gargalos na transmissão.
Um FIFO de Relógio Único é tipicamente usado quando tanto a operação de escrita quanto a operação de leitura são controladas pelo mesmo sinal de relógio. Como ambos os lados do FIFO operam dentro do mesmo domínio de relógio, a gestão do tempo é mais simples e é mais fácil evitar problemas de sincronização.
Uma aplicação comum é a aquisição de dados de sensores. Em muitos sistemas, um sensor pode gerar dados muito mais rapidamente do que a interface de comunicação responsável por transmitir esses dados para outro dispositivo.
Por exemplo, um FPGA pode coletar dados de um sensor através de uma interface SPI de alta velocidade. Cada amostra de sensor chega rapidamente e deve ser armazenada imediatamente para evitar a perda de informações. Ao mesmo tempo, os dados coletados podem precisar ser transmitidos através de uma interface UART operando a uma taxa de transmissão muito mais baixa.
À medida que os dados do sensor entram no FPGA, eles são escritos diretamente no FIFO. Os dados armazenados aguardam então dentro do buffer enquanto a UART os transmite gradualmente à sua própria velocidade. À medida que os dados saem do FIFO, novas amostras de sensor continuam a entrar no buffer. Este processo contínuo de escrita e leitura permite que ambos os lados do sistema operem a diferentes taxas de dados enquanto permanecem sincronizados pela mesma fonte de relógio.
Ao absorver diferenças de velocidade temporárias entre a coleta de dados e a transmissão de dados, um FIFO de relógio único ajuda a manter um fluxo de dados estável e previne a perda de dados.
Um FIFO de Dois Relógios é projetado para sistemas em que o lado de escrita e o lado de leitura operam com sinais de relógio diferentes. Esta situação é comum em designs de FPGA porque muitos blocos funcionais operam a diferentes frequências e requisitos de temporização.
Quando os dados se movem de um domínio de relógio para outro, conexões diretas podem criar problemas de sincronização. Os dados podem chegar muito cedo, muito tarde ou durante janelas de temporização instáveis, levando a uma operação não confiável.
Um FIFO de dois relógios fornece uma fronteira segura entre os dois domínios de relógio. Os dados recebidos são escritos no FIFO usando o relógio de origem. Uma vez armazenados, os dados permanecem no buffer até que o lado de destino os leia usando seu próprio relógio. O FIFO gerencia internamente o processo de transferência para que ambos os domínios de relógio possam operar de forma independente.
Um sistema de processamento de vídeo fornece um bom exemplo. Uma câmera pode capturar dados de imagem usando uma frequência de relógio, enquanto um controlador VGA emite dados de imagem usando uma frequência de relógio diferente. À medida que os dados de imagem são gerados pela câmera, eles são continuamente escritos no FIFO. O controlador VGA então lê os dados de imagem armazenados à taxa necessária para a saída de exibição.
Porque o relógio de escrita e o relógio de leitura são completamente independentes, o FIFO atua como uma ponte entre os dois sistemas de temporização. Isso permite que os dados de imagem se movam de forma confiável da interface da câmera para a interface de exibição sem erros de sincronização.
Por essa razão, os FIFOs de dois relógios são amplamente utilizados para cruzamento de domínios de relógio, transferência de dados em alta velocidade, sistemas de processamento de vídeo, interfaces de comunicação e outras aplicações onde os dados devem se mover entre ambientes de temporização independentes.
Dispositivos FPGA da Altera fornecem várias maneiras de implementar a funcionalidade FIFO. O melhor método depende dos requisitos de design, cronograma de desenvolvimento e nível de personalização necessário.
Na maioria dos projetos, o objetivo é o mesmo. Um FIFO deve ser adicionado entre dois blocos funcionais para que os dados possam ser armazenados temporariamente, transferidos de forma confiável e processados na velocidade necessária. A diferença está em como o FIFO é criado e integrado ao design FPGA.
Três métodos comuns de implementação são amplamente utilizados no desenvolvimento FPGA da Altera.
O primeiro método é construir um FIFO diretamente usando código RTL (Register Transfer Level).
Nesta abordagem, o projetista cria toda a estrutura do FIFO, incluindo o array de memória, ponteiro de leitura, ponteiro de escrita, lógica de detecção de cheio, lógica de detecção de vazio e circuitos de controle. Cada parte da operação do FIFO é definida manualmente dentro do código HDL.
Este método fornece o mais alto nível de flexibilidade. A profundidade do FIFO, largura de dados, bandeiras de status e comportamento de controle podem ser todos personalizados para corresponder aos requisitos específicos da aplicação. Recursos adicionais também podem ser adicionados se as implementações FIFO padrão não fornecerem a funcionalidade necessária.
No entanto, desenvolver um FIFO do zero requer uma forte compreensão da arquitetura FIFO, análise de temporização e técnicas de design FPGA. Mais verificação e teste também são necessários para garantir uma operação confiável em todas as condições.
Por essa razão, o desenvolvimento de FIFO personalizado é geralmente reservado para aplicações que requerem recursos especializados ou requisitos de desempenho exclusivos.
O segundo método é usar um núcleo FIFO IP de código aberto ou de terceiros.
Em vez de projetar o FIFO desde o início, um módulo FIFO existente é importado para o projeto e conectado à lógica circundante. Como o código-fonte está frequentemente disponível, o design ainda pode ser modificado quando recursos adicionais ou ajustes são necessários.
Essa abordagem pode reduzir significativamente o tempo de desenvolvimento. Grande parte da arquitetura FIFO já foi criada, testada e validada, permitindo que os projetistas se concentrem na integração do sistema em vez de no desenvolvimento de FIFO de baixo nível.
Quando os requisitos do projeto diferem ligeiramente do comportamento padrão do FIFO, o código-fonte pode ser editado para suportar a funcionalidade desejada, evitando ao mesmo tempo o esforço necessário para criar um novo design de FIFO totalmente novo.
O método mais comum é usar os núcleos FIFO IP fornecidos pelo software Quartus II.
O Quartus II inclui geradores FIFO integrados que permitem que estruturas FIFO sejam criadas através de uma interface de configuração gráfica. Em vez de escrever manualmente a lógica FIFO, o projetista seleciona os parâmetros necessários e permite que o software gere a implementação automaticamente.
Durante a configuração, várias definições importantes podem ser definidas. Estes incluem:
• Tipo FIFO (de relógio único ou de relógio duplo)
• Largura de dados
• Profundidade FIFO
• Opções de implementação de memória
• Sinais de status de cheio e vazio
• Limiares quase cheio e quase vazio
• Definições de relógio de leitura e gravação
Após a seleção dos parâmetros, o Quartus II gera os arquivos FIFO e a lógica de suporte necessária para o projeto FPGA.
Uma vez que a configuração FIFO esteja concluída, o Quartus II cria automaticamente uma implementação otimizada para o dispositivo Altera FPGA selecionado.
O FIFO gerado pode então ser conectado diretamente à lógica circundante. Os dados de entrada são conectados à interface de gravação, os dados de saída são conectados à interface de leitura e os sinais de status são usados para controlar o fluxo de dados em todo o sistema.
Como o design gerado é otimizado para a arquitetura FPGA alvo, a utilização de recursos é tipicamente mais eficiente do que muitas implementações desenvolvidas manualmente. O tempo de desenvolvimento também é reduzido porque grande parte do trabalho de design, verificação e otimização é tratado automaticamente pelo software.
Para a maioria dos projetos FPGA, o núcleo IP FIFO do Quartus II fornece o caminho mais rápido e simples para implementar a funcionalidade FIFO confiável, mantendo o uso eficiente dos recursos FPGA.
FIFO oferece uma maneira simples e confiável de armazenar dados em buffer, igualar taxas de transferência e suportar comunicação entre diferentes componentes do sistema. Ao entender as arquiteturas FIFO, sinais de status, operação síncrona e assíncrona, e métodos de implementação, os projetistas podem melhorar a integridade dos dados, prevenir condições de transbordamento e subfluxo, e construir sistemas digitais mais eficientes.
Os buffers FIFO atuam como armazenamento temporário entre circuitos que produzem dados e circuitos que consomem dados. Quando um dispositivo gera dados mais rápido do que outro pode processá-los, o FIFO armazena as informações de entrada e as libera quando o dispositivo receptor está pronto. Isso previne a perda de dados, melhora a confiabilidade do sistema e permite que ambos os circuitos operem de forma independente sem exigir um emparelhamento perfeito de velocidade.
Os FIFOs assíncronos usam relógios separados para operações de gravação e leitura, permitindo que os dados se movam com segurança entre domínios de relógio independentes. Isso previne problemas de temporização e sincronização que podem ocorrer quando os sinais são transferidos diretamente entre circuitos que operam em diferentes frequências. Como resultado, os FIFOs assíncronos são comumente usados em interfaces de comunicação, sistemas de vídeo, processadores e controladores de memória.
Os sinais de status FIFO fornecem informações em tempo real sobre o uso do buffer. Os sinais de cheio e quase cheio alertam quando o espaço de armazenamento está se esgotando, enquanto os sinais de vazio e quase vazio indicam quando há pouca ou nenhuma informação disponível. Esses sinais permitem que a lógica de controle ajuste as transferências de dados antes que erros ocorram, ajudando a manter a integridade dos dados e a operação estável do sistema.
Sistemas de vídeo frequentemente envolvem dispositivos que operam em diferentes frequências de relógio, como câmeras e controladores de exibição. Um FIFO de relógio duplo armazena dados de imagem de entrada usando um relógio e permite que sejam lidos usando outro relógio. Isso cria uma ponte confiável entre os dois domínios de tempo e assegura uma transferência contínua de imagem sem erros de sincronização ou corrupção de dados.
Os núcleos IP FIFO do Quartus II simplificam o desenvolvimento ao gerar automaticamente a lógica FIFO otimizada com base em configurações definidas pelo usuário, como profundidade, largura, tipo de relógio e sinais de status. Isso reduz o tempo de design, minimiza o esforço de verificação e muitas vezes oferece melhor utilização de recursos do que implementações codificadas manualmente, tornando-se a solução preferida para a maioria dos projetos FPGA.
29/07/2024
28/08/2024
06/10/2024
04/07/2024
20/09/2025
22/04/2024
15/07/2024
28/12/2023
15/11/2024
15/09/2025









