Programming an FPGA with a FOSS toolchain
This is a quick guide on how to program a Sipeed Tang Nano 9K (GOWIN GW1NR-9) using a fully open source toolchain for FPGA programming. I will use Arch Linux but you may find some of the required packages available in your distro’s package repository as well.
Install Yosys and OpenFPGALoader from the official Arch repository with pacman:
sudo pacman -S yosys openfpgaloader
Now you will need to install nextpnr and Project Apicula from AUR. I had a few problems with these packages so I will explain what I’ve done to make it work for me, but try a normal installation first as these problems will likely get fixed in the near future.
First download and install my apicula-git
package from AUR.
Then download the nextpnr-git
package, also from AUR, and edit the PKGBUILD
file to only build your target:
_ARCHS=('himbaechel')
And comment out this dependency:
himbaechel)
#makedepends+=('prjapicula')
Now you should be able to makepkg -i
, this will take some time so you can brew a mate meanwhile. If everything has gone well you should be able to run nextpnr-himbaechel --version
successfully.
At this point you have everything needed to synthesise, route&place, generate bitstreams and upload them into your Tang Nano. Let’s try out the LED example from the Sipeed wiki.
In a new directory create a led.v
Verilog file with the following code:
module led (
input clk, // clk input
input rst, // reset input
output reg [5:0] led // 6 LEDS pin
);
reg [23:0] counter;
always @(posedge clk or negedge rst) begin
if (!rst)
<= 24'd0;
counter else if (counter < 24'd1349_9999) // 0.5s delay
<= counter + 1'b1;
counter else
<= 24'd0;
counter end
always @(posedge clk or negedge rst) begin
if (!rst)
<= 6'b111110;
led else if (counter == 24'd1349_9999) // 0.5s delay
[5:0] <= {led[4:0],led[5]};
ledelse
<= led;
led end
endmodule
You will need a CST file for this board; you can find an example in the Apicula’s repo but you can also use this fragment (name it tangnano9k.cst
):
IO_LOC "clk" 52;
IO_LOC "led[0]" 10;
IO_LOC "led[1]" 11;
IO_LOC "led[2]" 13;
IO_LOC "led[3]" 14;
IO_LOC "led[4]" 15;
IO_LOC "led[5]" 16;
IO_LOC "key" 3;
IO_LOC "rst" 4;
You are ready to synthesise this design with the following yosys script:
yosys -p "read_verilog led.v; synth_gowin -top led -json led.json"
If the synthesis completes successfully there will be a new led.json
file. Next let’s use nextpnr:
nextpnr-himbaechel --json led.json --write pnrled.json --device GW1NR-LV9QN88PC6/I5 --vopt family=GW1N-9C --vopt cst=tangnano9k.cst
After a few seconds you should see a message saying Program finished normally and there should be a new pnrled.json
file that we will use to generate the bitstream:
gowin_pack -d GW1N-9C -o led.fs pnrled.json
Now it’s time to grab your dev board :D
Connect the Tang Nano 9K to a USB-C and try this:
openFPGALoader --scan-usb
This should list an FT2232 JTAG Debugger, if it doesn’t then try to unplug and plug again (and avoid sketchy USB hubs ^_^). If you do see the debugger then you can run:
openFPGALoader --detect
This should list a Gowin device and it means we are ready to upload the bitstream:
openFPGALoader -b tangnano9k -f led.fs
Once it’s finished, the six tiny LEDs next to the FPGA should be turning on progressively.