Tang Nano 20k FPGA dev board

Home Forums Electronics Tang Nano 20k FPGA dev board

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #1044
    modrobert's avatarmodrobert
    Keymaster
      Up
      1
      Down
      ::

      GOWIN FPGA Designer

      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’:

      #!/bin/bash
      cd /opt/gowin/IDE/bin
      export 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 / 1ps
      
      module 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
      `endif
      
      reg [23:0]  LED1_value_reg = 24'b0; // counter value
      reg         LED1_value_flag = 1'b0; // IO change flag
      
      always @(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
          end
      end
      
      reg [23:0]  LED5_value_reg = 24'b0; // counter value for LED5
      reg         LED5_value_flag = 1'b0; // IO change flag
      
      always @(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
          end
      end
      
      
      /********** IO voltage flip **********/
      reg LED1_reg = 1'b0; // Initial state
      
      always @(posedge Clock) begin
          if ( LED1_value_flag ) begin //  Flip flag 
              LED1_reg <= ~LED1_reg; // IO voltage flip
              `ifdef SIMULATION
                  $strobe("Time: %0t   LED1: %0d", $time, LED1_reg);
              `endif
          end
          else //  No flip flag
              LED1_reg <= LED1_reg; // IO voltage constant
      end
      
      assign LED1 = LED1_reg;
      
      /********** IO voltage flip **********/
      reg LED5_reg = 1'b0; // Initial state
      
      always @(posedge Clock) begin
          if ( LED5_value_flag ) begin //  Flip flag 
              LED5_reg <= ~LED5_reg; // IO voltage flip
              `ifdef SIMULATION
                  $strobe("Time: %0t  LED5: %0d", $time, LED5_reg);
              `endif
          end
          else //  No flip flag
              LED5_reg <= LED5_reg; // IO voltage constant
      end
      
      assign LED5 = LED5_reg;
      
      endmodule

      …and the testbench ‘tb_led.v’:

      `timescale 1ns / 1ps
      
      module 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
              $strobe("time: %0t | Testbench observed LED1 at: %b", $time, LED1);
          end
      
          always @(LED5) begin
              $strobe("time: %0t | Testbench observed LED5 at: %b", $time, LED5);
          end
      
      
          // Control the simulation timeline
          initial begin
              // Tell Verilator the name of the waveform file to create
              $dumpfile("waveform.fst");
      
              // Dump all signals inside the testbench and child modules (0 means everything)
              $dumpvars(0, tb_led);
      
              // Set a clean format for %0t reporting
              $timeformat(0, 4, "s", 20);
      
              // Let it run for 1.2 seconds
              #1200000000;
      
              $display("Simulation successfully completed!");
              $finish;
          end
      
      endmodule

      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.

      #1051
      modrobert's avatarmodrobert
      Keymaster
        Up
        1
        Down
        ::

        I tried some example code found here:
        https://github.com/sipeed/TangNano-20K-example

        The HDMI example works.

        Testing Tang Nano 20k HDMI support

      Viewing 2 posts - 1 through 2 (of 2 total)
      • You must be logged in to reply to this topic.