3 pontos por GN⁺ 2024-04-10 | 1 comentários | Compartilhar no WhatsApp

Como fiz uma placa de rede com lógica discreta

Este texto faz parte de uma série sobre o processo de construir um sistema de computador completo usando circuitos lógicos discretos. Até agora, foi criado um computador capaz de executar aplicações de rede como um servidor HTTP ou jogos em LAN.

Visão geral

  • No ano passado, foi criado um adaptador de camada física que converte sinal Ethernet 10BASE-T para SPI e também no sentido inverso. Na época, o funcionamento foi testado com um microcontrolador STM32, e agora está sendo implementado um módulo de camada MAC para conectar ao computador feito manualmente.
  • Os dois adaptadores são full-duplex e têm partes independentes de transmissor e receptor.

Receptor

Resumo do funcionamento do receptor:

  • Os dados seriais SPI são convertidos em dados paralelos em nível de byte, e o clock de byte é extraído.
  • Os 6 primeiros bytes são comparados com o valor de referência do endereço MAC de destino, e quadros que não correspondem são rejeitados.
  • Os bytes são gravados em um buffer de RAM estática.
  • Quando o quadro termina, o receptor é desativado, e quadros adicionais são rejeitados até que o usuário reinicie o receptor. O contador de bytes é interrompido e seu valor é disponibilizado ao usuário.

Coleta de dados

  • É necessário converter os dados seriais SPI em um fluxo de bytes.
  • Os dados seriais passam pelo registrador de deslocamento (U32). U30 e U31 contam bits e bytes, respectivamente.
  • O sinal de escrita da RAM estática recv_buf_we é formado usando o flip-flop D U29B. Esse sinal fica brevemente em nível baixo após cada um dos 8 bits dos dados de entrada.
  • Os bytes recebidos são gravados no buffer de RAM estática 6116 (U20) de 2 kB.
  • U13, U16 e U18 formam um multiplexador de endereços que seleciona como entrada de endereço da SRAM (U20) ou o contador de bytes ou o barramento de endereços do sistema.
  • O buffer tri-state U21 envia os bytes recebidos para a RAM.

Filtragem de endereço MAC

  • Ao analisar o tráfego Ethernet, foi observado que os quadros geralmente chegam em pequenos grupos (3 a 4 quadros separados por baixa latência). Os quadros de um grupo normalmente têm endereços MAC de destino diferentes.
  • Isso levou à conclusão de que o computador não conseguiria filtrar os quadros recebidos por MAC e reiniciar o receptor rápido o suficiente para capturar os quadros destinados a ele. Era necessário filtragem de endereço MAC em hardware.
  • Armazenar um endereço MAC personalizado em algum lugar e depois compará-lo com os 6 primeiros bytes recebidos seria complexo demais. Também seria possível usar repetição de um único byte (por exemplo, FE:FE:FE:FE:FE:FE), mas isso seria sem graça.
  • Para dar uma pequena variação ao MAC, ele foi definido como função do índice do byte:
    • o bit 0 é fixo em 0
    • o bit 1 é fixo em 1
    • os bits 2–4 são a inversão do índice do byte
    • os bits 5–7 são fixos em 1
  • Usando essa regra, o endereço MAC fica FE:FA:F6:F2:EE:EA. Também é necessário aceitar o MAC de broadcast FF:FF:FF:FF:FF:FF para funcionar com ARP.

Transmissor

  • De forma semelhante ao receptor, o transmissor não implementa geração de FCS em hardware; isso é feito em software.
  • Para simplificar ainda mais o transmissor, foi decidido suportar apenas quadros de comprimento fixo. Assim, não é necessário um comparador digital complexo, e a lógica de transmissão de quadros depende apenas de um único bit do contador de bytes.
  • O comprimento do quadro foi definido como 1024 bytes, o que fica próximo da MTU comum de 1500 bytes.
  • O preâmbulo de quadro exigido pelo 10BASE-T (uma sequência de 0x55 seguida por 0xD5) também está incluído nesses 1024 bytes e precisa ser carregado pelo software.

Contadores

  • Assim como no receptor, são usados dois contadores para contar bits (U12) e bytes (U14).
  • O primeiro contador recebe o clock de 20 MHz de um oscilador integrado.
  • Os 20 MHz não são usados diretamente e são divididos pelo menos por 2. Assim, o duty cycle do oscilador não afeta o sinal de saída.

Fluxo de dados

  • Os mesmos três multiplexadores 74HC157 do receptor (não mostrados aqui) são usados para selecionar as entradas de endereço da RAM (U22).
  • U23 é usado para carregar os dados na RAM.
  • U24 atua como armazenamento intermediário para o byte atualmente em transmissão. A ideia aqui é semelhante ao pipeline VGA do autor.
  • O contador de bytes 74HC4040 é um ripple counter e leva tempo para estabilizar, então U24 fornece uma saída estável enquanto a saída da RAM ainda não é válida.
  • Esses dados são enviados ao registrador de deslocamento U28 e deslocados bit a bit.

Interface com a CPU

Do ponto de vista do programador, a interface deste adaptador Ethernet é a seguinte:

  • Os dois buffers de quadro são mapeados em 0xF000.
  • Há dois registradores somente leitura:
    • o registrador de status de 8 bits em 0xFB00 tem dois flags:
      • RX_FULL - um quadro foi recebido
      • TX_BUSY - um quadro está sendo transmitido
    • o registrador de 16 bits com o comprimento dos dados recebidos em 0xFB02
  • Escrever qualquer valor em 0xFB00 reinicia o receptor.
  • Escrever qualquer valor em 0xFB01 inicia a transmissão.
  • Não há interrupções porque a CPU não oferece suporte a interrupções.

Programação

Havia interesse em suporte a rede, mas não em implementar uma pilha TCP/IP do zero. Além disso, como o primeiro compilador era ruim e programar em assembly era trabalhoso, era desejável um compilador C decente. Então foi criado um compilador C. Ele já está maduro o suficiente para compilar o uIP 1.0 (uma pequena biblioteca TCP/IP). Apesar da densidade de código muito baixa da CPU, o uIP é pequeno o bastante para caber na RAM e ainda deixar espaço para aplicações reais.

O desempenho de rede é muito baixo, mas ainda assim o resultado é bastante satisfatório considerando que não foram usados CPUs comerciais nem chips especializados:

  • tempo médio de ida e volta do ping: 85 ms
  • velocidade de download do servidor HTTP: 2.6kB/s (servindo arquivos estáticos a partir de um cartão SD)

Repositório do projeto

Modelos, arquivos de esquemáticos e desenhos de PCB estão no GitHub.

Opinião do GN⁺

  • Este projeto mostra um entendimento profundo de hardware e muita paixão por parte do desenvolvedor. O esforço para implementar tudo manualmente é extremamente impressionante, embora haja dúvidas do ponto de vista prático.
  • Os sistemas computacionais modernos são muito complexos e especializados, então implementar tudo do zero é muito ineficiente. Especialmente em áreas já bem estabelecidas e otimizadas, como pilhas de protocolo de rede, é mais sensato aproveitar implementações existentes.
  • Ainda assim, esse tipo de projeto tem um valor educacional muito alto, porque permite experimentar diretamente como hardware e software de baixo nível interagem e como os protocolos são implementados.
  • Além disso, em um momento em que a compreensão de hardware entre desenvolvedores vem diminuindo, este projeto pode servir como um exemplo valioso que relembra os fundamentos dos sistemas computacionais.
  • O ponto fraco é que o desempenho é muito baixo. Para aumentar a viabilidade prática, provavelmente seria necessária uma implementação mais otimizada. Mas isso não parece ser o objetivo principal do projeto.

1 comentários

 
GN⁺ 2024-04-10
Opiniões do Hacker News
  • Este projeto criou uma placa Ethernet para um computador personalizado que implementa filtragem de endereço MAC em hardware, e o rastreamento da pilha de raciocínio ao longo do processo é educativo e excelente.
  • A implementação mínima de uma placa Ethernet para um PC comum provavelmente seria parecida, mas exigiria calcular o checksum na CPU do PC e conectá-la via USB ou algo do tipo.
  • É impressionante que ele tenha criado pessoalmente o compilador C, o linker, a libc etc. para este projeto.
  • Fico admirado com a paixão e o esforço investidos em um projeto assim, e gostaria de tentar fazer um projeto de hardware/software desse tipo depois de me aposentar.
  • Antigamente, a placa Ethernet Etherlink 3c501 não tinha um bom desempenho.
  • Parece que ele criou uma placa de rede com circuitos de lógica discreta. (e não uma placa de rede lógica discreta)
  • Nem todas as placas de rede são feitas com componentes de lógica discreta. (pergunta ingênua)
  • A modularidade dessa configuração de computador é excelente.
  • Impressiona como isso foi explicado de forma simples e eficaz, e merece muito incentivo.