1. Blog>
  2. Program Your First FPGA With GOWIN GW1N-4

Program Your First FPGA With GOWIN GW1N-4

by: Nov 03,2020 9094 Views 0 Comments Posted in Technology

FPGA Gowin arduino IoT programming Internet of Things

If you’re a software developer like me, you might be thrilled to see so many exciting embedded hardware platforms that we can now program easily, from Arduinos to the PADI IoT Stamp and the STM32 Blue Pill.

Today we’ll look at a totally different kind of gadget that’s now within our programming reach — FPGA or Field-Programmable Gate Array. But unless you’re a hardware engineer it’s hard to understand how an FPGA works and why it’s different from microcontrollers and CPUs (even though they are all made from the same semiconductor stuff).

GOWIN FPGA dev kit DK-START-GW1N4

Instead of learning FPGA theory, we’ll go hands-on with a real FPGA dev kit — GOWIN DK-START-GW1N4, based on the GW1N-4 FPGA (with 4K LUTs). As we learn how to program the FPGA, we’ll soon realise that FPGA programming is really extraordinary, unlike any other kind of programming we have done before.

Disclosure: I’m using an evaluation dev kit that was kindly loaned to me by GOWIN and Nexcomm Asia. This is not a sponsored product review, this is actually my very first exploration of FPGA tech stemming from my interest in IoT.

Designing Your FPGA

GOWIN (or 高云 in China) provides a simple tool, GOWIN YunYuan (云源), as the starting point for designing our FPGA. All the tools we need for FPGA programming are in that screen above. Before we dive into the code, let’s get familiar with some FPGA concepts…

Grid of logic modules in an FPGA. Colour lines represent connections between logic modules.

GOWIN Configuration Function Unit — Our FPGA connects (and reconnects) thousands of these logic modules together

Think of an FPGA as a two-dimensional grid of semiconductor modules with many rows and columns (our dev kit packs over 4,000 of such tiny modules).

Each logic module has very limited computing capability — counting numbers, adding and multiplying numbers (but not division because that’s too complex).

We have the power to connect (and reconnect) all 4,000 of such modules together to create something useful, like an IoT Sensor device or a video gaming console.

Thankfully we don’t need to connect the modules ourselves. All we need to do: Write some code using the Verilog language. The Verilog compiler converts our code into connections between the logic modules. Let’s look at a simple Verilog code module…

// Demo Verilog Module that flashes the LED by shifting 4 bits
// from "SUG100-1.2E_Gowin YunYuan Software User Guide"

module demo ( // Declare our demo module.
  clk_50M,  // Declare 3 pins: clk_50M, rst_n, led.
  rst_n,   // We will connect these pins to the
  led);   // actual clock signal, reset signal and LEDs.

input clk_50M;  // Declare the clock pin as an Input signal.
input rst_n;   // Reset pin is also an Input, triggered by board restart or reset button.
output[3:0] led; // LED is actually 4 discrete LEDs at 4 Output signals. Each LED Output is 1 bit.
         // So think of "output[3:0] led" as an Output array of 4 bits: "output led[0], led[1], led[2], led[3]"
reg[3:0] led;   // Declare led (4 bits), cnt (25 bits) and clk_led (1 bit) as Registers that
reg[24:0] cnt;  // can remember a value in volatile FPGA memory (similar to RAM).
reg clk_led;   // So led refers to a 4-bit Output signal that is remembered when it gets updated.

// This block increments a counter and flips the clk_led bit on or off upon overflow.
always@(        // Code below is always triggered when these conditions are true...
  posedge clk_50M or // When the clock signal transitions from low to high (positive edge) OR
  negedge rst_n    // When the reset signal transitions from high to low (negative edge) which
  ) begin       // happens when the board restarts or reset button is pressed.

  if (!rst_n) begin   // If board restarts or reset button is pressed...
    clk_led <= 1'b0; // Init clk_led and cnt to 0. "1'b0" means "1-Bit, Binary Value 0"
    cnt <= 25'd0;   // "25'd0" means "25-bit, Decimal Value 0"
  end
  else begin
    if (cnt == 25'd2499_9999) begin // If our counter has reached its limit...
      clk_led <= ~clk_led; // Toggle the clk_led from 0 to 1 (and 1 to 0).
      cnt <= 25'd0;     // Reset the counter to 0.
    end
    else begin
      cnt <= cnt + 25'd1; // Else increment counter by 1. "25'd1" means "25-bit, Decimal Value 1"
    end
  end
end

// This block watches for the clk_led bit to flip from 0 to 1 and shifts the 4 LED lights left.
// The state of the 4 LED lights is remembered by the 4-bit register "led", which looks like this:
// { led[3] , led[2] , led[1] , led[0] } Register "led" is a 4-bit value.
//   ON    ON    ON    OFF   Suppose our 4 LEDs are ON, ON, ON, OFF...
//   0    0    0    1   Map ON to 0 (Low) and OFF to 1 (High)...
// Which equals Binary 0001 = Decimal 1, the "led" value for ON, ON, ON, OFF

// Now what happens when we shift each bit l place left?
// { led[2] , led[1] , led[0] , led[3] } Register "led" is shifted left 1 bit. Bit 3 wraps to 0.
//   ON    ON    OFF   ON   Now our 4 LEDs are ON, ON, OFF, ON...
//   0    0    1    0   Map ON to 0 (Low) and OFF to 1 (High)...
// Which equals Binary 0010 = Decimal 2, the "led" value for ON, ON, OFF, ON
// The first 3 columns { led[2], led[1], led[0] } can be written as { led[2:0] }
// Hence to shift left, we would write { led[2:0], led[3] }

always@(        // Code below is always triggered when these conditions are true...
  posedge clk_led or // When the clk_led register transitions from low to high (positive edge) OR
  negedge rst_n    // When the reset signal transitions from high to low (negative edge) which
  ) begin       // happens when the board restarts or reset button is pressed.

  if (!rst_n) begin // If board restarts or reset button is pressed...
    led <= 4'h1;  // Init the 4-bit led value to 1. "4'h1" means "4-bit, Hexadecimal Value 1".
  end        // Value 1 means ON, ON, ON, OFF for the 4 LEDs (see above)
  else begin
    led <= { led[2:0], led[3] }; // Else we shift the LEDs left 1 place (see above)
  end
end
endmodule

https://github.com/lupyuen/gowin-blink/blob/master/src/demo.v

Coding Your FPGA In Verilog

Take a moment to read through the above Verilog code (which looks like C). On an Arduino we write C programs that are compiled into CPU instructions. On the FPGA however, our Verilog programs are compiled into connections between many many logical semiconductor modules. Since FPGA operates at the logical hardware level, we will code using hardware concepts like…

Clocks at the logic level. Each row is a different Clock Signal.

Clock Signals: All computers (including microcontrollers and FPGAs) operate on very precise clock tick signals that alternate between high and low states at a fixed rate. That’s why we visualise the Clock Signal as a square wave, like you see in the screen.

In the Verilog code above, we use a Clock Signal named clk_50M. That’s because the GOWIN dev board includes a 50 MHz clock (crystal oscillator) that we may connect to the FPGA logic modules for performing timed operations.

Input / Output Signal Pins: On the Arduino we have digital input / output pins like D0, D1, D2, … that we may configure as input or output pins to interface with sensors and other peripherals. Our FPGA code uses the same concept of Input / Output Signal Pins (declared with the input and output Verilog keywords) to connect 4 LEDs and a reset switch.

Registers: If the Verilog code above were really a C program, we would expect variables like clk_50M to maintain their values in memory while the program was running. But with Verilog, the values are not saved in memory unless we declare them as Registers using the reg keyword.

Registers are 1 bit wide by default if we don’t specify the size. To declare led as a 4-bit Register, we use reg[3:0] led.

Connecting The FPGA Signal Pins

In the Verilog code, we have declared 3 Input / Output Signal Pins…

DK-START-GW1N4 dev kit. The GW1N-4 FPGA is at the top, with GPIO ports at the left and right. The bottom edge has 4 push buttons, 4 LEDs and 4 switches.

input clk_50M — To be connected to the 50 MHz clock on the dev board

input rst_n — To be connected to the Reset Button on the dev board

output[3:0] led — To be connected to the 4 LEDs on the dev board (see the photo)

The GOWIN dev board is remarkably dense with plenty of GPIO pins, LVDS pins (for connecting to high resolution displays), buttons, switches and LEDs. Each of these pins and components are wired to the 144 pins of the FPGA. In the schematic below we can see that the vast majority of the pins (labelled F_A_* and F_B_*) are allocated to the two GPIO ports.

The GW1N-4 FPGA wired to the onboard GPIO, LVDS, buttons, switches and LEDs

Arduino Uno Schematic. Pins PD0 and 1 are dedicated for Serial I/O. Pins PB2 to 5 are dedicated for SPI. From https://store.arduino.cc/usa/arduino-uno-rev3

Why do FPGAs have so many general-purpose pins? Because FPGAs can be used to build all kinds of hardware interfaces — I2C, SPI, UART / Serial, even HDMI for video processing. So we no longer need to dedicate specific pins for SPI and Serial ports like the Arduino. We are free now to configure as many ports as we wish, even multiple instances of the ports.

At the lower edge of the FPGA schematic above we can see 4 pins for LEDs: Pins 47, 57, 60 and 61. Here’s how we connect them to output[3:0] led

GOWIN FloorPlanner tool for connecting our Verilog ports to FPGA pins

With the GOWIN FloorPlanner tool we simply click the FPGA pin that we wish to connect to each LED port that was referenced in our Verilog code. We also connect clk_50M to Pin 6, which provides the 50 MHz clock signal, and rst_n to Pin 92, which changes its logic value when the board restarts or when the Reset Button is pressed.

These connections are also known as I/O Constraints. Remember that the FPGA tools will connect the logic modules for us in order to execute our Verilog code and make the LEDs flash. The LED Pins are located at the lower edge of the FPGA, so the tools will allocate logic modules near the lower edge to reduce the latency. In short, the location of the LED Pins actually imposes a constraint on the layout of the logic modules.

What Really Happens Inside The FPGA

After clicking the Synthesize and Place & Route functions in GOWIN YunYuan, we will get a “compiled FPGA program” — essentially a list of allocated logic modules, their locations in the FPGA grid, and how the modules are connected to one another and to the FPGA input/output pins. We can launch GOWIN FloorPlanner again to visualise the results:

How the logic modules were allocated inside the FPGA

The expected latency from the input (clock signal) to the output (LEDs)

How we could reduce the latency by selecting the modules closer to the input and output pins. (This is actually a 2D optimisation problem!)

All the details are explained in my presentation here…

One final step to wrap up the demo — connect the dev board to the PC via USB, power on the dev board and launch the GOWIN Programmer tool to upload our code into the FPGA…

Uploading our FPGA code with the GOWIN Programmer

This step feels exactly like uploading a program to the Arduino. When our code runs, the LEDs on the dev board flash as expected.

For the source files and detailed steps used in this demo, check out my GitHub repository…

lupyuen/gowin-blink

What’s Next?

I’m very grateful that GOWIN has created a dev kit that helps software developers like me to understand the internals of FPGA hardware. And inspire us to wire up our own hardware gadgets with FPGA.

What would I build with FPGA? Power drain has always been a major problem for IoT devices — we would create much better IoT sensing networks if FPGAs could run our devices for longer periods on battery power. I’m now experimenting with the simplest sensors (BME280 on I2C) and the simplest network transceivers (Wisol Sigfox on UART), connecting them with FPGA. I hope to create a very simple IoT device that works but consumes much less power than today’s CPU-based devices.


Note: The content and the pictures in this article are contributed by the author. The opinions expressed by contributors are their own and not those of PCBWay. If there is any infringement of content or pictures, please contact our editor (zoey@pcbway.com) for deleting.


Written by

Join us
Wanna be a dedicated PCBWay writer? We definately look forward to having you with us.
  • Comments(0)
Upload photo
You can only upload 5 files in total. Each file cannot exceed 2MB. Supports JPG, JPEG, GIF, PNG, BMP
0 / 10000
    Back to top