Your First Program

Introduction

Learning Cx is straightforward and you should be able to start coding your own applications in few hours. However, creating complex designs can be complex because you may create systems with strong timing constraints and multiple clock domains. So feel free to ask us questions! If you had been programming with procedural languages such as C, C++, you will have to make up your mind to understand that things may happen sequentially or in parallel in the digital world. The Synflow IDE will show you which parts of your code will be executed sequentially and which parts in parallel.

As shown in Figure 1, an application in Cx is organized as a hierarchy. At the top of the hierarchy is a network. A network may instantiate other networks, as well as tasks. Tasks and networks may refer to bundles: a bundle is an entity that defines constants and functions.

Modeling an Application. Figure 1: An application in Cx.

All tasks in a network are executed in parallel. You can add conditional statements to a task so it starts only when it has the required data. Inside a task, your code will be executed sequentially. Simple and straightforward.​If your code add data dependency or if it requires more than a single clock cycle to be executed, a Finite State Machine will automatically be added.

Blinking Led Lights

Blinking led lights and similar applications are the "hello world" of the digital IC world. Indeed, most FPGA based development boards are not equipped with a screen, and there are not libraries to display something easily on a screen using an FPGA. After learning a bit more about Cx and Synflow you will be able to code your own VGA controller (see here to get an idea of what you need to do) and an "hello world" application.

For now, let's begin with a simple blinking led lights application.

Create a new project

  • Right click in the project explorer view and select new Synflow Project. New Project.

  • Name your project LED and select Verilog in the hardware code generation box. LED Project.

Create a new package

A package is a list of identifiers separated by dots, and each package identifies a subset of a design that implements a particular feature. By convention, a package name begins with the company name (e.g. com.acme) or organization name (org.something). More details on the documentation. The running led lights is a basic application so you only need one package to store the source files.

  • Select the src folder, right click on it and click on New Package. New Package.

  • Create your package(for me it is com.synflow.led). Package Name.

Create a new source file

  • Right click on your src package and select new Cx task. New Source File.

  • Name it BlankingLed. The new source file is created and the SDK opens it in a new editor. Blanking Leds File.

Execute the code

You can execute the code generated by the SDK and see what happens.

  • Right click on your BlankingLed source file and select run as... Simulation. Simulation Leds File.

The result is an infinite execution of the loop.

Code the application

The process behind the blanking led lights is basically switching on and off a led. In other words, we need to write a Boolean true or false on the pin of a led to turn on and off the light. This can be done in multiple ways and we will use the simplest:

/*
* Copyright (c) 2016-2019 Synflow
* All rights reserved.
*/
package com.synflow.led;
task BlankingLed {
  out bool led;

  bool switch;

  void loop() {
    switch = !switch;
    led.write(switch);
  }
}

Inside the task, the code out bool led defines a port named led. A port is an interface defined by a network or a task to communicate with other networks/tasks. The direction of the port is out(put) so it sends data to the rest of the world. Inside the loop a global variable switch is negated and the result is written on the output port led.

Validate the code

When coding applications for FPGA, it's best to split the code of the application and the code to test the application. This allows to implement recursive builds. Start by creating a new package called packageName.test (e.g. com.synflow.led.tests) and create a new Cx network named TestBlanking.

testBlanking Network.
Figure: testBlanking Network.

Code your network. It may looks like this:

/*
* Copyright (c) 2016-2019 Synflo
* All rights reserved.
*/
package com.synflow.led.tests;

network TestBlanking {
    import com.synflow.led.BlankingLed;

    // instantiate entities
    blankingLed = new BlankingLed();

    testBlankingLed = new task {        
        void loop () {
            print("led = ", blankingLed.led.read);
        }
    };
}

Inside the network, the codeblankingLed = new BlankingLed();instantiates the task we just wrote. The codetestBlankingLed = new task {...} defines a new task that will constantly read the value of the led port. This is called an inner task (a task defined within a network) and within the task we directly read the output port of another task.

  • You can now open the network view of the IDE to visualize the network we just created. Network View.

  • You can also Execute the application: Right click on your TestBlanking file and select run as... Simulation.

Compilation and synthesis

We are using the Lattice Versa Development Kit for this application and the Synflow SDK will do most of the job.

  • Right click on BlankingLed.cx and select Run as... Hardware on FPGA. Compilation Step 1.

  • Create a new configuration file and name it synthesis_blanking.xml. Select your Vendor, Board, and Model. Compilation Step 2.

  • We are adding new boards on demand. So if your board is not on the list, drop us a line (and select Other in the meanwhile). Then click Apply, and Run. Compilation Step 3.

If you are using a Lattice FPGA or if you have the plugin for Altera and Xilinx, you will see the compilation and synthesis being executed (by the third party software) on the console view. Once done open the generated project by double clicking on the generated project file within the project folder. Compilation Step 4.

Run the application on the FPGA

If your board was not on the list, start by selecting the right FPGA/board within the third party tool.

By default, and considering that you are using a known FPGA based development board,your application is directly connected to the clock and the reset push-button of the FPGA. For this specific application, it means that we will switch on and off the led light at 100MHz... we can't actually see any switch at that speed. So we need a slower clock to perceive the change. There are two options to get a slower clock, dividing the input clock or using a Phase Locked Loop. A PLL is a feedback system that synchronizes an oscillator to the phase and frequency of an incoming signal.

Dividing a clock using logic is a bad idea because it can desynchronize the various parts of an application, creating random bugs on the FPGA. That is why we will use a PLL. Open the IPexpress window (or similar if you are using Xilinx or Altera) and select PLL. Name the PLL PLL and choose Verilog as the output format. PLL.

Configure the PLL so the resulting clock is as slow as possible (ideally 50 Hz), and generate your new PLL. Slow PLL.

This is a basic application so we will directly open the code generated by the Synflow IDE and instantiate the PLL. If your clock is still to fast, you can add a divisor to reduce the speed even further (and yes this is a bad coding style).

/*
 * Copyright (c) 2016-2019 synflow
 * All rights reserved.
 */
module BlankingLed(input clock, input reset_n, output reg  led);  
 wire clock_PLL;  
 reg clock_50hz;  
 reg [9:0] count;  

 PLL PLL1(    
   .CLK(clock),    
   .CLKOP(),    
   .CLKOK(clock_PLL),    
   .LOCK()  );  

   /**   
   *  My clock divider from 50 kHz to 50Hz   
   */  
   always @(negedge reset_n or posedge clock_PLL) begin    
    if (~reset_n) begin      
    clock_50hz  = 0;      
    count  = 0;    
   end else begin      
    if (count == 1000) begin         
      clock_50hz = ~clock_50hz;        
      count = 0;      
    end else begin         
      count = count + 1;      
    end    
   end  
  end  

   /**   * State variables   */  
   reg  switch;     
   /**   * Synchronous process   */  
   always @(negedge reset_n or posedge clock_50hz) begin
    // body of BlankingLed    
    if (~reset_n) begin      
      switch = 1'b0;      
      led = 1'b0;    
    end else begin            
      begin // line 12        
        led = ! (switch);        
        switch = ! (switch);      
      end    
    end  
   end
end module

Finally, we need to configure the pin I/Os file so the output pin of the FPGA is correctly connected to the led light (and to the clock / reset if you are using a custom board).

  • Open the constraint file or the Pin Planner window and connect the output of the FPGA to the led light. IO configuration.

Program the FPGA

With everything setup, you can now run the final synthesis and program the FPGA. Click on Bitstream File (or generate bitstream) and wait for the third party synthesizer to make its job. synthesis.

And program your FPGA!

You can further and apply the same algorithm to more leds. See the video on Youtube: https://youtu.be/-IeT8uM5k1Y

results matching ""

    No results matching ""