====== Open Source FPGA toolchain on The Go Board ====== {{ ::goboard.jpg?direct&300|}}The Go Board is an excellent FPGA dev board that contains four switches, four LEDs, two 7-segments, a PMOD, and a VGA connector. I love it for sketching out quick ideas and experiments. For details on buying one, plus all the documentation and video tutorials, head to: [[https://www.nandland.com|nandland.com]] Most of the material there focuses on the commercial iCEcube2 and Lattice Diamond tools. There is [[https://www.youtube.com/watch?v=P-9WCFi0p-0|one video]] that largely outlines the use of the open source tools, but this is from a few years ago. This article aims to take you through a more recent version of ''yosys'', ''nextpnr'', and the Icestorm tools on Windows specifically. There will also be tips along the way and some troubleshooting at the end for when you don't always get the happy path. ===== Getting the tools ===== There are various ways to get the tools. But for Windows, it's not so straight forward. My current pick is still downloading from: https://github.com/im-tomu/fomu.im/releases/download/td19/yosys-icestorm-nextpnr-win64.0.1.zip This is one version back from the latest, but it will suit fine. ===== The Hardware ===== The Go Board contains the iCE40HX1K FPGA in a VQ100 package. We need this information for later. The board operates at 25MHz. ===== Setting up a project ===== This will be pleasantly simple. Just create a project folder: ''blinky-from-scratch'' ===== Constraints ===== A constraint is what maps a pin to a name. The open source tools use the PCF file format (Physical Constraints File) just as the commercial iCEcube2 application does. Create the constraints file which maps the code names to the individual input and output pins of the FPGA called ''board-constraints.pcf'': set_io i_Clk 15 set_io o_LED_2 57 We are only interested in the clock-in and the pin that goes to the second LED (I picked that at random). That's all that will be in the constraints file. There is no harm in supplying the full constraints file if you prefer. You'll just see some "Warning: unmatched constraint" messages during the place and route step. ===== The FPGA Code ===== Create a ''blink.v'' verilog file which will contain simple clock divider routine and change a reg bit after each threshold of clock pulses. And then change the state of an LED on the Go Board. module blink ( input i_Clk, output o_LED_2 ); localparam integer slowDownClkThreshhold = 5000000; reg [31:0] thresholdCounter = 0; reg r_LED = 1'b0; always @(posedge i_Clk) begin if (thresholdCounter > slowDownClkThreshhold) begin r_LED <= !r_LED; thresholdCounter <= 0; end else begin thresholdCounter <= thresholdCounter + 1; end end assign o_LED_2 = r_LED; endmodule ===== The FPGA Tools ===== ''iverilog'' is a great tool for doing a quick synthesis and checking that there are no issues with the code. iverilog blink.v Once happy with the code, then we can move onto the actual synthesis using ''yosys''. Type: ''yosys'' and press enter. Execute the following commands at the yosys prompt: read_verilog blink.v synth_ice40 write_json design.json The above three commands will read in the blink.v verilog file, synthesise the code for an Ice40, then output the design as a JSON file. The following command runs the place and route for the Ice40 FPGA used on the Go Board. It sets the dev board's clock to 25MHz, uses the stripped down constraints file to map the pins, takes in the synthesised design JSON file from ''yosys'', sets the package type and finally outputs the bitstream in ascii/txt format. nextpnr-ice40.exe --hx1k --freq 25 --pcf board-constraints.pcf --json design.json --package vq100 --asc bitstream.txt The resulting bitstream.txt file cannot be used to send to the FPGA. It needs to be packed into a binary first: icepack bitstream.txt bitstream.bin ===== The correct USB Drivers ===== This document does not go into detail about the installation of the [[https://ftdichip.com/drivers/vcp-drivers/|Virtual COM Port driver]]. I am assuming that the reader has these already. But the point is that these drivers are only good for using the commercial tools. The open source tools require changing the drivers to the libusbK ones. Some details on how to convert the driver is here: https://github.com/joshajohnson/WTFpga/blob/a0347ae5b7c024e8f1ba95e6a5287bc7eb07af86/install.md#windows-installation Note: if you switch to libusbK, you cannot use the commercial tools like Lattice Diamond. ===== Programming the Go Board ===== Here is the simple part. Simply enter: iceprog bitstream.bin You will get the following output: init.. cdone: high reset.. cdone: low flash ID: 0x20 0x20 0x11 0x00 file size: 32220 erase 64kB sector at 0x000000.. programming.. reading.. VERIFY OK cdone: high Bye. Within a few seconds your Go Board will be executing your code. You are done. Congratulations on a successful open source toolchain for your Go Board. ===== Extra Notes ===== For ''yosys'' you can script the various commands that we entered earlier to help partially automate your workflow. For the constaints file, you can supply the entire set of constraints, but you will receive harmless warnings. If you would like to supress the warnings, add the ''-nowarn'' flag to each entry in the PCF file like this: set_io -nowarn o_LED_2 57 ===== Troubleshooting ===== When using ''iceprog'' if you get a message: Can't find iCE FTDI USB device (vendor_id 0x0403, device_id 0x6010 or 0x6014). ABORT. This means you are using the standard USB COM port drivers. You need to change them to libusbK. See the following on how to use zadig to change them: https://learn.adafruit.com/adafruit-ft232h-breakout/windows-setup or https://gojimmypi.blogspot.com/2020/12/ice40-fpga-programming-with-wsl-and.html ---- When using ''iceprog'' if you get a message: Found difference between flash and file! It is probable that you are trying to iceprog a bitstream that is not packed into a binary format yet. Check the ''icepack'' step in this article. ---- When using ''nextpnr'' you get a warning message in the output that says: Warning: No clocks found in design Could be a variety of reasons, and nothing to do with having no clock in your design. You probably do have one. The main reason could be the incorrect declaration and use of a reg. Check you are not using a 1-bit instead of a 32bit reg.