Bo mạch FPGA DIY của tôi có thể chạy Quake II
My DIY FPGA board can run Quake II
Một developer đã chế tạo thành công một bo mạch FPGA tùy chỉnh, có khả năng chạy game Quake II. Điểm nhấn của dự án này là việc sử dụng FPGA Efinix Ti60F256 tiên tiến hơn, cùng với 1GB bộ nhớ DDR3L. Dự án cho thấy rõ những thách thức và thành quả trong thiết kế digital tốc độ cao, bao gồm cả kỹ năng BGA soldering và việc layout PCB tỉ mỉ cho các giao diện bộ nhớ. Các developer có thể học hỏi từ cách tác giả tiếp cận việc tích hợp DDR3 controller, xử lý các ràng buộc về PCB routing, cũng như việc tích hợp nhiều thiết bị ngoại vi hiện đại như TMDS serializer và Wi-Fi thông qua ESP32.
Tôi không muốn đơn giản tạo lại những gì tôi đã có trước đây. Làm một cái gì đó cao cấp hơn có nghĩa là hàn BGA. Tôi không chắc mình có thể làm được hay không, nhưng tôi vẫn quyết định thử.
22-tháng-3-2026
- Phần 1/6: Giới thiệu
- Phần 2/6: Nguyên mẫu đầu tiên
- Phần 3/6: Bây giờ nó hầu như đã hoạt động
- Phần 4/6: Thế hệ tiếp theo (bạn đang ở đây)
- Phần 5/6: Thêm một lần lặp lại
- Phần 6/6: Tối ưu hóa phần cứng để chạy Quake II
Đã đến lúc thiết kế một bảng mới
Tôi không muốn đơn giản tạo lại những gì tôi đã có trước đây. Làm một cái gì đó cao cấp hơn có nghĩa là hàn BGA. Tôi không chắc mình có thể làm được hay không nhưng tôi vẫn quyết định thử.
Đặc biệt, tôi muốn có một FPGA tiên tiến hơn – Tôi đã chọn Efinix Ti60F256 – và bộ nhớ hiện đại hơn – IM8G16D3FFBG, là chip DDR3L 1GB. Cái đầu tiên có 256 chân và cái thứ hai có 96, cả hai đều có khoảng cách 0,8 mm.

Một số IC trong gói BGA-256. Tuy nhiên không phải Ti60 nhưng trông rất giống.
Sau những khó khăn với DDR1, tôi hoàn toàn không còn mong muốn phát minh lại bộ điều khiển bộ nhớ. May mắn thay, tôi đã tìm thấy thứ gì đó có cái tên đầy hứa hẹn “Lõi điều khiển mềm DDR3” trên trang web Efinix. Trên diễn đàn cộng đồng của họ, tôi cũng được giới thiệu một hướng dẫn về các đề xuất bố trí PCB DDR3.
Có nhiều thuật ngữ mới lạ nên tôi phải dành nhiều thời gian hơn để tìm hiểu lý thuyết.

Tôi hầu như không thể đáp ứng được yêu cầu về độ dài dấu vết. Các khuyến nghị cũng đề xuất định tuyến tất cả địa chỉ và dòng lệnh trên một lớp duy nhất, nhưng điều đó dường như là không thể. Thay vào đó, tôi cố gắng tính đến sự khác biệt về tốc độ truyền tín hiệu giữa các lớp khác nhau và bù đắp bằng cách rút ngắn các dấu vết trên lớp bên trong.

Lần này PCB có 6 lớp
Tôi đã nghiên cứu các khuyến nghị về số lượng và giá trị của tụ điện tách rời trên đầu vào nguồn điện. Tuy nhiên, tôi vẫn không thể tuân thủ chúng một cách nghiêm túc; rằng nhiều thành phần đơn giản là không vừa về mặt vật lý gần các chân nguồn và tôi thực sự không muốn hàn bất cứ thứ gì nhỏ hơn 0603 (tức là 0,06” x 0,03” — 1,6 x 0,8 mm). Tôi chỉ chen vào nhiều nhất có thể.

Tụ điện ở mặt sau bo mạch theo FPGA, mô hình 3d
Những thay đổi khác so với bảng trước:
- Một chip tuần tự hóa TMDS riêng biệt (TFP410) để tránh các thành phần giả màu xanh lá cây đó.
- Bộ giới hạn dòng điện cho các thiết bị USB được kết nối.
- Khả năng chuyển đổi điện áp đường truyền dữ liệu thẻ SD từ 3,3V sang 1,8V. Có khả năng điều này cho phép tăng tốc độ truyền dữ liệu lên 104 MB/s (chế độ UHS-1 SDR104).
- Một chiếc đồng hồ thời gian thực và một cục pin, để Linux không còn thấy mình như năm 1970 mỗi khi nó khởi động.
- Mô-đun ESP32 dùng làm bộ điều hợp WiFi.
- Trong trường hợp 500mA tiêu chuẩn ở 5V từ USB không đủ, tôi đã thêm cổng USB-C thứ hai và một con chip có khả năng yêu cầu điện áp cao hơn từ nguồn điện.
Cách hàn BGA
Hóa ra, việc đặt mua PCB sáu lớp từ JLCPCB đắt hơn đáng kể so với đặt hàng PCB hai lớp. Lần này, tổng số tiền lên tới hơn 100 đô la và giá gần như nhau cho dù tôi đặt mua 5, 10 hay 20 bản. Để so sánh, lô năm tấm ván hai lớp trước đây của tôi chỉ có giá 2 USD.

PCB và giấy nến; PCB trước đó được thêm vào để so sánh (dưới cùng bên phải)
Hầu hết các bài viết tìm thấy khi tìm kiếm “cách hàn BGA” đều là về sửa chữa. Làm nóng bằng súng nhiệt, tháo chip khỏi một thiết bị, làm sạch vật hàn cũ, đánh bóng lại (đặt một viên bi hàn lên mỗi miếng đệm) và hàn nó vào thiết bị đang được sửa chữa. Việc này khá khó khăn và cần có thiết bị cụ thể, nhưng may mắn thay, nó không cần thiết trong trường hợp này.
Việc hàn chip mới vào thiết bị mới dễ dàng hơn nhiều. Đầu tiên, bôi keo hàn lên tất cả các miếng tiếp xúc trên bo mạch. Sau đó, đặt khoai tây chiên lên trên và đun nóng. Lưu ý: Chất hàn phải được đánh giá ở cùng nhiệt độ với các viên hàn trên miếng chip. Nếu bạn may mắn, mọi thứ sẽ được hàn ở nơi cần thiết mà không có bất kỳ cầu nối nào ở những nơi không nên, và bạn đã hoàn thành. Nếu có sự cố xảy ra (có thể không nhìn thấy được), hãy loại bỏ nó và bắt đầu lại (hoặc tham khảo đoạn trên về cách sửa chữa).
Để bôi keo hàn một cách gọn gàng, cần có giấy nến. Giấy nến của tôi (được đặt hàng cùng với bảng mạch) có chiều rộng khớp chính xác với kích thước của PCB. Điều này khá quan trọng vì nó giúp việc căn chỉnh bảng dễ dàng hơn. Tôi dùng băng keo để cố định khuôn tô và dùng thẻ nhựa để phết hỗn hợp.
Tôi đã mua một chiếc máy sưởi đáy có thể điều chỉnh nhiệt độ, được liệt kê trên trang web của cửa hàng là “Công cụ loại bỏ màn hình trạm sưởi nhiệt độ không đổi Uyue 946”. Trước khi bắt tay vào công việc, tôi đã thực hành (tôi có rất nhiều PCB dự phòng) trên một số chip nhớ rẻ hơn được mua riêng cho mục đích này. Tôi làm nóng mẫu thử đến 221°C và quan sát chất hàn đổi màu và tạo thành những quả bóng.

Bộ sưởi đáy
Tôi đã kiểm tra các quả bóng thu được trên dấu vết của FPGA. Không có khuyết điểm nào được nhìn thấy nên tôi có thể tiếp tục.

Chạy thử
Với bộ gia nhiệt phía dưới, bạn chỉ có thể hàn các bộ phận ở mặt trên của bo mạch. Sau đó, hàng chục tụ điện và điện trở cần được thêm vào phía dưới mà không làm hỏng bất cứ thứ gì ở phía trên. Tôi quyết định hàn mặt dưới bằng súng nhiệt và sử dụng kem hàn có điểm nóng chảy thấp hơn (183°C) để đề phòng.
Đáng ngạc nhiên là mọi thứ đều hiệu quả ngay lần thử đầu tiên. Lần thử đầu tiên mất ba ngày: hàn mặt trên, mặt dưới và sau đó là các đầu nối riêng biệt. Không có vấn đề gì đáng kể. Ở một số chỗ, các chân liền kề được bắc cầu (may mắn là không nằm dưới chip BGA), nhưng tôi đã tách được chúng ra.

Chà, “mọi thứ đều ổn” thì có hơi cường điệu một chút. Sau vài tháng viết và gỡ lỗi trình điều khiển, tôi phát hiện ra rằng Wi-Fi không hoạt động do tôi đã sử dụng sai chân trên mô-đun ESP32, khiến quá trình truyền SPI bị chậm trễ. Vấn đề này đã được giải quyết trong lần sửa đổi tiếp theo của diễn đàn, tôi sẽ đề cập đến vấn đề này sau.
Hệ thống trên chip
Hệ thống trên chip (SoC) là một mạch tích hợp hợp nhất tất cả các thành phần thiết yếu của máy tính – bao gồm CPU, bộ nhớ, đồ họa (GPU) và giao diện I/O – vào một chip duy nhất.
Thuật ngữ “FPGA” là viết tắt của “mảng cổng lập trình trường” có nghĩa là chip có thể được lập trình để thực hiện bất kỳ logic kỹ thuật số tùy chỉnh nào. Logic kỹ thuật số tùy chỉnh này (trong trường hợp của tôi là SoC hoàn chỉnh) phải được xác định bằng ngôn ngữ mô tả phần cứng (HDL). Các HDL phổ biến nhất là Verilog và VHDL. Về cơ bản, mã HDL mô tả cách các phần tử logic, chẳng hạn như AND, OR và NOT, nên được kết nối với nhau.
Trong sơ đồ này, SoC nằm bên trong hình chữ nhật lớn màu xanh lá cây “FPGA Ti60”. Các hình chữ nhật màu xanh lá cây khác là các con chip khác trên bàn cờ.

Tất cả các thành phần trong sơ đồ không có nguồn được đánh dấu đều do tôi thiết kế và có sẵn trên github của tôi (Verilog mã, mã Scala). Bộ điều hợp DDR3 Tilelink, bộ điều khiển UART, bộ điều khiển I2C, bộ điều khiển âm thanh, bộ điều khiển SPI (giao diện SPI FLASH, ESP32 SPI và E2417 SPI có các yêu cầu khác nhau, vì vậy tôi đã kết thúc với 3 bộ điều khiển SPI khác nhau được tối ưu hóa cho các trường hợp sử dụng cụ thể), v.v. Đáng chú ý nhất là bộ điều khiển video và bộ điều khiển DMA.
Phần phức tạp nhất của SoC tất nhiên là lõi bộ xử lý. Và tôi không hề tự mình làm điều đó.
Tôi đã sử dụng các lõi IP sau:
- VexiiRiscv – lõi RISC-V được viết bằng SpinalHDL.
- Một số thành phần được phân phối cùng với SpinalHDL bao gồm kết nối Tilelink, cầu APB3, bộ điều khiển USB OHCI, PLIC.
- Bộ điều khiển thẻ SD ZipCPU/sdspi.
- Lõi điều khiển mềm Efinix DDR3 (không có nguồn, chỉ có thể sử dụng với Efinix FPGA).
Tôi phải nói rằng VexiiRiscv và SpinalHDL (cả hai đều được tạo bởi Dolu1990) cực kỳ ấn tượng. Những dự án này tiến bộ hơn nhiều so với bất kỳ dự án nào tôi có thể tự mình viết bằng HDL.
Khi bắt đầu dự án, tôi thích Verilog hơn và chỉ sử dụng SpinalHDL để tạo mô-đun Verilog từ các nguồn Scala của VexRiscv. Tuy nhiên, trong hai năm qua, tôi ngày càng sử dụng SpinalHDL nhiều hơn và giờ đây tôi thậm chí còn thích nó hơn Verilog khi viết các mô-đun của riêng mình.
Tuy nhiên, quá trình học tập không hề dễ dàng. SpinalHDL là một tập hợp các thư viện tạo mã Verilog/VHDL từ Scala. Nó trở nên khá phức tạp khi trừu tượng hóa phần cứng (đường ống, máy trạng thái hữu hạn, bus, bộ nhớ đệm – CPU không phải là thứ đơn giản) và nội dung tại thời điểm tạo (coroutine, khởi tạo chậm, kế thừa, plugin) được trộn lẫn trong một tệp duy nhất.
Ngoài ra, tôi mới làm quen với Scala và thường không thể biết liệu một chuỗi ký tự có phải là tên biến hay thứ gì đó được xác định sâu bên trong phần bên trong của SpinalHDL hay chỉ là cú pháp Scala tiêu chuẩn (Tôi nhớ đã tra cứu trên Google "???" nghĩa là gì trong Scala; Google bỏ qua các dấu chấm hỏi vì cho rằng tôi chỉ hỏi với rất nhiều biểu thức).
Tài liệu được viết tốt nhưng không bao gồm mọi thứ. Tôi chắc chắn sẽ mua một cuốn sách 1.000 trang như “Cơ bản về SpinalHDL” hoặc “Tìm hiểu SpinalHDL trong 21 ngày” nếu có ai đó viết cuốn sách này.
May mắn thay Dolu1990 luôn sẵn sàng giải đáp thắc mắc (Dolu1990, nếu bạn đọc được dòng này, xin cảm ơn!!!).
Kết quả

- Mức sử dụng FPGA: 53612/60800 XLR (89%), 241/256 khối bộ nhớ (95%).
- Lõi riscv32 đơn (hai lõi chỉ có thể phù hợp với thiết kế nếu tôi hy sinh FPU) hoạt động ở tần số 207 MHz.
- Điểm chuẩn Dhrystone: 511 DMIPS (2,46 DMIPS/MHz). Nó mạnh hơn Pentium nhưng kém hơn Pentium II một chút.
- RAM 1 GB – nhiều hơn mức mà một PC Pentium II trung bình có thể hy vọng.
- Điểm chuẩn dấu phẩy động: tối đa 207 MFLOPS (hoặc 117 MFLOPS trên điểm chuẩn thực tế hơn).
- Coremark 1.0: 783.08.
- Tốc độ đọc thẻ SD: 45,06 MB/giây.
- Bộ nhớ CPU: 348 MB/s.
- Bộ nhớ DMA: 1130 MB/s (giới hạn phần cứng lý thuyết là 1,6 GB/s nếu chúng tôi giả sử truyền dữ liệu trên mỗi tích tắc).
Tôi sẽ nói nhiều hơn về DMA khi tối ưu hóa Quake II. Tôi muốn triển khai GPU nhưng bị giới hạn bởi tài nguyên FPGA còn lại. Vì vậy, tôi đã tạo một “bộ điều khiển DMA” cũng có thể thực hiện một số thao tác liên quan đến đồ họa.
Và một vài ảnh chụp màn hình

Kim loại trần Hello World


Trình quản lý cửa sổ và triển khai TTY của tôi

Diệt vong

Anh hùng2
Xem thêm hình ảnh ở phần tiếp theo.
Phần tiếp theo: sắp ra mắt
Tác giả: sznio