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).U30eU31contam bits e bytes, respectivamente. - O sinal de escrita da RAM estática
recv_buf_weé formado usando o flip-flop DU29B. 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,U16eU18formam 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
U21envia 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 broadcastFF:FF:FF:FF:FF:FFpara 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
0x55seguida por0xD5) 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.U24atua 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
U24fornece 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
U28e 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
0xFB00tem dois flags:RX_FULL- um quadro foi recebidoTX_BUSY- um quadro está sendo transmitido
- o registrador de 16 bits com o comprimento dos dados recebidos em
0xFB02
- o registrador de status de 8 bits em
- Escrever qualquer valor em
0xFB00reinicia o receptor. - Escrever qualquer valor em
0xFB01inicia 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
Opiniões do Hacker News