First Steps with the Tang Nano FPGA Development Board

The Tang Nano is a very very low cost FPGA development board by Sipeed featuring a GW1N-1-LV FPGA produced by GOWIN Semiconductors. GOWIN is another Chinese chip manufacturer entering the FPGA arena, like Efinix and Anlogic.
The GW1N-1-LV is the smallest member of GOWINs “Little Bee” series, which consists of small footprint instant-on FPGA devices for IoT and interfacing solutions.

The Tang Nano FPGA development board

The Tang Nano offers the following features:

  • GW1N-1-LV FPGA (QFN48 package)
    • 1152 LUT’s
    • 864 FF’s
    • 4 BRAM’s à 18 kbit (72 kbit total)
    • 96 kbit flash memory
    • 1 PLL
  • 34 user IO pins
  • LCD interface connector (ZIF FFC)
  • 2 user buttons
  • 24 MHz oscillator
  • 64 MBit QSPI PSRAM
  • USB-JTAG downloader/debugger (via USB-C connector)
  • 4 pin JTAG header (split into 2 x 2 pins left/right of the USB-C connector)
  • costs just about 5 $ (like the Longan Nano)

Like most of Sipeed’s latest development boards the Tang Nano comes with a USB-C connector, thus a USB-C cable is required to use the board without unnecessary tinkering.
Regarding the LCD interface I am unsure how this would be useful, except for generating some fancy test patterns. Almost all user IO pins are utilized by the LCD interface if it is used, so there are not many pins left which could be used to get a video signal into the FPGA anymore.

The Toolchain

All steps from HDL to bitstream are handled by GOWIN FPGA Designer, a graphical IDE which offers a project based design flow. Both VHDL and Verilog are supported (allegedly up to SystemVerilog-2017).
Timing constraints are defined by industry standard SDC files, however it is not clear which subset of SDC commands is supported.
Pin assignments and IO constraints are defined in a proprietary CST file. Alternatively UCF syntax is supported, as known from Xilinx ISE.

The design flow is very simple and offers just the most basic options.
The synthesis tool can be set to either GowinSynthesis (included with GOWIN FPGA Designer) or Synplify Pro (external synthesis tool by Synopsys). I strongly doubt that anyone will use Synplify Pro for GOWIN FPGA’s. In the following GowinSynthesis is assumed to be the selected synthesis engine.
The PAR step is simple yet effective as well, however I did not test (yet) how PAR performs once the device utilization reaches a higher percentage.
Timing analysis and power analysis reports can be generated once implementation is complete.
GOWIN FPGA Designer also comes with a programmer utility which can be used to program the Tang Nano and read out some device IDs and status registers. The FPGA configuration bitstream can be programmed into embedded flash memory, into external flash memory or can be written directly to the (volatile) SRAM cells of the FPGA.

The Example

To test that the Tang Nano board is working properly I implemented the infamous blinky LED example.

The Tang Nano offers 2 different clock sources: an on-board 24 MHz oscillator and an integrated oscillator running at roughly 240 MHz.
The external 24 MHz clock reference should be used in conjunction with the PLL inside the FPGA, in order to generate an adequate clock signal to drive the logic on the FPGA fabric. For the start, the PLL is generated by using the IP Generator tool to get the correct parameters for the PLL. However, the 24 MHz reference clock can also be used to drive logic directly, without using the PLL.

/* On-Chip PLL 108 MHz. *****************************************************/
wire clk_108M;
wire pll_lock;
wire pll_reset = 1'b0;

assign clk_24M = XTAL_IN;

Gowin_rPLL Gowin_rPLL_inst(
    .clkout(clk_108M),
    .lock(pll_lock),
    .reset(pll_reset),
    .clkin(clk_24M));

To make use of the integrated oscillator another IP core is generated with the IP Generator tool. Alternatively the respective device primtive can be instantiated explicitly.

/* On-Chip Oscillator 2.5 MHz (240 MHz / 96). ********************************/
wire clk_2M5;
Gowin_OSC_div96 Gowin_OSC_div96_inst (.oscout(clk_2M5));

Finally one of the generated clocks can be used to drive a counter, which will get the RGB LED blinking.

/* Blink RGB LED. ***********************************************************/
localparam CNT_LEN = 26;
reg [CNT_LEN-1:0] cnt = 0;

always @ (posedge clk_108M, negedge rstn)
begin
    if (rstn == 1'b0) begin
        cnt <= 'd0;
    end else begin
        cnt <= cnt + 1;
    end
end

always @ (*)
begin
    LED_R <= ~cnt[CNT_LEN-1];
    LED_G <= ~cnt[CNT_LEN-2];
    LED_B <= ~cnt[CNT_LEN-3];
end

I use the 3 MSB’s of the counter to blink the red, green and blue color channel of the RGB LED respectively. Thus the RGB LED will cycle through all possible combinations of colors. The blinking speed may vary depending on the clock driving the counter.

The final step to get the blinky LED design running on the Tang Nano is to define the pin assignment and timing constraints.
The timing constraints consist of two create_clock commands for the 24 MHz reference clock input and the internal oscillator, which is set to 2.5 MHz.

# tang_nano.sdc
create_clock -name CLK -period 41.667 [get_ports {XTAL_IN}]
create_clock -name SLOW -period 400 [get_pins {Gowin_OSC_div96_inst/osc_inst.OSCOUT}]

The pin assignments can be created using the Floorplanner tool and the Tang Nano schematic. For simplicity the constraints can be copied over from the Tang Nano examples repository or my own example code (file tang_nano.cst). Note that I tried to stay as close to the net names of the schematic while naming the top level ports.

// tang_nano.cst
//Copyright (C)2014-2019 Gowin Semiconductor Corporation.
//All rights reserved. 
//File Title: Physical Constraints file
//GOWIN Version: V1.9.3Beta
//Part Number: GW1N-LV1QN48C6/I5
//Created Time: Tue 12 24 23:51:04 2019

IO_LOC "USER_BTN_A" 15;
IO_PORT "USER_BTN_A" IO_TYPE=LVCMOS33;
IO_LOC "XTAL_IN" 35;
IO_PORT "XTAL_IN" IO_TYPE=LVCMOS33;
IO_LOC "USER_BTN_B" 14;
IO_PORT "USER_BTN_B" IO_TYPE=LVCMOS33;
IO_LOC "LCD_R[0]" 27;
IO_PORT "LCD_R[0]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_R[1]" 28;
IO_PORT "LCD_R[1]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_R[2]" 29;
IO_PORT "LCD_R[2]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_R[3]" 30;
IO_PORT "LCD_R[3]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_R[4]" 31;
IO_PORT "LCD_R[4]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_G[0]" 32;
IO_PORT "LCD_G[0]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_G[1]" 33;
IO_PORT "LCD_G[1]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_G[2]" 34;
IO_PORT "LCD_G[2]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_G[3]" 38;
IO_PORT "LCD_G[3]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_G[4]" 39;
IO_PORT "LCD_G[4]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_G[5]" 40;
IO_PORT "LCD_G[5]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_B[0]" 41;
IO_PORT "LCD_B[0]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_B[1]" 42;
IO_PORT "LCD_B[1]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_B[2]" 43;
IO_PORT "LCD_B[2]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_B[3]" 44;
IO_PORT "LCD_B[3]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_B[4]" 45;
IO_PORT "LCD_B[4]" IO_TYPE=LVCMOS33;
IO_LOC "LCD_CLK" 11;
IO_PORT "LCD_CLK" IO_TYPE=LVCMOS33;
IO_LOC "LCD_DE" 5;
IO_PORT "LCD_DE" IO_TYPE=LVCMOS33;
IO_LOC "LCD_HSYNC" 10;
IO_PORT "LCD_HSYNC" IO_TYPE=LVCMOS33;
IO_LOC "LCD_VSYNC" 46;
IO_PORT "LCD_VSYNC" IO_TYPE=LVCMOS33;
IO_LOC "LED_R" 16;
IO_PORT "LED_R" IO_TYPE=LVCMOS33 SLEW_RATE=SLOW;
IO_LOC "LED_G" 17;
IO_PORT "LED_G" IO_TYPE=LVCMOS33 SLEW_RATE=SLOW;
IO_LOC "LED_B" 18;
IO_PORT "LED_B" IO_TYPE=LVCMOS33 SLEW_RATE=SLOW;
GOWIN FPGA Designer: Floorplanner

So far so good. The only thing left now is to generate a programming file for the Tang Nano and toss it on the board.

GOWIN FPGA Designer: Programmer

All done. Time to get impressed by the pinnacle of modern human civilization: a blinking LED.

The Tang Nano skillfully flashing its RGB LED

As usual, the example from this article is available on my Tang Nano github repository.

That’s it for today. See you next time.


References:

  1. https://www.seeedstudio.com/Sipeed-Tang-Nano-FPGA-board-powered-by-GW1N-1-FPGA-p-4304.html
  2. https://github.com/sipeed/Tang-Nano-Doc
  3. https://github.com/sipeed/Tang-Nano-examples
  4. http://dl.sipeed.com/TANG/Nano
  5. https://xesscorp.github.io/tang_nano_user/docs/_site/
  6. https://www.gowinsemi.com/en/product/detail/2/

Previous

Writing and Understanding RISC-V Assembly Code

Next

Some Docker Best Practices

2 Comments

  1. Paulo

    Good tutorial!

    I was wondering if you could help me with the programming tool. I have plugged the tang nano fpga board via usb-c to the pc (OS: Linux Mint), but the device doesn’t get recognized. Do you know if I have to set something first?

    In the Gowin Programmer, it says cable not found.
    I tested the cable with a smartphone and it allows data transfer, so… Will I just need to use the JTAG programmer?

    Best regards,
    Paulo

    • andrsmllr

      Hi,
      my first suggestion is to check the output of lsusb to see if the Tang Nano device was recognized by the Linux system. If not try a different USB cable and check with a different host system. If the Tang Nano is not recognized on different hosts it may be a hardware issue.
      Another problem can result from missing/wrong permissions, e.g. if the user running the programmer is not a member of the dialout group.
      Last but not least, try with the latest software release from GOWIN.
      If all the points above give no hint to the cause of the problem, there is always the option to use the JTAG dongle for programming the Tang Nano, which should always work; given that the JTAG dongle is recognized by the system that is.
      BR

Leave a Reply

Your email address will not be published. Required fields are marked *

Powered by WordPress & Theme by Anders Norén

Close Bitnami banner
Bitnami