3 điểm bởi GN⁺ 2024-04-10 | 1 bình luận | Chia sẻ qua WhatsApp

Tự làm card mạng logic rời rạc

Bài viết này là một phần của loạt bài về quá trình xây dựng một hệ thống máy tính hoàn chỉnh bằng các mạch logic rời rạc. Đến nay, tác giả đã tạo ra một máy tính có thể chạy các ứng dụng mạng như máy chủ HTTP hoặc game LAN.

Tổng quan

  • Năm ngoái, tác giả đã chế tạo một bộ điều hợp lớp vật lý chuyển đổi tín hiệu Ethernet 10BASE-T sang SPI và ngược lại. Khi đó, hoạt động được kiểm thử bằng vi điều khiển STM32, còn giờ đang triển khai mô-đun lớp MAC để kết nối với chiếc máy tính tự chế.
  • Cả hai bộ điều hợp đều là song công toàn phần, với phần phát và phần thu độc lập.

Bộ thu

Tóm tắt cách bộ thu hoạt động:

  • Dữ liệu SPI nối tiếp được chuyển thành dữ liệu song song theo từng byte, và xung nhịp byte được trích xuất.
  • 6 byte đầu tiên được so sánh với chuẩn địa chỉ MAC đích, và các frame không khớp sẽ bị loại bỏ.
  • Các byte được ghi vào bộ đệm RAM tĩnh.
  • Khi frame kết thúc, bộ thu bị vô hiệu hóa, và các frame tiếp theo sẽ bị từ chối cho đến khi người dùng khởi động lại bộ thu. Bộ đếm byte dừng lại và giá trị của nó được cung cấp cho người dùng.

Thu thập dữ liệu

  • Cần chuyển dữ liệu SPI nối tiếp thành luồng byte.
  • Dữ liệu nối tiếp được dịch qua thanh ghi dịch (U32). U30U31 lần lượt đếm bit và byte.
  • Tín hiệu ghi RAM tĩnh recv_buf_we được tạo bằng D flip-flop U29B. Tín hiệu này xuống thấp trong chốc lát sau mỗi 8 bit của dữ liệu đầu vào.
  • Các byte nhận được được ghi vào bộ đệm RAM tĩnh 6116 (U20) dung lượng 2kB.
  • U13, U16, U18 tạo thành bộ ghép kênh địa chỉ để chọn một trong hai nguồn cho đầu vào địa chỉ của SRAM (U20): bộ đếm byte hoặc bus địa chỉ hệ thống.
  • Bộ đệm ba trạng thái U21 chuyển các byte đã nhận vào RAM.

Lọc địa chỉ MAC

  • Khi phân tích lưu lượng Ethernet, tác giả nhận thấy các frame thường đến theo những nhóm nhỏ (3-4 frame cách nhau bởi độ trễ ngắn). Các frame trong một nhóm thường có địa chỉ MAC đích khác nhau.
  • Điều này dẫn đến suy nghĩ rằng máy tính của mình sẽ không thể lọc frame nhận được theo từng MAC rồi khởi động lại bộ thu đủ nhanh để bắt được frame dành cho nó. Vì vậy cần có cơ chế lọc MAC bằng phần cứng.
  • Việc lưu một địa chỉ MAC tùy chỉnh ở đâu đó rồi so sánh với 6 byte nhận đầu tiên là quá phức tạp. Có thể dùng một byte lặp lại (ví dụ FE:FE:FE:FE:FE:FE) nhưng khá nhàm chán.
  • Để tạo một chút biến tấu cho địa chỉ MAC của mình, tác giả làm nó thành hàm của chỉ số byte:
    • Bit 0 cố định là 0
    • Bit 1 cố định là 1
    • Bit 2-4 là giá trị đảo của chỉ số byte
    • Bit 5-7 cố định là 1
  • Với quy tắc này, địa chỉ MAC trở thành FE:FA:F6:F2:EE:EA. Ngoài ra, để hoạt động với ARP, cũng phải chấp nhận MAC quảng bá FF:FF:FF:FF:FF:FF.

Bộ phát

  • Tương tự bộ thu, bộ phát không triển khai tạo FCS trong phần cứng mà thực hiện bằng phần mềm.
  • Để đơn giản hóa hơn nữa, tác giả quyết định chỉ hỗ trợ frame có độ dài cố định. Cách này giúp tránh phải dùng bộ so sánh số phức tạp, và logic truyền frame chỉ cần dựa vào một bit duy nhất của bộ đếm byte.
  • Độ dài frame được chọn là 1024 byte, khá gần với MTU thông thường là 1500 byte.
  • Phần tiền tố frame cần cho 10BASE-T (chuỗi 0x55 theo sau bởi 0xD5) cũng nằm trong 1024 byte và phải được phần mềm nạp vào.

Bộ đếm

  • Cũng như bộ thu, hai bộ đếm được dùng để đếm bit (U12) và byte (U14).
  • Bộ đếm đầu tiên nhận xung clock 20MHz từ bộ dao động tích hợp.
  • 20MHz không được dùng trực tiếp mà ít nhất được chia đôi. Cách này giúp chu kỳ nhiệm vụ của bộ dao động không ảnh hưởng đến tín hiệu đầu ra.

Luồng dữ liệu

  • Để chọn đầu vào địa chỉ của RAM (U22), cùng ba bộ ghép kênh 74HC157 như ở bộ thu được sử dụng (không hiển thị ở đây).
  • U23 được dùng để nạp dữ liệu vào RAM.
  • U24 đóng vai trò là bộ lưu trữ trung gian cho byte hiện đang được truyền. Ý tưởng ở đây tương tự pipeline VGA của tác giả.
  • Bộ đếm byte 74HC4040 là bộ đếm ripple và cần thời gian để ổn định, vì vậy U24 cung cấp đầu ra ổn định trong lúc đầu ra RAM vẫn chưa hợp lệ.
  • Dữ liệu này được đưa vào thanh ghi dịch U28 và dịch ra từng bit.

Giao diện CPU

Từ góc nhìn của lập trình viên, giao diện của bộ điều hợp Ethernet này như sau:

  • Cả hai bộ đệm frame đều được ánh xạ tại 0xF000.
  • Có hai thanh ghi chỉ đọc:
    • Thanh ghi trạng thái 8 bit tại 0xFB00 có hai cờ:
      • RX_FULL - đã nhận được frame
      • TX_BUSY - đang truyền frame
    • Thanh ghi độ dài dữ liệu nhận 16 bit tại 0xFB02
  • Ghi bất kỳ giá trị nào vào 0xFB00 sẽ khởi động lại bộ thu.
  • Ghi bất kỳ giá trị nào vào 0xFB01 sẽ bắt đầu truyền.
  • Không có ngắt vì CPU của tác giả không hỗ trợ interrupt.

Lập trình

Tác giả muốn có hỗ trợ mạng nhưng không muốn tự triển khai một TCP/IP stack từ đầu. Đồng thời, trình biên dịch đầu tiên quá tệ và việc lập trình bằng assembly rất phiền, nên cần một trình biên dịch C tử tế. Vì vậy tác giả đã tự viết một trình biên dịch C. Nó đã đủ trưởng thành để biên dịch uIP 1.0 (một thư viện TCP/IP nhỏ). Dù mật độ mã của CPU này rất thấp, uIP vẫn đủ nhỏ để vừa trong RAM và còn chừa chỗ cho các ứng dụng thực tế.

Hiệu năng mạng rất thấp, nhưng xét việc không dùng CPU thương mại hay chip chuyên dụng nào thì tác giả vẫn rất hài lòng:

  • Thời gian khứ hồi ping trung bình 85ms
  • Tốc độ tải xuống của máy chủ HTTP là 2.6kB/s (phục vụ tệp tĩnh từ thẻ SD)

Kho lưu trữ dự án

Các model, file sơ đồ mạch và bản vẽ PCB có trên GitHub.

Ý kiến của GN⁺

  • Dự án này cho thấy sự hiểu biết sâu sắc và niềm đam mê phần cứng của tác giả. Nỗ lực tự triển khai mọi thứ thật sự rất ấn tượng, nhưng về mặt tính thực dụng thì vẫn gây nhiều băn khoăn.
  • Các hệ thống máy tính hiện đại rất phức tạp và chuyên biệt, nên việc tự xây dựng mọi thứ từ đầu là cực kỳ kém hiệu quả. Đặc biệt với những lĩnh vực đã được chuẩn hóa và tối ưu hóa tốt như network protocol stack, việc tận dụng các implementation sẵn có sẽ khôn ngoan hơn.
  • Dù vậy, những dự án như thế này có giá trị giáo dục rất cao. Chúng cho phép trải nghiệm trực tiếp cách phần cứng và phần mềm cấp thấp tương tác với nhau, cũng như cách các giao thức được triển khai.
  • Ngoài ra, trong bối cảnh ngày càng nhiều lập trình viên ngày nay hiểu biết ít hơn về phần cứng, dự án này có thể là một ví dụ quý giá giúp nhắc lại nền tảng của các hệ thống máy tính.
  • Điểm đáng tiếc là hiệu năng rất thấp. Nếu muốn tăng tính ứng dụng thực tế thì có lẽ cần một triển khai được tối ưu hơn. Nhưng có vẻ đó không phải mục tiêu chính của dự án này.

1 bình luận

 
GN⁺ 2024-04-10
Ý kiến trên Hacker News
  • Dự án này đã tạo ra một card Ethernet cho máy tính tự chế có triển khai lọc địa chỉ MAC bằng phần cứng, và chuỗi suy luận theo từng bước trong quá trình thực hiện rất giàu tính giáo dục và rất xuất sắc.
  • Cách triển khai tối thiểu của một card Ethernet cho PC thông thường có lẽ sẽ tương tự, nhưng sẽ phải tính checksum trên CPU của PC và kết nối qua USB hoặc tương tự.
  • Việc tự làm cả trình biên dịch C, linker và libc cho dự án này thật ấn tượng.
  • Tôi rất khâm phục niềm đam mê và công sức bỏ vào những dự án như thế này, và sau khi nghỉ hưu tôi cũng muốn thử làm một dự án phần cứng/phần mềm như vậy.
  • Trước đây, card Ethernet Etherlink 3c501 có hiệu năng không tốt.
  • Có vẻ như đây là việc làm một card mạng bằng mạch logic rời. (chứ không phải “card mạng logic rời”)
  • Không phải mọi card mạng đều được tạo từ linh kiện logic rời. (câu hỏi ngây thơ)
  • Tính mô-đun của bộ thiết lập máy tính này rất tuyệt vời.
  • Cách giải thích đơn giản mà hiệu quả rất ấn tượng và xứng đáng nhận được nhiều động viên.