
I recently bought a Tang Nano 20k development board from Sipeed. The hardware worked out of the box but I had some software problems with the IDE initially. Programming using the built-in Gowin programmer has been working fine so far (which seems to be common problem). I’m using Xubuntu 24.04.4 LTS (which is basically a slimmed down Ubuntu 24.04.4 LTS running with Xorg and XFCE) on a PC.
After downloading ‘Gowin_V1.9.11.03_Education_Linux.tar.gz’ from gowinsemi.com (requires registering), I unpacked the files into ‘/opt/gowin’ (any directory you create is fine), and tried to run it, but got library version errors and core dumps. In order to fix the problem I created a script called ‘gowin_ide.sh’ to launch ‘gw_ide’:
cd /opt/gowin/IDE/binexport LD_LIBRARY_PATH=/opt/gowin/IDE/lib./gw_ide
This will make sure the IDE uses its own libraries first (before system) and sub processes launched from the GUI also finds them. There was still a library error where it complains about undefined symbols in “libfontconfig”, this needed a separate fix:
rm /opt/gowin/IDE/lib/libfreetype.so.6
Now finally ‘gw_ide’ launches, and also the tools from within the GUI.
I then decided to try an example tutorial found here:
https://wiki.sipeed.com/hardware/en/tang/tang-nano-20k/example/led.html
This worked for the most part, just had to change the “IO Type” voltages to “LVCMOS33” in the FloorPlanner part, more info about in that comments of that article.
I modified the example LED blink design a bit, added another counter LED blink and a Verilog testbench (even though a testbench might be overkill in this case), mostly to figure out how to run a simulation with this toolchain because I didn’t feel like using DSim from Altair (requires registration) which is linked in the GUI.
Here is the modified ‘led.v’ example:
`timescale 1ns 1psmodule led( input wire Clock, output wire LED1, output wire LED5);/********** Counters **********///parameter Clock_frequency = 27_000_000; // Crystal oscillator frequency is 27Mhz`ifdef SIM_COUNT_OVERRIDE parameter LED1_value `SIM_COUNT_OVERRIDE; parameter LED5_value `SIM_COUNT_OVERRIDE;`else parameter LED1_value 13_499_999; // The number of times needed to time 0.5s parameter LED5_value 1_349_999; // This currently acts like a slow clock for GAO at 0.05s`endifreg [23:0] LED1_value_reg 24'b0; // counter valuereg LED1_value_flag 1'b0; // IO change flagalways @(posedge Clock) begin if ( LED1_value_reg < LED1_value ) begin // not count to 0.5s LED1_value_reg < LED1_value_reg 1'b1; // Continue counting LED1_value_flag < 1'b0; // No flip flag end else begin //Count to 0.5S LED1_value_reg < 24'b0; // Clear counter,prepare for next time counting. LED1_value_flag < 1'b1 ; // Flip flag endendreg [23:0] LED5_value_reg 24'b0; // counter value for LED5reg LED5_value_flag 1'b0; // IO change flagalways @(posedge Clock) begin if ( LED5_value_reg < LED5_value ) begin //not count to 0.05s LED5_value_reg < LED5_value_reg 1'b1; // Continue counting LED5_value_flag < 1'b0; // No flip flag end else begin LED5_value_reg < 24'b0; // Clear counter,prepare for next time counting. LED5_value_flag < 1'b1; // Flip flag endend/********** IO voltage flip **********/reg LED1_reg 1'b0; // Initial statealways @(posedge Clock) begin if ( LED1_value_flag ) begin // Flip flag LED1_reg < LED1_reg; // IO voltage flip `ifdef SIMULATION ("Time: %0t LED1: %0d", , LED1_reg); `endif end else // No flip flag LED1_reg < LED1_reg; // IO voltage constantendassign LED1 LED1_reg;/********** IO voltage flip **********/reg LED5_reg 1'b0; // Initial statealways @(posedge Clock) begin if ( LED5_value_flag ) begin // Flip flag LED5_reg < LED5_reg; // IO voltage flip `ifdef SIMULATION ("Time: %0t LED5: %0d", , LED5_reg); `endif end else // No flip flag LED5_reg < LED5_reg; // IO voltage constantendassign LED5 LED5_reg;endmodule
…and the testbench ‘tb_led.v’:
`timescale 1ns 1psmodule tb_led; // Declare signals to connect to the LED module reg Clock 0; wire LED1; wire LED5; // Instantiate your original LED module led uut ( .Clock(Clock), .LED1(LED1), .LED5(LED5) ); // Generate a 27MHz clock always #18.5185 Clock < Clock; always @(LED1) begin ("time: %0t | Testbench observed LED1 at: %b", , LED1); end always @(LED5) begin ("time: %0t | Testbench observed LED5 at: %b", , LED5); end // Control the simulation timeline initial begin // Tell Verilator the name of the waveform file to create ("waveform.fst"); // Dump all signals inside the testbench and child modules (0 means everything) (0, tb_led); // Set a clean format for %0t reporting (0, 4, "s", 20); // Let it run for 1.2 seconds #1200000000; ("Simulation successfully completed!"); ; endendmodule
What I ended up using for simulation is Verilator which is open source can be installed like this in Ubuntu Linux:
sudo apt-get install verilator
I also installed GTKWave Analyzer to visually see trace dumps from Verilator:
sudo apt-get install gtkwave
To build the simulation for my custom testbench I use a terminal shell (command line) in the directory where the Verilog sources are:
verilator --binary --timing --trace-fst --top-module tb_led -DSIMULATION -Wall +1364-2001ext+v led.v tb_led.v
…and then to run the simulation:
obj_dir/Vtb_led
The trace can be found in current directory after simulation run, I load it like this to view:
gtkwave waveform.fst
After playing around with the Gowin Analyzer Oscilloscope (GAO) for a while which is a tool included in the GUI, it seems very powerful (reminds me of Xilinx ChipScope), more info in the user guide.
I hope this info helps to get started, let me know if you have any questions or want to share your own tips.























You must be logged in to post a comment.