WebSerial FPGA Flasher: From RTL to Physical Silicon
Deploying hardware to an FPGA usually demands gigabytes of vendor software, proprietary cable drivers, and complex project managers. This guide breaks down the open-source physical synthesis pipeline (Yosys + nextpnr) and how the browser WebSerial API programs development boards directly over USB.
1. The open-source FPGA toolchain pipeline
Building a bitstream transforms behavioral Verilog code into physical configuration bits that configure Look-Up Tables (LUTs), flip-flops, Block RAMs (BRAM), and routing multiplexers. RTL Bench automates this entire four-stage pipeline in cloud build runners:
-
1. Logic Synthesis (Yosys): Maps high-level language constructs into target FPGA primitive cells
(e.g.,
synth_gowinfor GW1N/GW2A architectures, orsynth_ice40for Lattice iCE40). -
2. Physical Place & Route (nextpnr): Places logic cells onto the FPGA die grid and
routes interconnection wires while meeting timing constraints. Uses
nextpnr-himbaechelfor Gowin andnextpnr-ice40for Lattice. -
3. Bitstream Packing: Takes the completed routing database (JSON or ASC) and generates the
exact binary layout (
output.bin) expected by the FPGA's configuration state machine (viagowin_packoricepack). - 4. Telemetry Extraction: Extracts hardware resource consumption (LUTs, registers, BRAMs) and achieved maximum operating frequency ($F_{max}$) directly from the layout log.
.bin file
instantly without re-running synthesis. If you modify the top module or I/O standards, the cache automatically invalidates.
2. Supported hardware targets & specifications
RTL Bench supports three primary open-source development targets, each backed by native architecture definitions, default onboard clock pins, and I/O banks:
| Board | FPGA Part | Logic Resources | Memory & DSP | Default Clock |
|---|---|---|---|---|
| Tang Nano 9K | Gowin GW1NR-LV9QN88PC6/I5 | 8,640 LUT4, 6,480 FF | 468 Kbits BRAM, 2 Multipliers | 27 MHz (Pin 52) |
| Tang Nano 20K | Gowin GW2AR-LV18QN88C8/I7 | 20,736 LUT4, 15,552 FF | 828 Kbits BRAM, 48 Multipliers | 27 MHz (Pin 52) |
| iCE40UP5K | Lattice iCE40UP5K-SG48 | 5,280 LUT4, 5,280 FF | 120 Kb BRAM + 1 Mb SPRAM, 8 DSP | 12 MHz (Pin 35) |
3. Pin constraints: CST vs. PCF
Because an FPGA's pins can be wired to buttons, LEDs, HDMI transmitters, or external headers, the Place & Route engine requires a physical constraint file mapping module ports to package pin numbers:
- Gowin Physical Constraints (
pins.cst): UsesIO_LOC "port" pin;syntax with optionalIO_TYPEandPULL_MODErules. - Lattice Pin Constraints (
pins.pcf): Usesset_io [-pullup yes] port pinsyntax.
Synthesizable example: Clock divider & LED blinker
This Verilog module divides a 27 MHz clock down to blink an onboard LED once per second:
module led_blinker (
input wire clk, // Tang Nano 9K/20K: Pin 52 (27 MHz)
input wire rst_n, // Tang Nano Button S1: Pin 3 (active-low)
output reg led // Tang Nano Onboard LED 0: Pin 10 (active-low)
);
reg [24:0] counter;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
counter <= 25'd0;
led <= 1'b1; // LED off
end else begin
if (counter >= 25'd13_500_000) begin
counter <= 25'd0;
led <= ~led; // Toggle state
end else begin
counter <= counter + 1'b1;
end
end
end
endmodule
4. How WebSerial transfers bitstreams
Historically, browser sandboxes were isolated from external hardware. The WebSerial API allows web applications running on Chromium browsers (Chrome, Edge, Opera) to read from and write to physical serial ports:
-
User Gesture Prompt: Clicking โก Flash to FPGA triggers
navigator.serial.requestPort(), prompting you to select the board's USB-to-UART bridge from a system dialog. - Opening Serial Stream: The port opens at the target baud rate (typically 115,200 baud for MCU programming bridges).
-
Direct Stream Writing: An
activeSerialWriterstreams the packed binary array (Uint8Array) directly to the on-board USB interface controller (such as a CH552 or FT2232 chip). - SRAM Configuration: The on-board controller decodes the incoming stream and drives JTAG TDI/TCK signals into the FPGA's configuration core, switching the chip into user logic mode immediately.
-
Integrated UART Console: Once flashing finishes, RTL Bench automatically binds an asynchronous
TextDecoderStreamto the open port, giving you a live serial monitor to interact with soft-core CPUs or custom UART interfaces in real time!
Frequently asked questions
The WebSerial API lets modern web browsers connect directly to local USB COM ports. The browser sends compiled bitstream binaries straight to the FPGA board's on-board USB-JTAG bridge without installing vendor software suites.
RTL Bench supports open-source development boards including the Sipeed Tang Nano 9K (Gowin GW1NR-9C), Tang Nano 20K (Gowin GW2AR-18C), and Lattice iCE40 UltraPlus (iCE40UP5K-SG48).
If your logic exceeds device LUT capacities, fails timing constraints, or assigns an invalid pin, the build runner halts with the exact line number and netlist error from nextpnr. Pin issues trigger automatic safe-pin retries where available.