
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.
Discover more from modrobert weblog
Subscribe to get the latest posts sent to your email.