3 puntos por GN⁺ 2024-04-10 | 1 comentarios | Compartir por WhatsApp

Cómo hice una tarjeta de red de lógica discreta

Este artículo es parte de una serie sobre el proceso de construir un sistema de cómputo completo usando circuitos de lógica discreta. Hasta ahora, se ha construido una computadora capaz de ejecutar aplicaciones de red como un servidor HTTP o juegos LAN.

Resumen

  • El año pasado se fabricó un adaptador de capa física que convierte señales Ethernet 10BASE-T a SPI y viceversa. En ese momento se probó su funcionamiento usando un microcontrolador STM32, y ahora se está implementando un módulo de capa MAC para conectarlo a una computadora hecha a mano.
  • Ambos adaptadores son full-duplex y tienen secciones independientes de transmisión y recepción.

Receptor

Resumen del funcionamiento del receptor:

  • Los datos seriales SPI se convierten en datos paralelos por bytes, y se extrae el reloj de byte.
  • Los primeros 6 bytes se comparan con una referencia de dirección MAC de destino, y se descartan las tramas que no coinciden.
  • Los bytes se escriben en un búfer de RAM estática.
  • Cuando termina la trama, el receptor se desactiva, y se rechazan tramas adicionales hasta que el usuario reinicie el receptor. El contador de bytes se detiene y su valor se pone a disposición del usuario.

Captura de datos

  • Es necesario convertir los datos seriales SPI en un flujo de bytes.
  • Los datos seriales se desplazan al registro de corrimiento (U32). U30 y U31 cuentan los bits y los bytes, respectivamente.
  • La señal de escritura en RAM estática recv_buf_we se forma usando el flip-flop D U29B. Esta señal baja brevemente después de cada uno de los 8 bits de los datos de entrada.
  • Los bytes recibidos se escriben en un búfer de RAM estática 6116 (U20) de 2 kB.
  • U13, U16 y U18 forman un multiplexor de direcciones que selecciona ya sea el contador de bytes o el bus de direcciones del sistema como entrada de direcciones del SRAM (U20).
  • El búfer triestado U21 envía los bytes recibidos a la RAM.

Filtrado de direcciones MAC

  • Al analizar tráfico Ethernet, se observó que las tramas suelen llegar en grupos pequeños (3-4 tramas separadas por una latencia corta). Las tramas dentro de un grupo normalmente tienen diferentes direcciones MAC de destino.
  • Esto llevó a pensar que la computadora no podría filtrar las tramas recibidas por MAC y reiniciar el receptor lo suficientemente rápido como para capturar las tramas dirigidas a sí misma. Se necesitaba filtrado de direcciones MAC por hardware.
  • Guardar una dirección MAC personalizada en algún lugar y luego compararla con los primeros 6 bytes recibidos era demasiado complejo. También se podía hacer como repetición de un solo byte (por ejemplo, FE:FE:FE:FE:FE:FE), pero sería aburrido.
  • Para darle una pequeña variación a la MAC, se hizo como una función del índice del byte:
    • El bit 0 se fija en 0
    • El bit 1 se fija en 1
    • Los bits 2-4 son la inversión del índice del byte
    • Los bits 5-7 se fijan en 1
  • Con esta regla, la dirección MAC resulta ser FE:FA:F6:F2:EE:EA. Además, para que funcione con ARP, también debe aceptarse la MAC de broadcast FF:FF:FF:FF:FF:FF.

Transmisor

  • Igual que en el receptor, el transmisor no implementa la generación de FCS y eso se hace en software.
  • Para simplificar aún más el transmisor, se decidió soportar solo tramas de longitud fija. Esto evita la necesidad de un comparador digital complejo, y la lógica de transmisión de tramas depende solo de un único bit del contador de bytes.
  • La longitud de la trama se eligió en 1024 bytes, lo cual está cerca del MTU típico de 1500 bytes.
  • El preámbulo de trama requerido por 10BASE-T (una secuencia de 0x55 seguida de 0xD5) también está incluido dentro de esos 1024 bytes y debe cargarse desde software.

Contadores

  • Igual que en el receptor, se usan dos contadores para contar bits (U12) y bytes (U14).
  • El primer contador recibe el reloj de 20 MHz de un oscilador integrado.
  • Los 20 MHz no se usan directamente, sino que primero se dividen al menos entre 2. Así, el ciclo de trabajo del oscilador no afecta la señal de salida.

Flujo de datos

  • Para seleccionar la entrada de direcciones de la RAM (U22), se usan los mismos tres multiplexores 74HC157 que en el receptor (no mostrados aquí).
  • U23 se usa para cargar datos en la RAM.
  • U24 sirve como almacenamiento intermedio para el byte que se está transmitiendo en ese momento. La idea aquí es similar a la de la tubería VGA del autor.
  • El contador de bytes 74HC4040 es un contador ripple y tarda tiempo en estabilizarse, por lo que U24 proporciona una salida estable mientras la salida de la RAM todavía no es válida.
  • Estos datos se alimentan al registro de corrimiento U28 y se desplazan bit a bit.

Interfaz de CPU

Desde el punto de vista del programador, la interfaz del adaptador Ethernet es la siguiente:

  • Ambos búferes de tramas están mapeados en 0xF000.
  • Hay dos registros de solo lectura:
    • El registro de estado de 8 bits en 0xFB00 tiene dos banderas:
      • RX_FULL - se recibió una trama
      • TX_BUSY - una trama está en transmisión
    • El registro de 16 bits de longitud de datos recibidos en 0xFB02
  • Escribir cualquier valor en 0xFB00 reinicia el receptor.
  • Escribir cualquier valor en 0xFB01 inicia la transmisión.
  • No hay interrupciones porque esta CPU no las soporta.

Programación

Se quería tener soporte de red, pero no se quería implementar una pila TCP/IP completa desde cero. Además, como el primer compilador era terrible y programar en ensamblador era una molestia, se quería un compilador de C decente. Así que se hizo un compilador de C. Ya está lo suficientemente maduro como para compilar uIP 1.0 (una biblioteca TCP/IP pequeña). A pesar de que la densidad de código de esta CPU es muy baja, uIP es lo bastante pequeño para caber en la RAM y todavía dejar espacio para aplicaciones reales.

El rendimiento de red es muy bajo, pero considerando que no se usó ninguna CPU comercial ni chips especializados, el resultado sigue siendo muy satisfactorio:

  • Tiempo promedio de ida y vuelta de ping: 85 ms
  • Velocidad de descarga del servidor HTTP: 2.6 kB/s (sirviendo archivos estáticos desde una tarjeta SD)

Repositorio del proyecto

Los modelos, archivos de esquemáticos y diseños de PCB están en GitHub.

Opinión de GN⁺

  • Este proyecto muestra la profunda comprensión y pasión del desarrollador por el hardware. El esfuerzo por implementar todo manualmente es muy impresionante, aunque desde el punto de vista práctico deja algunas dudas.
  • Los sistemas de cómputo modernos son muy complejos y especializados, así que implementar todo desde cero es muy ineficiente. Especialmente en áreas bien establecidas y optimizadas, como la pila de protocolos de red, es más sensato aprovechar implementaciones existentes.
  • Aun así, este tipo de proyectos tiene un valor educativo muy alto, porque permite experimentar directamente cómo interactúan el hardware y el software de bajo nivel, y cómo se implementan los protocolos.
  • Además, en un momento en que entre muchos desarrolladores está disminuyendo la comprensión del hardware, este tipo de proyecto puede ser un ejemplo valioso que recuerde los fundamentos de los sistemas de cómputo.
  • Lo desafortunado es que el rendimiento es muy bajo. Para aumentar su utilidad práctica, parecería necesaria una implementación más optimizada. Pero ese no parece ser el objetivo principal del proyecto.

1 comentarios

 
GN⁺ 2024-04-10
Comentarios de Hacker News
  • Este proyecto creó una tarjeta Ethernet para una computadora personalizada que implementa filtrado de direcciones MAC por hardware, y el rastro de la pila de razonamiento del proceso de trabajo es educativo y excelente.
  • Una implementación mínima de una tarjeta Ethernet para una PC común sería similar, pero habría que calcular el checksum en el CPU de la PC y conectarla por USB o algo similar.
  • Impresiona que para este proyecto haya creado personalmente el compilador de C, el linker, libc, etc.
  • Admiro la pasión y el esfuerzo invertidos en proyectos así, y me gustaría intentar un proyecto de hardware/software como este después de jubilarme.
  • En el pasado, la tarjeta Ethernet Etherlink 3c501 no tenía buen rendimiento.
  • Parece que hizo una tarjeta de red con circuitos de lógica discreta. (No una «tarjeta de red de lógica discreta»)
  • No todas las tarjetas de red están hechas con componentes de lógica discreta. (pregunta ingenua)
  • La modularidad de esta configuración de computadora es excelente.
  • Impresiona que lo haya explicado de forma simple y efectiva, y merece mucho reconocimiento.